Title: [194933] trunk
Revision
194933
Author
[email protected]
Date
2016-01-12 16:10:26 -0800 (Tue, 12 Jan 2016)

Log Message

[iOS] Antialiasing doesn't work in WebGL
https://bugs.webkit.org/show_bug.cgi?id=153000
<rdar://problem/9165531>

Reviewed by Alex Christensen.

Source/WebCore:

WebGL has supported platform antialiasing since
the beginning, but we never hooked it up for iOS
because it used a slightly different extension.

Test: fast/canvas/webgl/antialiasing-enabled.html

* platform/graphics/mac/GraphicsContext3DMac.mm:
(WebCore::GraphicsContext3D::endPaint): Resolve the multisampling
buffer once we're done painting.
(WebCore::GraphicsContext3D::~GraphicsContext3D): We never created
the m_compositorTexture RenderBuffer on iOS, so no point deleting
it.

* platform/graphics/opengl/Extensions3DOpenGL.cpp:
(WebCore::Extensions3DOpenGL::supportsExtension): The iOS extension
has a slightly different name.
* platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
(WebCore::GraphicsContext3D::reshapeFBOs): Make sure to create the
multisample buffer with the correct format.
(WebCore::GraphicsContext3D::resolveMultisamplingIfNecessary): We
need to remember what our bound frame buffer is when we
enter this call, and restore it afterwards. In the middle we can
discard our multisample read buffer once we have resolved it
into the normal framebuffer.

LayoutTests:

New test to check if WebGL antialiasing happened on a rendered canvas.

* fast/canvas/webgl/antialiasing-enabled-expected.txt: Added.
* fast/canvas/webgl/antialiasing-enabled.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (194932 => 194933)


--- trunk/LayoutTests/ChangeLog	2016-01-13 00:04:25 UTC (rev 194932)
+++ trunk/LayoutTests/ChangeLog	2016-01-13 00:10:26 UTC (rev 194933)
@@ -1,3 +1,16 @@
+2016-01-12  Dean Jackson  <[email protected]>
+
+        [iOS] Antialiasing doesn't work in WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=153000
+        <rdar://problem/9165531>
+
+        Reviewed by Alex Christensen.
+
+        New test to check if WebGL antialiasing happened on a rendered canvas.
+
+        * fast/canvas/webgl/antialiasing-enabled-expected.txt: Added.
+        * fast/canvas/webgl/antialiasing-enabled.html: Added.
+
 2016-01-12  Ryan Haddad  <[email protected]>
 
         Skipped more tests related to picture element on ios-simulator and grouped them together in TestExpectations file.

Added: trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled-expected.txt (0 => 194933)


--- trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled-expected.txt	2016-01-13 00:10:26 UTC (rev 194933)
@@ -0,0 +1,5 @@
+To check anti-aliasing, we draw a triangle over half of a 2x2 quad, then check the pixel colors in the corners. Note that if you're looking at the rendering results on a high-dpi display you will see some artefacts as the canvas is scaled by the page zoom. Don't mistake that for anti-aliasing (the test code doesn't).
+
+PASS: top left corner was fully black.
+PASS: top right corner did not have a completely solid red channel.
+
Property changes on: trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled-expected.txt
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Added: trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled.html (0 => 194933)


--- trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled.html	2016-01-13 00:10:26 UTC (rev 194933)
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<head>
+    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
+<title>WebGL Triangle</title>
+<style>
+canvas {
+    width: 2px;
+    height: 2px;
+}
+</style>
+</head>
+<script id="vertexShaderSource" type="text/glsl">
+attribute vec4 position;
+void main() {
+  gl_Position = position;
+}
+</script>
+<script id="fragmentShaderSource" type="text/glsl">
+#ifdef GL_ES
+precision mediump float;
+#endif
+
+void main() {
+  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+</script>
+<script>
+
+if (window.testRunner) {
+    window.testRunner.waitUntilDone();
+    window.testRunner.dumpAsText();
+    window.testRunner.overridePreference("WebKitWebGLEnabled", "1");
+}
+
+function logResult(message) {
+    var output = document.getElementById("results");
+    output.innerHTML += message + "<br>";
+}
+
+function drawTriangle(canvas) {
+
+    canvas.width = 2;
+    canvas.height = 2;
+
+    var gl = canvas.getContext("webgl", { antialias: true });
+
+    if (!gl) {
+        logResult("ERROR: Couldn't create WebGL context.");
+        return;
+    }
+
+    if (!gl.getContextAttributes().antialias) {
+        logResult("ERROR: Antialiasing was not enabled at creation time.");
+        return;
+    }
+
+    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+
+    gl.shaderSource(vertexShader, document.getElementById("vertexShaderSource").textContent);
+
+    gl.compileShader(vertexShader);
+    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
+        logResult("ERROR: Vertex Shader failed to compile.");
+        logResult(gl.getShaderInfoLog(vertexShader));
+        return;
+    }
+
+    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fragmentShader, document.getElementById("fragmentShaderSource").textContent);
+    gl.compileShader(fragmentShader);
+    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
+        logResult("ERROR: Fragment Shader failed to compile.");
+        logResult(gl.getShaderInfoLog(fragmentShader));
+        return;
+    }
+
+    var program = gl.createProgram();
+    gl.attachShader(program, vertexShader);
+    gl.attachShader(program, fragmentShader);
+    gl.linkProgram(program);
+
+    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+        logResult("ERROR: Unable to link shaders into program.");
+        return;
+    }
+
+    gl.useProgram(program);
+    var positionAttribute = gl.getAttribLocation(program, "position");
+    gl.enableVertexAttribArray(positionAttribute);
+
+    var vertices = new Float32Array([
+       -1.0, -1.0,
+       1.0, -1.0,
+       1.0, 1.0
+    ]);
+    var triangleBuffer = gl.createBuffer();
+
+    gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+    gl.clearColor(0, 0, 0, 1);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+    gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);
+    gl.vertexAttribPointer(positionAttribute, 2, gl.FLOAT, false, 0, 0);
+
+    gl.drawArrays(gl.TRIANGLES, 0, 3);
+}
+
+function pixelAt(cssX, cssY, buffer) {
+    // Remember that "top" in CSS coordinates is the last row in WebGL. i.e. things are upside down.
+    var col = cssX;
+    var row = 1 - cssY;
+    return {
+        r: buffer[(row * 2 + col) * 4 + 0],
+        g: buffer[(row * 2 + col) * 4 + 1],
+        b: buffer[(row * 2 + col) * 4 + 2],
+        a: buffer[(row * 2 + col) * 4 + 3],
+    };
+}
+
+function pixelToString(pixel) {
+    return "{r: " + pixel.r + ", g: " + pixel.g + ", b: " + pixel.b + ", a: " + pixel.a + "}";
+}
+
+function testOutput(canvas) {
+    
+    var gl = canvas.getContext("webgl");
+    
+    if (!gl) {
+        logResult("FAIL: No WebGL context to examine.");
+        return;
+    }
+    
+    var imageBuffer = new Uint8Array(canvas.width * canvas.height * 4);
+    gl.readPixels(0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, imageBuffer);
+
+    // Check that the top left pixel is fully black.
+    var topLeft = pixelAt(0, 0, imageBuffer);
+    if (topLeft.r != 0 || topLeft.g != 0 || topLeft.b != 0 || topLeft.a != 255) {
+        logResult("FAIL: top left corner was not fully black. " + pixelToString(topLeft));
+        return;
+    }
+    logResult("PASS: top left corner was fully black.");
+    
+    // Check that the top right pixel isn't fully red. If it is, it implies we didn't multisample.
+    var topRight = pixelAt(1, 0, imageBuffer);
+    if (topRight.r == 255) {
+        logResult("FAIL: top right corner had a solid red channel. " + pixelToString(topRight));
+        return;
+    }
+    logResult("PASS: top right corner did not have a completely solid red channel.");
+}
+
+window.addEventListener("load", function () {
+    var canvas = document.querySelector("canvas");
+    drawTriangle(canvas);
+    testOutput(canvas);
+    if (window.testRunner)
+        window.testRunner.notifyDone();
+}, false);
+</script>
+<body>
+    <p>To check anti-aliasing, we draw a triangle over half of a 2x2 quad, then check the pixel colors
+    in the corners. Note that if you're looking at the rendering results on a high-dpi display
+    you will see some artefacts as the canvas is scaled by the page zoom. Don't mistake that for
+    anti-aliasing (the test code doesn't).</p>
+    <canvas></canvas>
+    <p id="results"></p>
+</body>
\ No newline at end of file
Property changes on: trunk/LayoutTests/fast/canvas/webgl/antialiasing-enabled.html
___________________________________________________________________

Added: svn:mime-type

Added: svn:keywords

Added: svn:eol-style

Modified: trunk/Source/WebCore/ChangeLog (194932 => 194933)


--- trunk/Source/WebCore/ChangeLog	2016-01-13 00:04:25 UTC (rev 194932)
+++ trunk/Source/WebCore/ChangeLog	2016-01-13 00:10:26 UTC (rev 194933)
@@ -1,3 +1,36 @@
+2016-01-11  Dean Jackson  <[email protected]>
+
+        [iOS] Antialiasing doesn't work in WebGL
+        https://bugs.webkit.org/show_bug.cgi?id=153000
+        <rdar://problem/9165531>
+
+        Reviewed by Alex Christensen.
+
+        WebGL has supported platform antialiasing since
+        the beginning, but we never hooked it up for iOS
+        because it used a slightly different extension.
+
+        Test: fast/canvas/webgl/antialiasing-enabled.html
+
+        * platform/graphics/mac/GraphicsContext3DMac.mm:
+        (WebCore::GraphicsContext3D::endPaint): Resolve the multisampling
+        buffer once we're done painting.
+        (WebCore::GraphicsContext3D::~GraphicsContext3D): We never created
+        the m_compositorTexture RenderBuffer on iOS, so no point deleting
+        it.
+
+        * platform/graphics/opengl/Extensions3DOpenGL.cpp:
+        (WebCore::Extensions3DOpenGL::supportsExtension): The iOS extension
+        has a slightly different name.
+        * platform/graphics/opengl/GraphicsContext3DOpenGL.cpp:
+        (WebCore::GraphicsContext3D::reshapeFBOs): Make sure to create the
+        multisample buffer with the correct format.
+        (WebCore::GraphicsContext3D::resolveMultisamplingIfNecessary): We
+        need to remember what our bound frame buffer is when we
+        enter this call, and restore it afterwards. In the middle we can
+        discard our multisample read buffer once we have resolved it
+        into the normal framebuffer.
+
 2016-01-12  Daniel Bates  <[email protected]>
 
         XSS Auditor should navigate to empty substitute data on full page block

Modified: trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm (194932 => 194933)


--- trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm	2016-01-13 00:04:25 UTC (rev 194932)
+++ trunk/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm	2016-01-13 00:10:26 UTC (rev 194933)
@@ -314,7 +314,6 @@
         makeContextCurrent();
         [m_contextObj renderbufferStorage:GL_RENDERBUFFER fromDrawable:nil];
         ::glDeleteRenderbuffers(1, &m_texture);
-        ::glDeleteRenderbuffers(1, &m_compositorTexture);
 #else
         CGLSetCurrentContext(m_contextObj);
         ::glDeleteTextures(1, &m_texture);
@@ -401,6 +400,8 @@
 void GraphicsContext3D::endPaint()
 {
     makeContextCurrent();
+    if (m_attrs.antialias)
+        resolveMultisamplingIfNecessary();
     ::glFlush();
     ::glBindRenderbuffer(GL_RENDERBUFFER, m_texture);
     [static_cast<EAGLContext*>(m_contextObj) presentRenderbuffer:GL_RENDERBUFFER];

Modified: trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp (194932 => 194933)


--- trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp	2016-01-13 00:04:25 UTC (rev 194932)
+++ trunk/Source/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp	2016-01-13 00:10:26 UTC (rev 194933)
@@ -156,11 +156,15 @@
 bool Extensions3DOpenGL::supportsExtension(const String& name)
 {
     // GL_ANGLE_framebuffer_blit and GL_ANGLE_framebuffer_multisample are "fake". They are implemented using other
-    // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample
+    // extensions. In particular GL_EXT_framebuffer_blit and GL_EXT_framebuffer_multisample/GL_APPLE_framebuffer_multisample.
     if (name == "GL_ANGLE_framebuffer_blit")
         return m_availableExtensions.contains("GL_EXT_framebuffer_blit");
     if (name == "GL_ANGLE_framebuffer_multisample")
+#if PLATFORM(IOS)
+        return m_availableExtensions.contains("GL_APPLE_framebuffer_multisample");
+#else
         return m_availableExtensions.contains("GL_EXT_framebuffer_multisample");
+#endif
 
     if (name == "GL_ANGLE_instanced_arrays") {
         return (m_availableExtensions.contains("GL_ARB_instanced_arrays") || m_availableExtensions.contains("GL_EXT_instanced_arrays"))

Modified: trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp (194932 => 194933)


--- trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp	2016-01-13 00:04:25 UTC (rev 194932)
+++ trunk/Source/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp	2016-01-13 00:10:26 UTC (rev 194933)
@@ -139,7 +139,11 @@
             sampleCount = maxSampleCount;
         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
         ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
+#if PLATFORM(IOS)
+        ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, GL_RGBA8_OES, width, height);
+#else
         ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height);
+#endif
         ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
         if (m_attrs.stencil || m_attrs.depth) {
             ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
@@ -221,11 +225,17 @@
     TemporaryOpenGLSetting scopedDepth(GL_DEPTH_TEST, GL_FALSE);
     TemporaryOpenGLSetting scopedStencil(GL_STENCIL_TEST, GL_FALSE);
 
+    GLint boundFrameBuffer;
+    ::glGetIntegerv(GL_FRAMEBUFFER_BINDING, &boundFrameBuffer);
+
     ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
     ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
 #if PLATFORM(IOS)
     UNUSED_PARAM(rect);
     ::glResolveMultisampleFramebufferAPPLE();
+    const GLenum discards[] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
+    ::glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE, 2, discards);
+    ::glBindFramebuffer(GL_FRAMEBUFFER, boundFrameBuffer);
 #else
     IntRect resolveRect = rect;
     if (rect.isEmpty())
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to