[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

zmo at google.com zmo at google.com
Wed Dec 22 11:15:15 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 54d574e22ae7c3da1a51aa24ea9e6ab6bb9550e3
Author: zmo at google.com <zmo at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Jul 16 01:00:28 2010 +0000

    2010-07-13  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Nate Chapin.
    
            WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
            https://bugs.webkit.org/show_bug.cgi?id=34719
    
            * src/GraphicsContext3D.cpp:
            (WebCore::GraphicsContext3DInternal::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
            (WebCore::GraphicsContext3DInternal::beginPaint): Just use paintRenderingResultsToCanvas().
    2010-07-13  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Nate Chapin.
    
            WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
            https://bugs.webkit.org/show_bug.cgi?id=34719
    
            Tests: fast/canvas/webgl/canvas-test.html
                   fast/canvas/webgl/gl-pixelstorei.html
    
            * html/HTMLCanvasElement.cpp:
            (WebCore::HTMLCanvasElement::makeRenderingResultsAvailable): Paint the WebGL rendering results to canvas if it's 3d.
            (WebCore::HTMLCanvasElement::toDataURL): Paint the WebGL rendering results to canvas if it's 3d.
            * html/canvas/CanvasRenderingContext2D.cpp:
            (WebCore::CanvasRenderingContext2D::drawImage): Paint the WebGL rendering results to canvas if it's 3d before drawing.
            * html/canvas/WebGLRenderingContext.cpp:
            (WebCore::WebGLRenderingContext::markContextChanged): Mark it always for canvas2d.drawImage purpose.
            (WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas): Paint the WebGL rendering results to canvas if it's dirty.
            * html/canvas/WebGLRenderingContext.h: Declare paintRenderingResultsToCanvas().
            * platform/graphics/GraphicsContext3D.h: Declare paintRenderingResultsToCanvas() & paintToCanvas().
            * platform/graphics/cg/GraphicsContext3DCG.cpp:
            (WebCore::GraphicsContext3D::paintToCanvas): Paint the rendered image pixels to the canvas.
            * platform/graphics/mac/GraphicsContext3DMac.mm:
            (WebCore::GraphicsContext3D::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
            * platform/graphics/qt/GraphicsContext3DQt.cpp:
            (WebCore::GraphicsContext3D::beginPaint): Just call paintRenderingResultsToCanvas().
            (WebCore::GraphicsContext3D::endPaint):
            (WebCore::GraphicsContext3D::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
    2010-07-13  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Nate Chapin.
    
            WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
            https://bugs.webkit.org/show_bug.cgi?id=34719
    
            * fast/canvas/webgl/canvas-test-expected.txt: Added.
            * fast/canvas/webgl/canvas-test.html: Added.
            * fast/canvas/webgl/gl-pixelstorei-expected.txt: Added.
            * fast/canvas/webgl/gl-pixelstorei.html: Added.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@63502 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 7e3bbf3..13c00c2 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
+2010-07-13  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Nate Chapin.
+
+        WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
+        https://bugs.webkit.org/show_bug.cgi?id=34719
+
+        * fast/canvas/webgl/canvas-test-expected.txt: Added.
+        * fast/canvas/webgl/canvas-test.html: Added.
+        * fast/canvas/webgl/gl-pixelstorei-expected.txt: Added.
+        * fast/canvas/webgl/gl-pixelstorei.html: Added.
+
 2010-07-15  Ojan Vafai  <ojan at chromium.org>
 
         Unreviewed.
diff --git a/LayoutTests/fast/canvas/webgl/canvas-test-expected.txt b/LayoutTests/fast/canvas/webgl/canvas-test-expected.txt
new file mode 100644
index 0000000..fe5b8ca
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/canvas-test-expected.txt
@@ -0,0 +1,30 @@
+This test ensures WebGL implementations interact correctly with the canvas tag.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Canvas.getContext
+PASS context exists
+
+Checking canvas and WebGL interaction
+PASS canvas.width is 300
+PASS canvas.height is 150
+PASS pixels are 0,0,0,0
+PASS getViewport() is "0,0,300,150"
+
+change display size of canvas and see that viewport does not change
+PASS getViewport() is "0,0,300,150"
+PASS canvas.width is 300
+PASS canvas.height is 150
+
+change the actual size of the canvas and see that the viewport does not change
+PASS pixels are 64,128,192,255
+PASS gl.clearColor should not change after canvas resize
+PASS gl.colorMask should not change after canvas resize
+PASS getViewport() is "0,0,300,150"
+PASS pixels are 0,0,0,0
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+ 
diff --git a/LayoutTests/fast/canvas/webgl/canvas-test.html b/LayoutTests/fast/canvas/webgl/canvas-test.html
new file mode 100644
index 0000000..9d8e80c
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/canvas-test.html
@@ -0,0 +1,195 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<title>WebGL Canvas Conformance Tests</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="resources/desktop-gl-constants.js" type="text/javascript"></script>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
+<canvas id="canvas2d" width="40" height="40"> </canvas>
+<script>
+if (window.initNonKhronosFramework) {
+  window.initNonKhronosFramework(true);
+}
+
+description("This test ensures WebGL implementations interact correctly with the canvas tag.");
+
+debug("");
+debug("Canvas.getContext");
+
+var canvas = document.getElementById("canvas");
+var canvas2d = document.getElementById("canvas2d");
+var ctx2d = canvas2d.getContext("2d");
+var gl = create3DContext(canvas);
+if (!gl) {
+  testFailed("context does not exist");
+} else {
+  testPassed("context exists");
+
+  debug("");
+  debug("Checking canvas and WebGL interaction");
+
+  // Check that a canvas with no width or height is 300x150 pixels
+  shouldBe('canvas.width', '300');
+  shouldBe('canvas.height', '150');
+
+  // Check get a 4 value gl parameter as a csv string.
+  function getValue4v(name) {
+    var v = gl.getParameter(name);
+    var result = '' +
+        v[0] + ',' +
+        v[1] + ',' +
+        v[2] + ',' +
+        v[3];
+    return result;
+  }
+
+  function getViewport() {
+    return getValue4v(gl.VIEWPORT);
+  }
+
+  function getClearColor() {
+    return getValue4v(gl.COLOR_CLEAR_VALUE);
+  }
+
+  function isAboutEqual(a, b) {
+    return Math.abs(a - b) < 0.01;
+  }
+
+  function isAboutEqualInt(a, b) {
+    return Math.abs(a - b) < 3;
+  }
+
+  function checkCanvasContentIs(r3d,g3d,b3d,a3d) {
+    var r2d;
+    var g2d;
+    var b2d;
+    var a2d;
+
+    function checkPixel(x, y, r3d,g3d,b3d,a3d) {
+      var offset = (y * 40 + x) * 4;
+      r2d = imgData.data[offset];
+      g2d = imgData.data[offset + 1];
+      b2d = imgData.data[offset + 2];
+      a2d = imgData.data[offset + 3];
+      //debug('' + x + ', ' + y + "(" + offset + ") = " + r2d + ", " + g2d + ", " + b2d + ", " + a2d);
+      return isAboutEqualInt(r2d, r3d) &&
+             isAboutEqualInt(g2d, g3d) &&
+             isAboutEqualInt(b2d, b3d) &&
+             isAboutEqualInt(a2d, a3d);
+    }
+
+    function checkPixels(r3d,g3d,b3d,a3d) {
+      return checkPixel(0, 0, r3d, g3d, b3d, a3d) &&
+             checkPixel(0, 39, r3d, g3d, b3d, a3d) &&
+             checkPixel(39, 0, r3d, g3d, b3d, a3d) &&
+             checkPixel(39, 39, r3d, g3d, b3d, a3d) &&
+             checkPixel(0, 0, r3d, g3d, b3d, a3d);
+    };
+
+    // Set to just take the color from the 3d canvas
+    ctx2d.globalCompositeOperation = 'copy';
+
+    // fill 2d canvas with orange
+    ctx2d.fillStyle = "rgb(255,192,128)";
+    ctx2d.fillRect (0, 0, 40, 40);
+
+    // get the image data
+    var imgData = ctx2d.getImageData(0, 0, 40, 40);
+
+    // check it got cleared.
+    if (!checkPixels(255, 192, 128, 255)) {
+      testFailed("unable to fill 2d context.");
+      return;
+    }
+
+    // draw 3d canvas on top.
+    ctx2d.drawImage(canvas, 0,0, 40, 40);
+
+    // get the image data
+    var imgData = ctx2d.getImageData(0, 0, 40, 40);
+
+    // Check it's the expected color.
+    if (!checkPixels(r3d, g3d, b3d, a3d)) {
+     testFailed("pixels are " + r2d + "," + g2d + "," + b2d + "," + a2d +
+                " expected " + r3d + "," + g3d + "," + b3d + "," + a3d);
+    } else {
+      testPassed("pixels are " + r3d + "," + g3d + "," + b3d + "," + a3d);
+    }
+  }
+
+  checkCanvasContentIs(0, 0, 0, 0);
+  shouldBe('getViewport()', '"0,0,300,150"');
+
+  // Change the display size of the canvas and check
+  // the viewport size does not change.
+  debug("");
+  debug("change display size of canvas and see that viewport does not change");
+  canvas.style.width = "100px";
+  canvas.style.height = "25px";
+  var intervalId;
+  intervalId = window.setInterval(function() {
+    if (canvas.clientWidth == 100 &&
+        canvas.clientHeight == 25) {
+      window.clearInterval(intervalId);
+      shouldBe('getViewport()', '"0,0,300,150"');
+      shouldBe('canvas.width', '300');
+      shouldBe('canvas.height', '150');
+
+      // Change the actual size of the canvas
+      // Check that the viewport does not change.
+      // Check that the clear color does not change.
+      // Check that the color mask does not change.
+      debug("");
+      debug("change the actual size of the canvas and see that the viewport does not change");
+      gl.clearColor(0.25, 0.5, 0.75, 1);
+      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+      checkCanvasContentIs(64, 128, 192, 255);
+      gl.colorMask(0,0,0,0);
+      canvas.width = 400;
+      canvas.height = 10;
+
+      var v = gl.getParameter(gl.COLOR_CLEAR_VALUE);
+      assertMsg(isAboutEqual(v[0], 0.25) &&
+                isAboutEqual(v[1], 0.5) &&
+                isAboutEqual(v[2], 0.75) &&
+                isAboutEqual(v[3], 1),
+                "gl.clearColor should not change after canvas resize");
+      v = gl.getParameter(gl.COLOR_WRITEMASK);
+      assertMsg(isAboutEqual(v[0], 0) &&
+                isAboutEqual(v[1], 0) &&
+                isAboutEqual(v[2], 0) &&
+                isAboutEqual(v[3], 0),
+                "gl.colorMask should not change after canvas resize");
+      shouldBe('getViewport()', '"0,0,300,150"');
+      checkCanvasContentIs(0, 0, 0, 0);
+
+      debug("");
+      successfullyParsed = true;
+      var epilogue = document.createElement("script");
+      epilogue.onload = finish;
+      epilogue.src = "../../js/resources/js-test-post.js";
+      document.body.appendChild(epilogue);
+    }
+   }, 1000/30);
+}
+
+function finish() {
+  if (window.nonKhronosFrameworkNotifyDone) {
+    window.nonKhronosFrameworkNotifyDone();
+  }
+}
+
+</script>
+<script>
+</script>
+
+</body>
+</html>
diff --git a/LayoutTests/fast/canvas/webgl/gl-pixelstorei-expected.txt b/LayoutTests/fast/canvas/webgl/gl-pixelstorei-expected.txt
new file mode 100644
index 0000000..088ce3a
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/gl-pixelstorei-expected.txt
@@ -0,0 +1,21 @@
+    
+There should be 5 red triangles on 5 black squares above
+
+This test checks that drawImage and readPixels are not effected by gl.Pixelstorei(gl.PACK_ALIGNMENT) and visa versa
+
+PASS drawing is correct in 3d context
+PASS drawing is correct in 2d context
+PASS PACK_ALIGNMENT is 1
+PASS drawing is correct in 3d context
+PASS drawing is correct in 2d context
+PASS PACK_ALIGNMENT is 2
+PASS drawing is correct in 3d context
+PASS drawing is correct in 2d context
+PASS PACK_ALIGNMENT is 4
+PASS drawing is correct in 3d context
+PASS drawing is correct in 2d context
+PASS PACK_ALIGNMENT is 8
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/gl-pixelstorei.html b/LayoutTests/fast/canvas/webgl/gl-pixelstorei.html
new file mode 100644
index 0000000..654baed
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/gl-pixelstorei.html
@@ -0,0 +1,124 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL pixelStorei Test</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/webgl-test.js"> </script>
+<script src="resources/desktop-gl-constants.js" type="text/javascript"></script>
+</head>
+<body>
+<canvas id="example" width="50" height="50"></canvas>
+<canvas id="2d00" width="50" height="50"></canvas>
+<canvas id="2d01" width="50" height="50"></canvas>
+<canvas id="2d02" width="50" height="50"></canvas>
+<canvas id="2d03" width="50" height="50"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+void main() {
+  gl_Position = vPosition;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+void main() {
+  gl_FragColor = vec4(1.0,0.0,0.0,1.0);
+}
+</script>
+
+<script>
+function fail(x,y, name, buf, shouldBe) {
+  var i = (y*50+x) * 4;
+  var reason = "pixel in "+name+" at ("+x+","+y+") is ("+buf[i]+","+buf[i+1]+","+buf[i+2]+","+buf[i+3]+"), should be "+shouldBe;
+  testFailed(reason);
+}
+
+function pass(name) {
+  testPassed("drawing is correct in " + name);
+}
+
+function init() {
+  debug("There should be 5 red triangles on 5 black squares above");
+  debug("");
+
+  debug("This test checks that drawImage and readPixels are not effected by gl.Pixelstorei(gl.PACK_ALIGNMENT) and visa versa");
+  debug("");
+
+  var canvas3d = document.getElementById("example");
+  gl = initWebGL("example", "vshader", "fshader", [ "vPosition"], [ 0, 0, 0, 1 ], 1);
+
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 0,0.5,0, -0.5,-0.5,0, 0.5,-0.5,0 ]), gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(0);
+  gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+  gl.drawArrays(gl.TRIANGLES, 0, 3);
+
+
+  function checkData(buf, name) {
+    // Test several locations
+    // First line should be all black
+    for (var i = 0; i < 50; ++i) {
+      if (buf[i*4] != 0 || buf[i*4+1] != 0 || buf[i*4+2] != 0 || buf[i*4+3] != 255) {
+        fail(i, 0, name, buf, "(0,0,0,255)");
+        return;
+      }
+    }
+
+    // Line 25 should be red for at least 6 red pixels starting 22 pixels in
+    var offset = (25*50+22) * 4;
+    for (var i = 0; i < 6; ++i) {
+      if (buf[offset+i*4] != 255 || buf[offset+i*4+1] != 0 || buf[offset+i*4+2] != 0 || buf[offset+i*4+3] != 255) {
+        fail(22 + i, 25, name, buf, "(255,0,0,255)");
+        return;
+      }
+    }
+
+    // Last line should be all black
+    offset = (49*50) * 4;
+    for (var i = 0; i < 50; ++i) {
+      if (buf[offset+i*4] != 0 || buf[offset+i*4+1] != 0 || buf[offset+i*4+2] != 0 || buf[offset+i*4+3] != 255) {
+        fail(i, 49, name, buf, "(0,0,0,255)");
+        return;
+      }
+    }
+
+    pass(name);
+  }
+
+  function checkColors() {
+    var buf = new Uint8Array(50 * 50 * 4);
+    gl.readPixels(0, 0, 50, 50, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    checkData(buf, "3d context");
+    var imgData = ctx2d.getImageData(0, 0, 50, 50);
+    checkData(imgData.data, "2d context");
+  }
+
+  var table = [1, 2, 4, 8];
+  for (var ii = 0; ii < table.length; ++ii) {
+    gl.pixelStorei(gl.PACK_ALIGNMENT, table[ii]);
+    ctx2d = document.getElementById("2d0" + ii).getContext("2d");
+    ctx2d.globalCompositeOperation = 'copy';
+    ctx2d.drawImage(canvas3d, 0, 0);
+    checkColors();
+    assertMsg(gl.getParameter(gl.PACK_ALIGNMENT) == table[ii],
+        "PACK_ALIGNMENT is " + table[ii]);
+  }
+}
+
+init();
+successfullyParsed = true;
+</script>
+</body>
+<script src="../../js/resources/js-test-post.js"></script>
+
+<script>
+</script>
+
+</body>
+</html>
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 0c60b52..b3608fe 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,32 @@
+2010-07-13  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Nate Chapin.
+
+        WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
+        https://bugs.webkit.org/show_bug.cgi?id=34719
+
+        Tests: fast/canvas/webgl/canvas-test.html
+               fast/canvas/webgl/gl-pixelstorei.html
+
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::makeRenderingResultsAvailable): Paint the WebGL rendering results to canvas if it's 3d.
+        (WebCore::HTMLCanvasElement::toDataURL): Paint the WebGL rendering results to canvas if it's 3d.
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::drawImage): Paint the WebGL rendering results to canvas if it's 3d before drawing.
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::markContextChanged): Mark it always for canvas2d.drawImage purpose.
+        (WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas): Paint the WebGL rendering results to canvas if it's dirty.
+        * html/canvas/WebGLRenderingContext.h: Declare paintRenderingResultsToCanvas().
+        * platform/graphics/GraphicsContext3D.h: Declare paintRenderingResultsToCanvas() & paintToCanvas().
+        * platform/graphics/cg/GraphicsContext3DCG.cpp:
+        (WebCore::GraphicsContext3D::paintToCanvas): Paint the rendered image pixels to the canvas.
+        * platform/graphics/mac/GraphicsContext3DMac.mm:
+        (WebCore::GraphicsContext3D::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
+        * platform/graphics/qt/GraphicsContext3DQt.cpp:
+        (WebCore::GraphicsContext3D::beginPaint): Just call paintRenderingResultsToCanvas().
+        (WebCore::GraphicsContext3D::endPaint):
+        (WebCore::GraphicsContext3D::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
+
 2010-07-15  Nico Weber  <thakis at chromium.org>
 
         Reviewed by Ojan Vafai.
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index ffd87c4..6174f51 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -297,6 +297,16 @@ bool HTMLCanvasElement::is3D() const
 }
 #endif
 
+void HTMLCanvasElement::makeRenderingResultsAvailable()
+{
+#if ENABLE(3D_CANVAS)
+    if (is3D()) {
+        WebGLRenderingContext* context3d = reinterpret_cast<WebGLRenderingContext*>(renderingContext());
+        context3d->paintRenderingResultsToCanvas();
+    }
+#endif
+}
+
 void HTMLCanvasElement::recalcStyle(StyleChange change)
 {
     HTMLElement::recalcStyle(change);
@@ -327,6 +337,8 @@ String HTMLCanvasElement::toDataURL(const String& mimeType, const double* qualit
 
     String lowercaseMimeType = mimeType.lower();
 
+    makeRenderingResultsAvailable();
+
     // FIXME: Make isSupportedImageMIMETypeForEncoding threadsafe (to allow this method to be used on a worker thread).
     if (mimeType.isNull() || !MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(lowercaseMimeType))
         return buffer()->toDataURL("image/png");
diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h
index 05bc256..b222007 100644
--- a/WebCore/html/HTMLCanvasElement.h
+++ b/WebCore/html/HTMLCanvasElement.h
@@ -32,10 +32,6 @@
 #include "HTMLElement.h"
 #include "IntSize.h"
 
-#if ENABLE(3D_CANVAS)    
-#include "GraphicsContext3D.h"
-#endif
-
 namespace WebCore {
 
 class CanvasContextAttributes;
@@ -114,6 +110,8 @@ public:
     bool is3D() const;
 #endif
 
+    void makeRenderingResultsAvailable();
+
 private:
     HTMLCanvasElement(const QualifiedName&, Document*);
 
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index b3bafc6..c573dd8 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -1157,6 +1157,8 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
     if (!sourceCanvas->originClean())
         canvas()->setOriginTainted();
 
+    sourceCanvas->makeRenderingResultsAvailable();
+
     c->drawImage(buffer->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
     willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty.
                         // FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this.
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index 2bbcad1..35dc64a 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -141,17 +141,23 @@ void WebGLRenderingContext::markContextChanged()
     RenderBox* renderBox = canvas()->renderBox();
     if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
         renderBox->layer()->rendererContentChanged();
-    else {
 #endif
-        if (!m_markedCanvasDirty) {
-            // Make sure the canvas's image buffer is allocated.
-            canvas()->buffer();
-            canvas()->willDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
-            m_markedCanvasDirty = true;
-        }
-#if USE(ACCELERATED_COMPOSITING)
+    if (!m_markedCanvasDirty) {
+        // Make sure the canvas's image buffer is allocated.
+        canvas()->buffer();
+        canvas()->willDraw(FloatRect(0, 0, canvas()->width(), canvas()->height()));
+        m_markedCanvasDirty = true;
     }
-#endif
+}
+
+bool WebGLRenderingContext::paintRenderingResultsToCanvas()
+{
+    if (m_markedCanvasDirty) {
+        m_markedCanvasDirty = false;
+        m_context->paintRenderingResultsToCanvas(this);
+        return true;
+    }
+    return false;
 }
 
 void WebGLRenderingContext::beginPaint()
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index fa0d9d0..1dd7d53 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -306,6 +306,10 @@ class WebKitCSSMatrix;
     
         void reshape(int width, int height);
 
+        // Return value true indicates canvas is updated during the call,
+        // false indicates no updates.
+        bool paintRenderingResultsToCanvas();
+
         // Helpers for notification about paint events.
         void beginPaint();
         void endPaint();
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index 2887e62..28388f4 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -68,6 +68,10 @@ typedef int Platform3DObject;
 const Platform3DObject NullPlatform3DObject = 0;
 #endif
 
+#if PLATFORM(CG)
+#include <CoreGraphics/CGContext.h>
+#endif
+
 namespace WebCore {
     class WebGLActiveInfo;
     class ArrayBuffer;
@@ -710,7 +714,14 @@ namespace WebCore {
         void viewport(long x, long y, unsigned long width, unsigned long height);
 
         void reshape(int width, int height);
-        
+
+#if PLATFORM(CG)
+        void paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight,
+                           int canvasWidth, int canvasHeight, CGContextRef context);
+#endif
+
+        void paintRenderingResultsToCanvas(WebGLRenderingContext* context);
+
         // Helpers for notification about paint events
         void beginPaint(WebGLRenderingContext* context);
         void endPaint();
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index 9f0f353..8af3d0e 100644
--- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -36,6 +36,8 @@
 #include <CoreGraphics/CGContext.h>
 #include <CoreGraphics/CGImage.h>
 
+#include <wtf/RetainPtr.h>
+
 namespace WebCore {
 
 bool GraphicsContext3D::getImageData(Image* image,
@@ -104,6 +106,41 @@ bool GraphicsContext3D::getImageData(Image* image,
                       format, type, neededAlphaOp, outputVector.data());
 }
 
+void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, CGContextRef context)
+{
+    if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
+        return;
+    int rowBytes = imageWidth * 4;
+    RetainPtr<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(0, imagePixels, rowBytes * imageHeight, 0);
+    RetainPtr<CGColorSpaceRef> colorSpace = CGColorSpaceCreateDeviceRGB();
+    RetainPtr<CGImageRef> cgImage = CGImageCreate(imageWidth,
+                                                  imageHeight,
+                                                  8,
+                                                  32,
+                                                  rowBytes,
+                                                  colorSpace.get(),
+                                                  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);
+    // 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);
+}
 
 } // namespace WebCore
 
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index ae9ace2..57664b6 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -39,10 +39,13 @@
 #include "WebGLBuffer.h"
 #include "Float32Array.h"
 #include "WebGLFramebuffer.h"
+#include "GraphicsContext.h"
+#include "HTMLCanvasElement.h"
 #include "Int32Array.h"
 #include "WebGLLayer.h"
 #include "WebGLProgram.h"
 #include "WebGLRenderbuffer.h"
+#include "WebGLRenderingContext.h"
 #include "WebGLShader.h"
 #include "WebGLTexture.h"
 #include "Uint8Array.h"
@@ -237,6 +240,54 @@ void GraphicsContext3D::makeContextCurrent()
     CGLSetCurrentContext(m_contextObj);
 }
 
+void GraphicsContext3D::paintRenderingResultsToCanvas(WebGLRenderingContext* context)
+{
+    HTMLCanvasElement* canvas = context->canvas();
+    ImageBuffer* imageBuffer = canvas->buffer();
+
+    int rowBytes = m_currentWidth * 4;
+    int totalBytes = rowBytes * m_currentHeight;
+
+    OwnArrayPtr<unsigned char> pixels(new unsigned char[totalBytes]);
+    if (!pixels)
+        return;
+
+    CGLSetCurrentContext(m_contextObj);
+
+    bool mustRestoreFBO;
+    if (m_attrs.antialias) {
+        ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
+        ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
+        ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
+        ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+        mustRestoreFBO = true;
+    } else {
+        if (m_boundFBO != m_fbo) {
+            mustRestoreFBO = true;
+            ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
+        }
+    }
+
+    GLint packAlignment = 4;
+    bool mustRestorePackAlignment = false;
+    ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment);
+    if (packAlignment > 4) {
+        ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
+        mustRestorePackAlignment = true;
+    }
+
+    ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels.get());
+
+    if (mustRestorePackAlignment)
+        ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
+
+    if (mustRestoreFBO)
+        ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
+
+    paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
+                  canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
+}
+
 void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
 {
     UNUSED_PARAM(context);
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 002765f..311d3a3 100644
--- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -521,6 +521,15 @@ void GraphicsContext3D::makeContextCurrent()
 
 void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
 {
+    paintRenderingResultsToCanvas();
+}
+
+void GraphicsContext3D::endPaint()
+{
+}
+
+void GraphicsContext3D::paintRenderingResultsToCanvas(WebGLRenderingContext* context)
+{
     m_internal->m_glWidget->makeCurrent();
     HTMLCanvasElement* canvas = context->canvas();
     ImageBuffer* imageBuffer = canvas->buffer();
@@ -528,10 +537,6 @@ void GraphicsContext3D::beginPaint(WebGLRenderingContext* context)
     paint(painter, QRect(QPoint(0, 0), QSize(m_currentWidth, m_currentHeight)));
 }
 
-void GraphicsContext3D::endPaint()
-{
-}
-
 void GraphicsContext3D::paint(QPainter* painter, const QRect& rect) const
 {
 #if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
diff --git a/WebKit/chromium/ChangeLog b/WebKit/chromium/ChangeLog
index 43bf858..5c48757 100644
--- a/WebKit/chromium/ChangeLog
+++ b/WebKit/chromium/ChangeLog
@@ -1,3 +1,14 @@
+2010-07-13  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Nate Chapin.
+
+        WebGL rendering results must be made available to Canvas.toDataURL and 2D drawImage
+        https://bugs.webkit.org/show_bug.cgi?id=34719
+
+        * src/GraphicsContext3D.cpp:
+        (WebCore::GraphicsContext3DInternal::paintRenderingResultsToCanvas): Implement paintRenderingResultsToCanvas().
+        (WebCore::GraphicsContext3DInternal::beginPaint): Just use paintRenderingResultsToCanvas().
+
 2010-07-15  Victor Wang  <victorw at chromium.org>
 
         Reviewed by David Levin.
diff --git a/WebKit/chromium/src/GraphicsContext3D.cpp b/WebKit/chromium/src/GraphicsContext3D.cpp
index aad9645..fec0b20 100644
--- a/WebKit/chromium/src/GraphicsContext3D.cpp
+++ b/WebKit/chromium/src/GraphicsContext3D.cpp
@@ -112,6 +112,7 @@ public:
 
     void reshape(int width, int height);
 
+    void paintRenderingResultsToCanvas(WebGLRenderingContext* context);
     void beginPaint(WebGLRenderingContext* context);
     void endPaint();
 
@@ -399,7 +400,7 @@ WebGLLayerChromium* GraphicsContext3DInternal::platformLayer() const
 }
 #endif
 
-void GraphicsContext3DInternal::beginPaint(WebGLRenderingContext* context)
+void GraphicsContext3DInternal::paintRenderingResultsToCanvas(WebGLRenderingContext* context)
 {
     HTMLCanvasElement* canvas = context->canvas();
     ImageBuffer* imageBuffer = canvas->buffer();
@@ -449,44 +450,20 @@ void GraphicsContext3DInternal::beginPaint(WebGLRenderingContext* context)
         canvas.drawBitmapRect(m_resizingBitmap, 0, dst);
     }
 #elif PLATFORM(CG)
-    if (m_renderOutput) {
-        int rowBytes = m_impl->width() * 4;
-        CGDataProviderRef dataProvider = CGDataProviderCreateWithData(0, m_renderOutput, rowBytes * m_impl->height(), 0);
-        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-        CGImageRef cgImage = CGImageCreate(m_impl->width(),
-                                           m_impl->height(),
-                                           8,
-                                           32,
-                                           rowBytes,
-                                           colorSpace,
-                                           kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
-                                           dataProvider,
-                                           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,
-                                 context->canvas()->width(),
-                                 context->canvas()->height());
-        // We want to completely overwrite the previous frame's
-        // rendering results.
-        CGContextSetBlendMode(imageBuffer->context()->platformContext(),
-                              kCGBlendModeCopy);
-        CGContextSetInterpolationQuality(imageBuffer->context()->platformContext(),
-                                         kCGInterpolationNone);
-        CGContextDrawImage(imageBuffer->context()->platformContext(),
-                           rect, cgImage);
-        CGImageRelease(cgImage);
-        CGColorSpaceRelease(colorSpace);
-        CGDataProviderRelease(dataProvider);
-    }
+    if (m_renderOutput)
+        context->graphicsContext3D()->paintToCanvas(m_renderOutput, m_impl->width(), m_impl->height(),
+                                                    canvas->width(), canvas->height(),
+                                                    imageBuffer->context()->platformContext());
 #else
 #error Must port to your platform
 #endif
 }
 
+void GraphicsContext3DInternal::beginPaint(WebGLRenderingContext* context)
+{
+    paintRenderingResultsToCanvas(context);
+}
+
 void GraphicsContext3DInternal::endPaint()
 {
 }
@@ -1325,6 +1302,7 @@ DELEGATE_TO_INTERNAL_6(vertexAttribPointer, unsigned long, int, int, bool, unsig
 
 DELEGATE_TO_INTERNAL_4(viewport, long, long, unsigned long, unsigned long)
 
+DELEGATE_TO_INTERNAL_1(paintRenderingResultsToCanvas, WebGLRenderingContext*)
 DELEGATE_TO_INTERNAL_1(beginPaint, WebGLRenderingContext*)
 DELEGATE_TO_INTERNAL(endPaint)
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list