Chromium Code Reviews| Index: Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp |
| diff --git a/Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp b/Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp |
| index 8715c44be61a490d0efe6489bddff8c640e9290d..687a1aa60c5afffe84a96191c13853206b12e616 100644 |
| --- a/Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp |
| +++ b/Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp |
| @@ -34,6 +34,7 @@ |
| #include "core/platform/graphics/GraphicsContext3D.h" |
| #include "core/platform/graphics/chromium/Canvas2DLayerManager.h" |
| #include "core/platform/graphics/chromium/GraphicsLayerChromium.h" |
| +#include "core/platform/graphics/gpu/SharedGraphicsContext3D.h" |
| #include <public/Platform.h> |
| #include <public/WebCompositorSupport.h> |
| #include <public/WebGraphicsContext3D.h> |
| @@ -44,7 +45,33 @@ using WebKit::WebTextureUpdater; |
| namespace WebCore { |
| -Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode, ThreadMode threadMode) |
| +static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& size) |
| +{ |
| + ASSERT(!context3D->webContext()->isContextLost()); |
| + GrContext* gr = context3D->grContext(); |
| + if (!gr) |
| + return 0; |
| + gr->resetContext(); |
| + SkImage::Info info; |
| + info.fWidth = size.width(); |
| + info.fHeight = size.height(); |
| + info.fColorType = SkImage::kPMColor_ColorType; |
| + info.fAlphaType = SkImage::kPremul_AlphaType; |
| + return SkSurface::NewRenderTarget(gr, info); |
| +} |
| + |
| +PassOwnPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(PassRefPtr<GraphicsContext3D> context, const IntSize& size, OpacityMode opacityMode, ThreadMode threading) |
| +{ |
| + SkAutoTUnref<SkSurface> surface(createSurface(context.get(), size)); |
| + if (!surface.get()) |
| + return PassOwnPtr<Canvas2DLayerBridge>(); |
| + SkDeferredCanvas* canvas = new SkDeferredCanvas(surface); |
| + OwnPtr<Canvas2DLayerBridge> layerBridge = adoptPtr(new Canvas2DLayerBridge(context, canvas)); |
| + layerBridge->init(opacityMode, threading); |
|
Stephen White
2013/05/28 18:05:43
You're gonna hate me, but I liked this better when
|
| + return layerBridge.release(); |
| +} |
| + |
| +Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas) |
| : m_canvas(canvas) |
| , m_context(context) |
| , m_bytesAllocated(0) |
| @@ -56,6 +83,21 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, |
| , m_lastImageId(0) |
| #endif |
| { |
| +} |
| + |
| +Canvas2DLayerBridge::~Canvas2DLayerBridge() |
| +{ |
| + GraphicsLayerChromium::unregisterContentsLayer(m_layer->layer()); |
| + Canvas2DLayerManager::get().layerToBeDestroyed(this); |
| + m_canvas->setNotificationClient(0); |
| +#if ENABLE(CANVAS_USES_MAILBOX) |
| + m_mailboxes.clear(); |
| +#endif |
| + m_layer->clearTexture(); |
| +} |
| + |
| +void Canvas2DLayerBridge::init(OpacityMode opacityMode, ThreadMode threadMode) |
| +{ |
| ASSERT(m_canvas); |
| // Used by browser tests to detect the use of a Canvas2DLayerBridge. |
| TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); |
|
Stephen White
2013/05/28 18:05:43
If this does stay in its own function, the tracing
|
| @@ -74,17 +116,6 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, |
| GraphicsLayerChromium::registerContentsLayer(m_layer->layer()); |
| } |
| -Canvas2DLayerBridge::~Canvas2DLayerBridge() |
| -{ |
| - GraphicsLayerChromium::unregisterContentsLayer(m_layer->layer()); |
| - Canvas2DLayerManager::get().layerToBeDestroyed(this); |
| - m_canvas->setNotificationClient(0); |
| -#if ENABLE(CANVAS_USES_MAILBOX) |
| - m_mailboxes.clear(); |
| -#endif |
| - m_layer->clearTexture(); |
| -} |
| - |
| void Canvas2DLayerBridge::limitPendingFrames() |
| { |
| if (m_didRecordDrawCommand) { |
| @@ -97,6 +128,13 @@ void Canvas2DLayerBridge::limitPendingFrames() |
| void Canvas2DLayerBridge::prepareForDraw() |
| { |
| + if (!isValid()) { |
| + if (m_canvas) { |
| + // drop pending commands because there is no surface to draw to |
| + m_canvas->silentFlush(); |
| + } |
| + return; |
| + } |
| #if !ENABLE(CANVAS_USES_MAILBOX) |
| m_layer->willModifyTexture(); |
| #endif |
| @@ -143,6 +181,8 @@ void Canvas2DLayerBridge::flush() |
| unsigned Canvas2DLayerBridge::prepareTexture(WebTextureUpdater& updater) |
| { |
| + if (!isValid()) |
| + return 0; |
| #if ENABLE(CANVAS_USES_MAILBOX) |
| ASSERT_NOT_REACHED(); |
| return 0; |
| @@ -166,12 +206,50 @@ unsigned Canvas2DLayerBridge::prepareTexture(WebTextureUpdater& updater) |
| WebGraphicsContext3D* Canvas2DLayerBridge::context() |
| { |
| + ASSERT(m_context.get()); |
| return m_context->webContext(); |
| } |
| +bool Canvas2DLayerBridge::isValid() |
| +{ |
| + RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get(); |
| + if (!sharedContext || sharedContext->webContext()->isContextLost()) { |
| + // Context was lost since last call to isValid and |
| + // SharedGraphicsContext3D has not recovered. |
| + m_context.clear(); |
| + m_layer->clearTexture(); |
| + return false; |
| + } |
| + if (m_context != sharedContext) { |
| + ASSERT(sharedContext.get()); |
| + // Old context was lost and sharedContext has recovered. |
| + // Use the new context to recover the layer |
| + m_context = sharedContext; |
| + m_layer->clearTexture(); |
| + IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height()); |
| + SkAutoTUnref<SkSurface> surface(createSurface(m_context.get(), size)); |
| + if (surface.get()) { |
| + m_canvas->setSurface(surface.get()); |
| + // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
| + } else { |
| + // Surface allocation failed. Reset m_context to trigger subsequent retry |
| + m_context.clear(); |
| + return false; |
| + } |
| +#if !ENABLE(CANVAS_USES_MAILBOX) |
| + GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->getDevice()->accessRenderTarget()); |
| + if (renderTarget) |
| + m_layer->setTextureId(renderTarget->asTexture()->getTextureHandle()); |
| +#endif |
| + } |
| + return true; |
| +} |
| + |
| bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox) |
| { |
| #if ENABLE(CANVAS_USES_MAILBOX) |
| + if (!m_canvas.get() || !isValid()) |
| + return false; |
| // Release to skia textures that were previouosly released by the |
| // compositor. We do this before acquiring the next snapshot in |
| // order to cap maximum gpu memory consumption. |