Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1389)

Unified Diff: Source/core/platform/graphics/chromium/Canvas2DLayerBridge.cpp

Issue 16032003: Fixing Canvas2DLayerBridge to handle lost graphics contexts (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Fixed unit tests Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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.

Powered by Google App Engine
This is Rietveld 408576698