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())