GraphicsContext3DCG needs to copy image data in paintToCanvas
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Jan 2013 19:18:54 +0000 (19:18 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 30 Jan 2013 19:18:54 +0000 (19:18 +0000)
https://bugs.webkit.org/show_bug.cgi?id=108310

Reviewed by Simon Fraser.

Make the CG implementation of GraphicsContext3D::paintToCanvas copy image data
before drawing if we're drawing into an accelerated context, matching the fix made
in http://trac.webkit.org/changeset/106095 for 2D canvas.

No new tests, depends on acceleration and would be flaky at best.

* platform/graphics/GraphicsContext3D.h:
(GraphicsContext3D): Make CG's paintToCanvas take a GraphicsContext instead of a CGContextRef.
* platform/graphics/cg/GraphicsContext3DCG.cpp:
(WebCore::releaseImageData): Added.
(WebCore::GraphicsContext3D::paintToCanvas): Copy image data if the destination is
an accelerated context. Also, use GraphicsContext API instead of CGContext.
* platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
(WebCore::GraphicsContext3D::paintRenderingResultsToCanvas):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@141288 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/GraphicsContext3D.h
Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp

index 4fd53e5..e36e34d 100644 (file)
@@ -1,3 +1,25 @@
+2013-01-30  Tim Horton  <timothy_horton@apple.com>
+
+        GraphicsContext3DCG needs to copy image data in paintToCanvas
+        https://bugs.webkit.org/show_bug.cgi?id=108310
+
+        Reviewed by Simon Fraser.
+
+        Make the CG implementation of GraphicsContext3D::paintToCanvas copy image data
+        before drawing if we're drawing into an accelerated context, matching the fix made
+        in http://trac.webkit.org/changeset/106095 for 2D canvas.
+
+        No new tests, depends on acceleration and would be flaky at best.
+
+        * platform/graphics/GraphicsContext3D.h:
+        (GraphicsContext3D): Make CG's paintToCanvas take a GraphicsContext instead of a CGContextRef.
+        * platform/graphics/cg/GraphicsContext3DCG.cpp:
+        (WebCore::releaseImageData): Added.
+        (WebCore::GraphicsContext3D::paintToCanvas): Copy image data if the destination is
+        an accelerated context. Also, use GraphicsContext API instead of CGContext.
+        * platform/graphics/opengl/GraphicsContext3DOpenGLCommon.cpp:
+        (WebCore::GraphicsContext3D::paintRenderingResultsToCanvas):
+
 2013-01-29  Jer Noble  <jer.noble@apple.com>
 
         MediaPlayerPrivateQTKit claims it supports application/x-diskcopy, breaking downloads.
index 336997f..0f8d379 100644 (file)
@@ -812,16 +812,13 @@ public:
 
     void reshape(int width, int height);
 
-#if USE(CG)
-    static void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
-                              int canvasWidth, int canvasHeight, CGContextRef);
-#elif PLATFORM(GTK) || PLATFORM(EFL)
+#if PLATFORM(GTK) || PLATFORM(EFL)
     void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
                        int canvasWidth, int canvasHeight, PlatformContextCairo* context);
 #elif PLATFORM(QT)
     void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
                        int canvasWidth, int canvasHeight, QPainter* context);
-#elif PLATFORM(BLACKBERRY)
+#elif PLATFORM(BLACKBERRY) || USE(CG)
     void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
                        int canvasWidth, int canvasHeight, GraphicsContext*);
 #endif
index 82fc769..ecf0cee 100644 (file)
@@ -253,25 +253,45 @@ bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
     return true;
 }
 
-void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context)
+static void releaseImageData(void*, const void* data, size_t)
+{
+    fastFree(const_cast<void*>(data));
+}
+
+void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, GraphicsContext* context)
 {
     if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
         return;
     int rowBytes = imageWidth * 4;
-    RetainPtr<CGDataProviderRef> dataProvider(AdoptCF, CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0));
-    RetainPtr<CGImageRef> cgImage(AdoptCF, CGImageCreate(imageWidth, imageHeight, 8, 32, rowBytes, deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
+    RetainPtr<CGDataProviderRef> dataProvider;
+
+    if (context->isAcceleratedContext()) {
+        unsigned char* copiedPixels;
+
+        if (!tryFastCalloc(imageHeight, rowBytes).getValue(copiedPixels))
+            return;
+
+        memcpy(copiedPixels, imagePixels, rowBytes * imageHeight);
+        dataProvider = adoptCF(CGDataProviderCreateWithData(0, copiedPixels, rowBytes * imageHeight, releaseImageData));
+    } else
+        dataProvider = adoptCF(CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0));
+
+    RetainPtr<CGImageRef> cgImage = adoptCF(CGImageCreate(imageWidth, imageHeight, 8, 32, rowBytes, deviceRGBColorSpaceRef(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
         dataProvider.get(), 0, false, kCGRenderingIntentDefault));
+
     // CSS styling may cause the canvas's content to be resized on
     // the page. Go back to the Canvas to figure out the correct
     // width and height to draw.
-    CGRect rect = CGRectMake(0, 0, canvasWidth, canvasHeight);
+    FloatRect canvasRect(0, 0, canvasWidth, canvasHeight);
+    FloatSize imageSize(imageWidth, imageHeight);
     // We want to completely overwrite the previous frame's
     // rendering results.
-    CGContextSaveGState(context);
-    CGContextSetBlendMode(context, kCGBlendModeCopy);
-    CGContextSetInterpolationQuality(context, kCGInterpolationNone);
-    CGContextDrawImage(context, rect, cgImage.get());
-    CGContextRestoreGState(context);
+
+    GraphicsContextStateSaver stateSaver(*context);
+    context->scale(FloatSize(1, -1));
+    context->translate(0, -imageHeight);
+    context->setImageInterpolationQuality(InterpolationNone);
+    context->drawNativeImage(cgImage.get(), imageSize, ColorSpaceDeviceRGB, canvasRect, FloatRect(FloatPoint(), imageSize), CompositeCopy);
 }
 
 } // namespace WebCore
index 58cfd7f..c7d7335 100644 (file)
@@ -120,7 +120,7 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer,
         }
     }
 
-#if PLATFORM(BLACKBERRY)
+#if PLATFORM(BLACKBERRY) || USE(CG)
     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
                   imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context());
 #else