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

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: Resolved merge with rate limiter CL Created 7 years, 5 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 e708983571b63bb574de04b4148c9e879c8c05d9..45eb9863a7fe7761cd85572f54088f6086b85368 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/GraphicsLayer.h"
#include "core/platform/graphics/chromium/Canvas2DLayerManager.h"
+#include "core/platform/graphics/gpu/SharedGraphicsContext3D.h"
#include "public/platform/Platform.h"
#include "public/platform/WebCompositorSupport.h"
#include "public/platform/WebGraphicsContext3D.h"
@@ -43,11 +44,38 @@ using WebKit::WebGraphicsContext3D;
namespace WebCore {
+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)
+{
+ TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
+ 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, opacityMode));
+ return layerBridge.release();
+}
+
Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode)
: m_canvas(canvas)
, m_context(context)
, m_bytesAllocated(0)
, m_didRecordDrawCommand(false)
+ , m_surfaceIsValid(true)
, m_framesPending(0)
, m_rateLimitingEnabled(false)
, m_next(0)
@@ -57,12 +85,12 @@ Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context,
ASSERT(m_canvas);
// Used by browser tests to detect the use of a Canvas2DLayerBridge.
TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
- m_canvas->setNotificationClient(this);
m_layer = adoptPtr(WebKit::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
m_layer->setOpaque(opacityMode == Opaque);
m_layer->setBlendBackgroundColor(opacityMode != Opaque);
GraphicsLayer::registerContentsLayer(m_layer->layer());
m_layer->setRateLimitContext(m_rateLimitingEnabled);
+ m_canvas->setNotificationClient(this);
}
Canvas2DLayerBridge::~Canvas2DLayerBridge()
@@ -70,9 +98,9 @@ Canvas2DLayerBridge::~Canvas2DLayerBridge()
GraphicsLayer::unregisterContentsLayer(m_layer->layer());
Canvas2DLayerManager::get().layerToBeDestroyed(this);
m_canvas->setNotificationClient(0);
+ m_mailboxes.clear();
m_layer->clearTexture();
m_layer.clear();
- m_mailboxes.clear();
}
void Canvas2DLayerBridge::limitPendingFrames()
@@ -93,6 +121,14 @@ void Canvas2DLayerBridge::limitPendingFrames()
void Canvas2DLayerBridge::prepareForDraw()
{
+ ASSERT(m_layer);
+ if (!isValid()) {
+ if (m_canvas) {
+ // drop pending commands because there is no surface to draw to
+ m_canvas->silentFlush();
+ }
+ return;
+ }
m_context->makeContextCurrent();
}
@@ -149,12 +185,45 @@ void Canvas2DLayerBridge::flush()
WebGraphicsContext3D* Canvas2DLayerBridge::context()
{
+ isValid(); // To ensure rate limiter is disabled if context is lost.
return m_context->webContext();
}
+bool Canvas2DLayerBridge::isValid()
+{
+ ASSERT(m_layer);
+ if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) {
+ // Attempt to recover.
+ m_layer->clearTexture();
+ RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get();
+ if (!sharedContext || sharedContext->webContext()->isContextLost()) {
+ m_surfaceIsValid = false;
+ } else {
+ m_context = sharedContext;
+ 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());
+ m_surfaceIsValid = true;
+ // FIXME: draw sad canvas picture into new buffer crbug.com/243842
+ } else {
+ // Surface allocation failed. Set m_surfaceIsValid to false to
+ // trigger subsequent retry.
+ m_surfaceIsValid = false;
+ }
+ }
+ }
+ if (!m_surfaceIsValid)
+ setRateLimitingEnabled(false);
+ return m_surfaceIsValid;
+
+}
+
bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outMailbox, WebKit::WebExternalBitmap* bitmap)
{
ASSERT(!bitmap);
+ if (!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.
@@ -235,18 +304,18 @@ void Canvas2DLayerBridge::mailboxReleased(const WebKit::WebExternalTextureMailbo
{
Vector<MailboxInfo>::iterator mailboxInfo;
for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
- if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.name))) {
- mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
- ASSERT(mailboxInfo->m_status == MailboxInUse);
- mailboxInfo->m_status = MailboxReleased;
- return;
- }
- }
- ASSERT_NOT_REACHED();
+ if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.name))) {
+ mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
+ ASSERT(mailboxInfo->m_status == MailboxInUse);
+ mailboxInfo->m_status = MailboxReleased;
+ return;
+ }
+ }
}
WebKit::WebLayer* Canvas2DLayerBridge::layer()
{
+ ASSERT(m_layer);
return m_layer->layer();
}
@@ -258,6 +327,8 @@ void Canvas2DLayerBridge::contextAcquired()
unsigned Canvas2DLayerBridge::backBufferTexture()
{
+ if (!isValid())
+ return 0;
contextAcquired();
m_canvas->flush();
m_context->flush();

Powered by Google App Engine
This is Rietveld 408576698