--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -931,33 +931,32 @@ public:
{
if (mContext) {
mContext->mUserDatas.RemoveElement(this);
}
}
static void PreTransactionCallback(void* aData)
{
- auto self = static_cast<CanvasRenderingContext2DUserData*>(aData);
- CanvasRenderingContext2D* context = self->mContext;
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(aData);
if (!context || !context->mTarget)
return;
context->OnStableState();
}
static void DidTransactionCallback(void* aData)
{
- auto self = static_cast<CanvasRenderingContext2DUserData*>(aData);
- if (self->mContext) {
- self->mContext->MarkContextClean();
- if (self->mContext->mDrawObserver) {
- if (self->mContext->mDrawObserver->FrameEnd()) {
+ CanvasRenderingContext2D* context = static_cast<CanvasRenderingContext2D*>(aData);
+ if (context) {
+ context->MarkContextClean();
+ if (context->mDrawObserver) {
+ if (context->mDrawObserver->FrameEnd()) {
// Note that this call deletes and nulls out mDrawObserver:
- self->mContext->RemoveDrawObserver();
+ context->RemoveDrawObserver();
}
}
}
}
bool IsForContext(CanvasRenderingContext2D* aContext)
{
return mContext == aContext;
}
@@ -6243,33 +6242,33 @@ CanvasRenderingContext2D::GetCanvasLayer
return nullptr;
}
if (!mResetLayer && aOldLayer) {
auto userData =
static_cast<CanvasRenderingContext2DUserData*>(
aOldLayer->GetUserData(&g2DContextLayerUserData));
- CanvasLayer::Data data;
+ CanvasInitializeData data;
if (mIsSkiaGL) {
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
}
}
data.mBufferProvider = mBufferProvider;
if (userData &&
userData->IsForContext(this) &&
- static_cast<CanvasLayer*>(aOldLayer)->IsDataValid(data)) {
+ static_cast<CanvasLayer*>(aOldLayer)->CreateOrGetCanvasRenderer()->IsDataValid(data)) {
RefPtr<Layer> ret = aOldLayer;
return ret.forget();
}
}
RefPtr<CanvasLayer> canvasLayer = aManager->CreateCanvasLayer();
if (!canvasLayer) {
NS_WARNING("CreateCanvasLayer returned null!");
@@ -6286,48 +6285,55 @@ CanvasRenderingContext2D::GetCanvasLayer
// notifications after this paint.
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
userData = new CanvasRenderingContext2DUserData(this);
- canvasLayer->SetDidTransactionCallback(
- CanvasRenderingContext2DUserData::DidTransactionCallback, userData);
canvasLayer->SetUserData(&g2DContextLayerUserData, userData);
- CanvasLayer::Data data;
+ CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
+ InitializeCanvasRenderer(aBuilder, canvasRenderer, aMirror);
+ uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
+ canvasLayer->SetContentFlags(flags);
+
+ mResetLayer = false;
+
+ return canvasLayer.forget();
+}
+
+void
+CanvasRenderingContext2D::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer,
+ bool aMirror)
+{
+ CanvasInitializeData data;
data.mSize = GetSize();
data.mHasAlpha = !mOpaque;
-
- canvasLayer->SetPreTransactionCallback(
- CanvasRenderingContext2DUserData::PreTransactionCallback, userData);
-
+ data.mPreTransCallback = CanvasRenderingContext2DUserData::PreTransactionCallback;
+ data.mPreTransCallbackData = this;
+ data.mDidTransCallback = CanvasRenderingContext2DUserData::DidTransactionCallback;
+ data.mDidTransCallbackData = this;
if (mIsSkiaGL) {
GLuint skiaGLTex = SkiaGLTex();
if (skiaGLTex) {
SkiaGLGlue* glue = gfxPlatform::GetPlatform()->GetSkiaGLGlue();
MOZ_ASSERT(glue);
data.mGLContext = glue->GetGLContext();
data.mFrontbufferGLTex = skiaGLTex;
}
}
data.mBufferProvider = mBufferProvider;
- canvasLayer->Initialize(data);
- uint32_t flags = mOpaque ? Layer::CONTENT_OPAQUE : 0;
- canvasLayer->SetContentFlags(flags);
- canvasLayer->Updated();
-
- mResetLayer = false;
-
- return canvasLayer.forget();
+ aRenderer->Initialize(data);
+ aRenderer->SetDirty();
}
void
CanvasRenderingContext2D::MarkContextClean()
{
if (mInvalidateCount > 0) {
mPredictManyRedrawCalls = mInvalidateCount > kCanvasMaxInvalidateCount;
}
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -463,16 +463,19 @@ public:
virtual void SetIsOpaque(bool aIsOpaque) override;
bool GetIsOpaque() override { return mOpaque; }
NS_IMETHOD Reset() override;
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer* aOldLayer,
LayerManager* aManager,
bool aMirror = false) override;
+ void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer,
+ bool aMirror = false) override;
virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;
void MarkContextClean() override;
void MarkContextCleanForFrameCapture() override;
bool IsContextCleanForFrameCapture() override;
NS_IMETHOD SetIsIPC(bool aIsIPC) override;
// this rect is in canvas device space
void Redraw(const mozilla::gfx::Rect& aR);
NS_IMETHOD Redraw(const gfxRect& aR) override { Redraw(ToRect(aR)); return NS_OK; }
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1311,31 +1311,27 @@ public:
explicit WebGLContextUserData(HTMLCanvasElement* canvas)
: mCanvas(canvas)
{}
/* PreTransactionCallback gets called by the Layers code every time the
* WebGL canvas is going to be composited.
*/
static void PreTransactionCallback(void* data) {
- WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
- HTMLCanvasElement* canvas = userdata->mCanvas;
- WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
+ WebGLContext* webgl = static_cast<WebGLContext*>(data);
// Prepare the context for composition
webgl->BeginComposition();
}
/** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
* so it really is the right place to put actions that have to be performed upon compositing
*/
static void DidTransactionCallback(void* data) {
- WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
- HTMLCanvasElement* canvas = userdata->mCanvas;
- WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
+ WebGLContext* webgl = static_cast<WebGLContext*>(data);
// Clean up the context after composition
webgl->EndComposition();
}
private:
RefPtr<HTMLCanvasElement> mCanvas;
};
@@ -1358,56 +1354,68 @@ WebGLContext::GetCanvasLayer(nsDisplayLi
RefPtr<CanvasLayer> canvasLayer = manager->CreateCanvasLayer();
if (!canvasLayer) {
NS_WARNING("CreateCanvasLayer returned null!");
return nullptr;
}
WebGLContextUserData* userData = nullptr;
if (builder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
+ userData = new WebGLContextUserData(mCanvasElement);
+ }
+
+ canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
+
+ CanvasRenderer* canvasRenderer = canvasLayer->CreateOrGetCanvasRenderer();
+ InitializeCanvasRenderer(builder, canvasRenderer, aMirror);
+ uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
+ canvasLayer->SetContentFlags(flags);
+
+ mResetLayer = false;
+ // We only wish to update mLayerIsMirror when a new layer is returned.
+ // If a cached layer is returned above, aMirror is not changing since
+ // the last cached layer was created and mLayerIsMirror is still valid.
+ mLayerIsMirror = aMirror;
+
+ return canvasLayer.forget();
+}
+
+void
+WebGLContext::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer,
+ bool aMirror)
+{
+ CanvasInitializeData data;
+ if (aBuilder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
// Make the layer tell us whenever a transaction finishes (including
// the current transaction), so we can clear our invalidation state and
// start invalidating again. We need to do this for the layer that is
// being painted to a window (there shouldn't be more than one at a time,
// and if there is, flushing the invalidation state more often than
// necessary is harmless).
// The layer will be destroyed when we tear down the presentation
// (at the latest), at which time this userData will be destroyed,
// releasing the reference to the element.
// The userData will receive DidTransactionCallbacks, which flush the
// the invalidation state to indicate that the canvas is up to date.
- userData = new WebGLContextUserData(mCanvasElement);
- canvasLayer->SetDidTransactionCallback(
- WebGLContextUserData::DidTransactionCallback, userData);
- canvasLayer->SetPreTransactionCallback(
- WebGLContextUserData::PreTransactionCallback, userData);
+ data.mPreTransCallback = WebGLContextUserData::PreTransactionCallback;
+ data.mPreTransCallbackData = this;
+ data.mDidTransCallback = WebGLContextUserData::DidTransactionCallback;
+ data.mDidTransCallbackData = this;
}
- canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
-
- CanvasLayer::Data data;
data.mGLContext = gl;
data.mSize = nsIntSize(mWidth, mHeight);
data.mHasAlpha = gl->Caps().alpha;
data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
data.mIsMirror = aMirror;
- canvasLayer->Initialize(data);
- uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
- canvasLayer->SetContentFlags(flags);
- canvasLayer->Updated();
-
- mResetLayer = false;
- // We only wish to update mLayerIsMirror when a new layer is returned.
- // If a cached layer is returned above, aMirror is not changing since
- // the last cached layer was created and mLayerIsMirror is still valid.
- mLayerIsMirror = aMirror;
-
- return canvasLayer.forget();
+ aRenderer->Initialize(data);
+ aRenderer->SetDirty();
}
layers::LayersBackend
WebGLContext::GetCompositorBackendType() const
{
if (mCanvasElement) {
return mCanvasElement->GetCompositorBackendType();
} else if (mOffscreenCanvas) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -457,16 +457,20 @@ public:
}
void InvalidateResolveCacheForTextureWithTexUnit(const GLuint);
already_AddRefed<Layer>
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
LayerManager* manager,
bool aMirror = false) override;
+ void
+ InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer,
+ bool aMirror = false) override;
// Note that 'clean' here refers to its invalidation state, not the
// contents of the buffer.
void MarkContextClean() override { mInvalidated = false; }
void MarkContextCleanForFrameCapture() override { mCapturedFrameInvalidated = false; }
bool IsContextCleanForFrameCapture() override { return !mCapturedFrameInvalidated; }
--- a/dom/canvas/nsICanvasRenderingContextInternal.h
+++ b/dom/canvas/nsICanvasRenderingContextInternal.h
@@ -21,30 +21,32 @@
{ 0xb84f2fed, 0x9d4b, 0x430b, \
{ 0xbd, 0xfb, 0x85, 0x57, 0x8a, 0xc2, 0xb4, 0x4b } }
class nsDisplayListBuilder;
namespace mozilla {
namespace layers {
class CanvasLayer;
+class CanvasRenderer;
class Layer;
class LayerManager;
} // namespace layers
namespace gfx {
class SourceSurface;
} // namespace gfx
} // namespace mozilla
class nsICanvasRenderingContextInternal :
public nsISupports,
public nsAPostRefreshObserver
{
public:
typedef mozilla::layers::CanvasLayer CanvasLayer;
+ typedef mozilla::layers::CanvasRenderer CanvasRenderer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICANVASRENDERINGCONTEXTINTERNAL_IID)
void SetCanvasElement(mozilla::dom::HTMLCanvasElement* parentCanvas)
{
RemovePostRefreshObserver();
@@ -134,16 +136,19 @@ public:
NS_IMETHOD Reset() = 0;
// Return the CanvasLayer for this context, creating
// one for the given layer manager if not available.
virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
Layer *oldLayer,
LayerManager *manager,
bool aMirror = false) = 0;
+ virtual void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer,
+ bool aMirror = false) { };
// Return true if the canvas should be forced to be "inactive" to ensure
// it can be drawn to the screen even if it's too large to be blitted by
// an accelerated CanvasLayer.
virtual bool ShouldForceInactiveLayer(LayerManager *manager) { return false; }
virtual void MarkContextClean() = 0;
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -1163,28 +1163,42 @@ HTMLCanvasElement::GetCanvasLayer(nsDisp
if (!layer) {
NS_WARNING("CreateCanvasLayer failed!");
return nullptr;
}
LayerUserData* userData = nullptr;
layer->SetUserData(&sOffscreenCanvasLayerUserDataDummy, userData);
- CanvasLayer::Data data;
- data.mRenderer = GetAsyncCanvasRenderer();
- data.mSize = GetWidthHeight();
- layer->Initialize(data);
+ CanvasRenderer* canvasRenderer = layer->CreateOrGetCanvasRenderer();
+ InitializeCanvasRenderer(aBuilder, canvasRenderer);
layer->Updated();
return layer.forget();
}
return nullptr;
}
+void
+HTMLCanvasElement::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer)
+{
+ if (mCurrentContext) {
+ mCurrentContext->InitializeCanvasRenderer(aBuilder, aRenderer);
+ }
+
+ if (mOffscreenCanvas) {
+ CanvasInitializeData data;
+ data.mRenderer = GetAsyncCanvasRenderer();
+ data.mSize = GetWidthHeight();
+ aRenderer->Initialize(data);
+ }
+}
+
bool
HTMLCanvasElement::ShouldForceInactiveLayer(LayerManager* aManager)
{
if (mCurrentContext) {
return mCurrentContext->ShouldForceInactiveLayer(aManager);
}
if (mOffscreenCanvas) {
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -25,16 +25,17 @@ class nsICanvasRenderingContextInternal;
class nsITimerCallback;
namespace mozilla {
class WebGLContext;
namespace layers {
class AsyncCanvasRenderer;
+class CanvasRenderer;
class CanvasLayer;
class Image;
class Layer;
class LayerManager;
class SharedSurfaceTextureClient;
} // namespace layers
namespace gfx {
class SourceSurface;
@@ -119,16 +120,17 @@ class HTMLCanvasElement final : public n
public CanvasRenderingContextHelper
{
enum {
DEFAULT_CANVAS_WIDTH = 300,
DEFAULT_CANVAS_HEIGHT = 150
};
typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
+ typedef layers::CanvasRenderer CanvasRenderer;
typedef layers::CanvasLayer CanvasLayer;
typedef layers::Layer Layer;
typedef layers::LayerManager LayerManager;
public:
explicit HTMLCanvasElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLCanvasElement, canvas)
@@ -303,16 +305,18 @@ public:
/*
* Helpers called by various users of Canvas
*/
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
Layer *aOldLayer,
LayerManager *aManager);
+ void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer);
// Should return true if the canvas layer should always be marked inactive.
// We should return true here if we can't do accelerated compositing with
// a non-BasicCanvasLayer.
bool ShouldForceInactiveLayer(LayerManager *aManager);
// Call this whenever we need future changes to the canvas
// to trigger fresh invalidation requests. This needs to be called
// whenever we render the canvas contents to the screen, or whenever we
new file mode 100644
--- /dev/null
+++ b/gfx/layers/CanvasRenderer.cpp
@@ -0,0 +1,39 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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/. */
+
+#include "CanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+CanvasRenderer::CanvasRenderer()
+ : mPreTransCallback(nullptr)
+ , mPreTransCallbackData(nullptr)
+ , mDidTransCallback(nullptr)
+ , mDidTransCallbackData(nullptr)
+ , mDirty(false)
+{
+ MOZ_COUNT_CTOR(CanvasRenderer);
+}
+
+CanvasRenderer::~CanvasRenderer()
+{
+ Destroy();
+ MOZ_COUNT_DTOR(CanvasRenderer);
+}
+
+void
+CanvasRenderer::Initialize(const CanvasInitializeData& aData)
+{
+ mPreTransCallback = aData.mPreTransCallback;
+ mPreTransCallbackData = aData.mPreTransCallbackData;
+ mDidTransCallback = aData.mDidTransCallback;
+ mDidTransCallbackData = aData.mDidTransCallbackData;
+
+ mSize = aData.mSize;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/CanvasRenderer.h
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_CANVASRENDERER_H
+#define GFX_CANVASRENDERER_H
+
+#include <stdint.h> // for uint32_t
+#include "GLContextTypes.h" // for GLContext
+#include "gfxContext.h" // for gfxContext, etc
+#include "gfxTypes.h"
+#include "gfxPlatform.h" // for gfxImageFormat
+#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
+#include "mozilla/Preferences.h" // for Preferences
+#include "mozilla/RefPtr.h" // for RefPtr
+#include "mozilla/gfx/2D.h" // for DrawTarget
+#include "mozilla/mozalloc.h" // for operator delete, etc
+#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
+
+namespace mozilla {
+namespace layers {
+
+class AsyncCanvasRenderer;
+class ClientCanvasRenderer;
+class CopyableCanvasRenderer;
+class PersistentBufferProvider;
+class WebRenderCanvasRendererSync;
+class WebRenderCanvasRendererAsync;
+
+struct CanvasInitializeData {
+ CanvasInitializeData()
+ : mBufferProvider(nullptr)
+ , mGLContext(nullptr)
+ , mRenderer(nullptr)
+ , mPreTransCallback(nullptr)
+ , mPreTransCallbackData(nullptr)
+ , mDidTransCallback(nullptr)
+ , mDidTransCallbackData(nullptr)
+ , mFrontbufferGLTex(0)
+ , mSize(0,0)
+ , mHasAlpha(false)
+ , mIsGLAlphaPremult(true)
+ , mIsMirror(false)
+ { }
+
+ // One of these three must be specified for Canvas2D, but never more than one
+ PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
+ mozilla::gl::GLContext* mGLContext; // or this, for GL.
+ AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
+
+ typedef void (* TransactionCallback)(void* closureData);
+ TransactionCallback mPreTransCallback;
+ void* mPreTransCallbackData;
+ TransactionCallback mDidTransCallback;
+ void* mDidTransCallbackData;
+
+ // Frontbuffer override
+ uint32_t mFrontbufferGLTex;
+
+ // The size of the canvas content
+ gfx::IntSize mSize;
+
+ // Whether the canvas drawingbuffer has an alpha channel.
+ bool mHasAlpha;
+
+ // Whether mGLContext contains data that is alpha-premultiplied.
+ bool mIsGLAlphaPremult;
+
+ // Whether the canvas front buffer is already being rendered somewhere else.
+ // When true, do not swap buffers or Morph() to another factory on mGLContext
+ bool mIsMirror;
+};
+
+// Based class which used for canvas rendering. There are many derived classes for
+// different purposes. such as:
+//
+// CopyableCanvasRenderer provides a utility which readback canvas content to a
+// SourceSurface. BasicCanvasLayer uses CopyableCanvasRenderer.
+//
+// ShareableCanvasRenderer provides IPC capabilities that allow sending canvas
+// content over IPC. This is pure virtual class because the IPC handling is
+// different in different LayerManager. So that we have following classes inherite
+// ShareableCanvasRenderer.
+//
+// ClientCanvasRenderer inherites ShareableCanvasRenderer and be used in
+// ClientCanvasLayer.
+// WebRenderCanvasRenderer inherites ShareableCanvasRenderer and provides all
+// functionality that WebRender uses.
+// WebRenderCanvasRendererSync inherites WebRenderCanvasRenderer and be used in
+// WebRenderCanvasLayer.
+// WebRenderCanvasRendererAsync inherites WebRenderCanvasRenderer and be used in
+// layers-free mode of WebRender.
+//
+// class diagram shows below:
+//
+// +--------------+
+// |CanvasRenderer|
+// +-------+------+
+// ^
+// |
+// +----------------------+
+// |CopyableCanvasRenderer|
+// +----------------------+
+// ^
+// |
+// +-----------+-----------+
+// |ShareableCanvasRenderer|
+// +-----+-----------------+
+// ^ ^
+// +-------------+ +-------+
+// | |
+// +--------------------+ +---------+-------------+
+// |ClientCanvasRenderer| |WebRenderCanvasRenderer|
+// +--------------------+ +--------+--+-----------+
+// ^ ^
+// +-----------------------+ +----+
+// | |
+// +-------------+-------------+ +-------------+--------------+
+// |WebRenderCanvasRendererSync| |WebRenderCanvasRendererAsync|
+// +---------------------------+ +----------------------------+
+class CanvasRenderer
+{
+public:
+ CanvasRenderer();
+ virtual ~CanvasRenderer();
+
+public:
+ virtual void Initialize(const CanvasInitializeData& aData);
+ virtual bool IsDataValid(const CanvasInitializeData& aData) { return true; }
+
+ virtual void ClearCachedResources() { }
+ virtual void Destroy() { }
+
+ const gfx::IntSize& GetSize() const { return mSize; }
+
+ void SetDirty() { mDirty = true; }
+ void ResetDirty() { mDirty = false; }
+ bool IsDirty() const { return mDirty; }
+
+ virtual CopyableCanvasRenderer* AsCopyableCanvasRenderer() { return nullptr; }
+ virtual ClientCanvasRenderer* AsClientCanvasRenderer() { return nullptr; }
+ virtual WebRenderCanvasRendererSync* AsWebRenderCanvasRendererSync() { return nullptr; }
+ virtual WebRenderCanvasRendererAsync* AsWebRenderCanvasRendererAsync() { return nullptr; }
+
+protected:
+ void FirePreTransactionCallback()
+ {
+ if (mPreTransCallback) {
+ mPreTransCallback(mPreTransCallbackData);
+ }
+ }
+
+ void FireDidTransactionCallback()
+ {
+ if (mDidTransCallback) {
+ mDidTransCallback(mDidTransCallbackData);
+ }
+ }
+
+ typedef void (* TransactionCallback)(void* closureData);
+ TransactionCallback mPreTransCallback;
+ void* mPreTransCallbackData;
+ TransactionCallback mDidTransCallback;
+ void* mDidTransCallbackData;
+ gfx::IntSize mSize;
+
+private:
+ /**
+ * Set to true in Updated(), cleared during a transaction.
+ */
+ bool mDirty;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/gfx/layers/CopyableCanvasRenderer.cpp
+++ b/gfx/layers/CopyableCanvasRenderer.cpp
@@ -1,14 +1,14 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/. */
-#include "CopyableCanvasLayer.h"
+#include "CopyableCanvasRenderer.h"
#include "BasicLayersImpl.h" // for FillWithMask, etc
#include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer
#include "SharedSurface.h" // for SharedSurface
#include "SharedSurfaceGL.h" // for SharedSurface
#include "gfxPattern.h" // for gfxPattern, etc
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
@@ -27,34 +27,41 @@
#include "client/TextureClientSharedSurface.h"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
using namespace mozilla::gl;
-CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData) :
- CanvasLayer(aLayerManager, aImplData)
+CopyableCanvasRenderer::CopyableCanvasRenderer()
+ : mGLContext(nullptr)
+ , mBufferProvider(nullptr)
, mGLFrontbuffer(nullptr)
+ , mAsyncRenderer(nullptr)
, mIsAlphaPremultiplied(true)
, mOriginPos(gl::OriginPos::TopLeft)
, mIsMirror(false)
+ , mOpaque(true)
+ , mCachedTempSurface(nullptr)
{
- MOZ_COUNT_CTOR(CopyableCanvasLayer);
+ MOZ_COUNT_CTOR(CopyableCanvasRenderer);
}
-CopyableCanvasLayer::~CopyableCanvasLayer()
+CopyableCanvasRenderer::~CopyableCanvasRenderer()
{
- MOZ_COUNT_DTOR(CopyableCanvasLayer);
+ Destroy();
+ MOZ_COUNT_DTOR(CopyableCanvasRenderer);
}
void
-CopyableCanvasLayer::Initialize(const Data& aData)
+CopyableCanvasRenderer::Initialize(const CanvasInitializeData& aData)
{
+ CanvasRenderer::Initialize(aData);
+
if (aData.mGLContext) {
mGLContext = aData.mGLContext;
mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
mOriginPos = gl::OriginPos::BottomLeft;
mIsMirror = aData.mIsMirror;
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
@@ -65,30 +72,104 @@ CopyableCanvasLayer::Initialize(const Da
mBufferProvider = aData.mBufferProvider;
}
} else if (aData.mBufferProvider) {
mBufferProvider = aData.mBufferProvider;
} else if (aData.mRenderer) {
mAsyncRenderer = aData.mRenderer;
mOriginPos = gl::OriginPos::BottomLeft;
} else {
- MOZ_CRASH("GFX: CanvasLayer created without BufferProvider, DrawTarget or GLContext?");
+ MOZ_CRASH("GFX: CanvasRenderer created without BufferProvider, DrawTarget or GLContext?");
}
- mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
+ mOpaque = !aData.mHasAlpha;
}
bool
-CopyableCanvasLayer::IsDataValid(const Data& aData)
+CopyableCanvasRenderer::IsDataValid(const CanvasInitializeData& aData)
{
return mGLContext == aData.mGLContext;
}
+void
+CopyableCanvasRenderer::ClearCachedResources()
+{
+ if (mBufferProvider) {
+ mBufferProvider->ClearCachedResources();
+ }
+
+ mCachedTempSurface = nullptr;
+}
+
+void
+CopyableCanvasRenderer::Destroy()
+{
+ if (mBufferProvider) {
+ mBufferProvider->ClearCachedResources();
+ }
+
+ mCachedTempSurface = nullptr;
+}
+
+already_AddRefed<SourceSurface>
+CopyableCanvasRenderer::ReadbackSurface()
+{
+ FirePreTransactionCallback();
+ if (mAsyncRenderer) {
+ MOZ_ASSERT(!mBufferProvider);
+ MOZ_ASSERT(!mGLContext);
+ return mAsyncRenderer->GetSurface();
+ }
+
+ if (!mGLContext) {
+ return nullptr;
+ }
+
+ SharedSurface* frontbuffer = nullptr;
+ if (mGLFrontbuffer) {
+ frontbuffer = mGLFrontbuffer.get();
+ } else {
+ GLScreenBuffer* screen = mGLContext->Screen();
+ const auto& front = screen->Front();
+ if (front) {
+ frontbuffer = front->Surf();
+ }
+ }
+
+ if (!frontbuffer) {
+ NS_WARNING("Null frame received.");
+ return nullptr;
+ }
+
+ IntSize readSize(frontbuffer->mSize);
+ SurfaceFormat format =
+ mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
+ bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
+
+ RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
+ // There will already be a warning from inside of GetTempSurface, but
+ // it doesn't hurt to complain:
+ if (NS_WARN_IF(!resultSurf)) {
+ return nullptr;
+ }
+
+ // Readback handles Flush/MarkDirty.
+ mGLContext->Readback(frontbuffer, resultSurf);
+ if (needsPremult) {
+ gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
+ }
+ MOZ_ASSERT(resultSurf);
+
+ FireDidTransactionCallback();
+
+ return resultSurf.forget();
+}
+
DataSourceSurface*
-CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
+CopyableCanvasRenderer::GetTempSurface(const IntSize& aSize,
const SurfaceFormat aFormat)
{
if (!mCachedTempSurface ||
aSize != mCachedTempSurface->GetSize() ||
aFormat != mCachedTempSurface->GetFormat())
{
// Create a surface aligned to 8 bytes since that's the highest alignment WebGL can handle.
uint32_t stride = GetAlignedStride<8>(aSize.width, BytesPerPixel(aFormat));
--- a/gfx/layers/CopyableCanvasRenderer.h
+++ b/gfx/layers/CopyableCanvasRenderer.h
@@ -1,19 +1,19 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_COPYABLECANVASLAYER_H
-#define GFX_COPYABLECANVASLAYER_H
+#ifndef GFX_COPYABLECANVASRENDERER_H
+#define GFX_COPYABLECANVASRENDERER_H
#include <stdint.h> // for uint32_t
+#include "CanvasRenderer.h"
#include "GLContextTypes.h" // for GLContext
-#include "Layers.h" // for CanvasLayer, etc
#include "gfxContext.h" // for gfxContext, etc
#include "gfxTypes.h"
#include "gfxPlatform.h" // for gfxImageFormat
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Preferences.h" // for Preferences
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/mozalloc.h" // for operator delete, etc
@@ -23,43 +23,54 @@ namespace mozilla {
namespace gl {
class SharedSurface;
} // namespace gl
namespace layers {
/**
- * A shared CanvasLayer implementation that supports copying
- * its contents into a gfxASurface using UpdateSurface.
+ * A shared CanvasRenderer implementation that supports copying
+ * its contents into a gfxASurface using RebackSurface.
*/
-class CopyableCanvasLayer : public CanvasLayer
+class CopyableCanvasRenderer : public CanvasRenderer
{
public:
- CopyableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
-
-protected:
- virtual ~CopyableCanvasLayer();
+ CopyableCanvasRenderer();
+ virtual ~CopyableCanvasRenderer();
public:
- virtual void Initialize(const Data& aData) override;
+ void Initialize(const CanvasInitializeData& aData) override;
+ bool IsDataValid(const CanvasInitializeData& aData) override;
+
+ void ClearCachedResources() override;
+ void Destroy() override;
+
+ CopyableCanvasRenderer* AsCopyableCanvasRenderer() override { return this; }
- virtual bool IsDataValid(const Data& aData) override;
+ bool NeedsYFlip() const { return mOriginPos == gl::OriginPos::BottomLeft; }
+ bool HasGLContext() const { return !!mGLContext; }
+ bool IsOpaque() const { return mOpaque; }
- bool IsGLLayer() { return !!mGLContext; }
+ PersistentBufferProvider* GetBufferProvider() { return mBufferProvider; }
+
+ already_AddRefed<gfx::SourceSurface> ReadbackSurface();
protected:
RefPtr<gl::GLContext> mGLContext;
RefPtr<PersistentBufferProvider> mBufferProvider;
UniquePtr<gl::SharedSurface> mGLFrontbuffer;
+ RefPtr<AsyncCanvasRenderer> mAsyncRenderer;
bool mIsAlphaPremultiplied;
gl::OriginPos mOriginPos;
bool mIsMirror;
+ bool mOpaque;
+
RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
const gfx::SurfaceFormat aFormat);
};
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2238,23 +2238,18 @@ BorderLayer::PrintInfo(std::stringstream
void
BorderLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
{
Layer::DumpPacket(aPacket, aParent);
}
CanvasLayer::CanvasLayer(LayerManager* aManager, void* aImplData)
: Layer(aManager, aImplData)
- , mPreTransCallback(nullptr)
- , mPreTransCallbackData(nullptr)
- , mPostTransCallback(nullptr)
- , mPostTransCallbackData(nullptr)
- , mSamplingFilter(gfx::SamplingFilter::GOOD)
- , mDirty(false)
-{}
+{
+}
CanvasLayer::~CanvasLayer() = default;
void
CanvasLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
Layer::PrintInfo(aStream, aPrefix);
if (mSamplingFilter != SamplingFilter::GOOD) {
@@ -2291,16 +2286,26 @@ CanvasLayer::DumpPacket(layerscope::Laye
Layer::DumpPacket(aPacket, aParent);
// Get this layer data
using namespace layerscope;
LayersPacket::Layer* layer = aPacket->mutable_layer(aPacket->layer_size()-1);
layer->set_type(LayersPacket::Layer::CanvasLayer);
DumpFilter(layer, mSamplingFilter);
}
+CanvasRenderer*
+CanvasLayer::CreateOrGetCanvasRenderer()
+{
+ if (!mCanvasRenderer) {
+ mCanvasRenderer.reset(CreateCanvasRendererInternal());
+ }
+
+ return mCanvasRenderer.get();
+}
+
void
ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
{
Layer::PrintInfo(aStream, aPrefix);
if (mSamplingFilter != SamplingFilter::GOOD) {
AppendToString(aStream, mSamplingFilter, " [filter=", "]");
}
}
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -29,16 +29,17 @@
#include "mozilla/UniquePtr.h" // for UniquePtr
#include "mozilla/gfx/BaseMargin.h" // for BaseMargin
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/TiledRegion.h" // for TiledIntRegion
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/gfx/UserData.h" // for UserData, etc
#include "mozilla/layers/BSPTree.h" // for LayerPolygon
+#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/LayerAttributes.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsAutoPtr.h" // for nsAutoPtr, nsRefPtr, etc
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsCSSPropertyID.h" // for nsCSSPropertyID
#include "nsDebug.h" // for NS_ASSERTION
#include "nsISupportsImpl.h" // for Layer::Release, etc
@@ -2704,125 +2705,51 @@ protected:
* if hardware compositing is not available, for reading from the GL
* buffer into an image surface that we can layer composite.)
*
* After Initialize is called, the underlying canvas Surface/GLContext
* must not be modified during a layer transaction.
*/
class CanvasLayer : public Layer {
public:
- struct Data {
- Data()
- : mBufferProvider(nullptr)
- , mGLContext(nullptr)
- , mRenderer(nullptr)
- , mFrontbufferGLTex(0)
- , mSize(0,0)
- , mHasAlpha(false)
- , mIsGLAlphaPremult(true)
- , mIsMirror(false)
- { }
-
- // One of these three must be specified for Canvas2D, but never more than one
- PersistentBufferProvider* mBufferProvider; // A BufferProvider for the Canvas contents
- mozilla::gl::GLContext* mGLContext; // or this, for GL.
- AsyncCanvasRenderer* mRenderer; // or this, for OffscreenCanvas
-
- // Frontbuffer override
- uint32_t mFrontbufferGLTex;
-
- // The size of the canvas content
- gfx::IntSize mSize;
-
- // Whether the canvas drawingbuffer has an alpha channel.
- bool mHasAlpha;
-
- // Whether mGLContext contains data that is alpha-premultiplied.
- bool mIsGLAlphaPremult;
-
- // Whether the canvas front buffer is already being rendered somewhere else.
- // When true, do not swap buffers or Morph() to another factory on mGLContext
- bool mIsMirror;
- };
-
- /**
- * CONSTRUCTION PHASE ONLY
- * Initialize this CanvasLayer with the given data. The data must
- * have either mSurface or mGLContext initialized (but not both), as
- * well as mSize.
- *
- * This must only be called once.
- */
- virtual void Initialize(const Data& aData) = 0;
-
void SetBounds(gfx::IntRect aBounds) { mBounds = aBounds; }
- /**
- * Check the data is owned by this layer is still valid for rendering
- */
- virtual bool IsDataValid(const Data& aData) { return true; }
-
virtual CanvasLayer* AsCanvasLayer() override { return this; }
/**
* Notify this CanvasLayer that the canvas surface contents have
* changed (or will change) before the next transaction.
*/
- void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); }
+ void Updated() { mCanvasRenderer->SetDirty(); SetInvalidRectToVisibleRegion(); }
/**
* Notify this CanvasLayer that the canvas surface contents have
* been painted since the last change.
*/
- void Painted() { mDirty = false; }
+ void Painted() { mCanvasRenderer->ResetDirty(); }
/**
* Returns true if the canvas surface contents have changed since the
* last paint.
*/
bool IsDirty()
{
// We can only tell if we are dirty if we're part of the
// widget's retained layer tree.
if (!mManager || !mManager->IsWidgetLayerManager()) {
return true;
}
- return mDirty;
- }
-
- /**
- * Register a callback to be called at the start of each transaction.
- */
- typedef void PreTransactionCallback(void* closureData);
- void SetPreTransactionCallback(PreTransactionCallback* callback, void* closureData)
- {
- mPreTransCallback = callback;
- mPreTransCallbackData = closureData;
+ return mCanvasRenderer->IsDirty();
}
const nsIntRect& GetBounds() const { return mBounds; }
-protected:
- void FirePreTransactionCallback()
- {
- if (mPreTransCallback) {
- mPreTransCallback(mPreTransCallbackData);
- }
- }
+ CanvasRenderer* CreateOrGetCanvasRenderer();
public:
- /**
- * Register a callback to be called at the end of each transaction.
- */
- typedef void (* DidTransactionCallback)(void* aClosureData);
- void SetDidTransactionCallback(DidTransactionCallback aCallback, void* aClosureData)
- {
- mPostTransCallback = aCallback;
- mPostTransCallbackData = aClosureData;
- }
/**
* CONSTRUCTION PHASE ONLY
* Set the filter used to resample this image (if necessary).
*/
void SetSamplingFilter(gfx::SamplingFilter aSamplingFilter)
{
if (mSamplingFilter != aSamplingFilter) {
@@ -2843,52 +2770,33 @@ public:
// transform, then we'd snap again when compositing the PaintedLayer).
mEffectiveTransform =
SnapTransform(GetLocalTransform(), gfxRect(0, 0, mBounds.width, mBounds.height),
nullptr)*
SnapTransformTranslation(aTransformToSurface, nullptr);
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
}
- bool GetIsAsyncRenderer() const
- {
- return !!mAsyncRenderer;
- }
-
protected:
CanvasLayer(LayerManager* aManager, void* aImplData);
virtual ~CanvasLayer();
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
virtual void DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent) override;
- void FireDidTransactionCallback()
- {
- if (mPostTransCallback) {
- mPostTransCallback(mPostTransCallbackData);
- }
- }
+ virtual CanvasRenderer* CreateCanvasRendererInternal() = 0;
+
+ UniquePtr<CanvasRenderer> mCanvasRenderer;
+ gfx::SamplingFilter mSamplingFilter;
/**
* 0, 0, canvaswidth, canvasheight
*/
gfx::IntRect mBounds;
- PreTransactionCallback* mPreTransCallback;
- void* mPreTransCallbackData;
- DidTransactionCallback mPostTransCallback;
- void* mPostTransCallbackData;
- gfx::SamplingFilter mSamplingFilter;
- RefPtr<AsyncCanvasRenderer> mAsyncRenderer;
-
-private:
- /**
- * Set to true in Updated(), cleared during a transaction.
- */
- bool mDirty;
};
/**
* ContainerLayer that refers to a "foreign" layer tree, through an
* ID. Usage of RefLayer looks like
*
* Construction phase:
* allocate ID for layer subtree
--- a/gfx/layers/ShareableCanvasRenderer.cpp
+++ b/gfx/layers/ShareableCanvasRenderer.cpp
@@ -1,47 +1,43 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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/. */
-#include "ShareableCanvasLayer.h"
+#include "ShareableCanvasRenderer.h"
#include "GLContext.h" // for GLContext
#include "GLScreenBuffer.h" // for GLScreenBuffer
#include "SharedSurfaceGL.h" // for SurfaceFactory_GLTexture, etc
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
namespace mozilla {
namespace layers {
-ShareableCanvasLayer::ShareableCanvasLayer(LayerManager* aLayerManager, void *aImplData)
- : CopyableCanvasLayer(aLayerManager, aImplData)
+ShareableCanvasRenderer::ShareableCanvasRenderer()
+ : mCanvasClient(nullptr)
+ , mFactory(nullptr)
, mFlags(TextureFlags::NO_FLAGS)
{
- MOZ_COUNT_CTOR(ShareableCanvasLayer);
+ MOZ_COUNT_CTOR(ShareableCanvasRenderer);
}
-ShareableCanvasLayer::~ShareableCanvasLayer()
+ShareableCanvasRenderer::~ShareableCanvasRenderer()
{
- MOZ_COUNT_DTOR(ShareableCanvasLayer);
- if (mBufferProvider) {
- mBufferProvider->ClearCachedResources();
- }
- if (mCanvasClient) {
- mCanvasClient->OnDetach();
- mCanvasClient = nullptr;
- }
+ MOZ_COUNT_DTOR(ShareableCanvasRenderer);
+
+ Destroy();
}
void
-ShareableCanvasLayer::Initialize(const Data& aData)
+ShareableCanvasRenderer::Initialize(const CanvasInitializeData& aData)
{
- CopyableCanvasLayer::Initialize(aData);
+ CopyableCanvasRenderer::Initialize(aData);
mCanvasClient = nullptr;
if (!mGLContext)
return;
gl::GLScreenBuffer* screen = mGLContext->Screen();
@@ -75,18 +71,39 @@ ShareableCanvasLayer::Initialize(const D
mFactory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext, caps, mFlags);
}
} else {
if (factory)
screen->Morph(Move(factory));
}
}
+void
+ShareableCanvasRenderer::ClearCachedResources()
+{
+ CopyableCanvasRenderer::ClearCachedResources();
+
+ if (mCanvasClient) {
+ mCanvasClient->Clear();
+ }
+}
+
+void
+ShareableCanvasRenderer::Destroy()
+{
+ CopyableCanvasRenderer::Destroy();
+
+ if (mCanvasClient) {
+ mCanvasClient->OnDetach();
+ mCanvasClient = nullptr;
+ }
+}
+
bool
-ShareableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
+ShareableCanvasRenderer::UpdateTarget(DrawTarget* aDestTarget)
{
MOZ_ASSERT(aDestTarget);
if (!aDestTarget) {
return false;
}
RefPtr<SourceSurface> surface;
@@ -102,17 +119,17 @@ ShareableCanvasLayer::UpdateTarget(DrawT
}
MOZ_ASSERT(surface);
if (!surface) {
return false;
}
aDestTarget->CopySurface(surface,
- IntRect(0, 0, mBounds.width, mBounds.height),
+ IntRect(0, 0, mSize.width, mSize.height),
IntPoint(0, 0));
return true;
}
gl::SharedSurface* frontbuffer = nullptr;
if (mGLFrontbuffer) {
frontbuffer = mGLFrontbuffer.get();
} else {
@@ -124,19 +141,18 @@ ShareableCanvasLayer::UpdateTarget(DrawT
}
if (!frontbuffer) {
NS_WARNING("Null frame received.");
return false;
}
IntSize readSize(frontbuffer->mSize);
- SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
- ? SurfaceFormat::B8G8R8X8
- : SurfaceFormat::B8G8R8A8;
+ SurfaceFormat format =
+ mOpaque ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8;
bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
// Try to read back directly into aDestTarget's output buffer
uint8_t* destData;
IntSize destSize;
int32_t destStride;
SurfaceFormat destFormat;
if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
@@ -169,69 +185,53 @@ ShareableCanvasLayer::UpdateTarget(DrawT
aDestTarget->CopySurface(resultSurf,
IntRect(0, 0, readSize.width, readSize.height),
IntPoint(0, 0));
return true;
}
CanvasClient::CanvasClientType
-ShareableCanvasLayer::GetCanvasClientType()
+ShareableCanvasRenderer::GetCanvasClientType()
{
if (mAsyncRenderer) {
return CanvasClient::CanvasClientAsync;
}
if (mGLContext) {
return CanvasClient::CanvasClientTypeShSurf;
}
return CanvasClient::CanvasClientSurface;
}
void
-ShareableCanvasLayer::UpdateCompositableClient()
+ShareableCanvasRenderer::UpdateCompositableClient()
{
- if (!mCanvasClient) {
- TextureFlags flags = TextureFlags::DEFAULT;
- if (mOriginPos == gl::OriginPos::BottomLeft) {
- flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
- }
-
- if (!mIsAlphaPremultiplied) {
- flags |= TextureFlags::NON_PREMULTIPLIED;
- }
-
- mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
- GetForwarder(),
- flags);
- if (!mCanvasClient) {
- return;
- }
-
- AttachCompositable();
+ if (!CreateCompositable()) {
+ return;
}
if (mCanvasClient && mAsyncRenderer) {
mCanvasClient->UpdateAsync(mAsyncRenderer);
}
if (!IsDirty()) {
return;
}
- Painted();
+ ResetDirty();
FirePreTransactionCallback();
if (mBufferProvider && mBufferProvider->GetTextureClient()) {
- if (!mBufferProvider->SetForwarder(mManager->AsShadowForwarder())) {
+ if (!mBufferProvider->SetForwarder(GetForwarder()->AsLayerForwarder())) {
gfxCriticalNote << "BufferProvider::SetForwarder failed";
return;
}
mCanvasClient->UpdateFromTexture(mBufferProvider->GetTextureClient());
} else {
- mCanvasClient->Update(gfx::IntSize(mBounds.width, mBounds.height), this);
+ mCanvasClient->Update(gfx::IntSize(mSize.width, mSize.height), this);
}
FireDidTransactionCallback();
mCanvasClient->Updated();
}
} // namespace layers
--- a/gfx/layers/ShareableCanvasRenderer.h
+++ b/gfx/layers/ShareableCanvasRenderer.h
@@ -1,50 +1,52 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_SHAREABLECANVASLAYER_H
-#define GFX_SHAREABLECANVASLAYER_H
+#ifndef GFX_SHAREABLECANVASRENDERER_H
+#define GFX_SHAREABLECANVASRENDERER_H
#include "CompositorTypes.h"
-#include "CopyableCanvasLayer.h"
+#include "CopyableCanvasRenderer.h"
#include "mozilla/layers/CanvasClient.h"
namespace mozilla {
namespace gl {
class SurfaceFactory;
} // namespace gl
namespace layers {
-class ShareableCanvasLayer : public CopyableCanvasLayer
+class ShareableCanvasRenderer : public CopyableCanvasRenderer
{
typedef CanvasClient::CanvasClientType CanvasClientType;
public:
- ShareableCanvasLayer(LayerManager* aLayerManager, void *aImplData);
-
-protected:
- virtual ~ShareableCanvasLayer();
+ ShareableCanvasRenderer();
+ virtual ~ShareableCanvasRenderer();
public:
- virtual void Initialize(const Data& aData) override;
+ void Initialize(const CanvasInitializeData& aData) override;
virtual CompositableForwarder* GetForwarder() = 0;
- virtual void AttachCompositable() = 0;
+ virtual bool CreateCompositable() = 0;
+
+ void ClearCachedResources() override;
+ void Destroy() override;
void UpdateCompositableClient();
const TextureFlags& Flags() const { return mFlags; }
-protected:
+ CanvasClient* GetCanvasClient() { return mCanvasClient; }
- bool UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr);
+protected:
+ bool UpdateTarget(gfx::DrawTarget* aDestTarget);
CanvasClientType GetCanvasClientType();
RefPtr<CanvasClient> mCanvasClient;
UniquePtr<gl::SurfaceFactory> mFactory;
TextureFlags mFlags;
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -2,16 +2,17 @@
* 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/. */
#include "BasicCanvasLayer.h"
#include "AsyncCanvasRenderer.h"
#include "basic/BasicLayers.h" // for BasicLayerManager
#include "basic/BasicLayersImpl.h" // for GetEffectiveOperator
+#include "CopyableCanvasRenderer.h"
#include "mozilla/mozalloc.h" // for operator new
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for Layer::AddRef, etc
#include "gfx2DGlue.h"
#include "GLScreenBuffer.h"
#include "GLContext.h"
#include "gfxUtils.h"
#include "mozilla/layers/PersistentBufferProvider.h"
@@ -20,120 +21,73 @@
class gfxContext;
using namespace mozilla::gfx;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
-already_AddRefed<SourceSurface>
-BasicCanvasLayer::UpdateSurface()
-{
- if (mAsyncRenderer) {
- MOZ_ASSERT(!mBufferProvider);
- MOZ_ASSERT(!mGLContext);
- return mAsyncRenderer->GetSurface();
- }
-
- if (!mGLContext) {
- return nullptr;
- }
-
- SharedSurface* frontbuffer = nullptr;
- if (mGLFrontbuffer) {
- frontbuffer = mGLFrontbuffer.get();
- } else {
- GLScreenBuffer* screen = mGLContext->Screen();
- const auto& front = screen->Front();
- if (front) {
- frontbuffer = front->Surf();
- }
- }
-
- if (!frontbuffer) {
- NS_WARNING("Null frame received.");
- return nullptr;
- }
-
- IntSize readSize(frontbuffer->mSize);
- SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
- ? SurfaceFormat::B8G8R8X8
- : SurfaceFormat::B8G8R8A8;
- bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
-
- RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
- // There will already be a warning from inside of GetTempSurface, but
- // it doesn't hurt to complain:
- if (NS_WARN_IF(!resultSurf)) {
- return nullptr;
- }
-
- // Readback handles Flush/MarkDirty.
- mGLContext->Readback(frontbuffer, resultSurf);
- if (needsPremult) {
- gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
- }
- MOZ_ASSERT(resultSurf);
-
- return resultSurf.forget();
-}
-
void
BasicCanvasLayer::Paint(DrawTarget* aDT,
const Point& aDeviceOffset,
Layer* aMaskLayer)
{
if (IsHidden())
return;
RefPtr<SourceSurface> surface;
+ CopyableCanvasRenderer* canvasRenderer = mCanvasRenderer->AsCopyableCanvasRenderer();
+ MOZ_ASSERT(canvasRenderer);
if (IsDirty()) {
Painted();
- FirePreTransactionCallback();
- surface = UpdateSurface();
- FireDidTransactionCallback();
+ surface = canvasRenderer->ReadbackSurface();
}
bool bufferPoviderSnapshot = false;
- if (!surface && mBufferProvider) {
- surface = mBufferProvider->BorrowSnapshot();
+ PersistentBufferProvider* bufferProvider = canvasRenderer->GetBufferProvider();
+ if (!surface && bufferProvider) {
+ surface = bufferProvider->BorrowSnapshot();
bufferPoviderSnapshot = !!surface;
}
if (!surface) {
return;
}
- const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
-
Matrix oldTM;
- if (needsYFlip) {
+ if (canvasRenderer->NeedsYFlip()) {
oldTM = aDT->GetTransform();
aDT->SetTransform(Matrix(oldTM).
PreTranslate(0.0f, mBounds.height).
PreScale(1.0f, -1.0f));
}
FillRectWithMask(aDT, aDeviceOffset,
Rect(0, 0, mBounds.width, mBounds.height),
surface, mSamplingFilter,
DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
aMaskLayer);
- if (needsYFlip) {
+ if (canvasRenderer->NeedsYFlip()) {
aDT->SetTransform(oldTM);
}
if (bufferPoviderSnapshot) {
- mBufferProvider->ReturnSnapshot(surface.forget());
+ bufferProvider->ReturnSnapshot(surface.forget());
}
}
+CanvasRenderer*
+BasicCanvasLayer::CreateCanvasRendererInternal()
+{
+ return new CopyableCanvasRenderer();
+}
+
already_AddRefed<CanvasLayer>
BasicLayerManager::CreateCanvasLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
RefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
return layer.forget();
}
--- a/gfx/layers/basic/BasicCanvasLayer.h
+++ b/gfx/layers/basic/BasicCanvasLayer.h
@@ -3,49 +3,47 @@
* 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 GFX_BASICCANVASLAYER_H
#define GFX_BASICCANVASLAYER_H
#include "BasicImplData.h" // for BasicImplData
#include "BasicLayers.h" // for BasicLayerManager
-#include "CopyableCanvasLayer.h" // for CopyableCanvasLayer
#include "Layers.h" // for CanvasLayer, etc
#include "nsDebug.h" // for NS_ASSERTION
#include "nsRegion.h" // for nsIntRegion
namespace mozilla {
namespace layers {
-class BasicCanvasLayer : public CopyableCanvasLayer,
+class BasicCanvasLayer : public CanvasLayer,
public BasicImplData
{
public:
explicit BasicCanvasLayer(BasicLayerManager* aLayerManager) :
- CopyableCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
+ CanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
{ }
virtual void SetVisibleRegion(const LayerIntRegion& aRegion) override
{
NS_ASSERTION(BasicManager()->InConstruction(),
"Can only set properties in construction phase");
CanvasLayer::SetVisibleRegion(aRegion);
}
virtual void Paint(gfx::DrawTarget* aDT,
const gfx::Point& aDeviceOffset,
Layer* aMaskLayer) override;
protected:
-
- already_AddRefed<gfx::SourceSurface> UpdateSurface();
-
BasicLayerManager* BasicManager()
{
return static_cast<BasicLayerManager*>(mManager);
}
+
+ CanvasRenderer* CreateCanvasRendererInternal() override;
};
} // namespace layers
} // namespace mozilla
#endif
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -17,17 +17,16 @@
#include "mozilla/layers/AsyncCanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorBridgeChild.h" // for CompositorBridgeChild
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
#include "mozilla/layers/TextureClientOGL.h"
#include "nsDebug.h" // for printf_stderr, NS_ASSERTION
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
-#include "ShareableCanvasLayer.h"
#include "TextureClientSharedSurface.h"
using namespace mozilla::gfx;
using namespace mozilla::gl;
namespace mozilla {
namespace layers {
@@ -86,40 +85,38 @@ CanvasClient2D::UpdateFromTexture(Textur
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
t->mFrameID = mFrameID;
GetForwarder()->UseTextures(this, textures);
aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
}
void
-CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
+CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer)
{
mBufferProviderTexture = nullptr;
AutoRemoveTexture autoRemove(this);
if (mBackBuffer && (mBackBuffer->IsReadLocked() || mBackBuffer->GetSize() != aSize)) {
autoRemove.mTexture = mBackBuffer;
mBackBuffer = nullptr;
}
bool bufferCreated = false;
if (!mBackBuffer) {
- bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
- gfxContentType contentType = isOpaque
- ? gfxContentType::COLOR
- : gfxContentType::COLOR_ALPHA;
+ gfxContentType contentType =
+ aCanvasRenderer->IsOpaque() ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA;
gfx::SurfaceFormat surfaceFormat
= gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
TextureFlags flags = TextureFlags::DEFAULT;
if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
}
- mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
+ mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aCanvasRenderer);
if (!mBackBuffer) {
NS_WARNING("Failed to allocate the TextureClient");
return;
}
mBackBuffer->EnableReadLock();
MOZ_ASSERT(mBackBuffer->CanExposeDrawTarget());
bufferCreated = true;
@@ -130,17 +127,17 @@ CanvasClient2D::Update(gfx::IntSize aSiz
TextureClientAutoLock autoLock(mBackBuffer, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
mBackBuffer = nullptr;
return;
}
RefPtr<DrawTarget> target = mBackBuffer->BorrowDrawTarget();
if (target) {
- if (!aLayer->UpdateTarget(target)) {
+ if (!aCanvasRenderer->UpdateTarget(target)) {
NS_WARNING("Failed to copy the canvas into a TextureClient.");
return;
}
updated = true;
}
}
if (bufferCreated && !AddTextureClient(mBackBuffer)) {
@@ -160,19 +157,19 @@ CanvasClient2D::Update(gfx::IntSize aSiz
mBackBuffer.swap(mFrontBuffer);
}
already_AddRefed<TextureClient>
CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
TextureFlags aFlags,
- ShareableCanvasLayer* aLayer)
+ ShareableCanvasRenderer* aCanvasRenderer)
{
- if (aLayer->IsGLLayer()) {
+ if (aCanvasRenderer->HasGLContext()) {
// We want a cairo backend here as we don't want to be copying into
// an accelerated backend and we like LockBits to work. This is currently
// the most effective way to make this work.
return TextureClient::CreateForRawBufferAccess(GetForwarder(),
aFormat, aSize, BackendType::CAIRO,
mTextureFlags | aFlags);
}
@@ -370,56 +367,56 @@ CloneSurface(gl::SharedSurface* src, gl:
destSurf->ProducerAcquire();
SharedSurface::ProdCopy(src, dest->Surf(), factory);
destSurf->ProducerRelease();
return dest.forget();
}
void
-CanvasClientSharedSurface::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
+CanvasClientSharedSurface::Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer)
{
Renderer renderer;
- renderer.construct<ShareableCanvasLayer*>(aLayer);
+ renderer.construct<ShareableCanvasRenderer*>(aCanvasRenderer);
UpdateRenderer(aSize, renderer);
}
void
CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer)
{
Renderer renderer;
renderer.construct<AsyncCanvasRenderer*>(aRenderer);
UpdateRenderer(aRenderer->GetSize(), renderer);
}
void
CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
{
GLContext* gl = nullptr;
- ShareableCanvasLayer* layer = nullptr;
+ ShareableCanvasRenderer* canvasRenderer = nullptr;
AsyncCanvasRenderer* asyncRenderer = nullptr;
- if (aRenderer.constructed<ShareableCanvasLayer*>()) {
- layer = aRenderer.ref<ShareableCanvasLayer*>();
- gl = layer->mGLContext;
+ if (aRenderer.constructed<ShareableCanvasRenderer*>()) {
+ canvasRenderer = aRenderer.ref<ShareableCanvasRenderer*>();
+ gl = canvasRenderer->mGLContext;
} else {
asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
gl = asyncRenderer->mGLContext;
}
gl->MakeCurrent();
RefPtr<TextureClient> newFront;
- if (layer && layer->mGLFrontbuffer) {
- mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
+ if (canvasRenderer && canvasRenderer->mGLFrontbuffer) {
+ mShSurfClient = CloneSurface(canvasRenderer->mGLFrontbuffer.get(), canvasRenderer->mFactory.get());
if (!mShSurfClient) {
gfxCriticalError() << "Invalid canvas front buffer";
return;
}
- } else if (layer && layer->mIsMirror) {
- mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), layer->mFactory.get());
+ } else if (canvasRenderer && canvasRenderer->mIsMirror) {
+ mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), canvasRenderer->mFactory.get());
if (!mShSurfClient) {
return;
}
} else {
mShSurfClient = gl->Screen()->Front();
if (mShSurfClient && mShSurfClient->GetAllocator() &&
mShSurfClient->GetAllocator() != GetForwarder()->GetTextureForwarder()) {
mShSurfClient = CloneSurface(mShSurfClient->Surf(), gl->Screen()->Factory());
@@ -439,19 +436,19 @@ CanvasClientSharedSurface::UpdateRendere
auto forwarder = GetForwarder();
bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
if (needsReadback) {
TextureFlags flags = TextureFlags::IMMUTABLE;
CompositableForwarder* shadowForwarder = nullptr;
- if (layer) {
- flags |= layer->Flags();
- shadowForwarder = layer->GetForwarder();
+ if (canvasRenderer) {
+ flags |= canvasRenderer->Flags();
+ shadowForwarder = canvasRenderer->GetForwarder();
} else {
MOZ_ASSERT(asyncRenderer);
flags |= mTextureFlags;
shadowForwarder = GetForwarder();
}
auto layersBackend = shadowForwarder->GetCompositorBackendType();
mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -23,28 +23,28 @@
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
namespace mozilla {
namespace layers {
class AsyncCanvasRenderer;
-class ShareableCanvasLayer;
+class ShareableCanvasRenderer;
class CompositableForwarder;
class ShadowableLayer;
class SharedSurfaceTextureClient;
/**
* Compositable client for 2d and webgl canvas.
*/
class CanvasClient : public CompositableClient
{
public:
- typedef MaybeOneOf<ShareableCanvasLayer*, AsyncCanvasRenderer*> Renderer;
+ typedef MaybeOneOf<ShareableCanvasRenderer*, AsyncCanvasRenderer*> Renderer;
/**
* Creates, configures, and returns a new canvas client. If necessary, a
* message will be sent to the compositor to create a corresponding image
* host.
*/
enum CanvasClientType {
CanvasClientSurface,
@@ -62,17 +62,17 @@ public:
{
mTextureFlags = aFlags;
}
virtual ~CanvasClient() {}
virtual void Clear() {};
- virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) = 0;
+ virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) = 0;
virtual bool AddTextureClient(TextureClient* aTexture) override
{
++mFrameID;
return CompositableClient::AddTextureClient(aTexture);
}
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) {}
@@ -100,17 +100,17 @@ public:
return TextureInfo(CompositableType::IMAGE, mTextureFlags);
}
virtual void Clear() override
{
mBackBuffer = mFrontBuffer = mBufferProviderTexture = nullptr;
}
- virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) override;
+ virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) override;
virtual void UpdateFromTexture(TextureClient* aBuffer) override;
virtual bool AddTextureClient(TextureClient* aTexture) override
{
return CanvasClient::AddTextureClient(aTexture);
}
@@ -119,17 +119,17 @@ public:
mBackBuffer = mFrontBuffer = nullptr;
}
private:
already_AddRefed<TextureClient>
CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
TextureFlags aFlags,
- ShareableCanvasLayer* aLayer);
+ ShareableCanvasRenderer* aCanvasRenderer);
RefPtr<TextureClient> mBackBuffer;
RefPtr<TextureClient> mFrontBuffer;
// We store this texture separately to make sure it is not written into
// in Update() if for some silly reason we end up alternating between
// UpdateFromTexture and Update.
// This code is begging for a cleanup. The situation described above should
// not be made possible.
@@ -158,17 +158,17 @@ public:
return TextureInfo(CompositableType::IMAGE);
}
virtual void Clear() override {
ClearSurfaces();
}
virtual void Update(gfx::IntSize aSize,
- ShareableCanvasLayer* aLayer) override;
+ ShareableCanvasRenderer* aCanvasRenderer) override;
void UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer);
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
virtual void Updated() override;
virtual void OnDetach() override;
};
@@ -188,17 +188,17 @@ public:
{
}
TextureInfo GetTextureInfo() const override
{
return TextureInfo(CompositableType::IMAGE);
}
- virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) override
+ virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) override
{
}
virtual void UpdateAsync(AsyncCanvasRenderer* aRenderer) override;
void SetLayer(ShadowableLayer* aLayer)
{
mLayer = aLayer;
--- a/gfx/layers/client/ClientCanvasLayer.cpp
+++ b/gfx/layers/client/ClientCanvasLayer.cpp
@@ -18,20 +18,28 @@ ClientCanvasLayer::~ClientCanvasLayer()
void
ClientCanvasLayer::RenderLayer()
{
AUTO_PROFILER_LABEL("ClientCanvasLayer::RenderLayer", GRAPHICS);
RenderMaskLayers(this);
- UpdateCompositableClient();
+ ClientCanvasRenderer* canvasRenderer = mCanvasRenderer->AsClientCanvasRenderer();
+ MOZ_ASSERT(canvasRenderer);
+ canvasRenderer->UpdateCompositableClient();
ClientManager()->Hold(this);
}
+CanvasRenderer*
+ClientCanvasLayer::CreateCanvasRendererInternal()
+{
+ return new ClientCanvasRenderer(this);
+}
+
already_AddRefed<CanvasLayer>
ClientLayerManager::CreateCanvasLayer()
{
NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
RefPtr<ClientCanvasLayer> layer =
new ClientCanvasLayer(this);
CREATE_SHADOW(Canvas);
return layer.forget();
--- a/gfx/layers/client/ClientCanvasLayer.h
+++ b/gfx/layers/client/ClientCanvasLayer.h
@@ -1,111 +1,85 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_CLIENTCANVASLAYER_H
#define GFX_CLIENTCANVASLAYER_H
-#include "CanvasClient.h" // for CanvasClient, etc
+#include "ClientCanvasRenderer.h"
#include "ClientLayerManager.h" // for ClientLayerManager, etc
#include "Layers.h" // for CanvasLayer, etc
#include "mozilla/Attributes.h" // for override
+#include "mozilla/layers/CanvasClient.h"// for CanvasClient, etc
#include "mozilla/layers/LayersMessages.h" // for CanvasLayerAttributes, etc
#include "mozilla/mozalloc.h" // for operator delete
#include "nsDebug.h" // for NS_ASSERTION
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
-#include "ShareableCanvasLayer.h"
namespace mozilla {
namespace layers {
class CompositableClient;
class ShadowableLayer;
-class ClientCanvasLayer : public ShareableCanvasLayer,
+class ClientCanvasLayer : public CanvasLayer,
public ClientLayer
{
public:
explicit ClientCanvasLayer(ClientLayerManager* aLayerManager) :
- ShareableCanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
+ CanvasLayer(aLayerManager, static_cast<ClientLayer*>(this))
{
MOZ_COUNT_CTOR(ClientCanvasLayer);
}
+ CanvasRenderer* CreateCanvasRendererInternal() override;
+
protected:
virtual ~ClientCanvasLayer();
public:
virtual void SetVisibleRegion(const LayerIntRegion& aRegion) override
{
NS_ASSERTION(ClientManager()->InConstruction(),
"Can only set properties in construction phase");
CanvasLayer::SetVisibleRegion(aRegion);
}
virtual void RenderLayer() override;
virtual void ClearCachedResources() override
{
- if (mBufferProvider) {
- mBufferProvider->ClearCachedResources();
- }
- if (mCanvasClient) {
- mCanvasClient->Clear();
- }
+ mCanvasRenderer->ClearCachedResources();
}
virtual void HandleMemoryPressure() override
{
- if (mBufferProvider) {
- mBufferProvider->ClearCachedResources();
- }
- if (mCanvasClient) {
- mCanvasClient->HandleMemoryPressure();
- }
+ mCanvasRenderer->ClearCachedResources();
}
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
{
aAttrs = CanvasLayerAttributes(mSamplingFilter, mBounds);
}
virtual Layer* AsLayer() override { return this; }
virtual ShadowableLayer* AsShadowableLayer() override { return this; }
virtual void Disconnect() override
{
- if (mBufferProvider) {
- mBufferProvider->ClearCachedResources();
- }
- mCanvasClient = nullptr;
- }
-
- virtual CompositableForwarder* GetForwarder() override
- {
- return mManager->AsShadowForwarder();
+ mCanvasRenderer->Destroy();
}
virtual CompositableClient* GetCompositableClient() override
{
- return mCanvasClient;
- }
-
- virtual void AttachCompositable() override
- {
- if (HasShadow()) {
- if (mAsyncRenderer) {
- static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(this);
- } else {
- mCanvasClient->Connect();
- ClientManager()->AsShadowForwarder()->Attach(mCanvasClient, this);
- }
- }
+ ClientCanvasRenderer* canvasRenderer = mCanvasRenderer->AsClientCanvasRenderer();
+ MOZ_ASSERT(canvasRenderer);
+ return canvasRenderer->GetCanvasClient();
}
protected:
ClientLayerManager* ClientManager()
{
return static_cast<ClientLayerManager*>(mManager);
}
};
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/ClientCanvasRenderer.cpp
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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/. */
+
+#include "ClientCanvasRenderer.h"
+
+#include "ClientCanvasLayer.h"
+
+namespace mozilla {
+namespace layers {
+
+CompositableForwarder*
+ClientCanvasRenderer::GetForwarder()
+{
+ return mLayer->Manager()->AsShadowForwarder();
+}
+
+bool
+ClientCanvasRenderer::CreateCompositable()
+{
+ if (!mCanvasClient) {
+ TextureFlags flags = TextureFlags::DEFAULT;
+ if (mOriginPos == gl::OriginPos::BottomLeft) {
+ flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+ }
+
+ if (!mIsAlphaPremultiplied) {
+ flags |= TextureFlags::NON_PREMULTIPLIED;
+ }
+
+ mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+ GetForwarder(),
+ flags);
+ if (!mCanvasClient) {
+ return false;
+ }
+
+ if (mLayer->HasShadow()) {
+ if (mAsyncRenderer) {
+ static_cast<CanvasClientBridge*>(mCanvasClient.get())->SetLayer(mLayer);
+ } else {
+ mCanvasClient->Connect();
+ GetForwarder()->AsLayerForwarder()->Attach(mCanvasClient, mLayer);
+ }
+ }
+ }
+
+ return true;
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/client/ClientCanvasRenderer.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_CLIENTCANVASRENDERER_H
+#define GFX_CLIENTCANVASRENDERER_H
+
+#include "ShareableCanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+class ClientCanvasLayer;
+class ClientCanvasRenderer : public ShareableCanvasRenderer
+{
+public:
+ explicit ClientCanvasRenderer(ClientCanvasLayer* aLayer)
+ : mLayer(aLayer)
+ { }
+
+ ClientCanvasRenderer* AsClientCanvasRenderer() override { return this; }
+
+ CompositableForwarder* GetForwarder() override;
+
+ bool CreateCompositable() override;
+
+protected:
+ ClientCanvasLayer* mLayer;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/gfx/layers/composite/CanvasLayerComposite.h
+++ b/gfx/layers/composite/CanvasLayerComposite.h
@@ -28,22 +28,16 @@ class CanvasLayerComposite : public Canv
{
public:
explicit CanvasLayerComposite(LayerManagerComposite* aManager);
protected:
virtual ~CanvasLayerComposite();
public:
- // CanvasLayer impl
- virtual void Initialize(const Data& aData) override
- {
- MOZ_CRASH("Incompatibe surface type");
- }
-
virtual bool SetCompositableHost(CompositableHost* aHost) override;
virtual void Disconnect() override
{
Destroy();
}
virtual void SetLayerManager(HostLayerManager* aManager) override;
@@ -58,16 +52,21 @@ public:
CompositableHost* GetCompositableHost() override;
virtual HostLayer* AsHostLayer() override { return this; }
virtual const char* Name() const override { return "CanvasLayerComposite"; }
protected:
+ CanvasRenderer* CreateCanvasRendererInternal() override {
+ MOZ_CRASH("Incompatible surface type");
+ return nullptr;
+ }
+
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
private:
gfx::SamplingFilter GetSamplingFilter();
private:
RefPtr<CompositableHost> mCompositableHost;
};
--- a/gfx/layers/mlgpu/CanvasLayerMLGPU.h
+++ b/gfx/layers/mlgpu/CanvasLayerMLGPU.h
@@ -27,32 +27,33 @@ class CanvasLayerMLGPU final : public Ca
{
public:
explicit CanvasLayerMLGPU(LayerManagerMLGPU* aManager);
protected:
~CanvasLayerMLGPU() override;
public:
- void Initialize(const Data& aData) override {
- MOZ_CRASH("Incompatibe surface type");
- }
-
Layer* GetLayer() override;
void Disconnect() override;
HostLayer* AsHostLayer() override { return this; }
CanvasLayerMLGPU* AsCanvasLayerMLGPU() override { return this; }
gfx::SamplingFilter GetSamplingFilter() override;
void ClearCachedResources() override;
void SetRegionToRender(LayerIntRegion&& aRegion) override;
MOZ_LAYER_DECL_NAME("CanvasLayerMLGPU", TYPE_CANVAS)
protected:
+ CanvasRenderer* CreateCanvasRendererInternal() override {
+ MOZ_CRASH("Incompatible surface type");
+ return nullptr;
+ }
+
void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
void CleanupResources();
};
} // namespace layers
} // namespace mozilla
#endif /* GFX_CanvasLayerMLGPU_H */
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -123,16 +123,17 @@ EXPORTS.mozilla.layers += [
'AtomicRefCountedWithFinalize.h',
'AxisPhysicsModel.h',
'AxisPhysicsMSDModel.h',
'basic/BasicCompositor.h',
'basic/MacIOSurfaceTextureHostBasic.h',
'basic/TextureHostBasic.h',
'BSPTree.h',
'BufferTexture.h',
+ 'CanvasRenderer.h',
'client/CanvasClient.h',
'client/CompositableClient.h',
'client/ContentClient.h',
'client/GPUVideoTextureClient.h',
'client/ImageClient.h',
'client/SingleTiledContentClient.h',
'client/TextureClient.h',
'client/TextureClientPool.h',
@@ -154,16 +155,17 @@ EXPORTS.mozilla.layers += [
'composite/ImageLayerComposite.h',
'composite/LayerManagerComposite.h',
'composite/PaintedLayerComposite.h',
'composite/TextRenderer.h',
'composite/TextureHost.h',
'composite/TiledContentHost.h',
'Compositor.h',
'CompositorTypes.h',
+ 'CopyableCanvasRenderer.h',
'D3D11ShareHandleImage.h',
'D3D11YCbCrImage.h',
'D3D9SurfaceImage.h',
'DirectionUtils.h',
'Effects.h',
'ImageDataSerializer.h',
'ipc/APZChild.h',
'ipc/APZCTreeManagerChild.h',
@@ -213,26 +215,28 @@ EXPORTS.mozilla.layers += [
'opengl/CompositorOGL.h',
'opengl/MacIOSurfaceTextureClientOGL.h',
'opengl/MacIOSurfaceTextureHostOGL.h',
'opengl/TextureClientOGL.h',
'opengl/TextureHostOGL.h',
'PaintThread.h',
'PersistentBufferProvider.h',
'RenderTrace.h',
+ 'ShareableCanvasRenderer.h',
'SourceSurfaceSharedData.h',
'SourceSurfaceVolatileData.h',
'TextureSourceProvider.h',
'TextureWrapperImage.h',
'TransactionIdAllocator.h',
'UpdateImageHelper.h',
'wr/ScrollingLayersHelper.h',
'wr/StackingContextHelper.h',
'wr/WebRenderBridgeChild.h',
'wr/WebRenderBridgeParent.h',
+ 'wr/WebRenderCanvasRenderer.h',
'wr/WebRenderCompositableHolder.h',
'wr/WebRenderDisplayItemLayer.h',
'wr/WebRenderImageHost.h',
'wr/WebRenderLayer.h',
'wr/WebRenderLayerManager.h',
'wr/WebRenderLayersLogging.h',
'wr/WebRenderMessageUtils.h',
'wr/WebRenderScrollData.h',
@@ -332,19 +336,21 @@ UNIFIED_SOURCES += [
'basic/BasicLayerManager.cpp',
'basic/BasicLayersImpl.cpp',
'basic/BasicPaintedLayer.cpp',
'basic/BasicTextLayer.cpp',
'basic/TextureHostBasic.cpp',
'BSPTree.cpp',
'BufferTexture.cpp',
'BufferUnrotate.cpp',
+ 'CanvasRenderer.cpp',
'client/CanvasClient.cpp',
'client/ClientBorderLayer.cpp',
'client/ClientCanvasLayer.cpp',
+ 'client/ClientCanvasRenderer.cpp',
'client/ClientColorLayer.cpp',
'client/ClientContainerLayer.cpp',
'client/ClientImageLayer.cpp',
'client/ClientLayerManager.cpp',
'client/ClientPaintedLayer.cpp',
'client/ClientTextLayer.cpp',
'client/ClientTiledPaintedLayer.cpp',
'client/CompositableClient.cpp',
@@ -372,17 +378,17 @@ UNIFIED_SOURCES += [
'composite/ImageHost.cpp',
'composite/ImageLayerComposite.cpp',
'composite/LayerManagerComposite.cpp',
'composite/PaintedLayerComposite.cpp',
'composite/TextRenderer.cpp',
'composite/TextureHost.cpp',
'composite/TiledContentHost.cpp',
'Compositor.cpp',
- 'CopyableCanvasLayer.cpp',
+ 'CopyableCanvasRenderer.cpp',
'Effects.cpp',
'FrameMetrics.cpp',
'GLImages.cpp',
'ImageDataSerializer.cpp',
'ImageLayers.cpp',
'ipc/APZChild.cpp',
'ipc/APZCTreeManagerChild.cpp',
'ipc/APZCTreeManagerParent.cpp',
@@ -439,26 +445,27 @@ UNIFIED_SOURCES += [
'opengl/TextureClientOGL.cpp',
'opengl/TextureHostOGL.cpp',
'opengl/TexturePoolOGL.cpp',
'PaintThread.cpp',
'protobuf/LayerScopePacket.pb.cc',
'ReadbackProcessor.cpp',
'RenderTrace.cpp',
'RotatedBuffer.cpp',
- 'ShareableCanvasLayer.cpp',
+ 'ShareableCanvasRenderer.cpp',
'SourceSurfaceSharedData.cpp',
'SourceSurfaceVolatileData.cpp',
'TextureSourceProvider.cpp',
'TextureWrapperImage.cpp',
'wr/ScrollingLayersHelper.cpp',
'wr/StackingContextHelper.cpp',
'wr/WebRenderBridgeChild.cpp',
'wr/WebRenderBridgeParent.cpp',
'wr/WebRenderCanvasLayer.cpp',
+ 'wr/WebRenderCanvasRenderer.cpp',
'wr/WebRenderColorLayer.cpp',
'wr/WebRenderCompositableHolder.cpp',
'wr/WebRenderContainerLayer.cpp',
'wr/WebRenderDisplayItemLayer.cpp',
'wr/WebRenderImageHost.cpp',
'wr/WebRenderImageLayer.cpp',
'wr/WebRenderLayer.cpp',
'wr/WebRenderLayerManager.cpp',
--- a/gfx/layers/wr/WebRenderCanvasLayer.cpp
+++ b/gfx/layers/wr/WebRenderCanvasLayer.cpp
@@ -15,62 +15,42 @@
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClientSharedSurface.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "PersistentBufferProvider.h"
#include "SharedSurface.h"
#include "SharedSurfaceGL.h"
#include "mozilla/webrender/WebRenderTypes.h"
+#include "WebRenderCanvasRenderer.h"
namespace mozilla {
namespace layers {
WebRenderCanvasLayer::~WebRenderCanvasLayer()
{
MOZ_COUNT_DTOR(WebRenderCanvasLayer);
- ClearWrResources();
-}
-
-void
-WebRenderCanvasLayer::ClearWrResources()
-{
- if (mExternalImageId.isSome()) {
- WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
- mExternalImageId = Nothing();
- }
}
-void
-WebRenderCanvasLayer::Initialize(const Data& aData)
+CanvasRenderer*
+WebRenderCanvasLayer::CreateCanvasRendererInternal()
{
- ShareableCanvasLayer::Initialize(aData);
-
- // XXX: Use basic surface factory until we support shared surface.
- if (!mGLContext || mGLFrontbuffer)
- return;
-
- gl::GLScreenBuffer* screen = mGLContext->Screen();
- auto factory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext, screen->mCaps, mFlags);
- screen->Morph(Move(factory));
+ return new WebRenderCanvasRendererSync(mManager->AsWebRenderLayerManager());
}
void
WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc)
{
- UpdateCompositableClient();
-
- if (mExternalImageId.isNothing()) {
- mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mCanvasClient));
- }
+ WebRenderCanvasRendererSync* canvasRenderer = mCanvasRenderer->AsWebRenderCanvasRendererSync();
+ MOZ_ASSERT(canvasRenderer);
+ canvasRenderer->UpdateCompositableClient();
Maybe<gfx::Matrix4x4> transform;
- const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
- if (needsYFlip) {
+ if (canvasRenderer->NeedsYFlip()) {
transform = Some(GetTransform().PreTranslate(0, mBounds.height, 0).PreScale(1, -1, 1));
}
ScrollingLayersHelper scroller(this, aBuilder, aSc);
StackingContextHelper sc(aSc, aBuilder, this, transform);
LayerRect rect(0, 0, mBounds.width, mBounds.height);
DumpLayerInfo("CanvasLayer", rect);
@@ -79,41 +59,23 @@ WebRenderCanvasLayer::RenderLayer(wr::Di
if (gfxPrefs::LayersDump()) {
printf_stderr("CanvasLayer %p texture-filter=%s\n",
this->GetLayer(),
Stringify(filter).c_str());
}
wr::WrImageKey key = GetImageKey();
- WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
+ WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(canvasRenderer->GetExternalImageId().value(), key));
WrManager()->AddImageKeyForDiscard(key);
wr::LayoutRect r = sc.ToRelativeLayoutRect(rect);
aBuilder.PushImage(r, r, filter, key);
}
void
-WebRenderCanvasLayer::AttachCompositable()
-{
- mCanvasClient->Connect();
-}
-
-CompositableForwarder*
-WebRenderCanvasLayer::GetForwarder()
-{
- return WrManager()->WrBridge();
-}
-
-void
WebRenderCanvasLayer::ClearCachedResources()
{
- ClearWrResources();
- if (mBufferProvider) {
- mBufferProvider->ClearCachedResources();
- }
- if (mCanvasClient) {
- mCanvasClient->Clear();
- }
+ mCanvasRenderer->ClearCachedResources();
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/wr/WebRenderCanvasLayer.h
+++ b/gfx/layers/wr/WebRenderCanvasLayer.h
@@ -1,55 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_WEBRENDERCANVASLAYER_H
#define GFX_WEBRENDERCANVASLAYER_H
+#include "Layers.h"
#include "mozilla/layers/WebRenderLayer.h"
#include "mozilla/layers/WebRenderLayerManager.h"
-#include "ShareableCanvasLayer.h"
namespace mozilla {
namespace gfx {
class SourceSurface;
}; // namespace gfx
namespace layers {
class WebRenderCanvasLayer : public WebRenderLayer,
- public ShareableCanvasLayer
+ public CanvasLayer
{
public:
explicit WebRenderCanvasLayer(WebRenderLayerManager* aLayerManager)
- : ShareableCanvasLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
+ : CanvasLayer(aLayerManager, static_cast<WebRenderLayer*>(this))
{
MOZ_COUNT_CTOR(WebRenderCanvasLayer);
}
- virtual void Initialize(const Data& aData) override;
-
- virtual CompositableForwarder* GetForwarder() override;
-
- virtual void AttachCompositable() override;
+ CanvasRenderer* CreateCanvasRendererInternal() override;
virtual void ClearCachedResources() override;
protected:
virtual ~WebRenderCanvasLayer();
- void ClearWrResources();
-
public:
Layer* GetLayer() override { return this; }
void RenderLayer(wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc) override;
-
-protected:
- wr::MaybeExternalImageId mExternalImageId;
};
} // namespace layers
} // namespace mozilla
#endif // GFX_WEBRENDERCANVASLAYER_H
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/WebRenderCanvasRenderer.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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/. */
+
+#include "WebRenderCanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+CompositableForwarder*
+WebRenderCanvasRenderer::GetForwarder()
+{
+ return mManager->WrBridge();
+}
+
+void
+WebRenderCanvasRenderer::Initialize(const CanvasInitializeData& aData)
+{
+ ShareableCanvasRenderer::Initialize(aData);
+
+ // XXX: Use basic surface factory until we support shared surface.
+ if (!mGLContext || mGLFrontbuffer)
+ return;
+
+ gl::GLScreenBuffer* screen = mGLContext->Screen();
+ auto factory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext,
+ screen->mCaps,
+ mFlags);
+ screen->Morph(Move(factory));
+}
+
+WebRenderCanvasRendererSync::~WebRenderCanvasRendererSync()
+{
+ Destroy();
+}
+
+void
+WebRenderCanvasRendererSync::Initialize(const CanvasInitializeData& aData)
+{
+ WebRenderCanvasRenderer::Initialize(aData);
+
+ if (mExternalImageId.isSome()) {
+ mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+ mExternalImageId.reset();
+ }
+}
+
+bool
+WebRenderCanvasRendererSync::CreateCompositable()
+{
+ if (!mCanvasClient) {
+ TextureFlags flags = TextureFlags::DEFAULT;
+ if (mOriginPos == gl::OriginPos::BottomLeft) {
+ flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+ }
+
+ if (!mIsAlphaPremultiplied) {
+ flags |= TextureFlags::NON_PREMULTIPLIED;
+ }
+
+ mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+ GetForwarder(),
+ flags);
+ if (!mCanvasClient) {
+ return false;
+ }
+
+ mCanvasClient->Connect();
+ }
+
+ if (mExternalImageId.isNothing()) {
+ mExternalImageId = Some(mManager->WrBridge()->AllocExternalImageIdForCompositable(mCanvasClient));
+ }
+
+ return true;
+}
+
+void
+WebRenderCanvasRendererSync::ClearCachedResources()
+{
+ if (mExternalImageId.isSome()) {
+ mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+ mExternalImageId.reset();
+ }
+}
+
+void
+WebRenderCanvasRendererSync::Destroy()
+{
+ if (mExternalImageId.isSome()) {
+ mManager->WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
+ mExternalImageId.reset();
+ }
+}
+
+WebRenderCanvasRendererAsync::~WebRenderCanvasRendererAsync()
+{
+ Destroy();
+}
+
+void
+WebRenderCanvasRendererAsync::Initialize(const CanvasInitializeData& aData)
+{
+ WebRenderCanvasRenderer::Initialize(aData);
+
+ if (mPipelineId.isSome()) {
+ mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+ mPipelineId.reset();
+ }
+}
+
+bool
+WebRenderCanvasRendererAsync::CreateCompositable()
+{
+ if (!mCanvasClient) {
+ TextureFlags flags = TextureFlags::DEFAULT;
+ if (mOriginPos == gl::OriginPos::BottomLeft) {
+ flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
+ }
+
+ if (!mIsAlphaPremultiplied) {
+ flags |= TextureFlags::NON_PREMULTIPLIED;
+ }
+
+ mCanvasClient = CanvasClient::CreateCanvasClient(GetCanvasClientType(),
+ GetForwarder(),
+ flags);
+ if (!mCanvasClient) {
+ return false;
+ }
+
+ mCanvasClient->Connect();
+ }
+
+ if (!mPipelineId) {
+ // Alloc async image pipeline id.
+ mPipelineId = Some(mManager->WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
+ mManager->WrBridge()->AddPipelineIdForCompositable(mPipelineId.ref(),
+ mCanvasClient->GetIPCHandle());
+ }
+
+ return true;
+}
+
+void
+WebRenderCanvasRendererAsync::ClearCachedResources()
+{
+ if (mPipelineId.isSome()) {
+ mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+ mPipelineId.reset();
+ }
+}
+
+void
+WebRenderCanvasRendererAsync::Destroy()
+{
+ if (mPipelineId.isSome()) {
+ mManager->WrBridge()->RemovePipelineIdForCompositable(mPipelineId.ref());
+ mPipelineId.reset();
+ }
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/wr/WebRenderCanvasRenderer.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_WEBRENDERCANVASRENDERER_H
+#define GFX_WEBRENDERCANVASRENDERER_H
+
+#include "ShareableCanvasRenderer.h"
+
+namespace mozilla {
+namespace layers {
+
+class WebRenderLayerManager;
+
+class WebRenderCanvasRenderer : public ShareableCanvasRenderer
+{
+public:
+ explicit WebRenderCanvasRenderer(WebRenderLayerManager* aManager)
+ : mManager(aManager)
+ { }
+
+ void Initialize(const CanvasInitializeData& aData) override;
+
+ CompositableForwarder* GetForwarder() override;
+
+protected:
+ WebRenderLayerManager* mManager;
+};
+
+class WebRenderCanvasRendererSync : public WebRenderCanvasRenderer
+{
+public:
+ explicit WebRenderCanvasRendererSync(WebRenderLayerManager* aManager)
+ : WebRenderCanvasRenderer(aManager)
+ { }
+ virtual ~WebRenderCanvasRendererSync();
+
+ WebRenderCanvasRendererSync* AsWebRenderCanvasRendererSync() override { return this; }
+
+ void Initialize(const CanvasInitializeData& aData) override;
+ bool CreateCompositable() override;
+
+ void ClearCachedResources() override;
+ void Destroy() override;
+
+ wr::MaybeExternalImageId GetExternalImageId() { return mExternalImageId; }
+protected:
+ wr::MaybeExternalImageId mExternalImageId;
+};
+
+class WebRenderCanvasRendererAsync : public WebRenderCanvasRenderer
+{
+public:
+ explicit WebRenderCanvasRendererAsync(WebRenderLayerManager* aManager)
+ : WebRenderCanvasRenderer(aManager)
+ { }
+ virtual ~WebRenderCanvasRendererAsync();
+
+ WebRenderCanvasRendererAsync* AsWebRenderCanvasRendererAsync() override { return this; }
+
+ void Initialize(const CanvasInitializeData& aData) override;
+ bool CreateCompositable() override;
+
+ void ClearCachedResources() override;
+ void Destroy() override;
+
+ Maybe<wr::PipelineId> GetPipelineId() { return mPipelineId; }
+protected:
+ Maybe<wr::PipelineId> mPipelineId;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -352,25 +352,36 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayL
gfxPoint p = destGFXRect.TopLeft() + aContainerParameters.mOffset;
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(destGFXRect.Width() / canvasSizeInPx.width,
destGFXRect.Height() / canvasSizeInPx.height);
layer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
if (layer->GetType() == layers::Layer::TYPE_CANVAS) {
RefPtr<CanvasLayer> canvasLayer = static_cast<CanvasLayer*>(layer.get());
canvasLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
+ nsIntRect bounds;
+ bounds.SetRect(0, 0, canvasSizeInPx.width, canvasSizeInPx.height);
+ canvasLayer->SetBounds(bounds);
} else if (layer->GetType() == layers::Layer::TYPE_IMAGE) {
RefPtr<ImageLayer> imageLayer = static_cast<ImageLayer*>(layer.get());
imageLayer->SetSamplingFilter(nsLayoutUtils::GetSamplingFilterForFrame(this));
}
return layer.forget();
}
void
+nsHTMLCanvasFrame::InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer)
+{
+ HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
+ element->InitializeCanvasRenderer(aBuilder, aRenderer);
+}
+
+void
nsHTMLCanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!IsVisibleForPainting(aBuilder))
return;
DisplayBorderBackgroundOutline(aBuilder, aLists);
--- a/layout/generic/nsHTMLCanvasFrame.h
+++ b/layout/generic/nsHTMLCanvasFrame.h
@@ -23,16 +23,17 @@ class nsPresContext;
class nsDisplayItem;
class nsAString;
nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aContext);
class nsHTMLCanvasFrame final : public nsContainerFrame
{
public:
+ typedef mozilla::layers::CanvasRenderer CanvasRenderer;
typedef mozilla::layers::Layer Layer;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsHTMLCanvasFrame)
explicit nsHTMLCanvasFrame(nsStyleContext* aContext)
@@ -47,16 +48,18 @@ public:
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists) override;
already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem,
const ContainerLayerParameters& aContainerParameters);
+ void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
+ CanvasRenderer* aRenderer);
/* get the size of the canvas's image */
nsIntSize GetCanvasSize();
virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
virtual mozilla::IntrinsicSize GetIntrinsicSize() override;
virtual nsSize GetIntrinsicRatio() override;