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:
Morris Tseng 2017-08-03 13:55:14 +08:00
Родитель 4fa6ccb4b3
Коммит f3d4ff499f
32 изменённых файлов: 963 добавлений и 455 удалений

Просмотреть файл

@ -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

178
gfx/layers/CanvasRenderer.h Normal file
Просмотреть файл

@ -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();