gecko-dev/gfx/layers/AsyncCanvasRenderer.h
Nathan Froyd ebdc4b2408 Bug 1542344 - fix API mismatches in ImageEncoder; r=mccr8
ImageEncoder::ExtractDataInternal takes a `const nsAString&` for its
options, but flattens it into a null-terminated `nsString` so callees
can take a `char16_t*`.  But nearly all of those callees eventually wind
up calling ImageEncoder::GetInputStream, which just constructs an
`nsDependentString` from the passed character pointer.

There's no reason to do all this extra work.  We can just pass the
original options reference all the way through the stack and avoid
needless conversions.

Differential Revision: https://phabricator.services.mozilla.com/D26353

--HG--
extra : moz-landing-system : lando
2019-04-08 01:51:17 +00:00

153 lines
5.0 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
#define MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_
#include "LayersTypes.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/Mutex.h"
#include "nsCOMPtr.h" // for nsCOMPtr
class nsICanvasRenderingContextInternal;
class nsIInputStream;
class nsISerialEventTarget;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
}
namespace gl {
class GLContext;
}
namespace dom {
class HTMLCanvasElement;
}
namespace layers {
class CanvasClient;
class TextureClient;
/**
* Since HTMLCanvasElement and OffscreenCanvas are not thread-safe, we create
* AsyncCanvasRenderer which is thread-safe wrapper object for communicating
* among main, worker and ImageBridgeChild threads.
*
* Each HTMLCanvasElement object is responsible for creating
* AsyncCanvasRenderer object. Once Canvas is transfered to worker,
* OffscreenCanvas will keep reference pointer of this object.
*
* Sometimes main thread needs AsyncCanvasRenderer's result, such as layers
* fallback to BasicLayerManager or calling toDataURL in Javascript. Simply call
* GetSurface() in main thread will readback the result to mSurface.
*
* If layers backend is LAYERS_CLIENT, this object will pass to ImageBridgeChild
* for submitting frames to Compositor.
*/
class AsyncCanvasRenderer final {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncCanvasRenderer)
public:
AsyncCanvasRenderer();
void NotifyElementAboutAttributesChanged();
void NotifyElementAboutInvalidation();
void SetCanvasClient(CanvasClient* aClient);
void SetWidth(uint32_t aWidth) { mWidth = aWidth; }
void SetHeight(uint32_t aHeight) { mHeight = aHeight; }
void SetIsAlphaPremultiplied(bool aIsAlphaPremultiplied) {
mIsAlphaPremultiplied = aIsAlphaPremultiplied;
}
// Active thread means the thread which spawns GLContext.
void SetActiveEventTarget();
void ResetActiveEventTarget();
// This will readback surface and return the surface
// in the DataSourceSurface.
// Can be called in main thread only.
already_AddRefed<gfx::DataSourceSurface> GetSurface();
// For SharedSurface_Basic case, before the frame sending to the compositor,
// we readback it to a texture client because SharedSurface_Basic cannot
// shared. We don't want to readback it again here, so just copy the content
// of that texture client here to avoid readback again.
void CopyFromTextureClient(TextureClient* aClient);
// Readback current WebGL's content and convert it to InputStream. This
// function called GetSurface implicitly and GetSurface handles only get
// called in the main thread. So this function can be called in main thread.
nsresult GetInputStream(const char* aMimeType,
const nsAString& aEncoderOptions,
nsIInputStream** aStream);
gfx::IntSize GetSize() const { return gfx::IntSize(mWidth, mHeight); }
CompositableHandle GetCanvasClientAsyncHandle() const {
return mCanvasClientAsyncHandle;
}
CanvasClient* GetCanvasClient() const { return mCanvasClient; }
already_AddRefed<nsISerialEventTarget> GetActiveEventTarget();
// The lifetime is controllered by HTMLCanvasElement.
// Only accessed in main thread.
dom::HTMLCanvasElement* mHTMLCanvasElement;
// Only accessed in active thread.
nsICanvasRenderingContextInternal* mContext;
// We need to keep a reference to the context around here, otherwise the
// canvas' surface texture destructor will deref and destroy it too early
// Only accessed in active thread.
RefPtr<gl::GLContext> mGLContext;
private:
virtual ~AsyncCanvasRenderer();
// Readback current WebGL's content and return it as DataSourceSurface.
already_AddRefed<gfx::DataSourceSurface> UpdateTarget();
bool mIsAlphaPremultiplied;
uint32_t mWidth;
uint32_t mHeight;
CompositableHandle mCanvasClientAsyncHandle;
// The lifetime of this pointer is controlled by OffscreenCanvas
// Can be accessed in active thread and ImageBridge thread.
// But we never accessed it at the same time on both thread. So no
// need to protect this member.
CanvasClient* mCanvasClient;
// When backend is LAYER_BASIC and SharedSurface type is Basic.
// CanvasClient will readback the GLContext to a TextureClient
// in order to send frame to compositor. To avoid readback again,
// we copy from this TextureClient to this mSurfaceForBasic directly
// by calling CopyFromTextureClient().
RefPtr<gfx::DataSourceSurface> mSurfaceForBasic;
// Protect non thread-safe objects.
Mutex mMutex;
// Can be accessed in any thread, need protect by mutex.
nsCOMPtr<nsISerialEventTarget> mActiveEventTarget;
};
} // namespace layers
} // namespace mozilla
#endif // MOZILLA_LAYERS_ASYNCCANVASRENDERER_H_