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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 16 matching lines...) Expand all
27 27
28 #include "core/platform/graphics/chromium/Canvas2DLayerBridge.h" 28 #include "core/platform/graphics/chromium/Canvas2DLayerBridge.h"
29 29
30 #include "GrContext.h" 30 #include "GrContext.h"
31 #include "SkDevice.h" 31 #include "SkDevice.h"
32 #include "SkSurface.h" 32 #include "SkSurface.h"
33 #include "core/platform/chromium/TraceEvent.h" 33 #include "core/platform/chromium/TraceEvent.h"
34 #include "core/platform/graphics/GraphicsContext3D.h" 34 #include "core/platform/graphics/GraphicsContext3D.h"
35 #include "core/platform/graphics/GraphicsLayer.h" 35 #include "core/platform/graphics/GraphicsLayer.h"
36 #include "core/platform/graphics/chromium/Canvas2DLayerManager.h" 36 #include "core/platform/graphics/chromium/Canvas2DLayerManager.h"
37 #include "core/platform/graphics/gpu/SharedGraphicsContext3D.h"
37 #include "public/platform/Platform.h" 38 #include "public/platform/Platform.h"
38 #include "public/platform/WebCompositorSupport.h" 39 #include "public/platform/WebCompositorSupport.h"
39 #include "public/platform/WebGraphicsContext3D.h" 40 #include "public/platform/WebGraphicsContext3D.h"
40 41
41 using WebKit::WebExternalTextureLayer; 42 using WebKit::WebExternalTextureLayer;
42 using WebKit::WebGraphicsContext3D; 43 using WebKit::WebGraphicsContext3D;
43 44
44 namespace WebCore { 45 namespace WebCore {
45 46
47 static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& siz e)
48 {
49 ASSERT(!context3D->webContext()->isContextLost());
50 GrContext* gr = context3D->grContext();
51 if (!gr)
52 return 0;
53 gr->resetContext();
54 SkImage::Info info;
55 info.fWidth = size.width();
56 info.fHeight = size.height();
57 info.fColorType = SkImage::kPMColor_ColorType;
58 info.fAlphaType = SkImage::kPremul_AlphaType;
59 return SkSurface::NewRenderTarget(gr, info);
60 }
61
62 PassOwnPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(PassRefPtr<GraphicsC ontext3D> context, const IntSize& size, OpacityMode opacityMode)
63 {
64 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
65 SkAutoTUnref<SkSurface> surface(createSurface(context.get(), size));
66 if (!surface.get())
67 return PassOwnPtr<Canvas2DLayerBridge>();
68 SkDeferredCanvas* canvas = new SkDeferredCanvas(surface);
69 OwnPtr<Canvas2DLayerBridge> layerBridge = adoptPtr(new Canvas2DLayerBridge(c ontext, canvas, opacityMode));
70 return layerBridge.release();
71 }
72
46 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode) 73 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, SkDeferredCanvas* canvas, OpacityMode opacityMode)
47 : m_canvas(canvas) 74 : m_canvas(canvas)
48 , m_context(context) 75 , m_context(context)
49 , m_bytesAllocated(0) 76 , m_bytesAllocated(0)
50 , m_didRecordDrawCommand(false) 77 , m_didRecordDrawCommand(false)
78 , m_surfaceIsValid(true)
51 , m_framesPending(0) 79 , m_framesPending(0)
52 , m_rateLimitingEnabled(false) 80 , m_rateLimitingEnabled(false)
53 , m_next(0) 81 , m_next(0)
54 , m_prev(0) 82 , m_prev(0)
55 , m_lastImageId(0) 83 , m_lastImageId(0)
56 { 84 {
57 ASSERT(m_canvas); 85 ASSERT(m_canvas);
58 // Used by browser tests to detect the use of a Canvas2DLayerBridge. 86 // Used by browser tests to detect the use of a Canvas2DLayerBridge.
59 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); 87 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
60 m_canvas->setNotificationClient(this);
61 m_layer = adoptPtr(WebKit::Platform::current()->compositorSupport()->createE xternalTextureLayer(this)); 88 m_layer = adoptPtr(WebKit::Platform::current()->compositorSupport()->createE xternalTextureLayer(this));
62 m_layer->setOpaque(opacityMode == Opaque); 89 m_layer->setOpaque(opacityMode == Opaque);
63 m_layer->setBlendBackgroundColor(opacityMode != Opaque); 90 m_layer->setBlendBackgroundColor(opacityMode != Opaque);
64 GraphicsLayer::registerContentsLayer(m_layer->layer()); 91 GraphicsLayer::registerContentsLayer(m_layer->layer());
65 m_layer->setRateLimitContext(m_rateLimitingEnabled); 92 m_layer->setRateLimitContext(m_rateLimitingEnabled);
93 m_canvas->setNotificationClient(this);
66 } 94 }
67 95
68 Canvas2DLayerBridge::~Canvas2DLayerBridge() 96 Canvas2DLayerBridge::~Canvas2DLayerBridge()
69 { 97 {
70 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 98 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
71 Canvas2DLayerManager::get().layerToBeDestroyed(this); 99 Canvas2DLayerManager::get().layerToBeDestroyed(this);
72 m_canvas->setNotificationClient(0); 100 m_canvas->setNotificationClient(0);
101 m_mailboxes.clear();
73 m_layer->clearTexture(); 102 m_layer->clearTexture();
74 m_layer.clear(); 103 m_layer.clear();
75 m_mailboxes.clear();
76 } 104 }
77 105
78 void Canvas2DLayerBridge::limitPendingFrames() 106 void Canvas2DLayerBridge::limitPendingFrames()
79 { 107 {
80 if (m_didRecordDrawCommand) { 108 if (m_didRecordDrawCommand) {
81 m_framesPending++; 109 m_framesPending++;
82 m_didRecordDrawCommand = false; 110 m_didRecordDrawCommand = false;
83 if (m_framesPending > 1) { 111 if (m_framesPending > 1) {
84 // Turn on the rate limiter if this layer tends to accumulate a 112 // Turn on the rate limiter if this layer tends to accumulate a
85 // non-discardable multi-frame backlog of draw commands. 113 // non-discardable multi-frame backlog of draw commands.
86 setRateLimitingEnabled(true); 114 setRateLimitingEnabled(true);
87 } 115 }
88 if (m_rateLimitingEnabled) { 116 if (m_rateLimitingEnabled) {
89 flush(); 117 flush();
90 } 118 }
91 } 119 }
92 } 120 }
93 121
94 void Canvas2DLayerBridge::prepareForDraw() 122 void Canvas2DLayerBridge::prepareForDraw()
95 { 123 {
124 ASSERT(m_layer);
125 if (!isValid()) {
126 if (m_canvas) {
127 // drop pending commands because there is no surface to draw to
128 m_canvas->silentFlush();
129 }
130 return;
131 }
96 m_context->makeContextCurrent(); 132 m_context->makeContextCurrent();
97 } 133 }
98 134
99 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted) 135 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted)
100 { 136 {
101 intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated; 137 intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
102 m_bytesAllocated = bytesAllocated; 138 m_bytesAllocated = bytesAllocated;
103 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta); 139 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta);
104 } 140 }
105 141
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 void Canvas2DLayerBridge::flush() 178 void Canvas2DLayerBridge::flush()
143 { 179 {
144 if (m_canvas->hasPendingCommands()) { 180 if (m_canvas->hasPendingCommands()) {
145 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); 181 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
146 m_canvas->flush(); 182 m_canvas->flush();
147 } 183 }
148 } 184 }
149 185
150 WebGraphicsContext3D* Canvas2DLayerBridge::context() 186 WebGraphicsContext3D* Canvas2DLayerBridge::context()
151 { 187 {
188 isValid(); // To ensure rate limiter is disabled if context is lost.
152 return m_context->webContext(); 189 return m_context->webContext();
153 } 190 }
154 191
192 bool Canvas2DLayerBridge::isValid()
193 {
194 ASSERT(m_layer);
195 if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) {
196 // Attempt to recover.
197 m_layer->clearTexture();
198 RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get() ;
199 if (!sharedContext || sharedContext->webContext()->isContextLost()) {
200 m_surfaceIsValid = false;
201 } else {
202 m_context = sharedContext;
203 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevi ce()->height());
204 SkAutoTUnref<SkSurface> surface(createSurface(m_context.get(), size) );
205 if (surface.get()) {
206 m_canvas->setSurface(surface.get());
207 m_surfaceIsValid = true;
208 // FIXME: draw sad canvas picture into new buffer crbug.com/2438 42
209 } else {
210 // Surface allocation failed. Set m_surfaceIsValid to false to
211 // trigger subsequent retry.
212 m_surfaceIsValid = false;
213 }
214 }
215 }
216 if (!m_surfaceIsValid)
217 setRateLimitingEnabled(false);
218 return m_surfaceIsValid;
219
220 }
221
155 bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outM ailbox, WebKit::WebExternalBitmap* bitmap) 222 bool Canvas2DLayerBridge::prepareMailbox(WebKit::WebExternalTextureMailbox* outM ailbox, WebKit::WebExternalBitmap* bitmap)
156 { 223 {
157 ASSERT(!bitmap); 224 ASSERT(!bitmap);
225 if (!isValid())
226 return false;
158 // Release to skia textures that were previouosly released by the 227 // Release to skia textures that were previouosly released by the
159 // compositor. We do this before acquiring the next snapshot in 228 // compositor. We do this before acquiring the next snapshot in
160 // order to cap maximum gpu memory consumption. 229 // order to cap maximum gpu memory consumption.
161 m_context->makeContextCurrent(); 230 m_context->makeContextCurrent();
162 flush(); 231 flush();
163 Vector<MailboxInfo>::iterator mailboxInfo; 232 Vector<MailboxInfo>::iterator mailboxInfo;
164 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) { 233 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) {
165 if (mailboxInfo->m_status == MailboxReleased) { 234 if (mailboxInfo->m_status == MailboxReleased) {
166 if (mailboxInfo->m_mailbox.syncPoint) { 235 if (mailboxInfo->m_mailbox.syncPoint) {
167 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); 236 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 // TODO(piman): fix this. 297 // TODO(piman): fix this.
229 ASSERT(m_mailboxes.size() <= 4); 298 ASSERT(m_mailboxes.size() <= 4);
230 ASSERT(mailboxInfo < m_mailboxes.end()); 299 ASSERT(mailboxInfo < m_mailboxes.end());
231 return mailboxInfo; 300 return mailboxInfo;
232 } 301 }
233 302
234 void Canvas2DLayerBridge::mailboxReleased(const WebKit::WebExternalTextureMailbo x& mailbox) 303 void Canvas2DLayerBridge::mailboxReleased(const WebKit::WebExternalTextureMailbo x& mailbox)
235 { 304 {
236 Vector<MailboxInfo>::iterator mailboxInfo; 305 Vector<MailboxInfo>::iterator mailboxInfo;
237 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) { 306 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai lboxInfo++) {
238 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.n ame))) { 307 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na me))) {
239 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; 308 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
240 ASSERT(mailboxInfo->m_status == MailboxInUse); 309 ASSERT(mailboxInfo->m_status == MailboxInUse);
241 mailboxInfo->m_status = MailboxReleased; 310 mailboxInfo->m_status = MailboxReleased;
242 return; 311 return;
243 } 312 }
244 } 313 }
245 ASSERT_NOT_REACHED();
246 } 314 }
247 315
248 WebKit::WebLayer* Canvas2DLayerBridge::layer() 316 WebKit::WebLayer* Canvas2DLayerBridge::layer()
249 { 317 {
318 ASSERT(m_layer);
250 return m_layer->layer(); 319 return m_layer->layer();
251 } 320 }
252 321
253 void Canvas2DLayerBridge::contextAcquired() 322 void Canvas2DLayerBridge::contextAcquired()
254 { 323 {
255 Canvas2DLayerManager::get().layerDidDraw(this); 324 Canvas2DLayerManager::get().layerDidDraw(this);
256 m_didRecordDrawCommand = true; 325 m_didRecordDrawCommand = true;
257 } 326 }
258 327
259 unsigned Canvas2DLayerBridge::backBufferTexture() 328 unsigned Canvas2DLayerBridge::backBufferTexture()
260 { 329 {
330 if (!isValid())
331 return 0;
261 contextAcquired(); 332 contextAcquired();
262 m_canvas->flush(); 333 m_canvas->flush();
263 m_context->flush(); 334 m_context->flush();
264 GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->g etDevice()->accessRenderTarget()); 335 GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->g etDevice()->accessRenderTarget());
265 if (renderTarget) { 336 if (renderTarget) {
266 return renderTarget->asTexture()->getTextureHandle(); 337 return renderTarget->asTexture()->getTextureHandle();
267 } 338 }
268 return 0; 339 return 0;
269 } 340 }
270 341
271 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { 342 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
272 // This copy constructor should only be used for Vector reallocation 343 // This copy constructor should only be used for Vector reallocation
273 // Assuming 'other' is to be destroyed, we swap m_image ownership 344 // Assuming 'other' is to be destroyed, we swap m_image ownership
274 // rather than do a refcount dance. 345 // rather than do a refcount dance.
275 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 346 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
276 m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image)); 347 m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image));
277 m_status = other.m_status; 348 m_status = other.m_status;
278 } 349 }
279 350
280 } 351 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698