From 976fdb14204b2bb1840e0e9c2a2077cc08c364c0 Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Thu, 3 Nov 2016 10:57:33 -0400 Subject: [PATCH] Bug 1309913: Pass the compositor type to canvas on creation. r=dvander MozReview-Commit-ID: 81HtvWPdLQa --HG-- extra : rebase_source : a448447fcb573beb320b2b2a352b97f77a5bafe3 --- dom/canvas/CanvasRenderingContext2D.cpp | 34 ++++++++++++++++----- dom/canvas/CanvasRenderingContext2D.h | 10 ++++-- dom/canvas/CanvasRenderingContextHelper.cpp | 9 +++++- dom/canvas/CanvasRenderingContextHelper.h | 5 +++ dom/html/HTMLCanvasElement.cpp | 3 +- gfx/thebes/gfxPlatform.cpp | 13 +++++--- layout/reftests/canvas/reftest.list | 3 +- 7 files changed, 59 insertions(+), 18 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index c778523e0fa3..92eaace1ae62 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1053,8 +1053,9 @@ DrawTarget* CanvasRenderingContext2D::sErrorTarget = nullptr; -CanvasRenderingContext2D::CanvasRenderingContext2D() +CanvasRenderingContext2D::CanvasRenderingContext2D(layers::LayersBackend aCompositorBackend) : mRenderingMode(RenderingMode::OpenGLBackendMode) + , mCompositorBackend(aCompositorBackend) // these are the default values from the Canvas spec , mWidth(0), mHeight(0) , mZero(false), mOpaque(false) @@ -1075,7 +1076,7 @@ CanvasRenderingContext2D::CanvasRenderingContext2D() nsContentUtils::RegisterShutdownObserver(mShutdownObserver); // The default is to use OpenGL mode - if (gfxPlatform::GetPlatform()->AllowOpenGLCanvas()) { + if (AllowOpenGLCanvas()) { mDrawObserver = new CanvasDrawObserver(this); } else { mRenderingMode = RenderingMode::SoftwareBackendMode; @@ -1321,6 +1322,26 @@ CanvasRenderingContext2D::RedrawUser(const gfxRect& aR) Redraw(newr); } +bool +CanvasRenderingContext2D::AllowOpenGLCanvas() const +{ + // If we somehow didn't have the correct compositor in the constructor, + // we could do something like this to get it: + // + // HTMLCanvasElement* el = GetCanvas(); + // if (el) { + // mCompositorBackend = el->GetCompositorBackendType(); + // } + // + // We could have LAYERS_NONE if there was no widget at the time of + // canvas creation, but in that case the + // HTMLCanvasElement::GetCompositorBackendType would return LAYERS_NONE + // as well, so it wouldn't help much. + + return (mCompositorBackend == LayersBackend::LAYERS_OPENGL) && + gfxPlatform::GetPlatform()->AllowOpenGLCanvas(); +} + bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode) { if (!IsTargetValid() || mRenderingMode == aRenderingMode) { @@ -1332,7 +1353,7 @@ bool CanvasRenderingContext2D::SwitchRenderingMode(RenderingMode aRenderingMode) #ifdef USE_SKIA_GPU // Do not attempt to switch into GL mode if the platform doesn't allow it. if ((aRenderingMode == RenderingMode::OpenGLBackendMode) && - !gfxPlatform::GetPlatform()->AllowOpenGLCanvas()) { + !AllowOpenGLCanvas()) { return false; } #endif @@ -1708,13 +1729,10 @@ CanvasRenderingContext2D::TrySkiaGLTarget(RefPtr& aOutDT, aOutDT = nullptr; aOutProvider = nullptr; - mIsSkiaGL = false; IntSize size(mWidth, mHeight); - if (!gfxPlatform::GetPlatform()->AllowOpenGLCanvas() || - !CheckSizeForSkiaGL(size)) { - + if (!AllowOpenGLCanvas() || !CheckSizeForSkiaGL(size)) { return false; } @@ -4760,7 +4778,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage, mIsSkiaGL && !srcSurf && aImage.IsHTMLVideoElement() && - gfxPlatform::GetPlatform()->AllowOpenGLCanvas()) { + AllowOpenGLCanvas()) { mozilla::gl::GLContext* gl = gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext(); MOZ_ASSERT(gl); diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 2ea4c5fd9d82..d95cea32eb3b 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -66,13 +66,13 @@ class CanvasRenderingContext2D final : virtual ~CanvasRenderingContext2D(); public: - CanvasRenderingContext2D(); + explicit CanvasRenderingContext2D(layers::LayersBackend aCompositorBackend); virtual JSObject* WrapObject(JSContext *aCx, JS::Handle aGivenProto) override; HTMLCanvasElement* GetCanvas() const { - if (mCanvasElement->IsInNativeAnonymousSubtree()) { + if (!mCanvasElement || mCanvasElement->IsInNativeAnonymousSubtree()) { return nullptr; } @@ -538,6 +538,10 @@ public: bool GetHitRegionRect(Element* aElement, nsRect& aRect) override; void OnShutdown(); + + // Check the global setup, as well as the compositor type: + bool AllowOpenGLCanvas() const; + protected: nsresult GetImageDataArray(JSContext* aCx, int32_t aX, int32_t aY, uint32_t aWidth, uint32_t aHeight, @@ -733,6 +737,8 @@ protected: RenderingMode mRenderingMode; + layers::LayersBackend mCompositorBackend; + // Member vars int32_t mWidth, mHeight; diff --git a/dom/canvas/CanvasRenderingContextHelper.cpp b/dom/canvas/CanvasRenderingContextHelper.cpp index e2b57abbc287..9616be68540e 100644 --- a/dom/canvas/CanvasRenderingContextHelper.cpp +++ b/dom/canvas/CanvasRenderingContextHelper.cpp @@ -122,6 +122,13 @@ CanvasRenderingContextHelper::ToBlob(JSContext* aCx, already_AddRefed CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType) +{ + return CreateContextHelper(aContextType, layers::LayersBackend::LAYERS_NONE); +} + +already_AddRefed +CanvasRenderingContextHelper::CreateContextHelper(CanvasContextType aContextType, + layers::LayersBackend aCompositorBackend) { MOZ_ASSERT(aContextType != CanvasContextType::NoContext); RefPtr ret; @@ -132,7 +139,7 @@ CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType) case CanvasContextType::Canvas2D: Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1); - ret = new CanvasRenderingContext2D(); + ret = new CanvasRenderingContext2D(aCompositorBackend); break; case CanvasContextType::WebGL1: diff --git a/dom/canvas/CanvasRenderingContextHelper.h b/dom/canvas/CanvasRenderingContextHelper.h index b047d60fcfc1..738150d16c51 100644 --- a/dom/canvas/CanvasRenderingContextHelper.h +++ b/dom/canvas/CanvasRenderingContextHelper.h @@ -7,6 +7,7 @@ #define MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_ #include "mozilla/dom/BindingDeclarations.h" +#include "mozilla/layers/LayersTypes.h" #include "nsSize.h" class nsICanvasRenderingContextInternal; @@ -66,6 +67,10 @@ protected: virtual already_AddRefed CreateContext(CanvasContextType aContextType); + already_AddRefed + CreateContextHelper(CanvasContextType aContextType, + layers::LayersBackend aCompositorBackend); + virtual nsIntSize GetWidthHeight() = 0; CanvasContextType mCurrentContextType; diff --git a/dom/html/HTMLCanvasElement.cpp b/dom/html/HTMLCanvasElement.cpp index 6b6e798513bb..47c06c12e1f4 100644 --- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -402,8 +402,9 @@ HTMLCanvasElement::WrapNode(JSContext* aCx, JS::Handle aGivenProto) already_AddRefed HTMLCanvasElement::CreateContext(CanvasContextType aContextType) { + // Note that the compositor backend will be LAYERS_NONE if there is no widget. RefPtr ret = - CanvasRenderingContextHelper::CreateContext(aContextType); + CreateContextHelper(aContextType, GetCompositorBackendType()); // Add Observer for webgl canvas. if (aContextType == CanvasContextType::WebGL1 || diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index 431fccb3bc9f..3d0209e4ff9c 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -1259,10 +1259,15 @@ bool gfxPlatform::AllowOpenGLCanvas() // For now, only allow Skia+OpenGL, unless it's blocked. // Allow acceleration on Skia if the preference is set, unless it's blocked // as long as we have the accelerated layers - if (gfxPrefs::CanvasAzureAccelerated() && - mCompositorBackend == LayersBackend::LAYERS_OPENGL && - (GetContentBackendFor(mCompositorBackend) == BackendType::SKIA)) - { + + // The compositor backend is only set correctly in the parent process, + // so we let content process always assume correct compositor backend. + // The callers have to do the right thing. + bool correctBackend = !XRE_IsParentProcess() || + ((mCompositorBackend == LayersBackend::LAYERS_OPENGL) && + (GetContentBackendFor(mCompositorBackend) == BackendType::SKIA)); + + if (gfxPrefs::CanvasAzureAccelerated() && correctBackend) { nsCOMPtr gfxInfo = do_GetService("@mozilla.org/gfx/info;1"); int32_t status; nsCString discardFailureId; diff --git a/layout/reftests/canvas/reftest.list b/layout/reftests/canvas/reftest.list index b3ac14c33281..0b6853db3ca5 100644 --- a/layout/reftests/canvas/reftest.list +++ b/layout/reftests/canvas/reftest.list @@ -66,8 +66,7 @@ random-if(cocoaWidget&&azureSkia) random-if(!cocoaWidget||OSX==1006||OSX==1007) # azure quartz uses CGDrawLinearGradient instead of DrawShading # so we have less control over degenerate behaviour as tested by this # test -# This test should pass with SkiaGL, but due to bug 1309913, e10s prevents SkiaGL from working. -fails-if((azureSkia&&!azureSkiaGL)||azureQuartz||(azureSkiaGL&&(browserIsRemote||Android))) == linear-gradient-1a.html linear-gradient-1-ref.html +fails-if((azureSkia&&!azureSkiaGL)||azureQuartz||(azureSkiaGL&&Android)) == linear-gradient-1a.html linear-gradient-1-ref.html # this passes with cairo on 10.7 and 10.8 but not with azure for reasons unknown # This test should pass with SkiaGL, but due to bug 1309913, e10s prevents SkiaGL from working.