Bug 570294, part i: Publish BasicImageLayer pixels to remote processes (slowly). r=Bas
authorChris Jones <jones.chris.g@gmail.com>
Wed, 21 Jul 2010 16:17:33 -0500
changeset 48142 77ceebc9b2f33c8e866da48be5c2f8524dde5acf
parent 48141 507ad177534a2027c077c2639c8707272b3af889
child 48143 595b4c395ba21affefb53c3db40846241ea92571
push id14589
push usercjones@mozilla.com
push dateFri, 23 Jul 2010 17:12:29 +0000
treeherdermozilla-central@49185ce20807 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs570294
milestone2.0b3pre
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 570294, part i: Publish BasicImageLayer pixels to remote processes (slowly). r=Bas
gfx/layers/basic/BasicLayers.cpp
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -106,17 +106,17 @@ public:
    * set up to account for all the properties of the layer (transform,
    * opacity, etc).
    */
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
                      float aOpacity) {}
 
-  virtual ShadowableLayer* AsShadowableLayer() { return NULL; }
+  virtual ShadowableLayer* AsShadowableLayer() { return nsnull; }
 };
 
 static BasicImplData*
 ToData(Layer* aLayer)
 {
   return static_cast<BasicImplData*>(aLayer->ImplData());
 }
 
@@ -420,65 +420,92 @@ public:
     ImageLayer::SetVisibleRegion(aRegion);
   }
 
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
                      float aOpacity);
 
+  static void PaintContext(gfxPattern* aPattern,
+                           const gfxIntSize& aSize,
+                           float aOpacity,
+                           gfxContext* aContext);
+
 protected:
   BasicLayerManager* BasicManager()
   {
     return static_cast<BasicLayerManager*>(mManager);
   }
+
+  already_AddRefed<gfxPattern>
+  GetAndPaintCurrentImage(gfxContext* aContext,
+                          float aOpacity);
+
+  gfxIntSize mSize;
 };
 
 void
 BasicImageLayer::Paint(gfxContext* aContext,
                        LayerManager::DrawThebesLayerCallback aCallback,
                        void* aCallbackData,
                        float aOpacity)
 {
-  if (!mContainer)
-    return;
+  nsRefPtr<gfxPattern> dontcare = GetAndPaintCurrentImage(aContext, aOpacity);
+}
 
-  gfxIntSize size;
-  nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&size);
+already_AddRefed<gfxPattern>
+BasicImageLayer::GetAndPaintCurrentImage(gfxContext* aContext,
+                                         float aOpacity)
+{
+  if (!mContainer)
+    return nsnull;
+
+  nsRefPtr<gfxASurface> surface = mContainer->GetCurrentAsSurface(&mSize);
   if (!surface) {
-    return;
+    return nsnull;
   }
 
   nsRefPtr<gfxPattern> pat = new gfxPattern(surface);
   if (!pat) {
-    return;
+    return nsnull;
   }
 
   pat->SetFilter(mFilter);
 
+  PaintContext(pat, mSize, aOpacity, aContext); 
+  return pat.forget();
+}
+
+/*static*/ void
+BasicImageLayer::PaintContext(gfxPattern* aPattern,
+                              const gfxIntSize& aSize,
+                              float aOpacity,
+                              gfxContext* aContext)
+{
   // Set PAD mode so that when the video is being scaled, we do not sample
   // outside the bounds of the video image.
   gfxPattern::GraphicsExtend extend = gfxPattern::EXTEND_PAD;
 
   // PAD is slow with X11 and Quartz surfaces, so prefer speed over correctness
   // and use NONE.
   nsRefPtr<gfxASurface> target = aContext->CurrentSurface();
   gfxASurface::gfxSurfaceType type = target->GetType();
   if (type == gfxASurface::SurfaceTypeXlib ||
       type == gfxASurface::SurfaceTypeXcb ||
       type == gfxASurface::SurfaceTypeQuartz) {
     extend = gfxPattern::EXTEND_NONE;
   }
 
-  pat->SetExtend(extend);
+  aPattern->SetExtend(extend);
 
   /* Draw RGB surface onto frame */
   aContext->NewPath();
   aContext->PixelSnappedRectangleAndSetPattern(
-      gfxRect(0, 0, size.width, size.height), pat);
+      gfxRect(0, 0, aSize.width, aSize.height), aPattern);
   if (aOpacity != 1.0) {
     aContext->Save();
     aContext->Clip();
     aContext->Paint(aOpacity);
     aContext->Restore();
   } else {
     aContext->Fill();
   }
@@ -1128,17 +1155,17 @@ private:
 };
 
 void
 BasicShadowableContainerLayer::InsertAfter(Layer* aChild, Layer* aAfter)
 {
   if (HasShadow()) {
     ShadowManager()->InsertAfter(ShadowManager()->Hold(this),
                                  ShadowManager()->Hold(aChild),
-                                 aAfter ? ShadowManager()->Hold(aAfter) : NULL);
+                                 aAfter ? ShadowManager()->Hold(aAfter) : nsnull);
   }
   BasicContainerLayer::InsertAfter(aChild, aAfter);
 }
 
 void
 BasicShadowableContainerLayer::RemoveChild(Layer* aChild)
 {
   if (HasShadow()) {
@@ -1177,27 +1204,82 @@ class BasicShadowableImageLayer : public
 public:
   BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
     BasicImageLayer(aManager)
   {
     MOZ_COUNT_CTOR(BasicShadowableImageLayer);
   }
   virtual ~BasicShadowableImageLayer()
   {
+    if (mBackSurface) {
+      BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackSurface);
+    }
     MOZ_COUNT_DTOR(BasicShadowableImageLayer);
   }
 
+  virtual void Paint(gfxContext* aContext,
+                     LayerManager::DrawThebesLayerCallback aCallback,
+                     void* aCallbackData,
+                     float aOpacity);
+
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
     aAttrs = ImageLayerAttributes(mFilter);
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
+
+  virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
+  {
+    mBackSurface = aBuffer;
+  }
+
+private:
+  BasicShadowLayerManager* BasicManager()
+  {
+    return static_cast<BasicShadowLayerManager*>(mManager);
+  }
+
+  nsRefPtr<gfxSharedImageSurface> mBackSurface;
 };
+ 
+void
+BasicShadowableImageLayer::Paint(gfxContext* aContext,
+                                 LayerManager::DrawThebesLayerCallback aCallback,
+                                 void* aCallbackData,
+                                 float aOpacity)
+{
+  gfxIntSize oldSize = mSize;
+  nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, aOpacity);
+  if (!pat || !HasShadow())
+    return;
+
+  if (oldSize != mSize) {
+    NS_ASSERTION(oldSize == gfxIntSize(0, 0), "video changed size?");
+
+    nsRefPtr<gfxSharedImageSurface> tmpFrontSurface;
+    // XXX error handling?
+    if (!BasicManager()->AllocDoubleBuffer(
+          mSize, gfxASurface::ImageFormatARGB32,
+          getter_AddRefs(tmpFrontSurface), getter_AddRefs(mBackSurface)))
+      NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
+
+    BasicManager()->CreatedImageBuffer(BasicManager()->Hold(this),
+                                       nsIntSize(mSize.width, mSize.height),
+                                       tmpFrontSurface);
+  }
+
+  nsRefPtr<gfxContext> tmpCtx = new gfxContext(mBackSurface);
+  PaintContext(pat, mSize, 1.0, tmpCtx);
+
+  BasicManager()->PaintedImage(BasicManager()->Hold(this),
+                               mBackSurface);
+}
+
 
 class BasicShadowableColorLayer : public BasicColorLayer,
                                   public BasicShadowableLayer
 {
 public:
   BasicShadowableColorLayer(BasicShadowLayerManager* aManager) :
     BasicColorLayer(aManager)
   {
@@ -1223,18 +1305,19 @@ class BasicShadowableCanvasLayer : publi
 public:
   BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
     BasicCanvasLayer(aManager)
   {
     MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
   }
   virtual ~BasicShadowableCanvasLayer()
   {
-    if (mBackBuffer)
+    if (mBackBuffer) {
       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBuffer);
+    }
     MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
   }
 
   virtual void Initialize(const Data& aData);
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
                      float aOpacity);
@@ -1312,17 +1395,17 @@ public:
   {
     MOZ_COUNT_DTOR(BasicShadowThebesLayer);
   }
 
   virtual already_AddRefed<gfxSharedImageSurface>
   Swap(gfxSharedImageSurface* aNewFront,
        const nsIntRect& aBufferRect,
        const nsIntPoint& aRotation)
-  { return NULL; }
+  { return nsnull; }
 
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
                      float aOpacity)
   {}
 
   MOZ_LAYER_DECL_NAME("BasicShadowThebesLayer", TYPE_SHADOW)
@@ -1332,48 +1415,87 @@ class BasicShadowImageLayer : public Sha
 public:
   BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowImageLayer);
   }
   virtual ~BasicShadowImageLayer()
   {
+    if (mFrontSurface) {
+      BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
+    }
     MOZ_COUNT_DTOR(BasicShadowImageLayer);
   }
 
-  virtual PRBool Init(gfxSharedImageSurface* front, const nsIntSize& size)
-  { return PR_TRUE; }
+  virtual PRBool Init(gfxSharedImageSurface* front, const nsIntSize& size);
 
   virtual already_AddRefed<gfxSharedImageSurface>
-  Swap(gfxSharedImageSurface* newFront)
-  { return NULL; }
+  Swap(gfxSharedImageSurface* newFront);
 
   virtual void Paint(gfxContext* aContext,
                      LayerManager::DrawThebesLayerCallback aCallback,
                      void* aCallbackData,
-                     float aOpacity)
-  {}
+                     float aOpacity);
 
   MOZ_LAYER_DECL_NAME("BasicShadowImageLayer", TYPE_SHADOW)
+
+protected:
+  BasicShadowLayerManager* BasicManager()
+  {
+    return static_cast<BasicShadowLayerManager*>(mManager);
+  }
+
+  // XXX ShmemImage?
+  nsRefPtr<gfxSharedImageSurface> mFrontSurface;
+  gfxIntSize mSize;
 };
 
+PRBool
+BasicShadowImageLayer::Init(gfxSharedImageSurface* front,
+                            const nsIntSize& size)
+{
+  mFrontSurface = front;
+  mSize = gfxIntSize(size.width, size.height);
+  return PR_TRUE;
+}
+
+already_AddRefed<gfxSharedImageSurface>
+BasicShadowImageLayer::Swap(gfxSharedImageSurface* newFront)
+{
+  already_AddRefed<gfxSharedImageSurface> tmp = mFrontSurface.forget();
+  mFrontSurface = newFront;
+  return tmp;
+}
+
+void
+BasicShadowImageLayer::Paint(gfxContext* aContext,
+                             LayerManager::DrawThebesLayerCallback aCallback,
+                             void* aCallbackData,
+                             float aOpacity)
+{
+  nsRefPtr<gfxPattern> pat = new gfxPattern(mFrontSurface);
+  pat->SetFilter(mFilter);
+  BasicImageLayer::PaintContext(pat, mSize, aOpacity, aContext);
+}
+
 class BasicShadowCanvasLayer : public ShadowCanvasLayer,
                                BasicImplData
 {
 public:
   BasicShadowCanvasLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowCanvasLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowCanvasLayer);
   }
   virtual ~BasicShadowCanvasLayer()
   {
-    if (mFrontSurface)
+    if (mFrontSurface) {
       BasicManager()->ShadowLayerManager::DestroySharedSurface(mFrontSurface);
+    }
     MOZ_COUNT_DTOR(BasicShadowCanvasLayer);
   }
 
   virtual void Initialize(const Data& aData);
 
   virtual void Updated(const nsIntRect& aRect)
   {}