зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1379920 - Introduce CanvasRenderer and its derived classes. r=nical,jrmuizel
This patch move common canvas interfaces out of layer. So I create a base class CanvasRenderer which move interfaces from CanvasLayer. CopyableCanvasRenderer from CopyableCanvasLayer, ClientCanvasRenderer from ClientCanvasLayer and WebRenderCanvasRenderer from WebRenderCanvasLayer. And finally, WebRenderCanvasRendererSync for the non layers free mode and WebRenderCanvasRendererAsync for the layers free mode. Summary all changes in this patch. * Move class CanvasLayer::Data to CanvasRenderer.h and rename it to CanvasInitializeData. Because this class not only use by layer but also * Move BasicCanvasLayer::UpdateSurface to CopyableCanvasRenderer::ReadbackSurface. * CanvasClient::Update now accepts ShareableCanvasRenderer as parameter. not CanvasLayer. use by layers-free mode. Move it out of layer's class makes more sense. * Add InitializeCanvasRenderer in the canvas related classes to initialize CanvasRenderer without involved layer. * All canvas layer has function "CreateCanvasRendererInternal" that initialize corresponding CanvasRenderer. * Description of all CanvasRenderer classes: ** CanvasRenderer: Based classes. ** CopyableCanvasRenderer: Can readback canvas content to a SourceSurface. Use by BasicCanvasLayer. ** ShareableCanvasRenderer: Provide IPC capabilities that allow sending canvas content over IPC. This is pure virtual class because the IPC handling is different in different LayerManager. ** ClientCanvasRenderer: Implement IPC handling for ClientLayerManager. Use by ClientCanvasLayer. ** WebRenderCanvasRenderer: Implement IPC handling for WebRenderLayerManager. ** WebRenderCanvasRendererSync: Use by WebRenderCanvasLayer. ** WebRenderCanvasRendererAsync: Use by layers-free mode in WebRender. class diagram shows below: +--------------+ |CanvasRenderer| +-------+------+ ^ | +----------------------+ |CopyableCanvasRenderer| +----------------------+ ^ | +-----------+-----------+ |ShareableCanvasRenderer| +-----+-----------------+ ^ ^ +-------------+ +-------+ | | +--------------------+ +---------+-------------+ |ClientCanvasRenderer| |WebRenderCanvasRenderer| +--------------------+ +--------+--+-----------+ ^ ^ +-----------------------+ +----+ | | +-------------+-------------+ +-------------+--------------+ |WebRenderCanvasRendererSync| |WebRenderCanvasRendererAsync| +---------------------------+ +----------------------------+ MozReview-Commit-ID: 5hqQ19W169r
This commit is contained in:
Родитель
4fa6ccb4b3
Коммит
f3d4ff499f
|
@ -932,8 +932,7 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
@ -942,13 +941,13 @@ public:
|
|||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6235,7 +6234,7 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
static_cast<CanvasRenderingContext2DUserData*>(
|
||||
aOldLayer->GetUserData(&g2DContextLayerUserData));
|
||||
|
||||
CanvasLayer::Data data;
|
||||
CanvasInitializeData data;
|
||||
|
||||
if (mIsSkiaGL) {
|
||||
GLuint skiaGLTex = SkiaGLTex();
|
||||
|
@ -6251,7 +6250,7 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
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();
|
||||
}
|
||||
|
@ -6278,17 +6277,30 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
// 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();
|
||||
|
@ -6302,14 +6314,8 @@ CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
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
|
||||
|
|
|
@ -468,6 +468,9 @@ public:
|
|||
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;
|
||||
|
|
|
@ -1287,9 +1287,7 @@ public:
|
|||
* 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();
|
||||
|
@ -1299,9 +1297,7 @@ public:
|
|||
* 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();
|
||||
|
@ -1334,6 +1330,32 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
|
|||
|
||||
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
|
||||
|
@ -1346,34 +1368,20 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
|
|||
// 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
|
||||
|
|
|
@ -462,6 +462,10 @@ public:
|
|||
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.
|
||||
|
|
|
@ -26,6 +26,7 @@ class nsDisplayListBuilder;
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
class CanvasLayer;
|
||||
class CanvasRenderer;
|
||||
class Layer;
|
||||
class LayerManager;
|
||||
} // namespace layers
|
||||
|
@ -40,6 +41,7 @@ class nsICanvasRenderingContextInternal :
|
|||
{
|
||||
public:
|
||||
typedef mozilla::layers::CanvasLayer CanvasLayer;
|
||||
typedef mozilla::layers::CanvasRenderer CanvasRenderer;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
typedef mozilla::layers::LayerManager LayerManager;
|
||||
|
||||
|
@ -139,6 +141,9 @@ public:
|
|||
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
|
||||
|
|
|
@ -1165,10 +1165,8 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
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();
|
||||
|
@ -1177,6 +1175,22 @@ HTMLCanvasElement::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ class WebGLContext;
|
|||
|
||||
namespace layers {
|
||||
class AsyncCanvasRenderer;
|
||||
class CanvasRenderer;
|
||||
class CanvasLayer;
|
||||
class Image;
|
||||
class Layer;
|
||||
|
@ -124,6 +125,7 @@ class HTMLCanvasElement final : public nsGenericHTMLElement,
|
|||
};
|
||||
|
||||
typedef layers::AsyncCanvasRenderer AsyncCanvasRenderer;
|
||||
typedef layers::CanvasRenderer CanvasRenderer;
|
||||
typedef layers::CanvasLayer CanvasLayer;
|
||||
typedef layers::Layer Layer;
|
||||
typedef layers::LayerManager LayerManager;
|
||||
|
@ -308,6 +310,8 @@ public:
|
|||
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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -3,7 +3,7 @@
|
|||
* 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
|
||||
|
@ -32,24 +32,31 @@ 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;
|
||||
|
@ -70,20 +77,97 @@ CopyableCanvasLayer::Initialize(const Data& aData)
|
|||
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.
|
||||
if (!mGLContext->Readback(frontbuffer, resultSurf)) {
|
||||
NS_WARNING("Failed to read back canvas surface.");
|
||||
return nullptr;
|
||||
}
|
||||
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 ||
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
* 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
|
||||
|
@ -28,33 +28,44 @@ class SharedSurface;
|
|||
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;
|
||||
|
||||
virtual bool IsDataValid(const Data& aData) override;
|
||||
void ClearCachedResources() override;
|
||||
void Destroy() override;
|
||||
|
||||
bool IsGLLayer() { return !!mGLContext; }
|
||||
CopyableCanvasRenderer* AsCopyableCanvasRenderer() override { return this; }
|
||||
|
||||
bool NeedsYFlip() const { return mOriginPos == gl::OriginPos::BottomLeft; }
|
||||
bool HasGLContext() const { return !!mGLContext; }
|
||||
bool IsOpaque() const { return mOpaque; }
|
||||
|
||||
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,
|
||||
|
|
|
@ -2148,13 +2148,8 @@ BorderLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* 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;
|
||||
|
||||
|
@ -2201,6 +2196,16 @@ CanvasLayer::DumpPacket(layerscope::LayersPacket* aPacket, const void* aParent)
|
|||
DumpFilter(layer, mSamplingFilter);
|
||||
}
|
||||
|
||||
CanvasRenderer*
|
||||
CanvasLayer::CreateOrGetCanvasRenderer()
|
||||
{
|
||||
if (!mCanvasRenderer) {
|
||||
mCanvasRenderer.reset(CreateCanvasRendererInternal());
|
||||
}
|
||||
|
||||
return mCanvasRenderer.get();
|
||||
}
|
||||
|
||||
void
|
||||
ImageLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "mozilla/gfx/UserData.h" // for UserData, etc
|
||||
#include "mozilla/layers/AnimationInfo.h" // for AnimationInfo
|
||||
#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
|
||||
|
@ -2686,70 +2687,21 @@ protected:
|
|||
*/
|
||||
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
|
||||
|
@ -2762,39 +2714,14 @@ public:
|
|||
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
|
||||
|
@ -2825,11 +2752,6 @@ public:
|
|||
ComputeEffectiveTransformForMaskLayers(aTransformToSurface);
|
||||
}
|
||||
|
||||
bool GetIsAsyncRenderer() const
|
||||
{
|
||||
return !!mAsyncRenderer;
|
||||
}
|
||||
|
||||
protected:
|
||||
CanvasLayer(LayerManager* aManager, void* aImplData);
|
||||
virtual ~CanvasLayer();
|
||||
|
@ -2838,29 +2760,15 @@ protected:
|
|||
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* 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
|
||||
|
@ -14,29 +14,25 @@
|
|||
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;
|
||||
|
||||
|
@ -80,8 +76,29 @@ ShareableCanvasLayer::Initialize(const Data& aData)
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -107,7 +124,7 @@ ShareableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
}
|
||||
|
||||
aDestTarget->CopySurface(surface,
|
||||
IntRect(0, 0, mBounds.width, mBounds.height),
|
||||
IntRect(0, 0, mSize.width, mSize.height),
|
||||
IntPoint(0, 0));
|
||||
return true;
|
||||
}
|
||||
|
@ -129,9 +146,8 @@ ShareableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -179,7 +195,7 @@ ShareableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
|
|||
}
|
||||
|
||||
CanvasClient::CanvasClientType
|
||||
ShareableCanvasLayer::GetCanvasClientType()
|
||||
ShareableCanvasRenderer::GetCanvasClientType()
|
||||
{
|
||||
if (mAsyncRenderer) {
|
||||
return CanvasClient::CanvasClientAsync;
|
||||
|
@ -192,26 +208,10 @@ ShareableCanvasLayer::GetCanvasClientType()
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -221,17 +221,17 @@ ShareableCanvasLayer::UpdateCompositableClient()
|
|||
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();
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
* 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 {
|
||||
|
@ -17,29 +17,31 @@ class SurfaceFactory;
|
|||
|
||||
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();
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#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
|
||||
|
@ -25,61 +26,6 @@ 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.
|
||||
if (!mGLContext->Readback(frontbuffer, resultSurf)) {
|
||||
NS_WARNING("Failed to read back canvas surface.");
|
||||
return nullptr;
|
||||
}
|
||||
if (needsPremult) {
|
||||
gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
|
||||
}
|
||||
MOZ_ASSERT(resultSurf);
|
||||
|
||||
return resultSurf.forget();
|
||||
}
|
||||
|
||||
void
|
||||
BasicCanvasLayer::Paint(DrawTarget* aDT,
|
||||
const Point& aDeviceOffset,
|
||||
|
@ -89,17 +35,18 @@ BasicCanvasLayer::Paint(DrawTarget* aDT,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -107,10 +54,8 @@ BasicCanvasLayer::Paint(DrawTarget* aDT,
|
|||
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).
|
||||
|
@ -123,15 +68,21 @@ BasicCanvasLayer::Paint(DrawTarget* aDT,
|
|||
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()
|
||||
{
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#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
|
||||
|
@ -16,12 +15,12 @@
|
|||
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
|
||||
|
@ -36,13 +35,12 @@ public:
|
|||
Layer* aMaskLayer) override;
|
||||
|
||||
protected:
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> UpdateSurface();
|
||||
|
||||
BasicLayerManager* BasicManager()
|
||||
{
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
CanvasRenderer* CreateCanvasRendererInternal() override;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#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;
|
||||
|
@ -91,7 +90,7 @@ CanvasClient2D::UpdateFromTexture(TextureClient* aTexture)
|
|||
}
|
||||
|
||||
void
|
||||
CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
|
||||
CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer)
|
||||
{
|
||||
mBufferProviderTexture = nullptr;
|
||||
|
||||
|
@ -103,10 +102,8 @@ CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
|
|||
|
||||
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;
|
||||
|
@ -114,7 +111,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
|
|||
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;
|
||||
|
@ -135,7 +132,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -165,9 +162,9 @@ 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.
|
||||
|
@ -375,10 +372,10 @@ CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory)
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -394,11 +391,11 @@ 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;
|
||||
|
@ -407,14 +404,14 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -444,9 +441,9 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
|
|||
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;
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
class AsyncCanvasRenderer;
|
||||
class ShareableCanvasLayer;
|
||||
class ShareableCanvasRenderer;
|
||||
class CompositableForwarder;
|
||||
class ShadowableLayer;
|
||||
class SharedSurfaceTextureClient;
|
||||
|
@ -39,7 +39,7 @@ class SharedSurfaceTextureClient;
|
|||
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
|
||||
|
@ -67,7 +67,7 @@ public:
|
|||
|
||||
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
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ public:
|
|||
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;
|
||||
|
||||
|
@ -124,7 +124,7 @@ private:
|
|||
CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
TextureFlags aFlags,
|
||||
ShareableCanvasLayer* aLayer);
|
||||
ShareableCanvasRenderer* aCanvasRenderer);
|
||||
|
||||
RefPtr<TextureClient> mBackBuffer;
|
||||
RefPtr<TextureClient> mFrontBuffer;
|
||||
|
@ -163,7 +163,7 @@ public:
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -193,7 +193,7 @@ public:
|
|||
return TextureInfo(CompositableType::IMAGE);
|
||||
}
|
||||
|
||||
virtual void Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer) override
|
||||
virtual void Update(gfx::IntSize aSize, ShareableCanvasRenderer* aCanvasRenderer) override
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,18 @@ ClientCanvasLayer::RenderLayer()
|
|||
|
||||
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()
|
||||
{
|
||||
|
|
|
@ -6,15 +6,15 @@
|
|||
#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 {
|
||||
|
@ -22,16 +22,18 @@ 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();
|
||||
|
||||
|
@ -47,22 +49,12 @@ public:
|
|||
|
||||
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
|
||||
|
@ -75,32 +67,14 @@ public:
|
|||
|
||||
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:
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -33,12 +33,6 @@ 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
|
||||
|
@ -63,6 +57,11 @@ public:
|
|||
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:
|
||||
|
|
|
@ -32,10 +32,6 @@ protected:
|
|||
~CanvasLayerMLGPU() override;
|
||||
|
||||
public:
|
||||
void Initialize(const Data& aData) override {
|
||||
MOZ_CRASH("Incompatibe surface type");
|
||||
}
|
||||
|
||||
Layer* GetLayer() override;
|
||||
void Disconnect() override;
|
||||
|
||||
|
@ -48,6 +44,11 @@ public:
|
|||
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();
|
||||
};
|
||||
|
|
|
@ -129,6 +129,7 @@ EXPORTS.mozilla.layers += [
|
|||
'basic/TextureHostBasic.h',
|
||||
'BSPTree.h',
|
||||
'BufferTexture.h',
|
||||
'CanvasRenderer.h',
|
||||
'client/CanvasClient.h',
|
||||
'client/CompositableClient.h',
|
||||
'client/ContentClient.h',
|
||||
|
@ -160,6 +161,7 @@ EXPORTS.mozilla.layers += [
|
|||
'composite/TiledContentHost.h',
|
||||
'Compositor.h',
|
||||
'CompositorTypes.h',
|
||||
'CopyableCanvasRenderer.h',
|
||||
'D3D11ShareHandleImage.h',
|
||||
'D3D11YCbCrImage.h',
|
||||
'D3D9SurfaceImage.h',
|
||||
|
@ -219,6 +221,7 @@ EXPORTS.mozilla.layers += [
|
|||
'PaintThread.h',
|
||||
'PersistentBufferProvider.h',
|
||||
'RenderTrace.h',
|
||||
'ShareableCanvasRenderer.h',
|
||||
'SourceSurfaceSharedData.h',
|
||||
'SourceSurfaceVolatileData.h',
|
||||
'TextureSourceProvider.h',
|
||||
|
@ -230,6 +233,7 @@ EXPORTS.mozilla.layers += [
|
|||
'wr/StackingContextHelper.h',
|
||||
'wr/WebRenderBridgeChild.h',
|
||||
'wr/WebRenderBridgeParent.h',
|
||||
'wr/WebRenderCanvasRenderer.h',
|
||||
'wr/WebRenderDisplayItemLayer.h',
|
||||
'wr/WebRenderImageHost.h',
|
||||
'wr/WebRenderLayer.h',
|
||||
|
@ -340,9 +344,11 @@ UNIFIED_SOURCES += [
|
|||
'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',
|
||||
|
@ -380,7 +386,7 @@ UNIFIED_SOURCES += [
|
|||
'composite/TextureHost.cpp',
|
||||
'composite/TiledContentHost.cpp',
|
||||
'Compositor.cpp',
|
||||
'CopyableCanvasLayer.cpp',
|
||||
'CopyableCanvasRenderer.cpp',
|
||||
'Effects.cpp',
|
||||
'FrameMetrics.cpp',
|
||||
'GLImages.cpp',
|
||||
|
@ -447,7 +453,7 @@ UNIFIED_SOURCES += [
|
|||
'ReadbackProcessor.cpp',
|
||||
'RenderTrace.cpp',
|
||||
'RotatedBuffer.cpp',
|
||||
'ShareableCanvasLayer.cpp',
|
||||
'ShareableCanvasRenderer.cpp',
|
||||
'SourceSurfaceSharedData.cpp',
|
||||
'SourceSurfaceVolatileData.cpp',
|
||||
'TextureSourceProvider.cpp',
|
||||
|
@ -458,6 +464,7 @@ UNIFIED_SOURCES += [
|
|||
'wr/WebRenderBridgeChild.cpp',
|
||||
'wr/WebRenderBridgeParent.cpp',
|
||||
'wr/WebRenderCanvasLayer.cpp',
|
||||
'wr/WebRenderCanvasRenderer.cpp',
|
||||
'wr/WebRenderColorLayer.cpp',
|
||||
'wr/WebRenderContainerLayer.cpp',
|
||||
'wr/WebRenderDisplayItemLayer.cpp',
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "SharedSurface.h"
|
||||
#include "SharedSurfaceGL.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "WebRenderCanvasRenderer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
@ -27,45 +28,24 @@ namespace layers {
|
|||
WebRenderCanvasLayer::~WebRenderCanvasLayer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WebRenderCanvasLayer);
|
||||
ClearWrResources();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCanvasLayer::ClearWrResources()
|
||||
CanvasRenderer*
|
||||
WebRenderCanvasLayer::CreateCanvasRendererInternal()
|
||||
{
|
||||
if (mExternalImageId.isSome()) {
|
||||
WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
|
||||
mExternalImageId = Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderCanvasLayer::Initialize(const Data& aData)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -84,35 +64,17 @@ WebRenderCanvasLayer::RenderLayer(wr::DisplayListBuilder& aBuilder,
|
|||
}
|
||||
|
||||
wr::WrImageKey key = GenerateImageKey();
|
||||
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
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
#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 {
|
||||
|
@ -18,35 +18,26 @@ class SourceSurface;
|
|||
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
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* -*- 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"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "GLScreenBuffer.h"
|
||||
#include "SharedSurfaceGL.h"
|
||||
#include "WebRenderBridgeChild.h"
|
||||
#include "WebRenderLayerManager.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
|
|
@ -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
|
|
@ -357,6 +357,9 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
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));
|
||||
|
@ -365,6 +368,14 @@ nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
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,
|
||||
|
|
|
@ -28,6 +28,7 @@ nsIFrame* NS_NewHTMLCanvasFrame (nsIPresShell* aPresShell, nsStyleContext* aCont
|
|||
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;
|
||||
|
@ -52,6 +53,8 @@ public:
|
|||
LayerManager* aManager,
|
||||
nsDisplayItem* aItem,
|
||||
const ContainerLayerParameters& aContainerParameters);
|
||||
void InitializeCanvasRenderer(nsDisplayListBuilder* aBuilder,
|
||||
CanvasRenderer* aRenderer);
|
||||
|
||||
/* get the size of the canvas's image */
|
||||
nsIntSize GetCanvasSize();
|
||||
|
|
Загрузка…
Ссылка в новой задаче