Backed out changeset d51327ec371e (bug 1289816) for canvas reftest failures
authorWes Kocher <wkocher@mozilla.com>
Thu, 28 Jul 2016 13:08:59 -0700
changeset 347207 fc2138a46d6c1e59649f0181807974605ace82ed
parent 347206 80b2d8a0999e03ef669bff6ddf7e628a26355b60
child 347208 b498c2f4fdd8ba44f0d064e29d60a3e61f5acfdd
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1289816
milestone50.0a1
backs outd51327ec371ec44324d42734978802f0b1eff9b9
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
Backed out changeset d51327ec371e (bug 1289816) for canvas reftest failures
gfx/layers/CopyableCanvasLayer.cpp
gfx/layers/CopyableCanvasLayer.h
gfx/layers/basic/BasicCanvasLayer.cpp
gfx/layers/basic/BasicCanvasLayer.h
--- a/gfx/layers/CopyableCanvasLayer.cpp
+++ b/gfx/layers/CopyableCanvasLayer.cpp
@@ -45,16 +45,18 @@ CopyableCanvasLayer::CopyableCanvasLayer
 CopyableCanvasLayer::~CopyableCanvasLayer()
 {
   MOZ_COUNT_DTOR(CopyableCanvasLayer);
 }
 
 void
 CopyableCanvasLayer::Initialize(const Data& aData)
 {
+  NS_ASSERTION(mSurface == nullptr, "BasicCanvasLayer::Initialize called twice!");
+
   if (aData.mGLContext) {
     mGLContext = aData.mGLContext;
     mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
     mOriginPos = gl::OriginPos::BottomLeft;
     mIsMirror = aData.mIsMirror;
 
     MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
 
@@ -65,61 +67,65 @@ CopyableCanvasLayer::Initialize(const Da
       mBufferProvider = aData.mBufferProvider;
     }
   } else if (aData.mBufferProvider) {
     mBufferProvider = aData.mBufferProvider;
   } else if (aData.mRenderer) {
     mAsyncRenderer = aData.mRenderer;
     mOriginPos = gl::OriginPos::BottomLeft;
   } else {
-    MOZ_CRASH("GFX: CanvasLayer created without BufferProvider, DrawTarget or GLContext?");
+    MOZ_CRASH("GFX: CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
   }
 
   mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
 }
 
 bool
 CopyableCanvasLayer::IsDataValid(const Data& aData)
 {
   return mGLContext == aData.mGLContext;
 }
 
 void
 CopyableCanvasLayer::UpdateTarget(DrawTarget* aDestTarget)
 {
-  MOZ_ASSERT(aDestTarget);
-  if (!aDestTarget) {
-    return;
+  AutoReturnSnapshot autoReturn;
+
+  if (mAsyncRenderer) {
+    mSurface = mAsyncRenderer->GetSurface();
+  } else if (!mGLFrontbuffer && mBufferProvider) {
+    mSurface = mBufferProvider->BorrowSnapshot();
+    if (aDestTarget) {
+      // If !aDestTarget we'll end up painting using mSurface later,
+      // so we can't return it to the provider (note that this will trigger a
+      // copy of the snapshot behind the scenes when the provider is unlocked).
+      autoReturn.mSnapshot = &mSurface;
+    }
+    // Either way we need to call ReturnSnapshot because ther may be an
+    // underlying TextureClient that has to be unlocked.
+    autoReturn.mBufferProvider = mBufferProvider;
   }
 
-  RefPtr<SourceSurface> surface;
-
-  if (!mGLContext) {
-    AutoReturnSnapshot autoReturn;
-
-    if (mAsyncRenderer) {
-      surface = mAsyncRenderer->GetSurface();
-    } else if (mBufferProvider && !mGLContext) {
-      surface = mBufferProvider->BorrowSnapshot();
-      autoReturn.mSnapshot = &surface;
-      autoReturn.mBufferProvider = mBufferProvider;
-    }
-
-    NS_ASSERTION(surface, "Must have surface to draw!");
-    if (surface) {
-      aDestTarget->CopySurface(surface,
+  if (!mGLContext && aDestTarget) {
+    NS_ASSERTION(mSurface, "Must have surface to draw!");
+    if (mSurface) {
+      aDestTarget->CopySurface(mSurface,
                                IntRect(0, 0, mBounds.width, mBounds.height),
                                IntPoint(0, 0));
+      mSurface = nullptr;
     }
 
     return;
   }
 
-  MOZ_ASSERT(!mBufferProvider);
-  MOZ_ASSERT(!mAsyncRenderer);
+  if ((!mGLFrontbuffer && mBufferProvider) || mAsyncRenderer) {
+    return;
+  }
+
+  MOZ_ASSERT(mGLContext);
 
   SharedSurface* frontbuffer = nullptr;
   if (mGLFrontbuffer) {
     frontbuffer = mGLFrontbuffer.get();
   } else {
     GLScreenBuffer* screen = mGLContext->Screen();
     const auto& front = screen->Front();
     if (front) {
@@ -134,50 +140,59 @@ CopyableCanvasLayer::UpdateTarget(DrawTa
 
   IntSize readSize(frontbuffer->mSize);
   SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
                           ? SurfaceFormat::B8G8R8X8
                           : SurfaceFormat::B8G8R8A8;
   bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
 
   // Try to read back directly into aDestTarget's output buffer
-  uint8_t* destData;
-  IntSize destSize;
-  int32_t destStride;
-  SurfaceFormat destFormat;
-  if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
-    if (destSize == readSize && destFormat == format) {
-      RefPtr<DataSourceSurface> data =
-        Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
-      mGLContext->Readback(frontbuffer, data);
-      if (needsPremult) {
-        gfxUtils::PremultiplyDataSurface(data, data);
+  if (aDestTarget) {
+    uint8_t* destData;
+    IntSize destSize;
+    int32_t destStride;
+    SurfaceFormat destFormat;
+    if (aDestTarget->LockBits(&destData, &destSize, &destStride, &destFormat)) {
+      if (destSize == readSize && destFormat == format) {
+        RefPtr<DataSourceSurface> data =
+          Factory::CreateWrappingDataSourceSurface(destData, destStride, destSize, destFormat);
+        mGLContext->Readback(frontbuffer, data);
+        if (needsPremult) {
+          gfxUtils::PremultiplyDataSurface(data, data);
+        }
+        aDestTarget->ReleaseBits(destData);
+        return;
       }
       aDestTarget->ReleaseBits(destData);
-      return;
     }
-    aDestTarget->ReleaseBits(destData);
   }
 
   RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
   // There will already be a warning from inside of GetTempSurface, but
   // it doesn't hurt to complain:
   if (NS_WARN_IF(!resultSurf)) {
     return;
   }
 
   // Readback handles Flush/MarkDirty.
   mGLContext->Readback(frontbuffer, resultSurf);
   if (needsPremult) {
     gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
   }
+  MOZ_ASSERT(resultSurf);
 
-  aDestTarget->CopySurface(resultSurf,
-                           IntRect(0, 0, readSize.width, readSize.height),
-                           IntPoint(0, 0));
+  if (aDestTarget) {
+    aDestTarget->CopySurface(resultSurf,
+                             IntRect(0, 0, readSize.width, readSize.height),
+                             IntPoint(0, 0));
+  } else {
+    // If !aDestSurface then we will end up painting using mSurface, so
+    // stick our surface into mSurface, so that the Paint() path is the same.
+    mSurface = resultSurf;
+  }
 }
 
 DataSourceSurface*
 CopyableCanvasLayer::GetTempSurface(const IntSize& aSize,
                                     const SurfaceFormat aFormat)
 {
   if (!mCachedTempSurface ||
       aSize != mCachedTempSurface->GetSize() ||
@@ -186,10 +201,16 @@ CopyableCanvasLayer::GetTempSurface(cons
     // Create a surface aligned to 8 bytes since that's the highest alignment WebGL can handle.
     uint32_t stride = GetAlignedStride<8>(aSize.width * BytesPerPixel(aFormat));
     mCachedTempSurface = Factory::CreateDataSourceSurfaceWithStride(aSize, aFormat, stride);
   }
 
   return mCachedTempSurface;
 }
 
+void
+CopyableCanvasLayer::DiscardTempSurface()
+{
+  mCachedTempSurface = nullptr;
+}
+
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/CopyableCanvasLayer.h
+++ b/gfx/layers/CopyableCanvasLayer.h
@@ -44,26 +44,31 @@ public:
 
   virtual bool IsDataValid(const Data& aData) override;
 
   bool IsGLLayer() { return !!mGLContext; }
 
 protected:
   void UpdateTarget(gfx::DrawTarget* aDestTarget = nullptr);
 
+  RefPtr<gfx::SourceSurface> mSurface;
   RefPtr<gl::GLContext> mGLContext;
+  GLuint mCanvasFrontbufferTexID;
   RefPtr<PersistentBufferProvider> mBufferProvider;
+
   UniquePtr<gl::SharedSurface> mGLFrontbuffer;
 
   bool mIsAlphaPremultiplied;
   gl::OriginPos mOriginPos;
   bool mIsMirror;
 
   RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
 
   gfx::DataSourceSurface* GetTempSurface(const gfx::IntSize& aSize,
                                          const gfx::SurfaceFormat aFormat);
+
+  void DiscardTempSurface();
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -6,127 +6,58 @@
 #include "BasicCanvasLayer.h"
 #include "AsyncCanvasRenderer.h"
 #include "basic/BasicLayers.h"          // for BasicLayerManager
 #include "basic/BasicLayersImpl.h"      // for GetEffectiveOperator
 #include "mozilla/mozalloc.h"           // for operator new
 #include "nsCOMPtr.h"                   // for already_AddRefed
 #include "nsISupportsImpl.h"            // for Layer::AddRef, etc
 #include "gfx2DGlue.h"
-#include "GLScreenBuffer.h"
-#include "GLContext.h"
-#include "gfxUtils.h"
-#include "mozilla/layers/PersistentBufferProvider.h"
-#include "client/TextureClientSharedSurface.h"
 
 class gfxContext;
 
 using namespace mozilla::gfx;
 using namespace mozilla::gl;
 
 namespace mozilla {
 namespace layers {
 
-already_AddRefed<SourceSurface>
-BasicCanvasLayer::UpdateSurface()
-{
-  if (mAsyncRenderer) {
-    return mAsyncRenderer->GetSurface();
-  }
-
-  if (mBufferProvider) {
-    // This is handled separately in Paint.
-    return nullptr;
-  }
-
-  if (!mGLContext) {
-    return nullptr;
-  }
-
-  SharedSurface* frontbuffer = nullptr;
-  if (mGLFrontbuffer) {
-    frontbuffer = mGLFrontbuffer.get();
-  } else {
-    GLScreenBuffer* screen = mGLContext->Screen();
-    const auto& front = screen->Front();
-    if (front) {
-      frontbuffer = front->Surf();
-    }
-  }
-
-  if (!frontbuffer) {
-    NS_WARNING("Null frame received.");
-    return nullptr;
-  }
-
-  IntSize readSize(frontbuffer->mSize);
-  SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
-                          ? SurfaceFormat::B8G8R8X8
-                          : SurfaceFormat::B8G8R8A8;
-  bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
-
-  RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
-  // There will already be a warning from inside of GetTempSurface, but
-  // it doesn't hurt to complain:
-  if (NS_WARN_IF(!resultSurf)) {
-    return nullptr;
-  }
-
-  // Readback handles Flush/MarkDirty.
-  mGLContext->Readback(frontbuffer, resultSurf);
-  if (needsPremult) {
-    gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
-  }
-  MOZ_ASSERT(resultSurf);
-
-  return resultSurf.forget();
-}
-
 void
 BasicCanvasLayer::Paint(DrawTarget* aDT,
                         const Point& aDeviceOffset,
                         Layer* aMaskLayer)
 {
   if (IsHidden())
     return;
 
-  RefPtr<SourceSurface> surface;
   if (IsDirty()) {
     Painted();
 
     FirePreTransactionCallback();
-    surface = UpdateSurface();
+    UpdateTarget();
     FireDidTransactionCallback();
   }
 
-  AutoReturnSnapshot autoReturn(mBufferProvider);
-
-  if (mBufferProvider) {
-    MOZ_ASSERT(!surface);
-    surface = mBufferProvider->BorrowSnapshot();
-    autoReturn.mSnapshot = &surface;
-  }
-
-  if (!surface) {
+  if (!mSurface) {
     return;
   }
 
   const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
 
   Matrix oldTM;
   if (needsYFlip) {
     oldTM = aDT->GetTransform();
     aDT->SetTransform(Matrix(oldTM).
                         PreTranslate(0.0f, mBounds.height).
                         PreScale(1.0f, -1.0f));
   }
 
   FillRectWithMask(aDT, aDeviceOffset,
                    Rect(0, 0, mBounds.width, mBounds.height),
-                   surface, mSamplingFilter,
+                   mSurface, mSamplingFilter,
                    DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
                    aMaskLayer);
 
   if (needsYFlip) {
     aDT->SetTransform(oldTM);
   }
 }
 
--- a/gfx/layers/basic/BasicCanvasLayer.h
+++ b/gfx/layers/basic/BasicCanvasLayer.h
@@ -31,19 +31,16 @@ public:
     CanvasLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void Paint(gfx::DrawTarget* aDT,
                      const gfx::Point& aDeviceOffset,
                      Layer* aMaskLayer) override;
 
 protected:
-
-  already_AddRefed<gfx::SourceSurface> UpdateSurface();
-
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
 };
 
 } // namespace layers
 } // namespace mozilla