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

Side by Side Diff: Source/platform/graphics/Canvas2DLayerBridge.cpp

Issue 211503006: Implementation of 2D canvas context lost/restored events (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: adding missing file Created 6 years, 9 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 return nullptr; 76 return nullptr;
77 RefPtr<Canvas2DLayerBridge> layerBridge; 77 RefPtr<Canvas2DLayerBridge> layerBridge;
78 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface. get())); 78 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface. get()));
79 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), ca nvas.release(), msaaSampleCount, opacityMode)); 79 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), ca nvas.release(), msaaSampleCount, opacityMode));
80 return layerBridge.release(); 80 return layerBridge.release();
81 } 81 }
82 82
83 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DP rovider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCou nt, OpacityMode opacityMode) 83 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DP rovider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCou nt, OpacityMode opacityMode)
84 : m_canvas(canvas) 84 : m_canvas(canvas)
85 , m_contextProvider(contextProvider) 85 , m_contextProvider(contextProvider)
86 , m_imageBuffer(0)
86 , m_msaaSampleCount(msaaSampleCount) 87 , m_msaaSampleCount(msaaSampleCount)
87 , m_bytesAllocated(0) 88 , m_bytesAllocated(0)
88 , m_didRecordDrawCommand(false) 89 , m_didRecordDrawCommand(false)
89 , m_surfaceIsValid(true) 90 , m_isSurfaceValid(true)
90 , m_framesPending(0) 91 , m_framesPending(0)
91 , m_framesSinceMailboxRelease(0) 92 , m_framesSinceMailboxRelease(0)
92 , m_destructionInProgress(false) 93 , m_destructionInProgress(false)
93 , m_rateLimitingEnabled(false) 94 , m_rateLimitingEnabled(false)
94 , m_isHidden(false) 95 , m_isHidden(false)
95 , m_next(0) 96 , m_next(0)
96 , m_prev(0) 97 , m_prev(0)
97 , m_lastImageId(0) 98 , m_lastImageId(0)
98 , m_releasedMailboxInfoIndex(InvalidMailboxIndex) 99 , m_releasedMailboxInfoIndex(InvalidMailboxIndex)
99 { 100 {
(...skipping 27 matching lines...) Expand all
127 m_mailboxes.clear(); 128 m_mailboxes.clear();
128 #ifndef NDEBUG 129 #ifndef NDEBUG
129 canvas2DLayerBridgeInstanceCounter.decrement(); 130 canvas2DLayerBridgeInstanceCounter.decrement();
130 #endif 131 #endif
131 } 132 }
132 133
133 void Canvas2DLayerBridge::beginDestruction() 134 void Canvas2DLayerBridge::beginDestruction()
134 { 135 {
135 ASSERT(!m_destructionInProgress); 136 ASSERT(!m_destructionInProgress);
136 m_destructionInProgress = true; 137 m_destructionInProgress = true;
138 m_imageBuffer = 0;
137 freeTransientResources(); 139 freeTransientResources();
138 setIsHidden(true); 140 setIsHidden(true);
139 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 141 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
140 m_canvas->setNotificationClient(0); 142 m_canvas->setNotificationClient(0);
141 m_layer->clearTexture(); 143 m_layer->clearTexture();
142 // Orphaning the layer is required to trigger the recration of a new layer 144 // Orphaning the layer is required to trigger the recration of a new layer
143 // in the case where destruction is caused by a canvas resize. Test: 145 // in the case where destruction is caused by a canvas resize. Test:
144 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html 146 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
145 m_layer->layer()->removeFromParent(); 147 m_layer->layer()->removeFromParent();
146 // To anyone who ever hits this assert: Please update crbug.com/344666 148 // To anyone who ever hits this assert: Please update crbug.com/344666
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 199 }
198 ++m_framesSinceMailboxRelease; 200 ++m_framesSinceMailboxRelease;
199 if (releasedMailboxHasExpired()) { 201 if (releasedMailboxHasExpired()) {
200 freeReleasedMailbox(); 202 freeReleasedMailbox();
201 } 203 }
202 } 204 }
203 205
204 void Canvas2DLayerBridge::prepareForDraw() 206 void Canvas2DLayerBridge::prepareForDraw()
205 { 207 {
206 ASSERT(m_layer); 208 ASSERT(m_layer);
207 if (!surfaceIsValid() && !recoverSurface()) { 209 if (!isSurfaceValid()) {
208 if (m_canvas) { 210 if (m_canvas) {
209 // drop pending commands because there is no surface to draw to 211 // drop pending commands because there is no surface to draw to
210 m_canvas->silentFlush(); 212 m_canvas->silentFlush();
211 } 213 }
212 return; 214 return;
213 } 215 }
214 context()->makeContextCurrent(); 216 context()->makeContextCurrent();
215 } 217 }
216 218
217 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted) 219 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted)
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0; 282 return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0;
281 } 283 }
282 284
283 bool Canvas2DLayerBridge::hasReleasedMailbox() const 285 bool Canvas2DLayerBridge::hasReleasedMailbox() const
284 { 286 {
285 return m_releasedMailboxInfoIndex != InvalidMailboxIndex; 287 return m_releasedMailboxInfoIndex != InvalidMailboxIndex;
286 } 288 }
287 289
288 void Canvas2DLayerBridge::freeReleasedMailbox() 290 void Canvas2DLayerBridge::freeReleasedMailbox()
289 { 291 {
290 if (m_contextProvider->context3d()->isContextLost() || !m_surfaceIsValid) 292 if (m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid)
291 return; 293 return;
292 MailboxInfo* mailboxInfo = releasedMailboxInfo(); 294 MailboxInfo* mailboxInfo = releasedMailboxInfo();
293 if (!mailboxInfo) 295 if (!mailboxInfo)
294 return; 296 return;
295 297
296 ASSERT(mailboxInfo->m_status == MailboxReleased); 298 ASSERT(mailboxInfo->m_status == MailboxReleased);
297 if (mailboxInfo->m_mailbox.syncPoint) { 299 if (mailboxInfo->m_mailbox.syncPoint) {
298 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); 300 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
299 mailboxInfo->m_mailbox.syncPoint = 0; 301 mailboxInfo->m_mailbox.syncPoint = 0;
300 } 302 }
301 // Invalidate texture state in case the compositor altered it since the copy -on-write. 303 // Invalidate texture state in case the compositor altered it since the copy -on-write.
302 if (mailboxInfo->m_image) { 304 if (mailboxInfo->m_image) {
303 if (isHidden() || releasedMailboxHasExpired()) 305 if (isHidden() || releasedMailboxHasExpired())
304 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF lags>(GrTexture::kReturnToCache_FlagBit)); 306 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF lags>(GrTexture::kReturnToCache_FlagBit));
305 mailboxInfo->m_image->getTexture()->invalidateCachedState(); 307 mailboxInfo->m_image->getTexture()->invalidateCachedState();
306 mailboxInfo->m_image.clear(); 308 mailboxInfo->m_image.clear();
307 } 309 }
308 mailboxInfo->m_status = MailboxAvailable; 310 mailboxInfo->m_status = MailboxAvailable;
309 m_releasedMailboxInfoIndex = InvalidMailboxIndex; 311 m_releasedMailboxInfoIndex = InvalidMailboxIndex;
310 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); 312 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
311 } 313 }
312 314
313 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() 315 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context()
314 { 316 {
315 // Check on m_layer is necessary because context() may be called during 317 // Check on m_layer is necessary because context() may be called during
316 // the destruction of m_layer 318 // the destruction of m_layer
317 if (m_layer && !surfaceIsValid()) { 319 if (m_layer)
318 recoverSurface(); // To ensure rate limiter is disabled if context is lo st. 320 isSurfaceValid(); // To ensure rate limiter is disabled if context is lo st.
Stephen White 2014/03/25 23:25:04 Naming nit: this looks like a getter (and has the
319 }
320 return m_contextProvider->context3d(); 321 return m_contextProvider->context3d();
321 } 322 }
322 323
323 bool Canvas2DLayerBridge::surfaceIsValid() 324 bool Canvas2DLayerBridge::isSurfaceValid()
324 { 325 {
325 return !m_destructionInProgress && !m_contextProvider->context3d()->isContex tLost() && m_surfaceIsValid; 326 if (m_destructionInProgress || !m_isSurfaceValid)
327 return false;
328 if (m_contextProvider->context3d()->isContextLost()) {
329 m_isSurfaceValid = false;
330 if (m_imageBuffer)
331 m_imageBuffer->notifySurfaceInvalid();
332 setRateLimitingEnabled(false);
333 }
334 return m_isSurfaceValid;
326 } 335 }
327 336
328 bool Canvas2DLayerBridge::recoverSurface() 337 bool Canvas2DLayerBridge::restoreSurface()
329 { 338 {
330 ASSERT(m_layer && !surfaceIsValid());
331 if (m_destructionInProgress) 339 if (m_destructionInProgress)
332 return false; 340 return false;
341 ASSERT(m_layer && !m_isSurfaceValid);
333 342
334 blink::WebGraphicsContext3D* sharedContext = 0; 343 blink::WebGraphicsContext3D* sharedContext = 0;
335 // We must clear the mailboxes before calling m_layer->clearTexture() to pre vent 344 // We must clear the mailboxes before calling m_layer->clearTexture() to pre vent
336 // re-entry via mailboxReleased from operating on defunct GrContext objects. 345 // re-entry via mailboxReleased from operating on defunct GrContext objects.
337 m_mailboxes.clear(); 346 m_mailboxes.clear();
338 m_releasedMailboxInfoIndex = InvalidMailboxIndex; 347 m_releasedMailboxInfoIndex = InvalidMailboxIndex;
339 m_layer->clearTexture(); 348 m_layer->clearTexture();
340 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre enGraphicsContext3DProvider()); 349 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre enGraphicsContext3DProvider());
341 if (m_contextProvider) 350 if (m_contextProvider)
342 sharedContext = m_contextProvider->context3d(); 351 sharedContext = m_contextProvider->context3d();
343 352
344 if (!sharedContext || sharedContext->isContextLost()) { 353 if (sharedContext && !sharedContext->isContextLost()) {
345 m_surfaceIsValid = false;
346 } else {
347 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice() ->height()); 354 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice() ->height());
348 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext() , size, m_msaaSampleCount)); 355 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext() , size, m_msaaSampleCount));
349 if (surface.get()) { 356 if (surface.get()) {
350 m_canvas->setSurface(surface.get()); 357 m_canvas->setSurface(surface.get());
351 m_surfaceIsValid = true; 358 m_isSurfaceValid = true;
352 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 359 // FIXME: draw sad canvas picture into new buffer crbug.com/243842
353 } else {
354 // Surface allocation failed. Set m_surfaceIsValid to false to
355 // trigger subsequent retry.
356 m_surfaceIsValid = false;
357 } 360 }
358 } 361 }
359 if (!m_surfaceIsValid)
360 setRateLimitingEnabled(false);
361 362
362 return m_surfaceIsValid; 363 return m_isSurfaceValid;
363 } 364 }
364 365
365 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa ilbox, blink::WebExternalBitmap* bitmap) 366 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa ilbox, blink::WebExternalBitmap* bitmap)
366 { 367 {
367 if (bitmap) { 368 if (bitmap) {
368 // Using accelerated 2d canvas with software renderer, which 369 // Using accelerated 2d canvas with software renderer, which
369 // should only happen in tests that use fake graphics contexts 370 // should only happen in tests that use fake graphics contexts
370 // or in Android WebView in software mode. In this case, we do 371 // or in Android WebView in software mode. In this case, we do
371 // not care about producing any results for this canvas. 372 // not care about producing any results for this canvas.
372 m_canvas->silentFlush(); 373 m_canvas->silentFlush();
373 m_lastImageId = 0; 374 m_lastImageId = 0;
374 return false; 375 return false;
375 } 376 }
376 if (!surfaceIsValid() && !recoverSurface()) 377 if (!isSurfaceValid())
377 return false; 378 return false;
378 379
379 blink::WebGraphicsContext3D* webContext = context(); 380 blink::WebGraphicsContext3D* webContext = context();
380 381
381 // Release to skia textures that were previouosly released by the 382 // Release to skia textures that were previouosly released by the
382 // compositor. We do this before acquiring the next snapshot in 383 // compositor. We do this before acquiring the next snapshot in
383 // order to cap maximum gpu memory consumption. 384 // order to cap maximum gpu memory consumption.
384 webContext->makeContextCurrent(); 385 webContext->makeContextCurrent();
385 flush(); 386 flush();
386 387
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 void Canvas2DLayerBridge::willUse() 492 void Canvas2DLayerBridge::willUse()
492 { 493 {
493 ASSERT(!m_destructionInProgress); 494 ASSERT(!m_destructionInProgress);
494 Canvas2DLayerManager::get().layerDidDraw(this); 495 Canvas2DLayerManager::get().layerDidDraw(this);
495 m_didRecordDrawCommand = true; 496 m_didRecordDrawCommand = true;
496 } 497 }
497 498
498 Platform3DObject Canvas2DLayerBridge::getBackingTexture() 499 Platform3DObject Canvas2DLayerBridge::getBackingTexture()
499 { 500 {
500 ASSERT(!m_destructionInProgress); 501 ASSERT(!m_destructionInProgress);
501 if (!surfaceIsValid() && !recoverSurface()) 502 if (!isSurfaceValid())
502 return 0; 503 return 0;
503 willUse(); 504 willUse();
504 m_canvas->flush(); 505 m_canvas->flush();
505 context()->flush(); 506 context()->flush();
506 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( ); 507 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( );
507 if (renderTarget) { 508 if (renderTarget) {
508 return renderTarget->asTexture()->getTextureHandle(); 509 return renderTarget->asTexture()->getTextureHandle();
509 } 510 }
510 return 0; 511 return 0;
511 } 512 }
512 513
513 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { 514 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
514 // This copy constructor should only be used for Vector reallocation 515 // This copy constructor should only be used for Vector reallocation
515 // Assuming 'other' is to be destroyed, we transfer m_image ownership 516 // Assuming 'other' is to be destroyed, we transfer m_image ownership
516 // rather than do a refcount dance. 517 // rather than do a refcount dance.
517 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 518 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
518 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); 519 m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
519 m_status = other.m_status; 520 m_status = other.m_status;
520 } 521 }
521 522
522 } 523 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698