Bug 780920, part 3: The ultimate compositor has to draw to the readback surface; shadow layers doesn't have access to all the needed rendering state. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Thu, 04 Oct 2012 00:05:24 -0700
changeset 109328 c18ffc64e3d0e43d36c12da6432e43935e4946b7
parent 109327 abefcbf2f2ee3b3feefe42fcae7e8b142255e057
child 109329 984026798238b2a6de2452982d8f30a02e04c951
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersroc
bugs780920
milestone18.0a1
Bug 780920, part 3: The ultimate compositor has to draw to the readback surface; shadow layers doesn't have access to all the needed rendering state. r=roc
gfx/layers/basic/BasicLayerManager.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
gfx/layers/ipc/PGrallocBuffer.ipdl
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.cpp
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
gfx/layers/ipc/ShadowLayersParent.h
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -18,16 +18,17 @@
 
 #define PIXMAN_DONT_DEFINE_STDINT
 #include "pixman.h"
 
 #include "BasicTiledThebesLayer.h"
 #include "BasicLayersImpl.h"
 #include "BasicThebesLayer.h"
 #include "BasicContainerLayer.h"
+#include "CompositorChild.h"
 #include "mozilla/Preferences.h"
 #include "nsIWidget.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace layers {
@@ -1098,23 +1099,24 @@ BasicShadowLayerManager::BeginTransactio
       }
     }
 
     // If we have a non-default target, we need to let our shadow manager draw
     // to it. This will happen at the end of the transaction.
     if (aTarget && (aTarget != mDefaultTarget) &&
         XRE_GetProcessType() == GeckoProcessType_Default) {
       mShadowTarget = aTarget;
-
-      // Create a temporary target for ourselves, so that mShadowTarget is only
-      // drawn to by our shadow manager.
-      nsRefPtr<gfxASurface> targetSurface = gfxPlatform::GetPlatform()->
-        CreateOffscreenSurface(aTarget->OriginalSurface()->GetSize(),
-                               aTarget->OriginalSurface()->GetContentType());
-      targetContext = new gfxContext(targetSurface);
+      // Create a temporary target for ourselves, so that
+      // mShadowTarget is only drawn to for the window snapshot.
+      nsRefPtr<gfxASurface> dummy =
+        gfxPlatform::GetPlatform()->CreateOffscreenSurface(
+          gfxIntSize(1, 1),
+          aTarget->OriginalSurface()->GetContentType());
+      mDummyTarget = new gfxContext(dummy);
+      aTarget = mDummyTarget;
     }
   }
   BasicLayerManager::BeginTransactionWithTarget(aTarget);
 }
 
 void
 BasicShadowLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
                                         void* aCallbackData,
@@ -1123,19 +1125,40 @@ BasicShadowLayerManager::EndTransaction(
   BasicLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
   ForwardTransaction();
 
   if (mRepeatTransaction) {
     mRepeatTransaction = false;
     BasicLayerManager::BeginTransaction();
     BasicShadowLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
   } else if (mShadowTarget) {
-    // Draw to shadow target at the recursion tail of the repeat transactions
-    ShadowLayerForwarder::ShadowDrawToTarget(mShadowTarget);
+    if (mWidget) {
+      if (CompositorChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
+        nsRefPtr<gfxASurface> target = mShadowTarget->OriginalSurface();
+        SurfaceDescriptor inSnapshot, snapshot;
+        if (AllocBuffer(target->GetSize(), target->GetContentType(),
+                        &inSnapshot) &&
+            // The compositor will usually reuse |snapshot| and return
+            // it through |outSnapshot|, but if it doesn't, it's
+            // responsible for freeing |snapshot|.
+            remoteRenderer->SendMakeSnapshot(inSnapshot, &snapshot)) {
+          AutoOpenSurface opener(OPEN_READ_ONLY, snapshot);
+          gfxASurface* source = opener.Get();
+
+          gfxContextAutoSaveRestore restore(mShadowTarget);
+          mShadowTarget->SetOperator(gfxContext::OPERATOR_OVER);
+          mShadowTarget->DrawSurface(source, source->GetSize());
+        }
+        if (IsSurfaceDescriptorValid(snapshot)) {
+          ShadowLayerForwarder::DestroySharedSurface(&snapshot);
+        }
+      }
+    }
     mShadowTarget = nullptr;
+    mDummyTarget = nullptr;
   }
 }
 
 bool
 BasicShadowLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
 {
   if (!BasicLayerManager::EndEmptyTransaction(aFlags)) {
     // Return without calling ForwardTransaction. This leaves the
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -188,18 +188,26 @@ protected:
 
   // Widget whose surface should be used as the basis for ThebesLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
-  // A context we want our shadow to draw into.
+  // When we're doing a transaction in order to draw to a non-default
+  // target, the layers transaction is only performed in order to send
+  // a PLayers:Update.  We save the original non-default target to
+  // mShadowTarget, and then perform the transaction using
+  // mDummyTarget as the render target.  After the transaction ends,
+  // we send a message to our remote side to capture the actual pixels
+  // being drawn to the default target, and then copy those pixels
+  // back to mShadowTarget.
   nsRefPtr<gfxContext> mShadowTarget;
+  nsRefPtr<gfxContext> mDummyTarget;
   // Image factory we use.
   nsRefPtr<ImageFactory> mFactory;
 
   // Cached surface for double buffering
   gfxCachedTempSurface mCachedSurface;
 
   BufferMode mDoubleBuffering;
   bool mUsingDefaultTarget;
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -40,16 +40,23 @@ protected:
   virtual PLayersChild* AllocPLayers(const LayersBackend& aBackendHint,
                                      const uint64_t& aId,
                                      LayersBackend* aBackend,
                                      int* aMaxTextureSize);
   virtual bool DeallocPLayers(PLayersChild *aChild);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
+  virtual PGrallocBufferChild* AllocPGrallocBuffer(
+    const gfxIntSize&, const uint32_t&, const uint32_t&,
+    MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE
+  { return nullptr; }
+  virtual bool DeallocPGrallocBuffer(PGrallocBufferChild*)
+  { return false; }
+
 private:
   nsRefPtr<LayerManager> mLayerManager;
 
   // When we're in a child process, this is the process-global
   // compositor that we use to forward transactions directly to the
   // compositor context in another process.
   static CompositorChild* sCompositor;
 
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -9,16 +9,17 @@
 #include "base/basictypes.h"
 
 #if defined(MOZ_WIDGET_ANDROID)
 # include <android/log.h>
 # include "AndroidBridge.h"
 #endif
 
 #include "AsyncPanZoomController.h"
+#include "AutoOpenSurface.h"
 #include "BasicLayers.h"
 #include "CompositorParent.h"
 #include "LayerManagerOGL.h"
 #include "nsGkAtoms.h"
 #include "nsIWidget.h"
 #include "RenderTrace.h"
 #include "ShadowLayersParent.h"
 #include "BasicLayers.h"
@@ -248,16 +249,27 @@ CompositorParent::RecvPause()
 
 bool
 CompositorParent::RecvResume()
 {
   ResumeComposition();
   return true;
 }
 
+bool
+CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+                                   SurfaceDescriptor* aOutSnapshot)
+{
+  AutoOpenSurface opener(OPEN_READ_WRITE, aInSnapshot);
+  nsRefPtr<gfxContext> target = new gfxContext(opener.Get());
+  ComposeToTarget(target);
+  *aOutSnapshot = aInSnapshot;
+  return true;
+}
+
 void
 CompositorParent::ScheduleRenderOnCompositorThread()
 {
   CancelableTask *renderTask = NewRunnableMethod(this, &CompositorParent::ScheduleComposition);
   CompositorLoop()->PostTask(FROM_HERE, renderTask);
 }
 
 void
@@ -488,21 +500,21 @@ private:
   AutoResolveRefLayers& operator=(const AutoResolveRefLayers&) MOZ_DELETE;
 };
 
 void
 CompositorParent::Composite()
 {
   NS_ABORT_IF_FALSE(CompositorThreadID() == PlatformThread::CurrentId(),
                     "Composite can only be called on the compositor thread");
-  mCurrentCompositeTask = NULL;
+  mCurrentCompositeTask = nullptr;
 
   mLastCompose = TimeStamp::Now();
 
-  if (mPaused || !mLayerManager || !mLayerManager->GetRoot()) {
+  if (!CanComposite()) {
     return;
   }
 
   Layer* layer = mLayerManager->GetRoot();
   AutoResolveRefLayers resolve(layer);
 
   bool requestNextFrame = TransformShadowTree(mLastCompose);
   if (requestNextFrame) {
@@ -523,16 +535,34 @@ CompositorParent::Composite()
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   if (mExpectedComposeTime + TimeDuration::FromMilliseconds(15) < TimeStamp::Now()) {
     printf_stderr("Compositor: Composite took %i ms.\n",
                   15 + (int)(TimeStamp::Now() - mExpectedComposeTime).ToMilliseconds());
   }
 #endif
 }
 
+void
+CompositorParent::ComposeToTarget(gfxContext* aTarget)
+{
+  if (!CanComposite()) {
+    return;
+  }
+  mLayerManager->BeginTransactionWithTarget(aTarget);
+  // Since CanComposite() is true, Composite() must end the layers txn
+  // we opened above.
+  Composite();
+}
+
+bool
+CompositorParent::CanComposite()
+{
+  return !(mPaused || !mLayerManager || !mLayerManager->GetRoot());
+}
+
 // Do a breadth-first search to find the first layer in the tree that is
 // scrollable.
 static void
 Translate2D(gfx3DMatrix& aTransform, const gfxPoint& aOffset)
 {
   aTransform._41 += aOffset.x;
   aTransform._42 += aOffset.y;
 }
@@ -1113,27 +1143,37 @@ public:
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   // FIXME/bug 774388: work out what shutdown protocol we need.
   virtual bool RecvWillStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvStop() MOZ_OVERRIDE { return true; }
   virtual bool RecvPause() MOZ_OVERRIDE { return true; }
   virtual bool RecvResume() MOZ_OVERRIDE { return true; }
+  virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+                                SurfaceDescriptor* aOutSnapshot)
+  { return true; }
 
   virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendType,
                                       const uint64_t& aId,
                                       LayersBackend* aBackend,
                                       int32_t* aMaxTextureSize) MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
                                    const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
 
+  virtual PGrallocBufferParent* AllocPGrallocBuffer(
+    const gfxIntSize&, const uint32_t&, const uint32_t&,
+    MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE
+  { return nullptr; }
+  virtual bool DeallocPGrallocBuffer(PGrallocBufferParent*)
+  { return false; }
+
 private:
   void DeferredDestroy();
 
   // There can be many CPCPs, and IPDL-generated code doesn't hold a
   // reference to top-level actors.  So we hold a reference to
   // ourself.  This is released (deferred) in ActorDestroy().
   nsRefPtr<CrossProcessCompositorParent> mSelfRef;
 };
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -64,16 +64,18 @@ public:
                    int aSurfaceWidth = -1, int aSurfaceHeight = -1);
 
   virtual ~CompositorParent();
 
   virtual bool RecvWillStop() MOZ_OVERRIDE;
   virtual bool RecvStop() MOZ_OVERRIDE;
   virtual bool RecvPause() MOZ_OVERRIDE;
   virtual bool RecvResume() MOZ_OVERRIDE;
+  virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
+                                SurfaceDescriptor* aOutSnapshot);
 
   virtual void ShadowLayersUpdated(ShadowLayersParent* aLayerTree,
                                    const TargetConfig& aTargetConfig,
                                    bool isFirstPaint) MOZ_OVERRIDE;
   void Destroy();
 
   LayerManager* GetLayerManager() { return mLayerManager; }
 
@@ -152,16 +154,17 @@ public:
 protected:
   virtual PLayersParent* AllocPLayers(const LayersBackend& aBackendHint,
                                       const uint64_t& aId,
                                       LayersBackend* aBackend,
                                       int32_t* aMaxTextureSize);
   virtual bool DeallocPLayers(PLayersParent* aLayers);
   virtual void ScheduleTask(CancelableTask*, int);
   virtual void Composite();
+  virtual void ComposeToTarget(gfxContext* aTarget);
   virtual void SetFirstPaintViewport(const nsIntPoint& aOffset, float aZoom, const nsIntRect& aPageRect, const gfx::Rect& aCssPageRect);
   virtual void SetPageRect(const gfx::Rect& aCssPageRect);
   virtual void SyncViewportInfo(const nsIntRect& aDisplayPort, float aDisplayResolution, bool aLayersUpdated,
                                 nsIntPoint& aScrollOffset, float& aScaleX, float& aScaleY);
   void SetEGLSurfaceSize(int width, int height);
 
 private:
   void PauseComposition();
@@ -213,29 +216,41 @@ private:
    * Add a compositor to the global compositor map.
    */
   static void AddCompositor(CompositorParent* compositor, uint64_t* id);
   /**
    * Remove a compositor from the global compositor map.
    */
   static CompositorParent* RemoveCompositor(uint64_t id);
 
+   /**
+   * Return true if current state allows compositing, that is
+   * finishing a layers transaction.
+   */
+  bool CanComposite();
 
   // Platform specific functions
   /**
    * Recursively applies the given translation to all top-level fixed position
    * layers that are descendants of the given layer.
    * aScaleDiff is considered to be the scale transformation applied when
    * displaying the layers, and is used to make sure the anchor points of
    * fixed position layers remain in the same position.
    */
   void TransformFixedLayers(Layer* aLayer,
                             const gfxPoint& aTranslation,
                             const gfxPoint& aScaleDiff);
 
+  virtual PGrallocBufferParent* AllocPGrallocBuffer(
+    const gfxIntSize&, const uint32_t&, const uint32_t&,
+    MaybeMagicGrallocBufferHandle*) MOZ_OVERRIDE
+  { return nullptr; }
+  virtual bool DeallocPGrallocBuffer(PGrallocBufferParent*)
+  { return false; }
+
   nsRefPtr<LayerManager> mLayerManager;
   nsIWidget* mWidget;
   TargetConfig mTargetConfig;
   CancelableTask *mCurrentCompositeTask;
   TimeStamp mLastCompose;
 #ifdef COMPOSITOR_PERFORMANCE_WARNING
   TimeStamp mExpectedComposeTime;
 #endif
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -1,15 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+include LayersSurfaces;
+include protocol PGrallocBuffer;
 include protocol PLayers;
 
 using mozilla::layers::LayersBackend;
 using mozilla::null_t;
 
 namespace mozilla {
 namespace layers {
 
@@ -17,30 +19,45 @@ namespace layers {
  * The PCompositor protocol is used to manage communication between
  * the main thread and the compositor thread context. It's primary
  * purpose is to manage the PLayers sub protocol.
  */
 // This should really be 'sync', but we're using 'rpc' as a workaround
 // for Bug 716631.
 rpc protocol PCompositor
 {
+  manages PGrallocBuffer;
   // A Compositor manages a single Layer Manager (PLayers)
   manages PLayers;
 
 parent:  
 
   // The child is about to be destroyed, so perform any necessary cleanup.
   sync WillStop();
 
   // Clean up in preparation for own destruction.
   sync Stop();
 
   // Pause/resume the compositor. These are intended to be used on mobile, when
   // the compositor needs to pause/resume in lockstep with the application.
   sync Pause();
   sync Resume();
 
+  // Make a snapshot of the content that would have been drawn to our
+  // render target at the time this message is received.  If the size
+  // or format of |inSnapshot| doesn't match our render target,
+  // results are undefined.
+  //
+  // NB: this message will result in animations, transforms, effects,
+  // and so forth being interpolated.  That's what we want to happen.
+  sync MakeSnapshot(SurfaceDescriptor inSnapshot)
+    returns (SurfaceDescriptor outSnapshot);
+
   sync PLayers(LayersBackend backendHint, uint64_t id)
     returns (LayersBackend backend, int32_t maxTextureSize);
+
+  // FIXME/bug 783451
+  sync PGrallocBuffer(gfxIntSize size, uint32_t format, uint32_t usage)
+    returns (MaybeMagicGrallocBufferHandle handle);
 };
 
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/PGrallocBuffer.ipdl
+++ b/gfx/layers/ipc/PGrallocBuffer.ipdl
@@ -1,31 +1,32 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=8 et :
  */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+include protocol PCompositor;
 include protocol PImageBridge;
 include protocol PImageContainer;
 include protocol PLayers;
 
 namespace mozilla {
 namespace layers {
 
 /**
  * This is a trivial protocol that's used to track gralloc buffers
  * across thread contexts.  A live PGrallocBuffer actor always
  * corresponds 1:1 to a pre-shared gralloc buffer (sharing is done by
  * the PGrallocBuffer constructor).
  */
 async protocol PGrallocBuffer {
-  /* FIXME: Bug 783451: shouldn't be managed by PImageContainer */
-  manager PImageBridge or PImageContainer or PLayers;
+  // FIXME: Bug 783451: shouldn't be managed by PCompositor or PImageContainer
+  manager PCompositor or PImageBridge or PImageContainer or PLayers;
 
   /** Gralloc buffers can be "owned" by either parent or child. */
 both:
   async __delete__();
 };
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -319,20 +319,16 @@ parent:
     returns (MaybeMagicGrallocBufferHandle handle);
   async PLayer();
 
   // The isFirstPaint flag can be used to indicate that this is the first update
   // for a particular document.
   sync Update(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint)
     returns (EditReply[] reply);
 
-  // Composite the layer tree to the given surface, and return the surface.
-  sync DrawToSurface(SurfaceDescriptor surfaceIn)
-    returns (SurfaceDescriptor surfaceOut);
-
   // We don't need to send a sync transaction if
   // no transaction operate require a swap.
   async UpdateNoSwap(Edit[] cset, TargetConfig targetConfig, bool isFirstPaint);
 
   async __delete__();
 };
 
 } // namespace layers
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -372,38 +372,16 @@ ShadowLayerForwarder::EndTransaction(Inf
     }
   }
 
   mIsFirstPaint = false;
   MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
   return true;
 }
 
-bool
-ShadowLayerForwarder::ShadowDrawToTarget(gfxContext* aTarget) {
-
-  SurfaceDescriptor descriptorIn, descriptorOut;
-  AllocBuffer(aTarget->OriginalSurface()->GetSize(),
-              aTarget->OriginalSurface()->GetContentType(),
-              &descriptorIn);
-  if (!mShadowManager->SendDrawToSurface(descriptorIn, &descriptorOut)) {
-    return false;
-  }
-
-  nsRefPtr<gfxASurface> surface = OpenDescriptor(OPEN_READ_WRITE, descriptorOut);
-  aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
-  aTarget->DrawSurface(surface, surface->GetSize());
-
-  surface = nullptr;
-  DestroySharedSurface(&descriptorOut);
-
-  return true;
-}
-
-
 SharedMemory::SharedMemoryType
 OptimalShmemType()
 {
 #if defined(MOZ_PLATFORM_MAEMO) && defined(MOZ_HAVE_SHAREDMEMORYSYSV)
   // Use SysV memory because maemo5 on the N900 only allots 64MB to
   // /dev/shm, even though it has 1GB(!!) of system memory.  Sys V shm
   // is allocated from a different pool.  We don't want an arbitrary
   // cap that's much much lower than available memory on the memory we
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -221,21 +221,16 @@ public:
   /**
    * End the current transaction and forward it to ShadowLayerManager.
    * |aReplies| are directions from the ShadowLayerManager to the
    * caller of EndTransaction().
    */
   bool EndTransaction(InfallibleTArray<EditReply>* aReplies);
 
   /**
-   * Composite ShadowLayerManager's layer tree into aTarget.
-   */
-  bool ShadowDrawToTarget(gfxContext* aTarget);
-
-  /**
    * Set an actor through which layer updates will be pushed.
    */
   void SetShadowManager(PLayersChild* aShadowManager)
   {
     mShadowManager = aShadowManager;
   }
 
   void SetParentBackendType(LayersBackend aBackendType)
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -476,40 +476,16 @@ ShadowLayersParent::RecvUpdate(const Inf
   if (compositeTime > 15) {
     printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n", compositeTime);
   }
 #endif
 
   return true;
 }
 
-bool
-ShadowLayersParent::RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
-                                      SurfaceDescriptor* surfaceOut)
-{
-  *surfaceOut = surfaceIn;
-  if (mDestroyed || layer_manager()->IsDestroyed()) {
-    return true;
-  }
-
-  AutoOpenSurface sharedSurface(OPEN_READ_WRITE, surfaceIn);
-
-  nsRefPtr<gfxASurface> localSurface =
-    gfxPlatform::GetPlatform()->CreateOffscreenSurface(sharedSurface.Size(),
-                                                       sharedSurface.ContentType());
-  nsRefPtr<gfxContext> context = new gfxContext(localSurface);
-
-  layer_manager()->BeginTransactionWithTarget(context);
-  layer_manager()->EndTransaction(NULL, NULL);
-  nsRefPtr<gfxContext> contextForCopy = new gfxContext(sharedSurface.Get());
-  contextForCopy->SetOperator(gfxContext::OPERATOR_SOURCE);
-  contextForCopy->DrawSurface(localSurface, localSurface->GetSize());
-  return true;
-}
-
 PGrallocBufferParent*
 ShadowLayersParent::AllocPGrallocBuffer(const gfxIntSize& aSize,
                                         const gfxContentType& aContent,
                                         MaybeMagicGrallocBufferHandle* aOutHandle)
 {
 #ifdef MOZ_HAVE_SURFACEDESCRIPTORGRALLOC
   return GrallocBufferActor::Create(aSize, aContent, aOutHandle);
 #else
--- a/gfx/layers/ipc/ShadowLayersParent.h
+++ b/gfx/layers/ipc/ShadowLayersParent.h
@@ -47,19 +47,16 @@ public:
   virtual void DestroySharedSurface(SurfaceDescriptor* aSurface);
 
 protected:
   virtual bool RecvUpdate(const EditArray& cset,
                           const TargetConfig& targetConfig,
                           const bool& isFirstPaint,
                           EditReplyArray* reply) MOZ_OVERRIDE;
 
-  virtual bool RecvDrawToSurface(const SurfaceDescriptor& surfaceIn,
-                                 SurfaceDescriptor* surfaceOut) MOZ_OVERRIDE;
-
   virtual bool RecvUpdateNoSwap(const EditArray& cset,
                                 const TargetConfig& targetConfig,
                                 const bool& isFirstPaint) MOZ_OVERRIDE;
 
   virtual PGrallocBufferParent*
   AllocPGrallocBuffer(const gfxIntSize& aSize, const gfxContentType& aContent,
                       MaybeMagicGrallocBufferHandle* aOutHandle) MOZ_OVERRIDE;
   virtual bool