Commit 2b0d65c9 authored by junov's avatar junov Committed by Commit bot

Disable GPU acceleration on 2D canvas when readbacks are needed

We are already disabling GPU acceleration to avoid readbacks caused
by calls to getImageData. This change applies the same principle
to canvas-to-canvas drawImage calls in order to avoid probable
future readbacks.

BUG=652126, 651517, 650116, 642539, 640144

Review-Url: https://codereview.chromium.org/2388293002
Cr-Commit-Position: refs/heads/master@{#422848}
parent 11b4bbce
...@@ -1290,6 +1290,12 @@ PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas( ...@@ -1290,6 +1290,12 @@ PassRefPtr<Image> HTMLCanvasElement::getSourceImageForCanvas(
? buffer()->newSkImageSnapshot(hint, reason) ? buffer()->newSkImageSnapshot(hint, reason)
: createTransparentImage(size())->imageForCurrentFrame(); : createTransparentImage(size())->imageForCurrentFrame();
} else { } else {
if (ExpensiveCanvasHeuristicParameters::
DisableAccelerationToAvoidReadbacks &&
!RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled() &&
hint == PreferNoAcceleration && m_context->isAccelerated() &&
hasImageBuffer())
buffer()->disableAcceleration();
RefPtr<blink::Image> image = renderingContext()->getImage(hint, reason); RefPtr<blink::Image> image = renderingContext()->getImage(hint, reason);
skImage = image ? image->imageForCurrentFrame() skImage = image ? image->imageForCurrentFrame()
: createTransparentImage(size())->imageForCurrentFrame(); : createTransparentImage(size())->imageForCurrentFrame();
......
...@@ -1000,6 +1000,44 @@ TEST_F(CanvasRenderingContext2DTest, GetImageDataDisablesAcceleration) { ...@@ -1000,6 +1000,44 @@ TEST_F(CanvasRenderingContext2DTest, GetImageDataDisablesAcceleration) {
savedFixedRenderingMode); savedFixedRenderingMode);
} }
TEST_F(CanvasRenderingContext2DTest,
PreferNoAccelerationHintDisablesAcceleration) {
bool savedFixedRenderingMode =
RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled();
RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(false);
createContext(NonOpaque);
FakeGLES2Interface gl;
std::unique_ptr<FakeWebGraphicsContext3DProvider> contextProvider(
new FakeWebGraphicsContext3DProvider(&gl));
IntSize size(300, 300);
RefPtr<Canvas2DLayerBridge> bridge =
makeBridge(std::move(contextProvider), size,
Canvas2DLayerBridge::EnableAcceleration);
std::unique_ptr<Canvas2DImageBufferSurface> surface(
new Canvas2DImageBufferSurface(bridge, size));
canvasElement().createImageBufferUsingSurfaceForTesting(std::move(surface));
EXPECT_TRUE(canvasElement().buffer()->isAccelerated());
SourceImageStatus status = InvalidSourceImageStatus;
canvasElement().getSourceImageForCanvas(
&status, PreferNoAcceleration, SnapshotReasonUnitTests, FloatSize(size));
EXPECT_EQ(NormalSourceImageStatus, status);
if (ExpensiveCanvasHeuristicParameters::DisableAccelerationToAvoidReadbacks) {
EXPECT_FALSE(canvasElement().buffer()->isAccelerated());
EXPECT_EQ(0u, getGlobalAcceleratedImageBufferCount());
EXPECT_EQ(0, getGlobalGPUMemoryUsage());
} else {
EXPECT_TRUE(canvasElement().buffer()->isAccelerated());
EXPECT_EQ(1u, getGlobalAcceleratedImageBufferCount());
EXPECT_EQ(720000, getGlobalGPUMemoryUsage());
}
// Restore global state to prevent side-effects on other tests
RuntimeEnabledFeatures::setCanvas2dFixedRenderingModeEnabled(
savedFixedRenderingMode);
}
TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) { TEST_F(CanvasRenderingContext2DTest, TextureUploadHeuristics) {
bool savedFixedRenderingMode = bool savedFixedRenderingMode =
RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled(); RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled();
......
...@@ -67,6 +67,13 @@ enum { ...@@ -67,6 +67,13 @@ enum {
GetImageDataForcesNoAcceleration = 1, GetImageDataForcesNoAcceleration = 1,
// Whan a canvas is used as a source image, if its destination is
// non-accelerated and the source canvas is accelerated, a readback
// from the gpu is necessary. This option cause the source canvas to
// switch to non-accelerated when this situation is encountered to
// prevent future canvas to canvas draws from requiring a readback.
DisableAccelerationToAvoidReadbacks = 1,
// When drawing very large images to canvases, there is a point where // When drawing very large images to canvases, there is a point where
// GPU acceleration becomes inefficient due to texture upload overhead, // GPU acceleration becomes inefficient due to texture upload overhead,
// especially when the image is large enough that it is likely to // especially when the image is large enough that it is likely to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment