Bug 756601 - Fix bugs with OMTC component alpha. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 10 May 2013 09:02:50 +1200
changeset 138220 3ea8287825682040bdc96aeeabb35386400782b6
parent 138219 a260551434fe50e44d061639f75a82726fc49d08
child 138221 3dcf16f8f334ab5a607e4d92dd4cdc50c9590b6d
push id3752
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 17:21:10 +0000
treeherdermozilla-aurora@1580544aef0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs756601
milestone23.0a1
Bug 756601 - Fix bugs with OMTC component alpha. r=roc
gfx/layers/ThebesLayerBuffer.cpp
gfx/layers/ThebesLayerBuffer.h
--- a/gfx/layers/ThebesLayerBuffer.cpp
+++ b/gfx/layers/ThebesLayerBuffer.cpp
@@ -292,17 +292,17 @@ FillSurface(gfxASurface* aSurface, const
   nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
   ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
   gfxUtils::ClipToRegion(ctx, aRegion);
   ctx->SetColor(aColor);
   ctx->Paint();
 }
 
 already_AddRefed<gfxContext>
-ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource)
+ThebesLayerBuffer::GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource, nsIntPoint *aTopLeft)
 {
   EnsureBuffer();
 
   nsRefPtr<gfxContext> ctx;
   if (aSource == BUFFER_BOTH && HaveBufferOnWhite()) {
     EnsureBufferOnWhite();
     MOZ_ASSERT(mBuffer, "We don't support azure here yet");
     gfxASurface* surfaces[2] = { mBuffer, mBufferOnWhite };
@@ -337,16 +337,20 @@ ThebesLayerBuffer::GetContextForQuadrant
   int32_t xBoundary = mBufferRect.XMost() - mBufferRotation.x;
   int32_t yBoundary = mBufferRect.YMost() - mBufferRotation.y;
   XSide sideX = aBounds.XMost() <= xBoundary ? RIGHT : LEFT;
   YSide sideY = aBounds.YMost() <= yBoundary ? BOTTOM : TOP;
   nsIntRect quadrantRect = GetQuadrantRectangle(sideX, sideY);
   NS_ASSERTION(quadrantRect.Contains(aBounds), "Messed up quadrants");
   ctx->Translate(-gfxPoint(quadrantRect.x, quadrantRect.y));
 
+  if (aTopLeft) {
+    *aTopLeft = nsIntPoint(quadrantRect.x, quadrantRect.y);
+  }
+
   return ctx.forget();
 }
 
 gfxASurface::gfxContentType
 ThebesLayerBuffer::BufferContentType()
 {
   if (mBuffer) {
     return mBuffer->GetContentType();
@@ -561,16 +565,21 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
         // The stuff we need to redraw will wrap around an edge of the
         // buffer, so move the pixels we can keep into a position that
         // lets us redraw in just one quadrant.
         if (mBufferRotation == nsIntPoint(0,0)) {
           nsIntRect srcRect(nsIntPoint(0, 0), mBufferRect.Size());
           nsIntPoint dest = mBufferRect.TopLeft() - destBufferRect.TopLeft();
           if (mBuffer) {
             mBuffer->MovePixels(srcRect, dest);
+            if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
+              EnsureBufferOnWhite();
+              MOZ_ASSERT(mBufferOnWhite);
+              mBufferOnWhite->MovePixels(srcRect, dest);
+            }
           } else {
             RefPtr<SourceSurface> source = mDTBuffer->Snapshot();
             mDTBuffer->CopySurface(source,
                                    IntRect(srcRect.x, srcRect.y, srcRect.width, srcRect.height),
                                    IntPoint(dest.x, dest.y));
           }
           result.mDidSelfCopy = true;
           // Don't set destBuffer; we special-case self-copies, and
@@ -661,22 +670,24 @@ ThebesLayerBuffer::BeginPaint(ThebesLaye
   }
   NS_ASSERTION(canHaveRotation || mBufferRotation == nsIntPoint(0,0),
                "Rotation disabled, but we have nonzero rotation?");
 
   nsIntRegion invalidate;
   invalidate.Sub(aLayer->GetValidRegion(), destBufferRect);
   result.mRegionToInvalidate.Or(result.mRegionToInvalidate, invalidate);
 
-  result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH);
+  nsIntPoint topLeft;
+  result.mContext = GetContextForQuadrantUpdate(drawBounds, BUFFER_BOTH, &topLeft);
 
   if (mode == Layer::SURFACE_COMPONENT_ALPHA) {
     MOZ_ASSERT(mBuffer && mBufferOnWhite, "Must not be using azure!");
-    FillSurface(mBuffer, result.mRegionToDraw, result.mRegionToDraw.GetBounds().TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0));
-    FillSurface(mBufferOnWhite, result.mRegionToDraw, result.mRegionToDraw.GetBounds().TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0));
+    FillSurface(mBuffer, result.mRegionToDraw, topLeft, gfxRGBA(0.0, 0.0, 0.0, 1.0));
+    FillSurface(mBufferOnWhite, result.mRegionToDraw, topLeft, gfxRGBA(1.0, 1.0, 1.0, 1.0));
+    gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
   } else if (contentType == gfxASurface::CONTENT_COLOR_ALPHA && !isClear) {
     if (result.mContext->IsCairo()) {
       gfxUtils::ClipToRegionSnapped(result.mContext, result.mRegionToDraw);
       result.mContext->SetOperator(gfxContext::OPERATOR_CLEAR);
       result.mContext->Paint();
       result.mContext->SetOperator(gfxContext::OPERATOR_OVER);
     } else {
       nsIntRegionRectIterator iter(result.mRegionToDraw);
--- a/gfx/layers/ThebesLayerBuffer.h
+++ b/gfx/layers/ThebesLayerBuffer.h
@@ -310,19 +310,21 @@ protected:
       mBufferOnWhite = nullptr;
       mDTBufferOnWhite = nullptr;
     } 
   }
 
   /**
    * Get a context at the specified resolution for updating |aBounds|,
    * which must be contained within a single quadrant.
+   *
+   * Optionally returns the TopLeft coordinate of the quadrant being drawn to.
    */
   already_AddRefed<gfxContext>
-  GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource);
+  GetContextForQuadrantUpdate(const nsIntRect& aBounds, ContextSource aSource, nsIntPoint* aTopLeft = nullptr);
 
   static bool IsClippingCheap(gfxContext* aTarget, const nsIntRegion& aRegion);
 
 protected:
   // Buffer helpers.  Don't use mBuffer directly; instead use one of
   // these helpers.
 
   /**