Bug 603885, part 6: Implement swap-and-readback. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Fri, 05 Nov 2010 02:17:07 -0500
changeset 56903 d6b5d3e3ffbf50787a266bbd316e4b9d5469d908
parent 56902 b5086952fc37ce26581b82665cb69bb439870a74
child 56904 f2b5fc8dc7a3c252f3aa360397a92b454c385071
push id16725
push usercjones@mozilla.com
push dateFri, 05 Nov 2010 07:21:46 +0000
treeherdermozilla-central@0aa98eae87ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs603885
milestone2.0b8pre
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 603885, part 6: Implement swap-and-readback. r=roc
gfx/layers/basic/BasicLayers.cpp
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -289,17 +289,32 @@ public:
     gfxIntSize prevSize = gfxIntSize(BufferDims().width, BufferDims().height);
     gfxIntSize newSize = aBuffer->GetSize();
     NS_ABORT_IF_FALSE(newSize == prevSize,
                       "Swapped-in buffer size doesn't match old buffer's!");
     SetBuffer(aBuffer,
               nsIntSize(newSize.width, newSize.height), aRect, aRotation);
   }
 
+  void SetBackingBufferAndUpdateFrom(
+    gfxASurface* aBuffer,
+    gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
+    const nsIntRegion& aUpdateRegion, float aXResolution, float aYResolution);
+
 private:
+  BasicThebesLayerBuffer(gfxASurface* aBuffer,
+                         const nsIntRect& aRect, const nsIntPoint& aRotation)
+    // The size policy doesn't really matter here; this constructor is
+    // intended to be used for creating temporaries
+    : ThebesLayerBuffer(ContainsVisibleBounds)
+  {
+    gfxIntSize sz = aBuffer->GetSize();
+    SetBuffer(aBuffer, nsIntSize(sz.width, sz.height), aRect, aRotation);
+  }
+
   BasicThebesLayer* mLayer;
 };
 
 class BasicThebesLayer : public ThebesLayer, BasicImplData {
 public:
   typedef BasicThebesLayerBuffer Buffer;
 
   BasicThebesLayer(BasicLayerManager* aLayerManager) :
@@ -538,16 +553,35 @@ BasicThebesLayerBuffer::DrawTo(ThebesLay
 
 already_AddRefed<gfxASurface>
 BasicThebesLayerBuffer::CreateBuffer(ContentType aType, 
                                      const nsIntSize& aSize)
 {
   return mLayer->CreateBuffer(aType, aSize);
 }
 
+void
+BasicThebesLayerBuffer::SetBackingBufferAndUpdateFrom(
+  gfxASurface* aBuffer,
+  gfxASurface* aSource, const nsIntRect& aRect, const nsIntPoint& aRotation,
+  const nsIntRegion& aUpdateRegion, float aXResolution, float aYResolution)
+{
+  SetBackingBuffer(aBuffer, aRect, aRotation);
+  nsRefPtr<gfxContext> destCtx =
+    GetContextForQuadrantUpdate(aUpdateRegion.GetBounds(),
+                                aXResolution, aYResolution);
+  destCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
+  if (IsClippingCheap(destCtx, aUpdateRegion)) {
+    gfxUtils::ClipToRegion(destCtx, aUpdateRegion);
+  }
+
+  BasicThebesLayerBuffer srcBuffer(aSource, aRect, aRotation);
+  srcBuffer.DrawBufferWithRotation(destCtx, 1.0, aXResolution, aYResolution);
+}
+
 class BasicImageLayer : public ImageLayer, BasicImplData {
 public:
   BasicImageLayer(BasicLayerManager* aLayerManager) :
     ImageLayer(aLayerManager, static_cast<BasicImplData*>(this)),
     mSize(-1, -1)
   {
     MOZ_COUNT_CTOR(BasicImageLayer);
   }
@@ -1461,16 +1495,26 @@ BasicShadowableThebesLayer::SetBackBuffe
     // to a texture it owns, then we probably got back the same buffer
     // we pushed in the update and all is well.  If not, ...
     mValidRegion = aValidRegion;
     mXResolution = aXResolution;
     mYResolution = aYResolution;
     mBuffer.SetBackingBuffer(backBuffer, aBuffer.rect(), aBuffer.rotation());
     return;
   }
+
+  const ThebesBuffer roFront = aReadOnlyFrontBuffer.get_ThebesBuffer();
+  nsRefPtr<gfxASurface> roFrontBuffer = BasicManager()->OpenDescriptor(roFront.buffer());
+  mBuffer.SetBackingBufferAndUpdateFrom(
+    backBuffer,
+    roFrontBuffer, roFront.rect(), roFront.rotation(),
+    aFrontUpdatedRegion, mXResolution, mYResolution);
+  // Now the new back buffer has the same (interesting) pixels as the
+  // new front buffer, and mValidRegion et al. are correct wrt the new
+  // back buffer (i.e. as they were for the old back buffer)
 }
 
 void
 BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
                                         const nsIntRegion& aRegionToDraw,
                                         const nsIntRegion& aRegionToInvalidate,
                                         LayerManager::DrawThebesLayerCallback aCallback,
                                         void* aCallbackData)
@@ -1952,18 +1996,18 @@ BasicShadowThebesLayer::Swap(const Thebe
 
   nsRefPtr<gfxASurface> unused;
   mFrontBuffer.Swap(
     newFrontBuffer, aNewFront.rect(), aNewFront.rotation(),
     getter_AddRefs(unused), &aNewBack->rect(), &aNewBack->rotation());
 
   mFrontBufferDescriptor = aNewFront.buffer();
 
-  *aReadOnlyFront = null_t();
-  aFrontUpdatedRegion->SetEmpty();
+  *aReadOnlyFront = aNewFront;
+  *aFrontUpdatedRegion = aUpdatedRegion;
 }
 
 void
 BasicShadowThebesLayer::Paint(gfxContext* aContext,
                               LayerManager::DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               float aOpacity)
 {