Bug 1227210: Ensure the mask and the surface are in the right space when being blended. r=mattwoodrow a=sylvestre
authorBas Schouten <bschouten@mozilla.com>
Thu, 26 Nov 2015 15:51:49 +0100
changeset 310751 e4a1b8b57f4929f7faf8b3adfd9e3eb1577c3580
parent 310750 ae6a25a60355526058bffa8862aef1c2fb5a2468
child 310752 90775224fe6288e413179d191da3fde297cf6069
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, sylvestre
bugs1227210
milestone45.0a2
Bug 1227210: Ensure the mask and the surface are in the right space when being blended. r=mattwoodrow a=sylvestre
gfx/layers/basic/BasicLayerManager.cpp
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -123,16 +123,26 @@ BasicLayerManager::PushGroupForLayer(gfx
       group.mMaskSurface = GetMaskForLayer(aLayer, &group.mMaskTransform);
       return group;
     }
   }
 
   Matrix maskTransform;
   RefPtr<SourceSurface> maskSurf = GetMaskForLayer(aLayer, &maskTransform);
 
+  if (maskSurf) {
+    // The returned transform will transform the mask to device space on the
+    // destination. Since the User->Device space transform will be applied
+    // to the mask by PopGroupAndBlend we need to adjust the transform to
+    // transform the mask to user space.
+    Matrix currentTransform = ToMatrix(group.mFinalTarget->CurrentMatrix());
+    currentTransform.Invert();
+    maskTransform = maskTransform * currentTransform;
+  }
+
   if (aLayer->CanUseOpaqueSurface() &&
       ((didCompleteClip && aRegion.GetNumRects() == 1) ||
        !aContext->CurrentMatrix().HasNonIntegerTranslation())) {
     // If the layer is opaque in its visible region we can push a gfxContentType::COLOR
     // group. We need to make sure that only pixels inside the layer's visible
     // region are copied back to the destination. Remember if we've already
     // clipped precisely to the visible region.
     group.mNeedsClipToVisibleRegion = !didCompleteClip || aRegion.GetNumRects() > 1;
@@ -167,18 +177,22 @@ BasicLayerManager::PopGroupForLayer(Push
 
   DrawTarget* dt = group.mFinalTarget->GetDrawTarget();
   RefPtr<DrawTarget> sourceDT = group.mGroupTarget->GetDrawTarget();
   group.mGroupTarget = nullptr;
 
   RefPtr<SourceSurface> src = sourceDT->Snapshot();
 
   if (group.mMaskSurface) {
-    dt->SetTransform(group.mMaskTransform * Matrix::Translation(-group.mFinalTarget->GetDeviceOffset()));
-    dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP, Matrix::Translation(group.mGroupOffset.x, group.mGroupOffset.y)),
+    Point finalOffset = group.mFinalTarget->GetDeviceOffset();
+    dt->SetTransform(group.mMaskTransform * Matrix::Translation(-finalOffset));
+    Matrix surfTransform = group.mMaskTransform;
+    surfTransform.Invert();
+    dt->MaskSurface(SurfacePattern(src, ExtendMode::CLAMP, surfTransform *
+                                                           Matrix::Translation(group.mGroupOffset.x, group.mGroupOffset.y)),
                     group.mMaskSurface, Point(0, 0), DrawOptions(group.mOpacity, group.mOperator));
   } else {
     // For now this is required since our group offset is in device space of the final target,
     // context but that may still have its own device offset. Once PushGroup/PopGroup logic is
     // migrated to DrawTargets this can go as gfxContext::GetDeviceOffset will essentially
     // always become null.
     dt->SetTransform(Matrix::Translation(-group.mFinalTarget->GetDeviceOffset()));
     dt->DrawSurface(src, Rect(group.mGroupOffset.x, group.mGroupOffset.y, src->GetSize().width, src->GetSize().height),