Bug 801176 - part2-v5: Let Canvas 2d context works on Workers. r=roc
--- dom/canvas/CanvasRenderingContext2D.cpp | 53 ++++++++++++----------- dom/canvas/OffscreenCanvas.cpp | 46 +++++++++++--------- dom/html/HTMLCanvasElement.cpp | 1 + gfx/layers/AsyncCanvasRenderer.cpp | 17 ++++++++ gfx/layers/AsyncCanvasRenderer.h | 16 +++++++ gfx/layers/Effects.cpp | 6 +++ gfx/layers/GLImages.cpp | 5 +-- gfx/layers/client/CanvasClient.cpp | 74 +++++++++++++++++++++++++-------- gfx/layers/client/CanvasClient.h | 10 ++++- 9 files changed, 162 insertions(+), 66 deletions(-)
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
|
||||
#include "TextureClientSharedSurface.h"
|
||||
#include "VRManagerChild.h"
|
||||
#include "gfxUtils.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
@@ -69,38 +70,69 @@ CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
|
||||
|
||||
void
|
||||
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
{
|
||||
Renderer renderer;
|
||||
renderer.construct<ClientCanvasLayer*>(aLayer);
|
||||
UpdateRenderer(aSize, renderer);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClient2D::UpdateAsync(AsyncCanvasRenderer* aRenderer)
|
||||
{
|
||||
Renderer renderer;
|
||||
renderer.construct<AsyncCanvasRenderer*>(aRenderer);
|
||||
UpdateRenderer(aRenderer->GetSize(), renderer);
|
||||
}
|
||||
|
||||
void
|
||||
CanvasClient2D::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
|
||||
{
|
||||
AutoRemoveTexture autoRemove(this);
|
||||
ClientCanvasLayer* layer = nullptr;
|
||||
AsyncCanvasRenderer* asyncRenderer = nullptr;
|
||||
if (aRenderer.constructed<ClientCanvasLayer*>()) {
|
||||
layer = aRenderer.ref<ClientCanvasLayer*>();
|
||||
} else {
|
||||
asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
|
||||
}
|
||||
|
||||
if (mBuffer &&
|
||||
(mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
|
||||
autoRemove.mTexture = mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
|
||||
bool bufferCreated = false;
|
||||
mBufferCreated = false;
|
||||
if (!mBuffer) {
|
||||
bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
|
||||
gfxContentType contentType = isOpaque
|
||||
? gfxContentType::COLOR
|
||||
: gfxContentType::COLOR_ALPHA;
|
||||
gfx::SurfaceFormat surfaceFormat
|
||||
= gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
|
||||
bool isOpaque;
|
||||
gfxContentType contentType;
|
||||
if (layer) {
|
||||
isOpaque = (layer->GetContentFlags() & Layer::CONTENT_OPAQUE);
|
||||
} else {
|
||||
isOpaque = (asyncRenderer->GetOpaque() & Layer::CONTENT_OPAQUE);
|
||||
}
|
||||
contentType = isOpaque
|
||||
? gfxContentType::COLOR
|
||||
: gfxContentType::COLOR_ALPHA;
|
||||
gfx::SurfaceFormat surfaceFormat =
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
|
||||
TextureFlags flags = TextureFlags::DEFAULT;
|
||||
if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
|
||||
flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
||||
}
|
||||
|
||||
mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
|
||||
flags = TextureFlags::NO_FLAGS;
|
||||
mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, layer);
|
||||
if (!mBuffer) {
|
||||
NS_WARNING("Failed to allocate the TextureClient");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mBuffer->CanExposeDrawTarget());
|
||||
|
||||
bufferCreated = true;
|
||||
mBufferCreated = true;
|
||||
}
|
||||
|
||||
bool updated = false;
|
||||
mUpdated = false;
|
||||
{
|
||||
TextureClientAutoLock autoLock(mBuffer, OpenMode::OPEN_WRITE_ONLY);
|
||||
if (!autoLock.Succeeded()) {
|
||||
@@ -108,19 +140,27 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget();
|
||||
if (target) {
|
||||
aLayer->UpdateTarget(target);
|
||||
updated = true;
|
||||
if (layer) {
|
||||
RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget();
|
||||
if (target) {
|
||||
layer->UpdateTarget(target);
|
||||
}
|
||||
} else {
|
||||
asyncRenderer->UpdateTarget(mBuffer);
|
||||
}
|
||||
mUpdated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferCreated && !AddTextureClient(mBuffer)) {
|
||||
void
|
||||
CanvasClient2D::Updated()
|
||||
{
|
||||
if (mBufferCreated && !AddTextureClient(mBuffer)) {
|
||||
mBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
if (mUpdated) {
|
||||
AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mBuffer;
|
||||
@@ -138,7 +178,7 @@ CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
|
||||
TextureFlags aFlags,
|
||||
ClientCanvasLayer* aLayer)
|
||||
{
|
||||
if (aLayer->IsGLLayer()) {
|
||||
if (aLayer && aLayer->IsGLLayer()) {
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user