Title: [91496] trunk/Source/WebCore
Revision
91496
Author
[email protected]
Date
2011-07-21 13:49:38 -0700 (Thu, 21 Jul 2011)

Log Message

Add fast path for ImageBuffer::draw
https://bugs.webkit.org/show_bug.cgi?id=64535

Reviewed by Simon Fraser.

No new tests. This patch doesn't change behavior; current tests are sufficient.

* platform/graphics/GraphicsContext.cpp:
(WebCore::GraphicsContext::drawImage): Moved the main method version next to wrapper versions.

* platform/graphics/ImageBuffer.h:
1) Added BackingStoreCopy enum for choosing to copy backing store or not in copyImage().
2) Added copyNativeImage() behind USE(CG) - same as copyImage() but gives NativeImagePtr.
* platform/graphics/cg/ImageBufferCG.cpp: Added new methods described above.

* platform/graphics/GraphicsContext.h: Adding drawNativeImage() for fast draw path.
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::GraphicsContext::drawNativeImage): Added. Draws a nativeImagePtr into context.

* platform/graphics/Image.h: Added imageWithColorSpace behind CG platform ifdef
* platform/graphics/cg/ImageCG.cpp:
(WebCore::BitmapImage::draw): Refactored out actual image drawing code into GraphicsContext,
so that it can be used by more than just BitmapImage without having to copy code.
(WebCore::Image::imageWithColorSpace): Made into an Image class function.

Updated copyImage() to for BackingStoreCopy:
* platform/graphics/qt/ImageBufferQt.cpp
* platform/graphics/filters/FETile.cpp
* platform/graphics/cairo/ImageBufferCairo.cpp
* platform/graphics/skia/ImageBufferSkia.cpp
* platform/graphics/wx/ImageBufferWx.cpp
* platform/graphics/wince/ImageBufferWinCE.cpp
* svg/SVGFEImageElement.cpp
* svg/graphics/SVGImage.cpp
* html/HTMLCanvasElement.cpp
* html/canvas/WebGLRenderingContext.cpp
* rendering/svg/RenderSVGResourcePattern.cpp

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (91495 => 91496)


--- trunk/Source/WebCore/ChangeLog	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/ChangeLog	2011-07-21 20:49:38 UTC (rev 91496)
@@ -1,3 +1,85 @@
+2011-07-19  Matthew Delaney  <[email protected]>
+
+        Add fast path for ImageBuffer::draw
+        https://bugs.webkit.org/show_bug.cgi?id=64535
+
+        Reviewed by Simon Fraser.
+
+        No new tests. This patch doesn't change behavior; current tests are sufficient.
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawImage): Moved the main method version next to wrapper versions.
+
+        * platform/graphics/ImageBuffer.h:
+        1) Added BackingStoreCopy enum for choosing to copy backing store or not in copyImage().
+        2) Added copyNativeImage() behind USE(CG) - same as copyImage() but gives NativeImagePtr.
+        * platform/graphics/cg/ImageBufferCG.cpp: Added new methods described above.
+
+        * platform/graphics/GraphicsContext.h: Adding drawNativeImage() for fast draw path.
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::drawNativeImage): Added. Draws a nativeImagePtr into context.
+
+        * platform/graphics/Image.h: Added imageWithColorSpace behind CG platform ifdef
+        * platform/graphics/cg/ImageCG.cpp:
+        (WebCore::BitmapImage::draw): Refactored out actual image drawing code into GraphicsContext,
+        so that it can be used by more than just BitmapImage without having to copy code.
+        (WebCore::Image::imageWithColorSpace): Made into an Image class function.
+
+        Updated copyImage() to for BackingStoreCopy:
+        * platform/graphics/qt/ImageBufferQt.cpp
+        * platform/graphics/filters/FETile.cpp
+        * platform/graphics/cairo/ImageBufferCairo.cpp
+        * platform/graphics/skia/ImageBufferSkia.cpp
+        * platform/graphics/wx/ImageBufferWx.cpp
+        * platform/graphics/wince/ImageBufferWinCE.cpp
+        * svg/SVGFEImageElement.cpp
+        * svg/graphics/SVGImage.cpp
+        * html/HTMLCanvasElement.cpp
+        * html/canvas/WebGLRenderingContext.cpp
+        * rendering/svg/RenderSVGResourcePattern.cpp
+
+<<<<<<< .mine
+2011-07-21  Matthew Delaney  <[email protected]>
+
+        Add fast path for ImageBuffer::draw, Take 2.
+        https://bugs.webkit.org/show_bug.cgi?id=64535
+
+        Reviewed by Simon Fraser.
+
+        No new tests. This patch doesn't change behavior; current tests are sufficient.
+
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawImage): Moved the main method version next to wrapper versions.
+
+        * platform/graphics/ImageBuffer.h:
+        1) Added BackingStoreCopy enum for choosing to copy backing store or not in copyImage().
+        2) Added copyNativeImage() behind USE(CG) - same as copyImage() but gives NativeImagePtr.
+        * platform/graphics/cg/ImageBufferCG.cpp: Added new methods described above.
+
+        * platform/graphics/GraphicsContext.h: Adding drawNativeImage() for fast draw path.
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::drawNativeImage): Added. Draws a nativeImagePtr into context.
+
+        * platform/graphics/Image.h: Added imageWithColorSpace behind CG platform ifdef
+        * platform/graphics/cg/ImageCG.cpp:
+        (WebCore::BitmapImage::draw): Refactored out actual image drawing code into GraphicsContext,
+        so that it can be used by more than just BitmapImage without having to copy code.
+        (WebCore::Image::imageWithColorSpace): Made into an Image class function.
+
+        Updated copyImage() to for BackingStoreCopy:
+        * platform/graphics/qt/ImageBufferQt.cpp
+        * platform/graphics/filters/FETile.cpp
+        * platform/graphics/cairo/ImageBufferCairo.cpp
+        * platform/graphics/skia/ImageBufferSkia.cpp
+        * platform/graphics/wx/ImageBufferWx.cpp
+        * platform/graphics/wince/ImageBufferWinCE.cpp
+        * svg/SVGFEImageElement.cpp
+        * svg/graphics/SVGImage.cpp
+        * html/HTMLCanvasElement.cpp
+        * html/canvas/WebGLRenderingContext.cpp
+        * rendering/svg/RenderSVGResourcePattern.cpp
+
+=======
 2011-07-21  David Kilzer  <[email protected]>
 
         <http://webkit.org/b/64972> Clean up generated HTMLEntityTable.cpp output
@@ -73,6 +155,7 @@
         (WebCore::RenderReplaced::positionForPoint): Modified to avoid relying entirely
         on InlineBox to calculate the position.
 
+>>>>>>> .r91495
 2011-07-21  Pavel Feldman  <[email protected]>
 
         Not reviewed: one liner typo fix in Inspector.json.

Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (91495 => 91496)


--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -309,7 +309,7 @@
 {
     if (!m_presentedImage) {
         // The buffer contains the last presented data, so save a copy of it.
-        m_presentedImage = buffer()->copyImage();
+        m_presentedImage = buffer()->copyImage(CopyBackingStore);
     }
 }
 
@@ -472,7 +472,7 @@
     if (!m_copiedImage && buffer()) {
         if (m_context)
             m_context->paintRenderingResultsToCanvas();
-        m_copiedImage = buffer()->copyImage();
+        m_copiedImage = buffer()->copyImage(CopyBackingStore);
     }
     return m_copiedImage.get();
 }

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp (91495 => 91496)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -3214,7 +3214,7 @@
     IntRect destRect(0, 0, size.width(), size.height());
     // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
     video->paintCurrentFrameInContext(buf->context(), destRect);
-    return buf->copyImage();
+    return buf->copyImage(CopyBackingStore);
 }
 
 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -351,26 +351,6 @@
     return m_state.paintingDisabled;
 }
 
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
-{
-    drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
-}
-
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
-{
-    drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
-}
-
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
-{
-    drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
-}
-
-void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
-{
-    drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
-}
-
 #if !OS(WINCE) || (PLATFORM(QT) && !HAVE(QRAWFONT))
 void GraphicsContext::drawText(const Font& font, const TextRun& run, const FloatPoint& point, int from, int to)
 {
@@ -433,6 +413,26 @@
     fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
 }
 
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
+{
+    drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
+}
+
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+{
+    drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+}
+
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+{
+    drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
+}
+
+void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+{
+    drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
+}
+
 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
 {
     if (paintingDisabled() || !image)

Modified: trunk/Source/WebCore/platform/graphics/GraphicsContext.h (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/GraphicsContext.h	2011-07-21 20:49:38 UTC (rev 91496)
@@ -265,6 +265,8 @@
         void applyFillPattern();
         void drawPath(const Path&);
         
+        void drawNativeImage(NativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver);
+
         // Allow font smoothing (LCD antialiasing). Not part of the graphics state.
         void setAllowsFontSmoothing(bool);
         

Modified: trunk/Source/WebCore/platform/graphics/Image.h (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/Image.h	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/Image.h	2011-07-21 20:49:38 UTC (rev 91496)
@@ -141,6 +141,7 @@
     virtual CGImageRef getCGImageRef() { return 0; }
     virtual CGImageRef getFirstCGImageRefOfSize(const IntSize&) { return 0; }
     virtual RetainPtr<CFArrayRef> getCGImageArray() { return 0; }
+    static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace);
 #endif
 
 #if PLATFORM(WIN)

Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h	2011-07-21 20:49:38 UTC (rev 91496)
@@ -58,6 +58,11 @@
         Unaccelerated,
         Accelerated
     };
+    
+    enum BackingStoreCopy {
+        CopyBackingStore, // Guarantee subsequent draws don't affect the copy.
+        DontCopyBackingStore // Subsequent draws may affect the copy.
+    };
 
     class ImageBuffer {
         WTF_MAKE_NONCOPYABLE(ImageBuffer); WTF_MAKE_FAST_ALLOCATED;
@@ -83,7 +88,7 @@
         GraphicsContext* context() const;
 
         bool isAccelerated() const { return m_accelerateRendering; }
-        PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer.
+        PassRefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore) const;
 
         PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const;
         PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&) const;
@@ -103,14 +108,15 @@
 #endif
 
     private:
+#if USE(CG)
+        NativeImagePtr copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
+#endif
+
         void clip(GraphicsContext*, const FloatRect&) const;
 
-        // The draw method draws the contents of the buffer without copying it.
-        void draw(GraphicsContext*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
-                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
-        void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
-                         const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
-        
+        void draw(GraphicsContext*, ColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
+
         inline void genericConvertToLuminanceMask();
 
         friend class GraphicsContext;

Modified: trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -86,8 +86,9 @@
     return m_context.get();
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
+    ASSERT(copyBehavior == CopyBackingStore);
     // BitmapImage will release the passed in surface on destruction
     return BitmapImage::create(copyCairoImageSurface(m_data.m_surface).leakRef());
 }

Modified: trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -152,6 +152,79 @@
     m_data->m_userToDeviceTransformKnownToBeIdentity = false;
 }
 
+void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op)
+{
+    RetainPtr<CGImageRef> image(imagePtr);
+
+    float currHeight = CGImageGetHeight(image.get());
+    if (currHeight <= srcRect.y())
+        return;
+
+    CGContextRef context = platformContext();
+    CGContextSaveGState(context);
+
+    bool shouldUseSubimage = false;
+
+    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
+    // and then set a clip to the portion that we want to display.
+    FloatRect adjustedDestRect = destRect;
+
+    if (srcRect.size() != imageSize) {
+        CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
+        // When the image is scaled using high-quality interpolation, we create a temporary CGImage
+        // containing only the portion we want to display. We need to do this because high-quality
+        // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
+        // into the destination rect. See <rdar://problem/6112909>.
+        shouldUseSubimage = (interpolationQuality != kCGInterpolationNone) && (srcRect.size() != destRect.size() || !getCTM().isIdentityOrTranslationOrFlipped());
+        float xScale = srcRect.width() / destRect.width();
+        float yScale = srcRect.height() / destRect.height();
+        if (shouldUseSubimage) {
+            FloatRect subimageRect = srcRect;
+            float leftPadding = srcRect.x() - floorf(srcRect.x());
+            float topPadding = srcRect.y() - floorf(srcRect.y());
+
+            subimageRect.move(-leftPadding, -topPadding);
+            adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);
+
+            subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
+            adjustedDestRect.setWidth(subimageRect.width() / xScale);
+
+            subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
+            adjustedDestRect.setHeight(subimageRect.height() / yScale);
+
+            image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
+            if (currHeight < srcRect.maxY()) {
+                ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
+                adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
+            }
+        } else {
+            adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
+            adjustedDestRect.setSize(FloatSize(imageSize.width() / xScale, imageSize.height() / yScale));
+        }
+
+        if (!destRect.contains(adjustedDestRect))
+            CGContextClipToRect(context, destRect);
+    }
+
+    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
+    if (!shouldUseSubimage && currHeight < imageSize.height())
+        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / imageSize.height());
+
+    setPlatformCompositeOperation(op);
+
+    // Flip the coords.
+    CGContextScaleCTM(context, 1, -1);
+    adjustedDestRect.setY(-adjustedDestRect.maxY());
+    
+    // Adjust the color space.
+    image = Image::imageWithColorSpace(image.get(), styleColorSpace);
+
+    // Draw the image.
+    CGContextDrawImage(context, adjustedDestRect, image.get());
+
+    CGContextRestoreGState(context);
+}
+
 // Draws a filled rectangle with a stroked border.
 void GraphicsContext::drawRect(const IntRect& rect)
 {

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -40,6 +40,7 @@
 #include <wtf/OwnArrayPtr.h>
 #include <wtf/RetainPtr.h>
 #include <wtf/Threading.h>
+#include <wtf/UnusedParam.h>
 #include <math.h>
 
 #if PLATFORM(MAC) || PLATFORM(CHROMIUM)
@@ -177,72 +178,74 @@
     return m_context.get();
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
-    // BitmapImage will release the passed in CGImage on destruction
-    CGImageRef ctxImage = 0;
-    if (!m_accelerateRendering)
-        ctxImage = CGBitmapContextCreateImage(context()->platformContext());
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
-    else
-        ctxImage = wkIOSurfaceContextCreateImage(context()->platformContext());
-#endif
-    return BitmapImage::create(ctxImage);
-}
+    RetainPtr<CGImageRef> image = copyNativeImage(copyBehavior);
 
-static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
-{
-    return CGImageCreate(size.width(), size.height(), 8, 32, data.m_bytesPerRow,
-                         data.m_colorSpace, data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
+    if (!image)
+        return 0;
+
+    return BitmapImage::create(image.get());
 }
 
-void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
-                       CompositeOperator op, bool useLowQualityScale)
+NativeImagePtr ImageBuffer::copyNativeImage(BackingStoreCopy copyBehavior) const
 {
+    CGImageRef image = 0;
     if (!m_accelerateRendering) {
-        if (destContext == context()) {
-            // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
-            RefPtr<Image> copy = copyImage();
-            destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
-        } else {
-            RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
-            destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+        switch (copyBehavior) {
+        case DontCopyBackingStore:
+            image = CGImageCreate(m_size.width(), m_size.height(), 8, 32, m_data.m_bytesPerRow, m_data.m_colorSpace, m_data.m_bitmapInfo, m_data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
+            break;
+        case CopyBackingStore:
+            image = CGBitmapContextCreateImage(context()->platformContext());
+            break;
+        default:
+            ASSERT_NOT_REACHED();
+            break;
         }
-    } else {
-        RefPtr<Image> copy = copyImage();
-        ColorSpace colorSpace = (destContext == context()) ? ColorSpaceDeviceRGB : styleColorSpace;
-        destContext->drawImage(copy.get(), colorSpace, destRect, srcRect, op, useLowQualityScale);
     }
+#if USE(IOSURFACE_CANVAS_BACKING_STORE)
+    else
+        image = wkIOSurfaceContextCreateImage(context()->platformContext());
+#endif
+
+    return image;
 }
 
-void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
-                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, bool useLowQualityScale)
 {
+    UNUSED_PARAM(useLowQualityScale);
+    ColorSpace colorSpace = (destContext == m_context) ? ColorSpaceDeviceRGB : styleColorSpace;
+
+    RetainPtr<CGImageRef> image;
+    if (destContext == m_context)
+        image.adoptCF(copyNativeImage(CopyBackingStore)); // Drawing into our own buffer, need to deep copy.
+    else
+        image.adoptCF(copyNativeImage(DontCopyBackingStore));
+
+    destContext->drawNativeImage(image.get(), m_size, colorSpace, destRect, srcRect, op);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
     if (!m_accelerateRendering) {
-        if (destContext == context()) {
-            // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
-            RefPtr<Image> copy = copyImage();
-            copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+        if (context == m_context) {
+            RefPtr<Image> copy = copyImage(CopyBackingStore); // Drawing into our own buffer, need to deep copy.
+            copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
         } else {
-            RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
-            imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+            RefPtr<Image> imageForRendering = copyImage(DontCopyBackingStore);
+            imageForRendering->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
         }
     } else {
-        RefPtr<Image> copy = copyImage();
-        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+        RefPtr<Image> copy = copyImage(CopyBackingStore);
+        copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     }
 }
 
 void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) const
 {
     CGContextRef platformContextToClip = contextToClip->platformContext();
-    RetainPtr<CGImageRef> image;
-    if (!m_accelerateRendering)
-        image.adoptCF(cgImage(m_size, m_data));
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
-    else
-        image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
-#endif
+    RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(DontCopyBackingStore));
     CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + rect.height());
     CGContextScaleCTM(platformContextToClip, 1, -1);
     CGContextClipToMask(platformContextToClip, FloatRect(FloatPoint(), rect.size()), image.get());
@@ -346,13 +349,7 @@
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
-    RetainPtr<CGImageRef> image;
-    if (!m_accelerateRendering)
-        image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
-#if USE(IOSURFACE_CANVAS_BACKING_STORE)
-    else
-        image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
-#endif
+    RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(CopyBackingStore));
 
     if (!image)
         return "data:,";

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageCG.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/cg/ImageCG.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageCG.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -128,7 +128,7 @@
     }
 }
 
-static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
+RetainPtr<CGImageRef> Image::imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
 {
     CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalImage);
 
@@ -195,74 +195,10 @@
         return;
     }
 
-    float currHeight = CGImageGetHeight(image.get());
-    if (currHeight <= srcRect.y())
-        return;
-
-    CGContextRef context = ctxt->platformContext();
-    GraphicsContextStateSaver stateSaver(*ctxt);
-
-    bool shouldUseSubimage = false;
-
-    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
-    // and then set a clip to the portion that we want to display.
-    FloatRect adjustedDestRect = destRect;
     FloatSize selfSize = currentFrameSize();
-    if (srcRect.size() != selfSize) {
-        CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
-        // When the image is scaled using high-quality interpolation, we create a temporary CGImage
-        // containing only the portion we want to display. We need to do this because high-quality
-        // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
-        // into the destination rect. See <rdar://problem/6112909>.
-        shouldUseSubimage = (interpolationQuality != kCGInterpolationNone) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
-        float xScale = srcRect.width() / destRect.width();
-        float yScale = srcRect.height() / destRect.height();
-        if (shouldUseSubimage) {
-            FloatRect subimageRect = srcRect;
-            float leftPadding = srcRect.x() - floorf(srcRect.x());
-            float topPadding = srcRect.y() - floorf(srcRect.y());
 
-            subimageRect.move(-leftPadding, -topPadding);
-            adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);
+    ctxt->drawNativeImage(image.get(), selfSize, styleColorSpace, destRect, srcRect, compositeOp);
 
-            subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
-            adjustedDestRect.setWidth(subimageRect.width() / xScale);
-
-            subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
-            adjustedDestRect.setHeight(subimageRect.height() / yScale);
-
-            image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
-            if (currHeight < srcRect.maxY()) {
-                ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
-                adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
-            }
-        } else {
-            adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
-            adjustedDestRect.setSize(FloatSize(selfSize.width() / xScale, selfSize.height() / yScale));
-        }
-
-        if (!destRect.contains(adjustedDestRect))
-            CGContextClipToRect(context, destRect);
-    }
-
-    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
-    if (!shouldUseSubimage && currHeight < selfSize.height())
-        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());
-
-    ctxt->setCompositeOperation(compositeOp);
-
-    // Flip the coords.
-    CGContextScaleCTM(context, 1, -1);
-    adjustedDestRect.setY(-adjustedDestRect.maxY());
-
-    // Adjust the color space.
-    image = imageWithColorSpace(image.get(), styleColorSpace);
-
-    // Draw the image.
-    CGContextDrawImage(context, adjustedDestRect, image.get());
-
-    stateSaver.restore();
-
     if (imageObserver())
         imageObserver()->didDraw(this);
 }
@@ -313,7 +249,7 @@
     }
 
     // Adjust the color space.
-    subImage = imageWithColorSpace(subImage.get(), styleColorSpace);
+    subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace);
     
     // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
     // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the

Modified: trunk/Source/WebCore/platform/graphics/filters/FETile.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/filters/FETile.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/filters/FETile.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -79,7 +79,7 @@
     tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
     tileImageContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());
 
-    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
+    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(CopyBackingStore), true, true);
 
     AffineTransform patternTransform;
     patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());

Modified: trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -121,8 +121,9 @@
     return m_context.get();
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
+    ASSERT(copyBehavior == CopyBackingStore);
     return StillImage::create(m_data.m_pixmap);
 }
 
@@ -131,7 +132,7 @@
 {
     if (destContext == context()) {
         // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
-        RefPtr<Image> copy = copyImage();
+        RefPtr<Image> copy = copyImage(CopyBackingStore);
         destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
     } else
         destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
@@ -142,7 +143,7 @@
 {
     if (destContext == context()) {
         // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
-        RefPtr<Image> copy = copyImage();
+        RefPtr<Image> copy = copyImage(CopyBackingStore);
         copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     } else
         m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);

Modified: trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -97,8 +97,9 @@
     return m_size.width() * m_size.height() * 4;
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
+    ASSERT(copyBehavior == CopyBackingStore);
     m_context->platformContext()->makeGrContextCurrent();
     return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), true);
 }

Modified: trunk/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -98,8 +98,9 @@
     return m_context.get();
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
+    ASSERT(copyBehavior == CopyBackingStore);
     return adoptRef(new BufferedImage(&m_data));
 }
 
@@ -111,14 +112,14 @@
 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
                        CompositeOperator op , bool useLowQualityScale)
 {
-    RefPtr<Image> imageCopy = copyImage();
+    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
     context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
 }
 
 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
                               const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
 {
-    RefPtr<Image> imageCopy = copyImage();
+    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
     imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
 }
 

Modified: trunk/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp (91495 => 91496)


--- trunk/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -88,8 +88,9 @@
     return String();
 }
 
-PassRefPtr<Image> ImageBuffer::copyImage() const
+PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyBehavior) const
 {
+    ASSERT(copyBehavior == CopyBackingStore);
     notImplemented();
     return 0;
 }
@@ -102,14 +103,14 @@
 void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
                        CompositeOperator op, bool useLowQualityScale)
 {
-    RefPtr<Image> imageCopy = copyImage();
+    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
     context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
 }
 
 void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
                               const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
 {
-    RefPtr<Image> imageCopy = copyImage();
+    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
     imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
 }
 

Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp (91495 => 91496)


--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -124,7 +124,7 @@
         if (!tileImage)
             return false;
 
-        RefPtr<Image> copiedImage = tileImage->copyImage();
+        RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
         if (!copiedImage)
             return false;
 

Modified: trunk/Source/WebCore/svg/SVGFEImageElement.cpp (91495 => 91496)


--- trunk/Source/WebCore/svg/SVGFEImageElement.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/svg/SVGFEImageElement.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -178,7 +178,7 @@
         SVGImageBufferTools::renderSubtreeToImageBuffer(m_targetImage.get(), renderer, contentTransformation);
     }
 
-    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio());
+    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage(CopyBackingStore) : m_cachedImage->image(), preserveAspectRatio());
 }
 
 void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const

Modified: trunk/Source/WebCore/svg/graphics/SVGImage.cpp (91495 => 91496)


--- trunk/Source/WebCore/svg/graphics/SVGImage.cpp	2011-07-21 20:31:39 UTC (rev 91495)
+++ trunk/Source/WebCore/svg/graphics/SVGImage.cpp	2011-07-21 20:49:38 UTC (rev 91496)
@@ -227,7 +227,7 @@
         if (!buffer) // failed to allocate image
             return 0;
         draw(buffer->context(), rect(), rect(), ColorSpaceDeviceRGB, CompositeSourceOver);
-        m_frameCache = buffer->copyImage();
+        m_frameCache = buffer->copyImage(CopyBackingStore);
     }
     return m_frameCache->nativeImageForCurrentFrame();
 }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to