From 8617d00c98fe3b148f695449a0b3e92b1c336709 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 11 Mar 2011 23:22:39 -0600 Subject: [PATCH] Bug 640444: Self-copies end up changing all buffer content, so we need to read back the entire buffer after swapping. r=Bas a=b --- gfx/layers/ThebesLayerBuffer.cpp | 2 ++ gfx/layers/ThebesLayerBuffer.h | 4 +++- gfx/layers/basic/BasicLayers.cpp | 11 ++++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gfx/layers/ThebesLayerBuffer.cpp b/gfx/layers/ThebesLayerBuffer.cpp index 5492d19c9137..0d2480b64621 100644 --- a/gfx/layers/ThebesLayerBuffer.cpp +++ b/gfx/layers/ThebesLayerBuffer.cpp @@ -222,6 +222,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, PRUint32 aFlags) { PaintState result; + result.mDidSelfCopy = PR_FALSE; float curXRes = aLayer->GetXResolution(); float curYRes = aLayer->GetYResolution(); @@ -336,6 +337,7 @@ ThebesLayerBuffer::BeginPaint(ThebesLayer* aLayer, ContentType aContentType, nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size()); nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft(); MovePixels(mBuffer, srcRect, dest, curXRes, curYRes); + result.mDidSelfCopy = PR_TRUE; // Don't set destBuffer; we special-case self-copies, and // just did the necessary work above. mBufferRect = destBufferRect; diff --git a/gfx/layers/ThebesLayerBuffer.h b/gfx/layers/ThebesLayerBuffer.h index 879eca6de7fd..dff6bb37a41f 100644 --- a/gfx/layers/ThebesLayerBuffer.h +++ b/gfx/layers/ThebesLayerBuffer.h @@ -110,12 +110,14 @@ public: * by ThebesLayerBuffer and must be redrawn on the screen. * mRegionToInvalidate is set when the buffer has changed from * opaque to transparent or vice versa, since the details of rendering can - * depend on the buffer type. + * depend on the buffer type. mDidSelfCopy is true if we kept our buffer + * but used MovePixels() to shift its content. */ struct PaintState { nsRefPtr mContext; nsIntRegion mRegionToDraw; nsIntRegion mRegionToInvalidate; + PRPackedBool mDidSelfCopy; }; enum { diff --git a/gfx/layers/basic/BasicLayers.cpp b/gfx/layers/basic/BasicLayers.cpp index b319fbf430d8..6f7f31936aa2 100644 --- a/gfx/layers/basic/BasicLayers.cpp +++ b/gfx/layers/basic/BasicLayers.cpp @@ -428,6 +428,7 @@ protected: const nsIntRegion& aRegionToDraw, const nsIntRegion& aExtendedRegionToDraw, const nsIntRegion& aRegionToInvalidate, + PRBool aDidSelfCopy, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData) { @@ -608,6 +609,7 @@ BasicThebesLayer::PaintThebes(gfxContext* aContext, SetAntialiasingFlags(this, state.mContext); PaintBuffer(state.mContext, state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate, + state.mDidSelfCopy, aCallback, aCallbackData); Mutated(); } else { @@ -1800,6 +1802,7 @@ private: const nsIntRegion& aRegionToDraw, const nsIntRegion& aExtendedRegionToDraw, const nsIntRegion& aRegionToInvalidate, + PRBool aDidSelfCopy, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData); @@ -1860,21 +1863,27 @@ BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext, const nsIntRegion& aRegionToDraw, const nsIntRegion& aExtendedRegionToDraw, const nsIntRegion& aRegionToInvalidate, + PRBool aDidSelfCopy, LayerManager::DrawThebesLayerCallback aCallback, void* aCallbackData) { Base::PaintBuffer(aContext, aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate, + aDidSelfCopy, aCallback, aCallbackData); if (!HasShadow()) { return; } nsIntRegion updatedRegion; - if (mIsNewBuffer) { + if (mIsNewBuffer || aDidSelfCopy) { // A buffer reallocation clears both buffers. The front buffer has all the // content by now, but the back buffer is still clear. Here, in effect, we // are saying to copy all of the pixels of the front buffer to the back. + // Also when we self-copied in the buffer, the buffer space + // changes and some changed buffer content isn't reflected in the + // draw or invalidate region (on purpose!). When this happens, we + // need to read back the entire buffer too. updatedRegion = mVisibleRegion; mIsNewBuffer = false; } else {