Bug 1369949 - compute precise clipping region for DrawTargetSkia::BorrowCGContext. r=mchang
authorLee Salzman <lsalzman@mozilla.com>
Fri, 09 Jun 2017 21:40:13 -0400
changeset 413854 f40ea9d14a1114c305108475053a5353fceb9304
parent 413853 07fcbdb153e29d0fec4420aac2593150365bf7c3
child 413855 e273a44edbae36c831756124c70e35e6e98d6554
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmchang
bugs1369949
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1369949 - compute precise clipping region for DrawTargetSkia::BorrowCGContext. r=mchang MozReview-Commit-ID: 9X3puHOd4dv
gfx/2d/DrawTargetSkia.cpp
--- a/gfx/2d/DrawTargetSkia.cpp
+++ b/gfx/2d/DrawTargetSkia.cpp
@@ -1035,39 +1035,45 @@ GfxMatrixToCGAffineTransform(const Matri
  *
  * tl;dr - CGRects assume origin is bottom left, DrawTarget rects assume top left.
  */
 static bool
 SetupCGContext(DrawTargetSkia* aDT,
                CGContextRef aCGContext,
                SkCanvas* aCanvas,
                const IntPoint& aOrigin,
-               const IntSize& aSize)
+               const IntSize& aSize,
+               bool aClipped)
 {
   // DrawTarget expects the origin to be at the top left, but CG
   // expects it to be at the bottom left. Transform to set the origin to
   // the top left. Have to set this before we do anything else.
   // This is transform (1) up top
   CGContextTranslateCTM(aCGContext, -aOrigin.x, aOrigin.y + aSize.height);
 
   // Transform (2) from the comments.
   CGContextScaleCTM(aCGContext, 1, -1);
 
   // Want to apply clips BEFORE the transform since the transform
   // will apply to the clips we apply.
-  SkIRect clipBounds;
-  if (!aCanvas->getDeviceClipBounds(&clipBounds)) {
-    clipBounds = SkIRect::MakeXYWH(aOrigin.x, aOrigin.y,
-                                   aSize.width, aSize.height);
+  if (aClipped) {
+    SkRegion clipRegion;
+    aCanvas->temporary_internal_getRgnClip(&clipRegion);
+    Vector<CGRect, 8> rects;
+    for (SkRegion::Iterator it(clipRegion); !it.done(); it.next()) {
+      const SkIRect& rect = it.rect();
+      if (!rects.append(CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()))) {
+        break;
+      }
+    }
+    if (rects.length()) {
+      CGContextClipToRects(aCGContext, rects.begin(), rects.length());
+    }
   }
 
-  CGContextClipToRect(aCGContext,
-                      CGRectMake(clipBounds.x(), clipBounds.y(),
-                                 clipBounds.width(), clipBounds.height()));
-
   CGContextConcatCTM(aCGContext, GfxMatrixToCGAffineTransform(aDT->GetTransform()));
   return true;
 }
 
 static bool
 SetupCGGlyphs(CGContextRef aCGContext,
               const GlyphBuffer& aBuffer,
               Vector<CGGlyph,32>& aGlyphs,
@@ -1122,19 +1128,20 @@ DrawTargetSkia::BorrowCGContext(const Dr
   if (!LockBits(&data, &size, &stride, &format, &origin)) {
     NS_WARNING("Could not lock skia bits to wrap CG around");
     return nullptr;
   }
 
   if (!mNeedLayer && (data == mCanvasData) && mCG && (mCGSize == size)) {
     // If our canvas data still points to the same data,
     // we can reuse the CG Context
+    CGContextSetAlpha(mCG, aOptions.mAlpha);
+    CGContextSetShouldAntialias(mCG, aOptions.mAntialiasMode != AntialiasMode::NONE);
     CGContextSaveGState(mCG);
-    CGContextSetAlpha(mCG, aOptions.mAlpha);
-    SetupCGContext(this, mCG, mCanvas, origin, size);
+    SetupCGContext(this, mCG, mCanvas, origin, size, true);
     return mCG;
   }
 
   if (!mColorSpace) {
     mColorSpace = (format == SurfaceFormat::A8) ?
                   CGColorSpaceCreateDeviceGray() : CGColorSpaceCreateDeviceRGB();
   }
 
@@ -1168,17 +1175,17 @@ DrawTargetSkia::BorrowCGContext(const Dr
     return nullptr;
   }
 
   CGContextSetAlpha(mCG, aOptions.mAlpha);
   CGContextSetShouldAntialias(mCG, aOptions.mAntialiasMode != AntialiasMode::NONE);
   CGContextSetShouldSmoothFonts(mCG, true);
   CGContextSetTextDrawingMode(mCG, kCGTextFill);
   CGContextSaveGState(mCG);
-  SetupCGContext(this, mCG, mCanvas, origin, size);
+  SetupCGContext(this, mCG, mCanvas, origin, size, !mNeedLayer);
   return mCG;
 }
 
 void
 DrawTargetSkia::ReturnCGContext(CGContextRef aCGContext)
 {
   MOZ_ASSERT(aCGContext == mCG);
   ReleaseBits(mCanvasData);