Bug 695406 - Reset IPC double buffers if the ContentType has changed. r=cjones
authorOleg Romashin <romaxa@gmail.com>, Matt Woodrow <mwoodrow@mozilla.com>
Fri, 21 Oct 2011 14:29:09 +1300
changeset 79704 75eaad17724f031b2fd2dc61ec999222a02363ef
parent 79703 1e9e171fc33da7afae98ea5be29082e52876ea35
child 79724 e79245e249c486bf7ebb3748846b4e2872a56b16
child 79726 c36c8203eefeb47cb8446cc2345066354477ff90
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs695406
milestone10.0a1
Bug 695406 - Reset IPC double buffers if the ContentType has changed. r=cjones
gfx/layers/basic/BasicLayers.cpp
gfx/layers/opengl/CanvasLayerOGL.cpp
gfx/layers/opengl/ImageLayerOGL.cpp
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -2384,17 +2384,18 @@ BasicShadowableThebesLayer::CreateBuffer
 }
 
 
 class BasicShadowableImageLayer : public BasicImageLayer,
                                   public BasicShadowableLayer
 {
 public:
   BasicShadowableImageLayer(BasicShadowLayerManager* aManager) :
-    BasicImageLayer(aManager)
+    BasicImageLayer(aManager),
+    mBufferIsOpaque(false)
   {
     MOZ_COUNT_CTOR(BasicShadowableImageLayer);
   }
   virtual ~BasicShadowableImageLayer()
   {
     DestroyBackBuffer();
     MOZ_COUNT_DTOR(BasicShadowableImageLayer);
   }
@@ -2446,16 +2447,17 @@ private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   // For YUV Images these are the 3 planes (Y, Cb and Cr),
   // for RGB images only mBackSurface is used.
   SurfaceDescriptor mBackBuffer;
+  bool mBufferIsOpaque;
   nsRefPtr<gfxSharedImageSurface> mBackBufferY;
   nsRefPtr<gfxSharedImageSurface> mBackBufferU;
   nsRefPtr<gfxSharedImageSurface> mBackBufferV;
   gfxIntSize mCbCrSize;
 };
  
 void
 BasicShadowableImageLayer::Paint(gfxContext* aContext)
@@ -2513,22 +2515,26 @@ BasicShadowableImageLayer::Paint(gfxCont
     return;
   }
 
   gfxIntSize oldSize = mSize;
   nsRefPtr<gfxPattern> pat = GetAndPaintCurrentImage(aContext, GetEffectiveOpacity());
   if (!pat || !HasShadow())
     return;
 
-  if (oldSize != mSize || !IsSurfaceDescriptorValid(mBackBuffer)) {
+  bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
+  if (oldSize != mSize || 
+      !IsSurfaceDescriptorValid(mBackBuffer) ||
+      isOpaque != mBufferIsOpaque) {
     DestroyBackBuffer();
+    mBufferIsOpaque = isOpaque;
 
     if (!BasicManager()->AllocBuffer(
           mSize,
-          (GetContentFlags() & CONTENT_OPAQUE) ?
+          isOpaque ?
             gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
           &mBackBuffer))
       NS_RUNTIMEABORT("creating ImageLayer 'front buffer' failed!");
   }
 
   nsRefPtr<gfxASurface> backSurface =
     BasicManager()->OpenDescriptor(mBackBuffer);
   nsRefPtr<gfxContext> tmpCtx = new gfxContext(backSurface);
@@ -2570,17 +2576,18 @@ public:
   }
 };
 
 class BasicShadowableCanvasLayer : public BasicCanvasLayer,
                                    public BasicShadowableLayer
 {
 public:
   BasicShadowableCanvasLayer(BasicShadowLayerManager* aManager) :
-    BasicCanvasLayer(aManager)
+    BasicCanvasLayer(aManager),
+    mBufferIsOpaque(false)
   {
     MOZ_COUNT_CTOR(BasicShadowableCanvasLayer);
   }
   virtual ~BasicShadowableCanvasLayer()
   {
     DestroyBackBuffer();
     MOZ_COUNT_DTOR(BasicShadowableCanvasLayer);
   }
@@ -2617,16 +2624,17 @@ public:
 
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
   SurfaceDescriptor mBackBuffer;
+  bool mBufferIsOpaque;
 };
 
 void
 BasicShadowableCanvasLayer::Initialize(const Data& aData)
 {
   BasicCanvasLayer::Initialize(aData);
   if (!HasShadow())
       return;
@@ -2646,20 +2654,24 @@ BasicShadowableCanvasLayer::Initialize(c
 void
 BasicShadowableCanvasLayer::Paint(gfxContext* aContext)
 {
   if (!HasShadow()) {
     BasicCanvasLayer::Paint(aContext);
     return;
   }
 
-  if (!IsSurfaceDescriptorValid(mBackBuffer)) {
+  bool isOpaque = (GetContentFlags() & CONTENT_OPAQUE);
+  if (!IsSurfaceDescriptorValid(mBackBuffer) ||
+      isOpaque != mBufferIsOpaque) {
+    DestroyBackBuffer();
+    mBufferIsOpaque = isOpaque;
     if (!BasicManager()->AllocBuffer(
         gfxIntSize(mBounds.width, mBounds.height),
-        (GetContentFlags() & CONTENT_OPAQUE) ?
+        isOpaque ?
           gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA,
         &mBackBuffer))
     NS_RUNTIMEABORT("creating CanvasLayer back buffer failed!");
   }
 
   nsRefPtr<gfxASurface> backSurface =
     BasicManager()->OpenDescriptor(mBackBuffer);
 
@@ -2938,17 +2950,23 @@ protected:
 
 void
 BasicShadowImageLayer::Swap(const SharedImage& aNewFront,
                             SharedImage* aNewBack)
 {
   nsRefPtr<gfxASurface> surface =
     BasicManager()->OpenDescriptor(aNewFront);
   // Destroy mFrontBuffer if size different
-  if (surface->GetSize() != mSize) {
+  bool needDrop = false;
+  if (IsSurfaceDescriptorValid(mFrontBuffer)) {
+    nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontBuffer);
+    needDrop = surface->GetSize() != mSize ||
+               surface->GetContentType() != front->GetContentType();
+  }
+  if (needDrop) {
     DestroyFrontBuffer();
     mSize = surface->GetSize();
   }
 
   // If mFrontBuffer
   if (IsSurfaceDescriptorValid(mFrontBuffer)) {
     *aNewBack = mFrontBuffer;
   } else {
@@ -3054,17 +3072,23 @@ BasicShadowCanvasLayer::Initialize(const
 void
 BasicShadowCanvasLayer::Swap(const CanvasSurface& aNewFront, bool needYFlip,
                              CanvasSurface* aNewBack)
 {
   nsRefPtr<gfxASurface> surface =
     BasicManager()->OpenDescriptor(aNewFront);
   // Destroy mFrontBuffer if size different
   gfxIntSize sz = surface->GetSize();
-  if (sz != gfxIntSize(mBounds.width, mBounds.height)) {
+  bool needDrop = false;
+  if (IsSurfaceDescriptorValid(mFrontSurface)) {
+    nsRefPtr<gfxASurface> front = BasicManager()->OpenDescriptor(mFrontSurface);
+    needDrop = sz != gfxIntSize(mBounds.width, mBounds.height) ||
+               surface->GetContentType() != front->GetContentType();
+  }
+  if (needDrop) {
     DestroyFrontBuffer();
     mBounds.SetRect(0, 0, sz.width, sz.height);
   }
 
   mNeedsYFlip = needYFlip;
   // If mFrontBuffer
   if (IsSurfaceDescriptorValid(mFrontSurface)) {
     *aNewBack = mFrontSurface;
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -319,17 +319,18 @@ ShadowCanvasLayerOGL::Init(const CanvasS
 void
 ShadowCanvasLayerOGL::Swap(const CanvasSurface& aNewFront,
                            bool needYFlip,
                            CanvasSurface* aNewBack)
 {
   if (!mDestroyed) {
     nsRefPtr<gfxASurface> surf = ShadowLayerForwarder::OpenDescriptor(aNewFront);
     gfxIntSize sz = surf->GetSize();
-    if (!mTexImage || mTexImage->GetSize() != sz) {
+    if (!mTexImage || mTexImage->GetSize() != sz ||
+        mTexImage->GetContentType() != surf->GetContentType()) {
       Init(aNewFront, needYFlip);
     }
     nsIntRegion updateRegion(nsIntRect(0, 0, sz.width, sz.height));
     mTexImage->DirectUpdate(surf, updateRegion);
   }
 
   *aNewBack = aNewFront;
 }
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -880,17 +880,18 @@ void
 ShadowImageLayerOGL::Swap(const SharedImage& aNewFront,
                           SharedImage* aNewBack)
 {
   if (!mDestroyed) {
     if (aNewFront.type() == SharedImage::TSurfaceDescriptor) {
       nsRefPtr<gfxASurface> surf =
         ShadowLayerForwarder::OpenDescriptor(aNewFront.get_SurfaceDescriptor());
       gfxIntSize size = surf->GetSize();
-      if (mSize != size || !mTexImage) {
+      if (mSize != size || !mTexImage ||
+          mTexImage->GetContentType() != surf->GetContentType()) {
         Init(aNewFront);
       }
       // XXX this is always just ridiculously slow
       nsIntRegion updateRegion(nsIntRect(0, 0, size.width, size.height));
       mTexImage->DirectUpdate(surf, updateRegion);
     } else {
       const YUVImage& yuv = aNewFront.get_YUVImage();