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 286770 e210473d793ce93f41642780fc66b56e97972eee
parent 286769 0fb279e041e14f05a1a1dd9fed8eb00b46f16d90
child 286771 a2a7b1c4dc5bde72d8c288211f4075a8d74f3253
push id30056
push userryanvm@gmail.com
push dateSun, 06 Mar 2016 00:19:57 +0000
treeherdermozilla-central@fcd55efa0672 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs801176
milestone47.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 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;