Title: [266189] trunk
Revision
266189
Author
[email protected]
Date
2020-08-26 13:42:28 -0700 (Wed, 26 Aug 2020)

Log Message

Flickering on sedona.dev
https://bugs.webkit.org/show_bug.cgi?id=215141

Reviewed by Darin Adler.

Source/WebCore:

Test: fast/canvas/webgl/compositing-without-drawing.html

Our logic to determine if a canvas needs to be "repainted"
was over-zealous for WebGL. We were marking any context
that called draw commands as dirty, but they could in fact
be rendering to an offscreen texture/framebuffer. Then, when
it came time to composite, we'd happily swap buffers and
show something that had never been rendered to.

The fix is simply to ignore any of the dirtying notifications
when we are not bound to the default (canvas) framebuffer.

* html/canvas/WebGLRenderingContextBase.cpp:
(WebCore::WebGLRenderingContextBase::markContextChangedAndNotifyCanvasObserver): Only
mark if we're rendering to the default framebuffer.

LayoutTests:

Test that serves an animation frame that touches
WebGL, but not in a way that requires a recomposite.

* fast/canvas/webgl/compositing-without-drawing-expected.html: Added.
* fast/canvas/webgl/compositing-without-drawing.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (266188 => 266189)


--- trunk/LayoutTests/ChangeLog	2020-08-26 20:32:40 UTC (rev 266188)
+++ trunk/LayoutTests/ChangeLog	2020-08-26 20:42:28 UTC (rev 266189)
@@ -1,3 +1,16 @@
+2020-08-26  Dean Jackson  <[email protected]>
+
+        Flickering on sedona.dev
+        https://bugs.webkit.org/show_bug.cgi?id=215141
+
+        Reviewed by Darin Adler.
+
+        Test that serves an animation frame that touches
+        WebGL, but not in a way that requires a recomposite.
+
+        * fast/canvas/webgl/compositing-without-drawing-expected.html: Added.
+        * fast/canvas/webgl/compositing-without-drawing.html: Added.
+
 2020-08-26  Alex Christensen  <[email protected]>
 
         Implement DataTransfer constructor and multipart form filename encoding as other browsers do

Added: trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing-expected.html (0 => 266189)


--- trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing-expected.html	2020-08-26 20:42:28 UTC (rev 266189)
@@ -0,0 +1,101 @@
+<style>
+body {
+    font-family: monospace;
+}
+canvas {
+    width: 10px;
+    height: 10px;
+}
+</style>
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+}
+
+const WIDTH = 10;
+const HEIGHT = 10;
+
+const COLORS = [
+    [0, 0, 1, 1],
+    [0, 1, 1, 1],
+    [0, 0.5, 0, 1],
+    [1, 0, 1, 1],
+    [1, 1, 0.5, 1],
+    [0.5, 0, 1, 1],
+    [0.5, 0.5, 0.5, 1],
+    [0.5, 0.5, 1, 1],
+    [0.25, 1, 1, 1],
+    [0, 1, 0, 1]
+];
+
+let gl;
+let currentFrame = 0;
+
+function output(msg) {
+    const div = document.getElementById("output");
+    div.innerHTML += `${msg}<br>`;
+}
+
+function step1() {
+
+    output("Step 1. Create a WebGL canvas and render into it.");
+    output("We do this for 10 frames, each time a different color ending in pure green (0, 1, 0, 1).");
+    output("-----");
+
+    const canvas = document.querySelector("canvas");
+    canvas.width = WIDTH;
+    canvas.height = HEIGHT;
+
+    output("Create WebGL context");
+
+    gl = canvas.getContext("webgl");
+
+    function clearToColor() {
+        if (currentFrame >= COLORS.length) {
+            requestAnimationFrame(step2);
+            return;
+        }
+
+        output(`Clear to ${COLORS[currentFrame]}`);
+
+        gl.clearColor(...COLORS[currentFrame]);
+        gl.clear(gl.COLOR_BUFFER_BIT);
+
+        currentFrame++;
+        requestAnimationFrame(clearToColor);
+    }
+
+    clearToColor();
+}
+
+function step2() {
+
+    output("");
+    output("Step 2. Create a framebuffer and render into it, but don't draw into the canvas.");
+    output("-----");
+
+    output("Create a texture");
+
+    // THIS IS WHERE WE CREATE THE TEXTURE IN THE ACTUAL TEST.
+
+    output("Create and bind framebuffer");
+
+    // THIS IS WHERE WE CREATE THE FRAMEBUFFER IN THE ACTUAL TEST.
+
+    output("Clear framebuffer to red (1, 0, 0, 1). This was not used above.");
+
+    // DON'T DO ANYTHING HERE.
+
+    output("The canvas above should be green.");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function runTest() {
+    requestAnimationFrame(step1);
+}
+
+window.addEventListener("load", runTest, false);
+</script>
+<canvas></canvas>
+<div id="output"></div>
Property changes on: trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing-expected.html
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Date Revision \ No newline at end of property

Added: svn:mime-type

+text/html \ No newline at end of property

Added: trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing.html (0 => 266189)


--- trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing.html	2020-08-26 20:42:28 UTC (rev 266189)
@@ -0,0 +1,112 @@
+<style>
+body {
+    font-family: monospace;
+}
+canvas {
+    width: 10px;
+    height: 10px;
+}
+</style>
+<script>
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+}
+
+const WIDTH = 10;
+const HEIGHT = 10;
+
+const COLORS = [
+    [0, 0, 1, 1],
+    [0, 1, 1, 1],
+    [0, 0.5, 0, 1],
+    [1, 0, 1, 1],
+    [1, 1, 0.5, 1],
+    [0.5, 0, 1, 1],
+    [0.5, 0.5, 0.5, 1],
+    [0.5, 0.5, 1, 1],
+    [0.25, 1, 1, 1],
+    [0, 1, 0, 1]
+];
+
+let gl;
+let currentFrame = 0;
+
+function output(msg) {
+    const div = document.getElementById("output");
+    div.innerHTML += `${msg}<br>`;
+}
+
+function step1() {
+
+    output("Step 1. Create a WebGL canvas and render into it.");
+    output("We do this for 10 frames, each time a different color ending in pure green (0, 1, 0, 1).");
+    output("-----");
+
+    const canvas = document.querySelector("canvas");
+    canvas.width = WIDTH;
+    canvas.height = HEIGHT;
+
+    output("Create WebGL context");
+
+    gl = canvas.getContext("webgl");
+
+    function clearToColor() {
+        if (currentFrame >= COLORS.length) {
+            requestAnimationFrame(step2);
+            return;
+        }
+
+        output(`Clear to ${COLORS[currentFrame]}`);
+
+        gl.clearColor(...COLORS[currentFrame]);
+        gl.clear(gl.COLOR_BUFFER_BIT);
+
+        currentFrame++;
+        requestAnimationFrame(clearToColor);
+    }
+
+    clearToColor();
+}
+
+function step2() {
+
+    output("");
+    output("Step 2. Create a framebuffer and render into it, but don't draw into the canvas.");
+    output("-----");
+
+    output("Create a texture");
+
+    const texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, WIDTH, HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
+
+    output("Create and bind framebuffer");
+
+    const framebuffer = gl.createFramebuffer();
+    gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
+    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
+
+    output("Clear framebuffer to red (1, 0, 0, 1). This was not used above.");
+
+    gl.clearColor(1, 0, 0, 1);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+
+    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
+
+    output("The canvas above should be green.");
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+function runTest() {
+    requestAnimationFrame(step1);
+}
+
+window.addEventListener("load", runTest, false);
+</script>
+<canvas></canvas>
+<div id="output"></div>
Property changes on: trunk/LayoutTests/fast/canvas/webgl/compositing-without-drawing.html
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Date Revision \ No newline at end of property

Added: svn:mime-type

+text/html \ No newline at end of property

Modified: trunk/Source/WebCore/ChangeLog (266188 => 266189)


--- trunk/Source/WebCore/ChangeLog	2020-08-26 20:32:40 UTC (rev 266188)
+++ trunk/Source/WebCore/ChangeLog	2020-08-26 20:42:28 UTC (rev 266189)
@@ -1,3 +1,26 @@
+2020-08-26  Dean Jackson  <[email protected]>
+
+        Flickering on sedona.dev
+        https://bugs.webkit.org/show_bug.cgi?id=215141
+
+        Reviewed by Darin Adler.
+
+        Test: fast/canvas/webgl/compositing-without-drawing.html
+
+        Our logic to determine if a canvas needs to be "repainted"
+        was over-zealous for WebGL. We were marking any context
+        that called draw commands as dirty, but they could in fact
+        be rendering to an offscreen texture/framebuffer. Then, when
+        it came time to composite, we'd happily swap buffers and
+        show something that had never been rendered to.
+
+        The fix is simply to ignore any of the dirtying notifications
+        when we are not bound to the default (canvas) framebuffer.
+
+        * html/canvas/WebGLRenderingContextBase.cpp:
+        (WebCore::WebGLRenderingContextBase::markContextChangedAndNotifyCanvasObserver): Only
+        mark if we're rendering to the default framebuffer.
+
 2020-08-26  Alex Christensen  <[email protected]>
 
         Implement DataTransfer constructor and multipart form filename encoding as other browsers do

Modified: trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp (266188 => 266189)


--- trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-08-26 20:32:40 UTC (rev 266188)
+++ trunk/Source/WebCore/html/canvas/WebGLRenderingContextBase.cpp	2020-08-26 20:42:28 UTC (rev 266189)
@@ -1086,6 +1086,10 @@
 
 void WebGLRenderingContextBase::markContextChangedAndNotifyCanvasObserver()
 {
+    // If we're not touching the default framebuffer, nothing visible has changed.
+    if (m_framebufferBinding)
+        return;
+
     markContextChanged();
     if (!isAccelerated())
         return;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to