Log Message
Reuse buffer allocation if canvas size does not change https://bugs.webkit.org/show_bug.cgi?id=80871
Patch by Sami Kyostila <[email protected]> on 2012-03-23 Reviewed by Stephen White. Source/WebCore: If the user changes the width or height attributes of a canvas element, the contents of the canvas should be cleared and the context state should be reset. This has become a common idiom to clear the canvas "efficiently" at the start of a frame. Previously, this code path triggered a full reallocation of the image buffer backing the canvas, leading to reduced performance. This patch implements an optimization where we reuse the previous image buffer allocation if the size of the canvas did not change. Also, instead of clearing the canvas every time its dimensions are touched, we only clear if anything has been drawn into the canvas since it was previously cleared. Note that for now this optimization only applies for 2D canvases, since it is not entirely clear how touching the dimensions of a WebGL canvas should work. Test: fast/canvas/canvas-resize-after-paint-without-layout.html + existing layout tests for canvas resetting. * html/HTMLCanvasElement.cpp: (WebCore::HTMLCanvasElement::HTMLCanvasElement): (WebCore::HTMLCanvasElement::reset): (WebCore::HTMLCanvasElement::createImageBuffer): Save the initial graphics context state so we can restore it without creating a new context. (WebCore::HTMLCanvasElement::clearImageBuffer): (WebCore): (WebCore::HTMLCanvasElement::clearCopiedImage): * html/HTMLCanvasElement.h: (HTMLCanvasElement): * html/canvas/CanvasRenderingContext2D.cpp: (WebCore::CanvasRenderingContext2D::reset): No need to notify the compositor when the context is reset, because clearing the image buffer does the same thing. We can also skip the notification if we did not have an image buffer at the time of the reset, because the reset will not have any visual impact in this case. Finally, if the canvas size did change, the notification is also unnecessary because of the call to RenderObject::repaint() from HTMLCanvasElement::reset(). LayoutTests: Add layout test to check canvas resizing without changing its layout size. We also update the expected image one canvas clearing test. The test is setting the size of a canvas and expecting it to be cleared in the process. With the optimization to retain the underlying ImageBuffer, we no longer call RenderReplaced::repaint() as a part of this process. This function used to repaint both the canvas itself (100x50) as well as its local selection rectangle (100x54). In this case the local selection rectangle is larger than the canvas because the canvas is contained within an anonymous RenderBlock that also has two empty text nodes. The extra 4 pixels are needed for drawing the selection rectangle around any descenders in the the text of those nodes. Since clearing the canvas has no effect on the selection rectangle, we only need to repaint the area of the canvas itself. * fast/canvas/canvas-resize-after-paint-without-layout.html: Added. * fast/canvas/canvas-resize-after-paint-without-layout-expected.txt: Added. * platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png: Added. * platform/chromium-linux/fast/canvas/setWidthResetAfterForcedRender-expected.png: Updated.
Modified Paths
- trunk/LayoutTests/ChangeLog
- trunk/LayoutTests/platform/chromium-linux/fast/canvas/setWidthResetAfterForcedRender-expected.png
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/html/HTMLCanvasElement.cpp
- trunk/Source/WebCore/html/HTMLCanvasElement.h
- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Added Paths
- trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout-expected.txt
- trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout.html
- trunk/LayoutTests/platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png
- trunk/LayoutTests/platform/chromium-linux/platform/chromium/virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout-expected.png
Diff
Modified: trunk/LayoutTests/ChangeLog (111871 => 111872)
--- trunk/LayoutTests/ChangeLog 2012-03-23 16:54:01 UTC (rev 111871)
+++ trunk/LayoutTests/ChangeLog 2012-03-23 16:58:53 UTC (rev 111872)
@@ -1,3 +1,32 @@
+2012-03-23 Sami Kyostila <[email protected]>
+
+ Reuse buffer allocation if canvas size does not change
+ https://bugs.webkit.org/show_bug.cgi?id=80871
+
+ Reviewed by Stephen White.
+
+ Add layout test to check canvas resizing without changing its layout size.
+
+ We also update the expected image one canvas clearing test. The test
+ is setting the size of a canvas and expecting it to be cleared in the process.
+ With the optimization to retain the underlying ImageBuffer, we no longer call
+ RenderReplaced::repaint() as a part of this process. This function used to
+ repaint both the canvas itself (100x50) as well as its local selection
+ rectangle (100x54).
+
+ In this case the local selection rectangle is larger than the canvas because
+ the canvas is contained within an anonymous RenderBlock that also has two empty
+ text nodes. The extra 4 pixels are needed for drawing the selection rectangle
+ around any descenders in the the text of those nodes.
+
+ Since clearing the canvas has no effect on the selection rectangle, we only
+ need to repaint the area of the canvas itself.
+
+ * fast/canvas/canvas-resize-after-paint-without-layout.html: Added.
+ * fast/canvas/canvas-resize-after-paint-without-layout-expected.txt: Added.
+ * platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png: Added.
+ * platform/chromium-linux/fast/canvas/setWidthResetAfterForcedRender-expected.png: Updated.
+
2012-03-23 Dan Bernstein <[email protected]>
Added all tests that failed more than once on the Lion WebKit2 Release bot between r111814
Added: trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout-expected.txt (0 => 111872)
--- trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout-expected.txt 2012-03-23 16:58:53 UTC (rev 111872)
@@ -0,0 +1 @@
+
Added: trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout.html (0 => 111872)
--- trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout.html (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout.html 2012-03-23 16:58:53 UTC (rev 111872)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- Check that resizing a (potentially accelerated) canvas properly clears its
+ contents even if the layout size of the canvas does not change. Expected
+ output is a blank canvas.
+ https://bugs.webkit.org/show_bug.cgi?id=80871 -->
+<html>
+ <head>
+ <style>
+ #canvas {
+ outline: solid 1px black;
+ width: 300px;
+ height: 300px;
+ }
+ </style>
+ <script src=""
+ <script>
+ if (window.layoutTestController)
+ layoutTestController.dumpAsText(true);
+
+ function runTest() {
+ var canvas = document.getElementById('canvas');
+ var ctx = canvas.getContext('2d');
+ ctx.fillStyle = 'red';
+ ctx.fillRect(0, 0, 300, 300);
+ runRepaintTest();
+ }
+
+ function repaintTest() {
+ var canvas = document.getElementById('canvas');
+ // This changes the resolution of the canvas but keeps its layout size constant.
+ canvas.width = canvas.width / 2;
+ }
+ </script>
+ </head>
+ <body _onload_="runTest();">
+ <canvas id="canvas" width="300" height="300"/>
+ </body>
+</html>
Added: trunk/LayoutTests/platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png (0 => 111872)
--- trunk/LayoutTests/platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png (rev 0)
+++ trunk/LayoutTests/platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png 2012-03-23 16:58:53 UTC (rev 111872)
@@ -0,0 +1,5 @@
+\x89PNG
+
+
+IHDR X ' )tEXtchecksum 1938f5125b87a23c432f1fe8536b9f9f\xA3\xBD\x87
+\xE5IDATx\x9C\xED\xDC1n\x840 EA\xED\xCD9\xA5\xD3gI\xB3z-\x9A)q\xF3\xCB'[b\xCC97 :?w x\x81 X 1\x81 X 1\x81 {\x9D~=\x8E\xE3\xE2\xC0;Q\xF8R灵m\xDBZ\xEB\xCA\xC0c\x8C\xBB' \xF0!O\x84 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X 1\x81 X \xB1\xD7c\x8C+w <\xC6y`\xAD\xB5.\xDE\xBC\xDB\xF7\xFD\xEE |\xC2! @L` \xC4 @l\xCC9\xEF\xDE \xF0(n\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b &\xB0 b \xF6\xB1ɢB~\x8F IEND\xAEB`\x82
\ No newline at end of file
Modified: trunk/LayoutTests/platform/chromium-linux/fast/canvas/setWidthResetAfterForcedRender-expected.png
(Binary files differ)
Added: trunk/LayoutTests/platform/chromium-linux/platform/chromium/virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout-expected.png (0 => 111872)
--- trunk/LayoutTests/platform/chromium-linux/platform/chromium/virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout-expected.png (rev 0)
+++ trunk/LayoutTests/platform/chromium-linux/platform/chromium/virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout-expected.png 2012-03-23 16:58:53 UTC (rev 111872)
@@ -0,0 +1,6 @@
+\x89PNG
+
+
+IHDR X ' )tEXtchecksum aebe383ca6efdf3e0b347cd43d1aec21\xC6\x9B
+\xCEIDATx\x9C\xED\xDC1
+\xC30 A_\xF0\xFF\xBF\xAC< N\xB7X\xD8̔Rs\x95X!Ь\xB5 :\x9F\xDD \xBC\x8D\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88\x9D\x97\xAB3s\xF3\xC0/\xBF\xA8 <\xD4u`Nv\xD8\xCD=\xE0\xB9< \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4 @L` \xC4\xCE3s\xE7 \xAF1k\xAD\xDD3 \xBC\x8A'B \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88 , \x80\x98\xC0 \x88}\xC9O\xB2Z\xF9[ IEND\xAEB`\x82
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (111871 => 111872)
--- trunk/Source/WebCore/ChangeLog 2012-03-23 16:54:01 UTC (rev 111871)
+++ trunk/Source/WebCore/ChangeLog 2012-03-23 16:58:53 UTC (rev 111872)
@@ -1,3 +1,50 @@
+2012-03-23 Sami Kyostila <[email protected]>
+
+ Reuse buffer allocation if canvas size does not change
+ https://bugs.webkit.org/show_bug.cgi?id=80871
+
+ Reviewed by Stephen White.
+
+ If the user changes the width or height attributes of a canvas element,
+ the contents of the canvas should be cleared and the context state
+ should be reset. This has become a common idiom to clear the canvas
+ "efficiently" at the start of a frame.
+
+ Previously, this code path triggered a full reallocation of the image
+ buffer backing the canvas, leading to reduced performance. This patch
+ implements an optimization where we reuse the previous image buffer
+ allocation if the size of the canvas did not change. Also, instead of
+ clearing the canvas every time its dimensions are touched, we only clear
+ if anything has been drawn into the canvas since it was previously
+ cleared.
+
+ Note that for now this optimization only applies for 2D canvases,
+ since it is not entirely clear how touching the dimensions of a WebGL
+ canvas should work.
+
+ Test: fast/canvas/canvas-resize-after-paint-without-layout.html +
+ existing layout tests for canvas resetting.
+
+ * html/HTMLCanvasElement.cpp:
+ (WebCore::HTMLCanvasElement::HTMLCanvasElement):
+ (WebCore::HTMLCanvasElement::reset):
+ (WebCore::HTMLCanvasElement::createImageBuffer): Save the initial
+ graphics context state so we can restore it without creating a new
+ context.
+ (WebCore::HTMLCanvasElement::clearImageBuffer):
+ (WebCore):
+ (WebCore::HTMLCanvasElement::clearCopiedImage):
+ * html/HTMLCanvasElement.h:
+ (HTMLCanvasElement):
+ * html/canvas/CanvasRenderingContext2D.cpp:
+ (WebCore::CanvasRenderingContext2D::reset): No need to notify the
+ compositor when the context is reset, because clearing the image buffer
+ does the same thing. We can also skip the notification if we did not
+ have an image buffer at the time of the reset, because the reset will
+ not have any visual impact in this case. Finally, if the canvas size
+ did change, the notification is also unnecessary because of the call
+ to RenderObject::repaint() from HTMLCanvasElement::reset().
+
2012-03-22 Martin Robinson <[email protected]>
Fix some code generation warnings on GTK+.
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (111871 => 111872)
--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2012-03-23 16:54:01 UTC (rev 111871)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2012-03-23 16:58:53 UTC (rev 111872)
@@ -92,6 +92,7 @@
#endif
, m_originClean(true)
, m_hasCreatedImageBuffer(false)
+ , m_didClearImageBuffer(false)
{
ASSERT(hasTagName(canvasTag));
}
@@ -247,13 +248,26 @@
if (!ok || h < 0)
h = DefaultHeight;
+ if (m_contextStateSaver) {
+ // Reset to the initial graphics context state.
+ m_contextStateSaver->restore();
+ m_contextStateSaver->save();
+ }
+
if (m_context && m_context->is2d()) {
CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext2D*>(m_context.get());
context2D->reset();
}
IntSize oldSize = size();
- setSurfaceSize(IntSize(w, h)); // The image buffer gets cleared here.
+ // If the size of an existing buffer matches, we can just clear it instead of reallocating.
+ // This optimization is only done for 2D canvases for now.
+ if (m_hasCreatedImageBuffer && oldSize == IntSize(w, h) && m_context && m_context->is2d()) {
+ if (!m_didClearImageBuffer)
+ clearImageBuffer();
+ return;
+ }
+ setSurfaceSize(IntSize(w, h));
#if ENABLE(WEBGL)
if (m_context && m_context->is3d() && oldSize != size())
@@ -262,8 +276,13 @@
if (RenderObject* renderer = this->renderer()) {
if (m_rendererIsCanvas) {
- if (oldSize != size())
+ if (oldSize != size()) {
toRenderHTMLCanvas(renderer)->canvasSizeChanged();
+#if USE(ACCELERATED_COMPOSITING)
+ if (renderBox() && renderBox()->hasLayer() && renderBox()->layer()->hasAcceleratedCompositing())
+ renderBox()->layer()->contentChanged(RenderLayer::CanvasChanged);
+#endif
+ }
if (hadImageBuffer)
renderer->repaint();
}
@@ -353,6 +372,7 @@
{
m_size = size;
m_hasCreatedImageBuffer = false;
+ m_contextStateSaver.clear();
m_imageBuffer.clear();
clearCopiedImage();
}
@@ -498,6 +518,7 @@
ASSERT(!m_imageBuffer);
m_hasCreatedImageBuffer = true;
+ m_didClearImageBuffer = true;
FloatSize logicalSize = size();
FloatSize deviceSize = convertLogicalToDevice(logicalSize);
@@ -529,6 +550,7 @@
m_imageBuffer->context()->setShadowsIgnoreTransforms(true);
m_imageBuffer->context()->setImageInterpolationQuality(DefaultInterpolationQuality);
m_imageBuffer->context()->setStrokeThickness(1);
+ m_contextStateSaver = adoptPtr(new GraphicsContextStateSaver(*m_imageBuffer->context()));
#if USE(JSC)
JSC::JSLock lock(JSC::SilenceAssertionsOnly);
@@ -573,9 +595,25 @@
return m_copiedImage.get();
}
+void HTMLCanvasElement::clearImageBuffer() const
+{
+ ASSERT(m_hasCreatedImageBuffer);
+ ASSERT(!m_didClearImageBuffer);
+ ASSERT(m_context);
+
+ m_didClearImageBuffer = true;
+
+ if (m_context->is2d()) {
+ CanvasRenderingContext2D* context2D = static_cast<CanvasRenderingContext2D*>(m_context.get());
+ // No need to undo transforms/clip/etc. because we are called right after the context is reset.
+ context2D->clearRect(0, 0, width(), height());
+ }
+}
+
void HTMLCanvasElement::clearCopiedImage()
{
m_copiedImage.clear();
+ m_didClearImageBuffer = false;
}
AffineTransform HTMLCanvasElement::baseTransform() const
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.h (111871 => 111872)
--- trunk/Source/WebCore/html/HTMLCanvasElement.h 2012-03-23 16:54:01 UTC (rev 111871)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.h 2012-03-23 16:58:53 UTC (rev 111872)
@@ -45,6 +45,7 @@
class CanvasContextAttributes;
class CanvasRenderingContext;
class GraphicsContext;
+class GraphicsContextStateSaver;
class HTMLCanvasElement;
class Image;
class ImageData;
@@ -143,6 +144,7 @@
void reset();
void createImageBuffer() const;
+ void clearImageBuffer() const;
void setSurfaceSize(const IntSize&);
@@ -166,7 +168,9 @@
// m_createdImageBuffer means we tried to malloc the buffer. We didn't necessarily get it.
mutable bool m_hasCreatedImageBuffer;
+ mutable bool m_didClearImageBuffer;
mutable OwnPtr<ImageBuffer> m_imageBuffer;
+ mutable OwnPtr<GraphicsContextStateSaver> m_contextStateSaver;
mutable RefPtr<Image> m_presentedImage;
mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue).
Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (111871 => 111872)
--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2012-03-23 16:54:01 UTC (rev 111871)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp 2012-03-23 16:58:53 UTC (rev 111872)
@@ -161,11 +161,6 @@
m_stateStack.resize(1);
m_stateStack.first() = State();
m_path.clear();
-#if USE(ACCELERATED_COMPOSITING)
- RenderBox* renderBox = canvas()->renderBox();
- if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing())
- renderBox->layer()->contentChanged(RenderLayer::CanvasChanged);
-#endif
}
CanvasRenderingContext2D::State::State()
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes
