Index: third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp |
diff --git a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp |
index f0c6e688a144f9002dd86a67163e4d67f65f68a6..1b3c7b72d175b72ce0de97ff7e755f68f8be08a8 100644 |
--- a/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp |
+++ b/third_party/WebKit/Source/core/html/HTMLCanvasElement.cpp |
@@ -742,7 +742,7 @@ bool HTMLCanvasElement::originClean() const |
return m_originClean; |
} |
-bool HTMLCanvasElement::shouldAccelerate(const IntSize& size, const WebGraphicsContext3DProvider* sharedMainThreadContextProvider) const |
+bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const |
{ |
if (m_context && !m_context->is2d()) |
return false; |
@@ -785,9 +785,6 @@ bool HTMLCanvasElement::shouldAccelerate(const IntSize& size, const WebGraphicsC |
if (!settings || canvasPixelCount < settings->minimumAccelerated2dCanvasSize()) |
return false; |
- if (sharedMainThreadContextProvider->isSoftwareRendering()) |
- return false; |
- |
// When GPU allocated memory runs low (due to having created too many |
// accelerated canvases), the compositor starves and browser becomes laggy. |
// Thus, we should stop allocating more GPU memory to new canvases created |
@@ -825,11 +822,8 @@ bool HTMLCanvasElement::shouldUseDisplayList(const IntSize& deviceSize) |
return true; |
} |
-std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface(const IntSize& deviceSize, int* msaaSampleCount, sk_sp<SkColorSpace> colorSpace) |
+std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createAcceleratedImageBufferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace, int* msaaSampleCount) |
{ |
- OpacityMode opacityMode = !m_context || m_context->creationAttributes().alpha() ? NonOpaque : Opaque; |
- |
- *msaaSampleCount = 0; |
if (is3D()) { |
// If 3d, but the use of the canvas will be for non-accelerated content |
// then make a non-accelerated ImageBuffer. This means copying the internal |
@@ -837,37 +831,53 @@ std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createImageBufferSurface( |
return wrapUnique(new AcceleratedImageBufferSurface(deviceSize, opacityMode, colorSpace)); |
} |
- std::unique_ptr<WebGraphicsContext3DProvider> contextProvider = wrapUnique(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
+ if (!shouldAccelerate(deviceSize)) |
+ return nullptr; |
+ |
+ if (document().settings()) |
+ *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCount(); |
+ |
+ // Avoid creating |contextProvider| until we're sure we want to try use it, |
+ // since it costs us GPU memory. |
+ std::unique_ptr<WebGraphicsContext3DProvider> contextProvider(Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); |
if (!contextProvider) { |
CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Accelerated2DCanvasGPUContextLost); |
- } else if (shouldAccelerate(deviceSize, contextProvider.get())) { |
- if (document().settings()) |
- *msaaSampleCount = document().settings()->accelerated2dCanvasMSAASampleCount(); |
- std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new Canvas2DImageBufferSurface(std::move(contextProvider), deviceSize, *msaaSampleCount, opacityMode, Canvas2DLayerBridge::EnableAcceleration, colorSpace)); |
- if (surface->isValid()) { |
- CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreated); |
- return surface; |
- } |
- CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreationFailed); |
+ return nullptr; |
} |
- std::unique_ptr<RecordingImageBufferFallbackSurfaceFactory> surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); |
+ if (contextProvider->isSoftwareRendering()) |
Justin Novosad
2016/08/26 14:11:12
In a follow-up CL It would be nice to be able to m
|
+ return nullptr; // Don't use accelerated canvas with swiftshader. |
+ std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new Canvas2DImageBufferSurface(std::move(contextProvider), deviceSize, *msaaSampleCount, opacityMode, Canvas2DLayerBridge::EnableAcceleration, std::move(colorSpace))); |
+ if (surface->isValid()) { |
+ CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreated); |
+ return surface; |
+ } |
+ |
+ CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCanvasImageBufferCreationFailed); |
+ return nullptr; |
+} |
+ |
+std::unique_ptr<ImageBufferSurface> HTMLCanvasElement::createSoftwareImageBufferSurface(const IntSize& deviceSize, OpacityMode opacityMode, sk_sp<SkColorSpace> colorSpace) |
+{ |
if (shouldUseDisplayList(deviceSize)) { |
- std::unique_ptr<ImageBufferSurface> surface = wrapUnique(new RecordingImageBufferSurface(deviceSize, std::move(surfaceFactory), opacityMode, colorSpace)); |
+ auto surface = wrapUnique(new RecordingImageBufferSurface(deviceSize, wrapUnique(new UnacceleratedSurfaceFactory), opacityMode, colorSpace)); |
if (surface->isValid()) { |
CanvasMetrics::countCanvasContextUsage(CanvasMetrics::DisplayList2DCanvasImageBufferCreated); |
- return surface; |
+ return std::move(surface); |
} |
- surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); // recreate because previous one was released |
+ // We fallback to a non-display-list surface without recording a metric here. |
} |
- auto surface = surfaceFactory->createSurface(deviceSize, opacityMode, colorSpace); |
- if (!surface->isValid()) { |
- CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreationFailed); |
- } else { |
+ |
+ auto surfaceFactory = wrapUnique(new UnacceleratedSurfaceFactory()); |
+ auto surface = surfaceFactory->createSurface(deviceSize, opacityMode, std::move(colorSpace)); |
+ if (surface->isValid()) { |
CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreated); |
+ return surface; |
} |
- return surface; |
+ |
+ CanvasMetrics::countCanvasContextUsage(CanvasMetrics::Unaccelerated2DCanvasImageBufferCreationFailed); |
+ return nullptr; |
} |
void HTMLCanvasElement::createImageBuffer() |
@@ -887,16 +897,18 @@ void HTMLCanvasElement::createImageBufferInternal(std::unique_ptr<ImageBufferSur |
if (!ImageBuffer::canCreateImageBuffer(size())) |
return; |
+ OpacityMode opacityMode = !m_context || m_context->creationAttributes().alpha() ? NonOpaque : Opaque; |
int msaaSampleCount = 0; |
- std::unique_ptr<ImageBufferSurface> surface; |
- if (externalSurface) { |
- surface = std::move(externalSurface); |
- } else { |
- surface = createImageBufferSurface(size(), &msaaSampleCount, m_context->skColorSpace()); |
- } |
- m_imageBuffer = ImageBuffer::create(std::move(surface)); |
- if (!m_imageBuffer) |
+ std::unique_ptr<ImageBufferSurface> surface = std::move(externalSurface); |
+ if (!surface) |
+ surface = createAcceleratedImageBufferSurface(size(), opacityMode, m_context->skColorSpace(), &msaaSampleCount); |
+ if (!surface) |
+ surface = createSoftwareImageBufferSurface(size(), opacityMode, m_context->skColorSpace()); |
+ if (!surface) |
return; |
+ DCHECK(surface->isValid()); |
+ m_imageBuffer = ImageBuffer::create(std::move(surface)); |
+ DCHECK(m_imageBuffer); |
m_imageBuffer->setClient(this); |
m_didFailToCreateImageBuffer = false; |