Reuse buffer allocation if canvas size does not change
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2012 16:58:53 +0000 (16:58 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Mar 2012 16:58:53 +0000 (16:58 +0000)
commitc4c64c92aa1a1cca60da2f0f93c9fd0899743105
tree8014e8677510fef385e88eddb21d3ed9ad79650c
parent26273774ef0a298547caad8dc74807b72ca0c618
Reuse buffer allocation if canvas size does not change
https://bugs.webkit.org/show_bug.cgi?id=80871

Patch by Sami Kyostila <skyostil@chromium.org> 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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111872 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/canvas-resize-after-paint-without-layout.html [new file with mode: 0644]
LayoutTests/platform/chromium-linux/fast/canvas/canvas-resize-after-paint-without-layout-expected.png [new file with mode: 0644]
LayoutTests/platform/chromium-linux/fast/canvas/setWidthResetAfterForcedRender-expected.png
LayoutTests/platform/chromium-linux/platform/chromium/virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout-expected.png [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLCanvasElement.cpp
Source/WebCore/html/HTMLCanvasElement.h
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp