Bug 990854. Update CopySurface() to be as fast as DrawSurface(). r=mwoodrow
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Thu, 03 Apr 2014 11:24:05 +0800
changeset 197210 56e8252c546761a9a27b3532a018e13a85a5d235
parent 197209 d17583440ac02f764678280a11e98e65a465590a
child 197211 3711e30f99676595aef04478c47cb76b303a7d4f
push idunknown
push userunknown
push dateunknown
reviewersmwoodrow
bugs990854, 987292
milestone31.0a1
Bug 990854. Update CopySurface() to be as fast as DrawSurface(). r=mwoodrow Bug 987292 made DrawSurface faster by avoiding creating CGImageRef. We can do the same for CopySurface.
gfx/2d/DrawTargetCG.cpp
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -25,21 +25,16 @@ CG_EXTERN void CGContextSetCTM(CGContext
 namespace mozilla {
 namespace gfx {
 
 static CGRect RectToCGRect(Rect r)
 {
   return CGRectMake(r.x, r.y, r.width, r.height);
 }
 
-static CGRect IntRectToCGRect(IntRect r)
-{
-  return CGRectMake(r.x, r.y, r.width, r.height);
-}
-
 CGBlendMode ToBlendMode(CompositionOp op)
 {
   CGBlendMode mode;
   switch (op) {
     case CompositionOp::OP_OVER:
       mode = kCGBlendModeNormal;
       break;
     case CompositionOp::OP_ADD:
@@ -1224,44 +1219,41 @@ DrawTargetCG::CopySurface(SourceSurface 
 {
   MarkChanged();
 
   if (aSurface->GetType() == SurfaceType::COREGRAPHICS_IMAGE ||
       aSurface->GetType() == SurfaceType::COREGRAPHICS_CGCONTEXT ||
       aSurface->GetType() == SurfaceType::DATA) {
     CGImageRef image = GetRetainedImageFromSourceSurface(aSurface);
 
-    /* we have two options here:
-     *  - create a subimage -- this is slower
-     *  - fancy things with clip and different dest rects */
-    CGImageRef subimage = CGImageCreateWithImageInRect(image, IntRectToCGRect(aSourceRect));
-    CGImageRelease(image);
     // XXX: it might be more efficient for us to do the copy directly if we have access to the bits
 
     CGContextSaveGState(mCg);
 
     // CopySurface ignores the clip, so we need to use private API to temporarily reset it
     CGContextResetClip(mCg);
+    CGRect destRect = CGRectMake(aDestination.x, aDestination.y,
+                                 aSourceRect.width, aSourceRect.height);
+    CGContextClipToRect(mCg, destRect);
+
     CGContextSetBlendMode(mCg, kCGBlendModeCopy);
 
     CGContextScaleCTM(mCg, 1, -1);
 
-    CGRect flippedRect = CGRectMake(aDestination.x, -(aDestination.y + aSourceRect.height),
-                                    aSourceRect.width, aSourceRect.height);
+    CGRect flippedRect = CGRectMake(aDestination.x - aSourceRect.x, -(aDestination.y - aSourceRect.y + double(CGImageGetHeight(image))),
+                                    CGImageGetWidth(image), CGImageGetHeight(image));
 
     // Quartz seems to copy A8 surfaces incorrectly if we don't initialize them
     // to transparent first.
     if (mFormat == SurfaceFormat::A8) {
       CGContextClearRect(mCg, flippedRect);
     }
-    CGContextDrawImage(mCg, flippedRect, subimage);
+    CGContextDrawImage(mCg, flippedRect, image);
 
     CGContextRestoreGState(mCg);
-
-    CGImageRelease(subimage);
   }
 }
 
 void
 DrawTargetCG::DrawSurfaceWithShadow(SourceSurface *aSurface, const Point &aDest, const Color &aColor, const Point &aOffset, Float aSigma, CompositionOp aOperator)
 {
   MarkChanged();