Index: third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
diff --git a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
index e2fb6df93a917264297cce6c1b1204cf811f47b3..e85fa09048e3ad909aa8b839736e0120b403451f 100644 |
--- a/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
+++ b/third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp |
@@ -171,6 +171,8 @@ bool Canvas2DLayerBridge::shouldAccelerate(AccelerationHint hint) const |
bool Canvas2DLayerBridge::isAccelerated() const |
{ |
+ if (m_accelerationMode == DisableAcceleration) |
+ return false; |
if (isHibernating()) |
return false; |
if (m_softwareRenderingWhileHidden) |
@@ -464,22 +466,49 @@ void Canvas2DLayerBridge::reportSurfaceCreationFailure() |
} |
} |
+void Canvas2DLayerBridge::disableAcceleration() |
+{ |
+ DCHECK(isAccelerated()); |
+ bool surfaceIsAccelerated; |
+ RefPtr<SkSurface> newSurface = createSkSurface(nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated); |
+ if (newSurface) { |
+ DCHECK(!surfaceIsAccelerated); |
+ flush(); |
+ SkPaint copyPaint; |
+ copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode); |
+ m_surface->draw(newSurface->getCanvas(), 0, 0, ©Paint); // GPU readback here |
+ m_accelerationMode = DisableAcceleration; // Acceleration gets permanently disabled |
+ GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
+ m_layer->clearTexture(); |
+ m_layer->layer()->removeFromParent(); |
+ m_surface = newSurface; |
+ if (m_imageBuffer) |
+ m_imageBuffer->didDisableAcceleration(); |
+ } |
+} |
+ |
SkSurface* Canvas2DLayerBridge::getOrCreateSurface(AccelerationHint hint) |
{ |
- if (m_surface) |
+ if (m_surface) { |
+ // Note: in layout tests, canvas2dFixedRenderingMode is set to true to inhibit |
+ // mode switching so that we continue to get test coverage for GPU acceleration |
+ // despite the use of getImageData in tests |
+ if (hint == ForceNoAcceleration && isAccelerated() && !RuntimeEnabledFeatures::canvas2dFixedRenderingModeEnabled()) |
+ disableAcceleration(); |
return m_surface.get(); |
+ } |
- if (m_layer && !isHibernating() && hint == PreferAcceleration) { |
+ if (m_layer && !isHibernating() && hint == PreferAcceleration && m_accelerationMode != DisableAcceleration) { |
return nullptr; // re-creation will happen through restore() |
} |
bool wantAcceleration = shouldAccelerate(hint); |
- bool surfaceIsAccelerated; |
if (CANVAS2D_BACKGROUND_RENDER_SWITCH_TO_CPU && isHidden() && wantAcceleration) { |
wantAcceleration = false; |
m_softwareRenderingWhileHidden = true; |
} |
+ bool surfaceIsAccelerated; |
m_surface = createSkSurface(wantAcceleration ? m_contextProvider->grContext() : nullptr, m_size, m_msaaSampleCount, m_opacityMode, &surfaceIsAccelerated); |
if (!m_surface) |
@@ -580,7 +609,7 @@ void Canvas2DLayerBridge::beginDestruction() |
unregisterTaskObserver(); |
- if (m_layer) { |
+ if (m_layer && m_accelerationMode != DisableAcceleration) { |
GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
m_layer->clearTexture(); |
// Orphaning the layer is required to trigger the recration of a new layer |
@@ -709,7 +738,7 @@ gpu::gles2::GLES2Interface* Canvas2DLayerBridge::contextGL() |
{ |
// Check on m_layer is necessary because contextGL() may be called during |
// the destruction of m_layer |
- if (m_layer && !m_destructionInProgress) { |
+ if (m_layer && m_accelerationMode != DisableAcceleration && !m_destructionInProgress) { |
// Call checkSurfaceValid to ensure rate limiter is disabled if context is lost. |
if (!checkSurfaceValid()) |
return nullptr; |
@@ -724,7 +753,7 @@ bool Canvas2DLayerBridge::checkSurfaceValid() |
return false; |
if (isHibernating()) |
return true; |
- if (!m_layer) |
+ if (!m_layer || m_accelerationMode == DisableAcceleration) |
return true; |
if (!m_surface) |
return false; |
@@ -875,6 +904,9 @@ void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb |
// 2) Release the SkImage, which will return the texture to skia's scratch |
// texture pool. |
m_mailboxes.remove(releasedMailboxInfo); |
+ |
+ if (m_mailboxes.isEmpty() && m_accelerationMode == DisableAcceleration) |
+ m_layer.reset(); |
} |
WebLayer* Canvas2DLayerBridge::layer() const |
@@ -908,7 +940,7 @@ void Canvas2DLayerBridge::prepareSurfaceForPaintingIfNeeded() |
void Canvas2DLayerBridge::finalizeFrame(const FloatRect &dirtyRect) |
{ |
DCHECK(!m_destructionInProgress); |
- if (m_layer) |
+ if (m_layer && m_accelerationMode != DisableAcceleration) |
m_layer->layer()->invalidateRect(enclosingIntRect(dirtyRect)); |
if (m_rateLimiter) |
m_rateLimiter->reset(); |