Bug 603885, part 2: Set up the framework for swap-and-readback. r=roc sr=vlad
authorChris Jones <jones.chris.g@gmail.com>
Fri, 05 Nov 2010 02:17:07 -0500
changeset 56899 bffc3f0cf9499b91e1fb4db27e7f23abfb9c1e2b
parent 56898 dc526c0277432c0f597fd56273aad35290d771c6
child 56900 4f4736cb9e70d54254a16582f8140bea2ce2cd2f
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, vlad
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 2: Set up the framework for swap-and-readback. r=roc sr=vlad
gfx/layers/basic/BasicLayers.cpp
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/opengl/ThebesLayerOGL.cpp
gfx/layers/opengl/ThebesLayerOGL.h
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -1400,17 +1400,19 @@ public:
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
   virtual bool MustRetainContent() { return HasShadow(); }
 
   virtual PRBool SupportsSurfaceDescriptor() const { return PR_TRUE; }
 
   void SetBackBufferAndAttrs(const ThebesBuffer& aBuffer,
                              const nsIntRegion& aValidRegion,
-                             float aXResolution, float aYResolution);
+                             float aXResolution, float aYResolution,
+                             const OptionalThebesBuffer& aReadOnlyFrontBuffer,
+                             const nsIntRegion& aFrontUpdatedRegion);
 
   virtual void Disconnect()
   {
     mBackBuffer = SurfaceDescriptor();
     BasicShadowableLayer::Disconnect();
   }
 
   virtual BasicShadowableThebesLayer* AsThebes() { return this; }
@@ -1441,25 +1443,34 @@ private:
   SurfaceDescriptor mNewFrontBuffer;
   nsIntSize mBufferSize;
 };
 
 void
 BasicShadowableThebesLayer::SetBackBufferAndAttrs(const ThebesBuffer& aBuffer,
                                                   const nsIntRegion& aValidRegion,
                                                   float aXResolution,
-                                                  float aYResolution);
+                                                  float aYResolution,
+                                                  const OptionalThebesBuffer& aReadOnlyFrontBuffer,
+                                                  const nsIntRegion& aFrontUpdatedRegion)
 {
   mBackBuffer = aBuffer.buffer();
-  mValidRegion = aValidRegion;
-  mXResolution = aXResolution;
-  mYResolution = aYResolution;
+  nsRefPtr<gfxASurface> backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
 
-  nsRefPtr<gfxASurface> backBuffer = BasicManager()->OpenDescriptor(mBackBuffer);
-  mBuffer.SetBackingBuffer(backBuffer, aBuffer.rect(), aBuffer.rotation());
+  if (OptionalThebesBuffer::Tnull_t == aReadOnlyFrontBuffer.type()) {
+    // We didn't get back a read-only ref to our old back buffer (the
+    // parent's new front buffer).  If the parent is pushing updates
+    // 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;
+  }
 }
 
 void
 BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
                                         const nsIntRegion& aRegionToDraw,
                                         const nsIntRegion& aRegionToInvalidate,
                                         LayerManager::DrawThebesLayerCallback aCallback,
                                         void* aCallbackData)
@@ -1840,17 +1851,18 @@ public:
   {
     DestroyFrontBuffer();
     ShadowThebesLayer::Disconnect();
   }
 
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution);
+       float* aNewXResolution, float* aNewYResolution,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
 
   virtual void DestroyFrontBuffer()
   {
     mFrontBuffer.Clear();
     mValidRegion.SetEmpty();
     mOldValidRegion.SetEmpty();
     mOldXResolution = 1.0;
     mOldYResolution = 1.0;
@@ -1902,17 +1914,19 @@ BasicShadowThebesLayer::SetFrontBuffer(c
   mFrontBufferDescriptor = aNewFront.buffer();
 }
 
 void
 BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
                              const nsIntRegion& aUpdatedRegion,
                              ThebesBuffer* aNewBack,
                              nsIntRegion* aNewBackValidRegion,
-                             float* aNewXResolution, float* aNewYResolution)
+                             float* aNewXResolution, float* aNewYResolution,
+                             OptionalThebesBuffer* aReadOnlyFront,
+                             nsIntRegion* aFrontUpdatedRegion)
 {
   // This code relies on Swap() arriving *after* attribute mutations.
   aNewBack->buffer() = mFrontBufferDescriptor;
   // We have to invalidate the pixels painted into the new buffer.
   // They might overlap with our old pixels.
   if (mOldXResolution == mXResolution && mOldYResolution == mYResolution) {
     aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
   } else {
@@ -1937,16 +1951,19 @@ BasicShadowThebesLayer::Swap(const Thebe
     BasicManager()->OpenDescriptor(aNewFront.buffer());
 
   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();
 }
 
 void
 BasicShadowThebesLayer::Paint(gfxContext* aContext,
                               LayerManager::DrawThebesLayerCallback aCallback,
                               void* aCallbackData,
                               float aOpacity)
 {
@@ -2368,17 +2385,18 @@ BasicShadowLayerManager::EndTransaction(
       switch (reply.type()) {
       case EditReply::TOpThebesBufferSwap: {
         MOZ_LAYERS_LOG(("[LayersForwarder] ThebesBufferSwap"));
 
         const OpThebesBufferSwap& obs = reply.get_OpThebesBufferSwap();
         BasicShadowableThebesLayer* thebes = GetBasicShadowable(obs)->AsThebes();
         thebes->SetBackBufferAndAttrs(
           obs.newBackBuffer(),
-          obs.newValidRegion(), obs.newXResolution(), obs.newYResolution());
+          obs.newValidRegion(), obs.newXResolution(), obs.newYResolution(),
+          obs.readOnlyFrontBuffer(), obs.frontUpdatedRegion());
         break;
       }
       case EditReply::TOpBufferSwap: {
         MOZ_LAYERS_LOG(("[LayersForwarder] BufferSwap"));
 
         const OpBufferSwap& obs = reply.get_OpBufferSwap();
         const SurfaceDescriptor& descr = obs.newBackBuffer();
         BasicShadowableLayer* layer = GetBasicShadowable(obs);
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -82,16 +82,17 @@ union SurfaceDescriptor {
   SurfaceDescriptorX11;
 };
 
 struct ThebesBuffer {
   SurfaceDescriptor buffer;
   nsIntRect rect;
   nsIntPoint rotation; 
 };
+union OptionalThebesBuffer { ThebesBuffer; null_t; };
 
 struct OpCreateThebesBuffer {
   PLayer layer;
   ThebesBuffer initialFront;
   nsIntRegion frontValidRegion;
   float xResolution;
   float yResolution;
 };
@@ -209,16 +210,24 @@ union Edit {
 struct OpBufferSwap   { PLayer layer; SurfaceDescriptor newBackBuffer; };
 
 struct OpThebesBufferSwap {
   PLayer layer;
   ThebesBuffer newBackBuffer;
   nsIntRegion newValidRegion;
   float newXResolution;
   float newYResolution;
+  // If the parent took the child's old back buffer and returned its
+  // old front buffer, |readOnlyFrontBuffer| may (if non-null) contain
+  // the child's old back buffer (parent's new front buffer).  This
+  // buffer can be used to read back the newly updated region into the
+  // child's new back buffer.  This buffer must be considered
+  // read-only, but sadly that's not enforced.
+  OptionalThebesBuffer readOnlyFrontBuffer;
+  nsIntRegion frontUpdatedRegion;
 };
 
 // Unit of a "changeset reply".  This is a weird abstraction, probably
 // only to be used for buffer swapping.
 union EditReply {
   OpBufferSwap;
   OpThebesBufferSwap;
 };
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -48,16 +48,17 @@
 
 class gfxSharedImageSurface;
 
 namespace mozilla {
 namespace layers {
 
 struct Edit;
 struct EditReply;
+class OptionalThebesBuffer;
 class PLayerChild;
 class PLayersChild;
 class PLayersParent;
 class ShadowableLayer;
 class ShadowThebesLayer;
 class ShadowContainerLayer;
 class ShadowImageLayer;
 class ShadowColorLayer;
@@ -500,17 +501,18 @@ public:
    *
    * Publish the remote layer's back ThebesLayerBuffer to this shadow,
    * swapping out the old front ThebesLayerBuffer (the new back buffer
    * for the remote layer).
    */
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution) = 0;
+       float* aNewXResolution, float* aNewYResolution,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion) = 0;
 
   /**
    * CONSTRUCTION PHASE ONLY
    *
    * Destroy the current front buffer.
    */
   virtual void DestroyFrontBuffer() = 0;
 
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -371,22 +371,26 @@ ShadowLayersParent::RecvUpdate(const nsT
       ShadowLayerParent* shadow = AsShadowLayer(op);
       ShadowThebesLayer* thebes =
         static_cast<ShadowThebesLayer*>(shadow->AsLayer());
       const ThebesBuffer& newFront = op.newFrontBuffer();
 
       ThebesBuffer newBack;
       nsIntRegion newValidRegion;
       float newXResolution, newYResolution;
+      OptionalThebesBuffer readonlyFront;
+      nsIntRegion frontUpdatedRegion;
       thebes->Swap(newFront, op.updatedRegion(),
-                   &newBack, &newValidRegion, &newXResolution, &newYResolution);
+                   &newBack, &newValidRegion, &newXResolution, &newYResolution,
+                   &readonlyFront, &frontUpdatedRegion);
       replyv.push_back(
         OpThebesBufferSwap(
           shadow, NULL,
-          newBack, newValidRegion, newXResolution, newYResolution));
+          newBack, newValidRegion, newXResolution, newYResolution,
+          readonlyFront, frontUpdatedRegion));
       break;
     }
     case Edit::TOpPaintCanvas: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint CanvasLayer"));
 
       const OpPaintCanvas& op = edit.get_OpPaintCanvas();
       ShadowLayerParent* shadow = AsShadowLayer(op);
       ShadowCanvasLayer* canvas =
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -645,27 +645,31 @@ ShadowThebesLayerOGL::SetFrontBuffer(con
   mDeadweight = aNewFront.buffer();
 }
 
 void
 ShadowThebesLayerOGL::Swap(const ThebesBuffer& aNewFront,
                            const nsIntRegion& aUpdatedRegion,
                            ThebesBuffer* aNewBack,
                            nsIntRegion* aNewBackValidRegion,
-                           float* aNewXResolution, float* aNewYResolution)
+                           float* aNewXResolution, float* aNewYResolution,
+                           OptionalThebesBuffer* aReadOnlyFront,
+                           nsIntRegion* aFrontUpdatedRegion)
 {
   if (!mDestroyed && mBuffer) {
     nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront.buffer());
     mBuffer->Upload(surf, aUpdatedRegion, aNewFront.rect(), aNewFront.rotation());
   }
 
   *aNewBack = aNewFront;
   *aNewBackValidRegion = mValidRegion;
   *aNewXResolution = 1.0;
   *aNewYResolution = 1.0;
+  *aReadOnlyFront = null_t();
+  aFrontUpdatedRegion->SetEmpty();
 }
 
 void
 ShadowThebesLayerOGL::DestroyFrontBuffer()
 {
   mBuffer = nsnull;
   if (SurfaceDescriptor::T__None != mDeadweight.type()) {
     mOGLManager->DestroySharedSurface(&mDeadweight, mAllocator);
--- a/gfx/layers/opengl/ThebesLayerOGL.h
+++ b/gfx/layers/opengl/ThebesLayerOGL.h
@@ -96,17 +96,18 @@ public:
 
   // ShadowThebesLayer impl
   virtual void SetFrontBuffer(const ThebesBuffer& aNewFront,
                               const nsIntRegion& aValidRegion,
                               float aXResolution, float aYResolution);
   virtual void
   Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
        ThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
-       float* aNewXResolution, float* aNewYResolution);
+       float* aNewXResolution, float* aNewYResolution,
+       OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
   virtual void DestroyFrontBuffer();
 
   // LayerOGL impl
   void Destroy();
   Layer* GetLayer();
   virtual PRBool IsEmpty();
   virtual void RenderLayer(int aPreviousFrameBuffer,
                            const nsIntPoint& aOffset);