Bug 780260 - Add serial numbers to Images and use it to check if an image has been painted to its BasicShadowableImageLayer already. r=cjones
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 23 Aug 2012 12:08:26 +1200
changeset 105122 d76195e9e2b8c4ea553cd977dac86b73ac4d9108
parent 105121 6e3a0a5d61a3bfc2f489068a752733f15bb7fb68
child 105123 fdc76cb3b523191deb357accab5b24f2e22dad26
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
reviewerscjones
bugs780260
milestone17.0a1
Bug 780260 - Add serial numbers to Images and use it to check if an image has been painted to its BasicShadowableImageLayer already. r=cjones
gfx/layers/ImageContainer.cpp
gfx/layers/ImageContainer.h
gfx/layers/basic/BasicImageLayer.cpp
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -34,16 +34,18 @@ using namespace mozilla::ipc;
 using namespace android;
 using mozilla::gfx::DataSourceSurface;
 using mozilla::gfx::SourceSurface;
 
 
 namespace mozilla {
 namespace layers {
 
+PRInt32 Image::sSerialCounter = 0;
+
 already_AddRefed<Image>
 ImageFactory::CreateImage(const ImageFormat *aFormats,
                           uint32_t aNumFormats,
                           const gfxIntSize &,
                           BufferRecycleBin *aRecycleBin)
 {
   if (!aNumFormats) {
     return nullptr;
--- a/gfx/layers/ImageContainer.h
+++ b/gfx/layers/ImageContainer.h
@@ -75,26 +75,31 @@ public:
   virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
   virtual gfxIntSize GetSize() = 0;
 
   ImageBackendData* GetBackendData(LayersBackend aBackend)
   { return mBackendData[aBackend]; }
   void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
   { mBackendData[aBackend] = aData; }
 
+  PRInt32 GetSerial() { return mSerial; }
+
 protected:
   Image(void* aImplData, ImageFormat aFormat) :
     mImplData(aImplData),
+    mSerial(PR_ATOMIC_INCREMENT(&sSerialCounter)),
     mFormat(aFormat)
   {}
 
   nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
 
   void* mImplData;
+  PRInt32 mSerial;
   ImageFormat mFormat;
+  static PRInt32 sSerialCounter;
 };
 
 /**
  * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
  * want to recycle from one image to the next.It's a separate object from 
  * ImageContainer because images need to store a strong ref to their RecycleBin
  * and we must avoid creating a reference loop between an ImageContainer and
  * its active image.
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -172,17 +172,18 @@ BasicImageLayer::GetAsSurface(gfxASurfac
 }
 
 class BasicShadowableImageLayer : public BasicImageLayer,
                                   public BasicShadowableLayer
 {
 public:
   BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
     BasicImageLayer(aManager),
-    mBufferIsOpaque(false)
+    mBufferIsOpaque(false),
+    mLastPaintedImageSerial(0)
   {
     MOZ_COUNT_CTOR(BasicShadowableImageLayer);
   }
   virtual ~BasicShadowableImageLayer()
   {
     DestroyBackBuffer();
     MOZ_COUNT_DTOR(BasicShadowableImageLayer);
   }
@@ -241,16 +242,17 @@ private:
   // For YUV Images these are the 3 planes (Y, Cb and Cr),
   // for RGB images only mBackSurface is used.
   SurfaceDescriptor mBackBuffer;
   bool mBufferIsOpaque;
   SurfaceDescriptor mBackBufferY;
   SurfaceDescriptor mBackBufferU;
   SurfaceDescriptor mBackBufferV;
   gfxIntSize mCbCrSize;
+  PRInt32 mLastPaintedImageSerial;
 };
  
 void
 BasicShadowableImageLayer::Paint(gfxContext* aContext, Layer* aMaskLayer)
 {
   if (!HasShadow()) {
     BasicImageLayer::Paint(aContext, aMaskLayer);
     return;
@@ -369,27 +371,30 @@ BasicShadowableImageLayer::Paint(gfxCont
     }
     if (type != gfxASurface::CONTENT_ALPHA &&
         isOpaque) {
       type = gfxASurface::CONTENT_COLOR;
     }
 
     if (!BasicManager()->AllocBuffer(mSize, type, &mBackBuffer))
       NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
+  } else if (mLastPaintedImageSerial == image->GetSerial()) {
+    return;
   }
 
   AutoOpenSurface backSurface(OPEN_READ_WRITE, mBackBuffer);
   nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface.Get());
   tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
   PaintContext(pat,
                nsIntRegion(nsIntRect(0, 0, mSize.width, mSize.height)),
                1.0, tmpCtx, nullptr);
 
   BasicManager()->PaintedImage(BasicManager()->Hold(this),
                                mBackBuffer);
+  mLastPaintedImageSerial = image->GetSerial();
 }
 
 class BasicShadowImageLayer : public ShadowImageLayer, public BasicImplData {
 public:
   BasicShadowImageLayer(BasicShadowLayerManager* aLayerManager) :
     ShadowImageLayer(aLayerManager, static_cast<BasicImplData*>(this))
   {
     MOZ_COUNT_CTOR(BasicShadowImageLayer);