Bug 914505 - Make sure that ThebesLayerBuffer::SupportsAzureContent is correct for the first frame. r=nrc
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 12 Sep 2013 16:53:46 +1200
changeset 159664 771e3bbcd72126a43ee5267b8d6e01281ad75b20
parent 159663 3c13601b792428dba422c2d23426a402cef965ce
child 159665 7502c616895dfe1016d9ac47a330dcd45fb5effa
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnrc
bugs914505
milestone26.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 914505 - Make sure that ThebesLayerBuffer::SupportsAzureContent is correct for the first frame. r=nrc
gfx/layers/ThebesLayerBuffer.cpp
gfx/layers/ThebesLayerBuffer.h
gfx/layers/client/ContentClient.cpp
gfx/layers/client/ContentClient.h
gfx/layers/opengl/ThebesLayerOGL.cpp
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -419,16 +419,20 @@ ThebesLayerBuffer::IsAzureBuffer()
 {
   MOZ_ASSERT(!(mDTBuffer && mBuffer), "Trying to use Azure and Thebes in the same buffer?");
   if (mDTBuffer) {
     return true;
   }
   if (mBuffer) {
     return false;
   }
+  if (mBufferProvider) {
+    return gfxPlatform::GetPlatform()->SupportsAzureContentForType(
+      mBufferProvider->BackendType());
+  }
   return SupportsAzureContent();
 }
 
 void
 ThebesLayerBuffer::EnsureBuffer()
 {
   if ((!mBuffer && !mDTBuffer) && mBufferProvider) {
     if (IsAzureBuffer()) {
@@ -646,46 +650,38 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
           result.mDidSelfCopy = true;
           // Don't set destBuffer; we special-case self-copies, and
           // just did the necessary work above.
           mBufferRect = destBufferRect;
         } else {
           // We can't do a real self-copy because the buffer is rotated.
           // So allocate a new buffer for the destination.
           destBufferRect = ComputeBufferRect(neededRegion.GetBounds());
-          if (IsAzureBuffer()) {
-            MOZ_ASSERT(!mBuffer);
-            destDTBuffer = CreateDTBuffer(contentType, destBufferRect, bufferFlags, &destDTBufferOnWhite);
-          } else {
-            MOZ_ASSERT(!mDTBuffer);
-            destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags, getter_AddRefs(destBufferOnWhite));
-          }
+          CreateBuffer(contentType, destBufferRect, bufferFlags,
+                       getter_AddRefs(destBuffer), getter_AddRefs(destBufferOnWhite),
+                       &destDTBuffer, &destDTBufferOnWhite);
           if (!destBuffer && !destDTBuffer)
             return result;
         }
       } else {
         mBufferRect = destBufferRect;
         mBufferRotation = newRotation;
       }
     } else {
       // No pixels are going to be kept. The whole visible region
       // will be redrawn, so we don't need to copy anything, so we don't
       // set destBuffer.
       mBufferRect = destBufferRect;
       mBufferRotation = nsIntPoint(0,0);
     }
   } else {
     // The buffer's not big enough, so allocate a new one
-    if (IsAzureBuffer()) {
-      MOZ_ASSERT(!mBuffer);
-      destDTBuffer = CreateDTBuffer(contentType, destBufferRect, bufferFlags, &destDTBufferOnWhite);
-    } else {
-      MOZ_ASSERT(!mDTBuffer);
-      destBuffer = CreateBuffer(contentType, destBufferRect, bufferFlags, getter_AddRefs(destBufferOnWhite));
-    }
+    CreateBuffer(contentType, destBufferRect, bufferFlags,
+                 getter_AddRefs(destBuffer), getter_AddRefs(destBufferOnWhite),
+                 &destDTBuffer, &destDTBufferOnWhite);
     if (!destBuffer && !destDTBuffer)
       return result;
   }
 
   NS_ASSERTION(!(aFlags & PAINT_WILL_RESAMPLE) || destBufferRect == neededRegion.GetBounds(),
                "If we're resampling, we need to validate the entire buffer");
 
   // If we have no buffered data already, then destBuffer will be a fresh buffer
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -240,22 +240,24 @@ public:
     ALLOW_REPEAT = 0x01,
     BUFFER_COMPONENT_ALPHA = 0x02 // Dual buffers should be created for drawing with
                                   // component alpha.
   };
   /**
    * Return a new surface of |aSize| and |aType|.
    * @param aFlags if ALLOW_REPEAT is set, then the buffer should be configured
    * to allow repeat-mode, otherwise it should be in pad (clamp) mode
+   * If the created buffer supports azure content, then the result(s) will
+   * be returned in aBlackDT/aWhiteDT, otherwise aBlackSurface/aWhiteSurface
+   * will be used.
    */
-  virtual already_AddRefed<gfxASurface>
-  CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, gfxASurface** aWhiteSurface) = 0;
-  virtual TemporaryRef<gfx::DrawTarget>
-  CreateDTBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, RefPtr<gfx::DrawTarget>* aWhiteDT)
-  { NS_RUNTIMEABORT("CreateDTBuffer not implemented on this platform!"); return nullptr; }
+  virtual void
+  CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+               gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
+               RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) = 0;
   virtual bool SupportsAzureContent() const 
   { return false; }
 
   /**
    * Get the underlying buffer, if any. This is useful because we can pass
    * in the buffer as the default "reference surface" if there is one.
    * Don't use it for anything else!
    */
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -72,52 +72,51 @@ ContentClient::CreateContentClient(Compo
 
 }
 
 ContentClientBasic::ContentClientBasic(CompositableForwarder* aForwarder,
                                        BasicLayerManager* aManager)
 : ContentClient(aForwarder), ThebesLayerBuffer(ContainsVisibleBounds), mManager(aManager)
 {}
 
-already_AddRefed<gfxASurface>
+void
 ContentClientBasic::CreateBuffer(ContentType aType,
                                  const nsIntRect& aRect,
                                  uint32_t aFlags,
-                                 gfxASurface**)
+                                 gfxASurface** aBlackSurface,
+                                 gfxASurface** aWhiteSurface,
+                                 RefPtr<gfx::DrawTarget>* aBlackDT,
+                                 RefPtr<gfx::DrawTarget>* aWhiteDT)
 {
   MOZ_ASSERT(!(aFlags & BUFFER_COMPONENT_ALPHA));
+  if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
+    gfxASurface::gfxImageFormat format =
+      gfxPlatform::GetPlatform()->OptimalFormatForContent(aType);
+
+    *aBlackDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
+      IntSize(aRect.width, aRect.height),
+      ImageFormatToSurfaceFormat(format));
+    return;
+  }
+
   nsRefPtr<gfxASurface> referenceSurface = GetBuffer();
   if (!referenceSurface) {
     gfxContext* defaultTarget = mManager->GetDefaultTarget();
     if (defaultTarget) {
       referenceSurface = defaultTarget->CurrentSurface();
     } else {
       nsIWidget* widget = mManager->GetRetainerWidget();
       if (!widget || !(referenceSurface = widget->GetThebesSurface())) {
         referenceSurface = mManager->GetTarget()->CurrentSurface();
       }
     }
   }
-  return referenceSurface->CreateSimilarSurface(
+  nsRefPtr<gfxASurface> ret = referenceSurface->CreateSimilarSurface(
     aType, gfxIntSize(aRect.width, aRect.height));
-}
-
-TemporaryRef<DrawTarget>
-ContentClientBasic::CreateDTBuffer(ContentType aType,
-                                   const nsIntRect& aRect,
-                                   uint32_t aFlags,
-                                   RefPtr<DrawTarget>* aWhiteDT)
-{
-  MOZ_ASSERT(!(aFlags & BUFFER_COMPONENT_ALPHA));
-  gfxASurface::gfxImageFormat format =
-    gfxPlatform::GetPlatform()->OptimalFormatForContent(aType);
-
-  return gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
-    IntSize(aRect.width, aRect.height),
-    ImageFormatToSurfaceFormat(format));
+  *aBlackSurface = ret.forget().get();
 }
 
 void
 ContentClientRemoteBuffer::DestroyBuffers()
 {
   if (!mDeprecatedTextureClient) {
     return;
   }
@@ -220,56 +219,47 @@ bool
 ContentClientBasic::SupportsAzureContent() const
 {
   return gfxPlatform::GetPlatform()->SupportsAzureContent();
 }
  
 bool
 ContentClientRemoteBuffer::SupportsAzureContent() const
 {
-  if (!mDeprecatedTextureClient) {
-    // Hopefully we don't call this method before we have a texture client. But if
-    // we do, then we have no idea if we can support Azure for whatever surface the
-    // texture client might come up with.
-    return false;
-  }
+  MOZ_ASSERT(mDeprecatedTextureClient);
 
   return gfxPlatform::GetPlatform()->SupportsAzureContentForType(
     mDeprecatedTextureClient->BackendType());
 }
 
-TemporaryRef<DrawTarget>
-ContentClientRemoteBuffer::CreateDTBuffer(ContentType aType,
-                                          const nsIntRect& aRect,
-                                          uint32_t aFlags,
-                                          RefPtr<gfx::DrawTarget>* aWhiteDT)
+void
+ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
+                                        const nsIntRect& aRect,
+                                        uint32_t aFlags,
+                                        gfxASurface** aBlackSurface,
+                                        gfxASurface** aWhiteSurface,
+                                        RefPtr<gfx::DrawTarget>* aBlackDT,
+                                        RefPtr<gfx::DrawTarget>* aWhiteDT)
 {
   BuildDeprecatedTextureClients(aType, aRect, aFlags);
 
-  RefPtr<DrawTarget> ret = mDeprecatedTextureClient->LockDrawTarget();
-  if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    *aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
+  if (gfxPlatform::GetPlatform()->SupportsAzureContentForType(
+        mDeprecatedTextureClient->BackendType())) {
+    *aBlackDT = mDeprecatedTextureClient->LockDrawTarget();
+    if (aFlags & BUFFER_COMPONENT_ALPHA) {
+      *aWhiteDT = mDeprecatedTextureClientOnWhite->LockDrawTarget();
+    }
+  } else {
+    nsRefPtr<gfxASurface> ret = mDeprecatedTextureClient->LockSurface();
+    *aBlackSurface = ret.forget().get();
+    if (aFlags & BUFFER_COMPONENT_ALPHA) {
+     nsRefPtr<gfxASurface> retWhite = mDeprecatedTextureClientOnWhite->LockSurface();
+      *aWhiteSurface = retWhite.forget().get();
+    }
   }
-  return ret.forget();
-}
-
-already_AddRefed<gfxASurface>
-ContentClientRemoteBuffer::CreateBuffer(ContentType aType,
-                                        const nsIntRect& aRect,
-                                        uint32_t aFlags,
-                                        gfxASurface** aWhiteSurface)
-{
-  BuildDeprecatedTextureClients(aType, aRect, aFlags);
-
-  nsRefPtr<gfxASurface> ret = mDeprecatedTextureClient->LockSurface();
-  if (aFlags & BUFFER_COMPONENT_ALPHA) {
-    nsRefPtr<gfxASurface> retWhite = mDeprecatedTextureClientOnWhite->LockSurface();
-    *aWhiteSurface = retWhite.forget().get();
-  }
-  return ret.forget();
 }
 
 nsIntRegion
 ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                             const nsIntRegion& aVisibleRegion,
                                             bool aDidSelfCopy)
 {
   nsIntRegion updatedRegion;
--- a/gfx/layers/client/ContentClient.h
+++ b/gfx/layers/client/ContentClient.h
@@ -147,24 +147,19 @@ public:
   }
 
   void DrawTo(ThebesLayer* aLayer, gfxContext* aTarget, float aOpacity,
               gfxASurface* aMask, const gfxMatrix* aMaskTransform)
   {
     ThebesLayerBuffer::DrawTo(aLayer, aTarget, aOpacity, aMask, aMaskTransform);
   }
 
-  virtual already_AddRefed<gfxASurface> CreateBuffer(ContentType aType,
-                                                     const nsIntRect& aRect,
-                                                     uint32_t aFlags,
-                                                     gfxASurface**) MOZ_OVERRIDE;
-  virtual TemporaryRef<gfx::DrawTarget> CreateDTBuffer(ContentType aType,
-                                                       const nsIntRect& aRect,
-                                                       uint32_t aFlags,
-                                                       RefPtr<gfx::DrawTarget>* aWhiteDT);
+  virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+                            gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
+                            RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
   virtual bool SupportsAzureContent() const;
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     MOZ_CRASH("Should not be called on non-remote ContentClient");
   }
 
 private:
@@ -233,24 +228,19 @@ public:
   {
     return ThebesLayerBuffer::BufferRect();
   }
   virtual const nsIntPoint& BufferRotation() const
   {
     return ThebesLayerBuffer::BufferRotation();
   }
 
-  virtual already_AddRefed<gfxASurface> CreateBuffer(ContentType aType,
-                                                     const nsIntRect& aRect,
-                                                     uint32_t aFlags,
-                                                     gfxASurface** aWhiteSurface) MOZ_OVERRIDE;
-  virtual TemporaryRef<gfx::DrawTarget> CreateDTBuffer(ContentType aType,
-                                                       const nsIntRect& aRect,
-                                                       uint32_t aFlags,
-                                                       RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
+  virtual void CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+                            gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
+                            RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE;
 
   virtual bool SupportsAzureContent() const MOZ_OVERRIDE;
 
   void DestroyBuffers();
 
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
   {
     return mTextureInfo;
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -350,23 +350,26 @@ public:
   {
     // Let ThebesLayerBuffer do all the hard work for us! :D
     return ThebesLayerBuffer::BeginPaint(mLayer, 
                                          aContentType, 
                                          aFlags);
   }
 
   // ThebesLayerBuffer interface
-  virtual already_AddRefed<gfxASurface>
-  CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags, gfxASurface**)
+  void
+  CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags,
+               gfxASurface** aBlackSurface, gfxASurface** aWhiteSurface,
+               RefPtr<gfx::DrawTarget>* aBlackDT, RefPtr<gfx::DrawTarget>* aWhiteDT) MOZ_OVERRIDE
   {
     NS_ASSERTION(gfxASurface::CONTENT_ALPHA != aType,"ThebesBuffer has color");
 
     mTexImage = CreateClampOrRepeatTextureImage(gl(), aRect.Size(), aType, aFlags);
-    return mTexImage ? mTexImage->GetBackingSurface() : nullptr;
+    nsRefPtr<gfxASurface> ret = mTexImage ? mTexImage->GetBackingSurface() : nullptr;
+    *aBlackSurface = ret.forget().get();
   }
 
   virtual nsIntPoint GetOriginOffset() {
     return BufferRect().TopLeft() - BufferRotation();
   }
 };