Bug 1309913: Pass the compositor type to canvas on creation. r=dvander
☠☠ backed out by 19c01532ecbd ☠ ☠
authorMilan Sreckovic <milan@mozilla.com>
Tue, 01 Nov 2016 16:54:33 -0400
changeset 363354 e71aa9bcb92c2310f08c39425e8e1568f981eba8
parent 363353 2016d6d9e3533b76cf7848dd13cc962485c363b9
child 363355 b13127fafa7e7b61fc41fece179078f06f6208fd
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-beta@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1309913
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1309913: Pass the compositor type to canvas on creation. r=dvander MozReview-Commit-ID: H9HXXlyqa88
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/CanvasRenderingContext2D.h
dom/canvas/CanvasRenderingContextHelper.cpp
dom/canvas/CanvasRenderingContextHelper.h
dom/html/HTMLCanvasElement.cpp
gfx/thebes/gfxPlatform.cpp
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -1048,18 +1048,19 @@ NS_INTERFACE_MAP_END
 
 
 // Initialize our static variables.
 uint32_t CanvasRenderingContext2D::sNumLivingContexts = 0;
 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)
   , mResetLayer(true)
   , mIPC(false)
   , mIsSkiaGL(false)
   , mHasPendingStableStateCallback(false)
   , mDrawObserver(nullptr)
@@ -1070,17 +1071,17 @@ CanvasRenderingContext2D::CanvasRenderin
   , mInvalidateCount(0)
 {
   sNumLivingContexts++;
 
   mShutdownObserver = new CanvasShutdownObserver(this);
   nsContentUtils::RegisterShutdownObserver(mShutdownObserver);
 
   // The default is to use OpenGL mode
-  if (gfxPlatform::GetPlatform()->AllowOpenGLCanvas()) {
+  if (AllowOpenGLCanvas()) {
     mDrawObserver = new CanvasDrawObserver(this);
   } else {
     mRenderingMode = RenderingMode::SoftwareBackendMode;
   }
 }
 
 CanvasRenderingContext2D::~CanvasRenderingContext2D()
 {
@@ -1316,28 +1317,48 @@ CanvasRenderingContext2D::RedrawUser(con
     ++mInvalidateCount;
     return;
   }
 
   gfx::Rect newr = mTarget->GetTransform().TransformBounds(ToRect(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) {
     return false;
   }
 
   MOZ_ASSERT(mBufferProvider);
 
 #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
 
   RefPtr<PersistentBufferProvider> oldBufferProvider = mBufferProvider;
 
   // Return the old target to the buffer provider.
   // We need to do this before calling EnsureTarget.
@@ -1703,23 +1724,20 @@ LayerManagerFromCanvasElement(nsINode* a
 
 bool
 CanvasRenderingContext2D::TrySkiaGLTarget(RefPtr<gfx::DrawTarget>& aOutDT,
                                           RefPtr<layers::PersistentBufferProvider>& aOutProvider)
 {
   aOutDT = nullptr;
   aOutProvider = nullptr;
 
-
   mIsSkiaGL = false;
 
   IntSize size(mWidth, mHeight);
-  if (!gfxPlatform::GetPlatform()->AllowOpenGLCanvas() ||
-      !CheckSizeForSkiaGL(size)) {
-
+  if (!AllowOpenGLCanvas() || !CheckSizeForSkiaGL(size)) {
     return false;
   }
 
 
   RefPtr<LayerManager> layerManager = LayerManagerFromCanvasElement(mCanvasElement);
 
   if (!layerManager) {
     return false;
@@ -4755,17 +4773,17 @@ CanvasRenderingContext2D::DrawImage(cons
 
   nsLayoutUtils::DirectDrawInfo drawInfo;
 
 #ifdef USE_SKIA_GPU
   if (mRenderingMode == RenderingMode::OpenGLBackendMode &&
       mIsSkiaGL &&
       !srcSurf &&
       aImage.IsHTMLVideoElement() &&
-      gfxPlatform::GetPlatform()->AllowOpenGLCanvas()) {
+      AllowOpenGLCanvas()) {
     mozilla::gl::GLContext* gl = gfxPlatform::GetPlatform()->GetSkiaGLGlue()->GetGLContext();
     MOZ_ASSERT(gl);
 
     HTMLVideoElement* video = &aImage.GetAsHTMLVideoElement();
     if (!video) {
       return;
     }
 
--- a/dom/canvas/CanvasRenderingContext2D.h
+++ b/dom/canvas/CanvasRenderingContext2D.h
@@ -61,23 +61,23 @@ class CanvasShutdownObserver;
  **/
 class CanvasRenderingContext2D final :
   public nsICanvasRenderingContextInternal,
   public nsWrapperCache
 {
   virtual ~CanvasRenderingContext2D();
 
 public:
-  CanvasRenderingContext2D();
+  explicit CanvasRenderingContext2D(layers::LayersBackend aCompositorBackend);
 
   virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   HTMLCanvasElement* GetCanvas() const
   {
-    if (mCanvasElement->IsInNativeAnonymousSubtree()) {
+    if (!mCanvasElement || mCanvasElement->IsInNativeAnonymousSubtree()) {
       return nullptr;
     }
 
     // corresponds to changes to the old bindings made in bug 745025
     return mCanvasElement->GetOriginalCanvas();
   }
 
   void Save();
@@ -533,16 +533,20 @@ public:
   // Given a point, return hit region ID if it exists
   nsString GetHitRegion(const mozilla::gfx::Point& aPoint) override;
 
 
   // return true and fills in the bound rect if element has a hit region.
   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,
                              JSObject** aRetval);
 
   nsresult PutImageData_explicit(int32_t aX, int32_t aY, uint32_t aW, uint32_t aH,
                                  dom::Uint8ClampedArray* aArray,
                                  bool aHasDirtyRect, int32_t aDirtyX, int32_t aDirtyY,
@@ -728,16 +732,18 @@ protected:
   static std::vector<CanvasRenderingContext2D*>& DemotableContexts();
   static void DemoteOldestContextIfNecessary();
 
   static void AddDemotableContext(CanvasRenderingContext2D* aContext);
   static void RemoveDemotableContext(CanvasRenderingContext2D* aContext);
 
   RenderingMode mRenderingMode;
 
+  layers::LayersBackend mCompositorBackend;
+
   // Member vars
   int32_t mWidth, mHeight;
 
   // This is true when the canvas is valid, but of zero size, this requires
   // specific behavior on some operations.
   bool mZero;
 
   bool mOpaque;
--- a/dom/canvas/CanvasRenderingContextHelper.cpp
+++ b/dom/canvas/CanvasRenderingContextHelper.cpp
@@ -118,26 +118,33 @@ CanvasRenderingContextHelper::ToBlob(JSC
                                        format,
                                        GetWidthHeight(),
                                        callback);
 }
 
 already_AddRefed<nsICanvasRenderingContextInternal>
 CanvasRenderingContextHelper::CreateContext(CanvasContextType aContextType)
 {
+  return CreateContextHelper(aContextType, layers::LayersBackend::LAYERS_NONE);
+}
+
+already_AddRefed<nsICanvasRenderingContextInternal>
+CanvasRenderingContextHelper::CreateContextHelper(CanvasContextType aContextType,
+                                                  layers::LayersBackend aCompositorBackend)
+{
   MOZ_ASSERT(aContextType != CanvasContextType::NoContext);
   RefPtr<nsICanvasRenderingContextInternal> ret;
 
   switch (aContextType) {
   case CanvasContextType::NoContext:
     break;
 
   case CanvasContextType::Canvas2D:
     Telemetry::Accumulate(Telemetry::CANVAS_2D_USED, 1);
-    ret = new CanvasRenderingContext2D();
+    ret = new CanvasRenderingContext2D(aCompositorBackend);
     break;
 
   case CanvasContextType::WebGL1:
     Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_USED, 1);
 
     ret = WebGL1Context::Create();
     if (!ret)
       return nullptr;
--- a/dom/canvas/CanvasRenderingContextHelper.h
+++ b/dom/canvas/CanvasRenderingContextHelper.h
@@ -2,16 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
 #define MOZILLA_DOM_CANVASRENDERINGCONTEXTHELPER_H_
 
 #include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/layers/LayersTypes.h"
 #include "nsSize.h"
 
 class nsICanvasRenderingContextInternal;
 class nsIGlobalObject;
 
 namespace mozilla {
 
 class ErrorResult;
@@ -61,16 +62,20 @@ protected:
 
   void ToBlob(JSContext* aCx, nsIGlobalObject* aGlobal, EncodeCompleteCallback* aCallback,
               const nsAString& aType, JS::Handle<JS::Value> aParams,
               ErrorResult& aRv);
 
   virtual already_AddRefed<nsICanvasRenderingContextInternal>
   CreateContext(CanvasContextType aContextType);
 
+  already_AddRefed<nsICanvasRenderingContextInternal>
+  CreateContextHelper(CanvasContextType aContextType,
+                      layers::LayersBackend aCompositorBackend);
+
   virtual nsIntSize GetWidthHeight() = 0;
 
   CanvasContextType mCurrentContextType;
   nsCOMPtr<nsICanvasRenderingContextInternal> mCurrentContext;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -395,18 +395,19 @@ NS_IMPL_ELEMENT_CLONE(HTMLCanvasElement)
 HTMLCanvasElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLCanvasElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
 already_AddRefed<nsICanvasRenderingContextInternal>
 HTMLCanvasElement::CreateContext(CanvasContextType aContextType)
 {
+  // Note that the compositor backend will be LAYERS_NONE if there is no widget.
   RefPtr<nsICanvasRenderingContextInternal> ret =
-    CanvasRenderingContextHelper::CreateContext(aContextType);
+    CreateContextHelper(aContextType, GetCompositorBackendType());
 
   // Add Observer for webgl canvas.
   if (aContextType == CanvasContextType::WebGL1 ||
       aContextType == CanvasContextType::WebGL2) {
     if (!mContextObserver) {
       mContextObserver = new HTMLCanvasElementObserver(this);
     }
   }
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1251,20 +1251,25 @@ gfxPlatform::SupportsAzureContentForDraw
   return SupportsAzureContentForType(aTarget->GetBackendType());
 }
 
 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<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
     int32_t status;
     nsCString discardFailureId;
     return !gfxInfo ||
       (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_CANVAS2D_ACCELERATION,
                                               discardFailureId,
                                               &status)) &&
        status == nsIGfxInfo::FEATURE_STATUS_OK);