Bug 801176 - part6-v1: Modify BufferProvider operations to fix assertions. r=roc
authorvincentliu <vliu@mozilla.com>
Fri, 04 Mar 2016 15:24:00 +0800
changeset 336837 e210473d793ce93f41642780fc66b56e97972eee
parent 336836 0fb279e041e14f05a1a1dd9fed8eb00b46f16d90
child 336838 a2a7b1c4dc5bde72d8c288211f4075a8d74f3253
push id12189
push usercku@mozilla.com
push dateFri, 04 Mar 2016 07:52:22 +0000
reviewersroc
bugs801176
milestone47.0a1
Bug 801176 - part6-v1: Modify BufferProvider operations to fix assertions. r=roc --- dom/canvas/CanvasRenderingContext2D.cpp | 12 +++-- dom/canvas/OffscreenCanvas.cpp | 2 - gfx/layers/AsyncCanvasRenderer.cpp | 85 +++++++++++++++++++++++++-------- gfx/layers/AsyncCanvasRenderer.h | 1 + 4 files changed, 73 insertions(+), 27 deletions(-)
dom/canvas/CanvasRenderingContext2D.cpp
dom/canvas/OffscreenCanvas.cpp
gfx/layers/AsyncCanvasRenderer.cpp
gfx/layers/AsyncCanvasRenderer.h
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5662,25 +5662,27 @@ void CanvasRenderingContext2D::RemoveDra
     delete mDrawObserver;
     mDrawObserver = nullptr;
   }
 }
 
 PersistentBufferProvider*
 CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
 {
-  if (!mTarget) {
-    EnsureTarget();
-  }
-
   if (mBufferProvider) {
     return mBufferProvider;
-  } else {
+  }
+
+  if (!mTarget) {
     return nullptr;
   }
+
+  mBufferProvider = new PersistentBufferProviderBasic(mTarget);
+
+  return mBufferProvider;
 }
 
 already_AddRefed<Layer>
 CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
                                          Layer *aOldLayer,
                                          LayerManager *aManager)
 {
   if (mOpaque || mIsSkiaGL) {
--- a/dom/canvas/OffscreenCanvas.cpp
+++ b/dom/canvas/OffscreenCanvas.cpp
@@ -158,19 +158,17 @@ OffscreenCanvas::GetContext(JSContext* a
       auto forwarder = mCanvasClient->GetForwarder();
 
       UniquePtr<gl::SurfaceFactory> factory =
         gl::GLScreenBuffer::CreateFactory(gl, caps, forwarder, flags);
 
       if (factory)
         screen->Morph(Move(factory));
     } else if (contextType == CanvasContextType::Canvas2D) {
-      CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext2D*>(mCurrentContext.get());
       mCanvasRenderer->mGLContext = nullptr;
-      mCanvasRenderer->mBufferProvider = context2D->GetBufferProvider(nullptr);
 
       mCanvasClient = ImageBridgeChild::GetSingleton()->
         CreateCanvasClient(CanvasClient::CanvasClientSurface, flags).take();
     }
     mCanvasRenderer->SetCanvasClient(mCanvasClient);
   }
 
   return result;
--- a/gfx/layers/AsyncCanvasRenderer.cpp
+++ b/gfx/layers/AsyncCanvasRenderer.cpp
@@ -6,26 +6,32 @@
 
 #include "AsyncCanvasRenderer.h"
 
 #include "gfxUtils.h"
 #include "GLContext.h"
 #include "GLReadTexImageHelper.h"
 #include "GLScreenBuffer.h"
 #include "mozilla/dom/HTMLCanvasElement.h"
+#include "mozilla/dom/CanvasRenderingContext2D.h"
 #include "mozilla/layers/BufferTexture.h"
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/TextureClient.h"
 #include "mozilla/layers/TextureClientSharedSurface.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 #include "PersistentBufferProvider.h"
 
 namespace mozilla {
+
+namespace dom {
+class CanvasRenderingContext2D;
+}
+
 namespace layers {
 
 AsyncCanvasRenderer::AsyncCanvasRenderer()
   : mHTMLCanvasElement(nullptr)
   , mContext(nullptr)
   , mGLContext(nullptr)
   , mIsAlphaPremultiplied(true)
   , mWidth(0)
@@ -233,16 +239,28 @@ AsyncCanvasRenderer::UpdateTarget()
   }
 
   return surface.forget();
 }
 
 void
 AsyncCanvasRenderer::UpdateTarget(TextureClient* aTexture)
 {
+  if (!mContext) {
+    return;
+  }
+
+  mBufferProvider = nullptr;
+
+  dom::CanvasRenderingContext2D* context2D = static_cast<dom::CanvasRenderingContext2D*>(mContext);
+  if (!context2D) {
+    return;
+  }
+
+  mBufferProvider = context2D->GetBufferProvider(nullptr);
   if (!mBufferProvider) {
     return;
   }
 
   RefPtr<gfx::SourceSurface> surface = mBufferProvider->GetSnapshot();
 
   if (surface) {
     NS_ASSERTION(surface, "Must have surface to draw!");
@@ -251,51 +269,78 @@ AsyncCanvasRenderer::UpdateTarget(Textur
   }
 }
 
 already_AddRefed<gfx::DataSourceSurface>
 AsyncCanvasRenderer::GetSurface()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MutexAutoLock lock(mMutex);
-  if (mSurfaceForBasic) {
-    // Since SourceSurface isn't thread-safe, we need copy to a new SourceSurface.
-    RefPtr<gfx::DataSourceSurface> result =
-      gfx::Factory::CreateDataSourceSurfaceWithStride(mSurfaceForBasic->GetSize(),
-                                                      mSurfaceForBasic->GetFormat(),
-                                                      mSurfaceForBasic->Stride());
+
+  if (!mContext) {
+    return nullptr;
+  }
+
+  if (mGLContext) {
+    if (mSurfaceForBasic) {
+      // Since SourceSurface isn't thread-safe, we need copy to a new SourceSurface.
+      RefPtr<gfx::DataSourceSurface> result =
+        gfx::Factory::CreateDataSourceSurfaceWithStride(mSurfaceForBasic->GetSize(),
+                                                        mSurfaceForBasic->GetFormat(),
+                                                        mSurfaceForBasic->Stride());
+
+      gfx::DataSourceSurface::ScopedMap srcMap(mSurfaceForBasic, gfx::DataSourceSurface::READ);
+      gfx::DataSourceSurface::ScopedMap dstMap(result, gfx::DataSourceSurface::WRITE);
 
-    gfx::DataSourceSurface::ScopedMap srcMap(mSurfaceForBasic, gfx::DataSourceSurface::READ);
-    gfx::DataSourceSurface::ScopedMap dstMap(result, gfx::DataSourceSurface::WRITE);
+      if (NS_WARN_IF(!srcMap.IsMapped()) ||
+          NS_WARN_IF(!dstMap.IsMapped())) {
+        return nullptr;
+      }
 
-    if (NS_WARN_IF(!srcMap.IsMapped()) ||
-        NS_WARN_IF(!dstMap.IsMapped())) {
+      memcpy(dstMap.GetData(),
+             srcMap.GetData(),
+             srcMap.GetStride() * mSurfaceForBasic->GetSize().height);
+      return result.forget();
+    } else {
+      return UpdateTarget();
+    }
+  } else {
+    dom::CanvasRenderingContext2D* context2D = static_cast<dom::CanvasRenderingContext2D*>(mContext);
+    if (!context2D) {
       return nullptr;
     }
 
-    memcpy(dstMap.GetData(),
-           srcMap.GetData(),
-           srcMap.GetStride() * mSurfaceForBasic->GetSize().height);
-    return result.forget();
-  } else {
-    return UpdateTarget();
+    mBufferProvider = context2D->GetBufferProvider(nullptr);
+
+    if (!mBufferProvider) {
+      return nullptr;
+    }
+
+    RefPtr<gfx::SourceSurface> sourceSurface = mBufferProvider->GetSnapshot();
+
+    if (!sourceSurface) {
+      return nullptr;
+    }
+    return sourceSurface->GetDataSurface();
   }
 }
 
 nsresult
 AsyncCanvasRenderer::GetInputStream(const char *aMimeType,
                                     const char16_t *aEncoderOptions,
                                     nsIInputStream **aStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   RefPtr<gfx::DataSourceSurface> surface = GetSurface();
   if (!surface) {
     return NS_ERROR_FAILURE;
   }
 
-  // Handle y flip.
-  RefPtr<gfx::DataSourceSurface> dataSurf = gl::YInvertImageSurface(surface);
+  // Only handle y flip in webgl.
+  RefPtr<gfx::DataSourceSurface> dataSurf = mGLContext
+                                            ? gl::YInvertImageSurface(surface)
+                                            : surface;
 
   return gfxUtils::GetInputStream(dataSurf, false, aMimeType, aEncoderOptions, aStream);
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/AsyncCanvasRenderer.h
+++ b/gfx/layers/AsyncCanvasRenderer.h
@@ -25,16 +25,17 @@ class DrawTarget;
 }
 
 namespace gl {
 class GLContext;
 }
 
 namespace dom {
 class HTMLCanvasElement;
+class CanvasRenderingContext2D;
 }
 
 namespace layers {
 
 class CanvasClient;
 class PersistentBufferProvider;
 class TextureClient;