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

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: rebase Created 6 years, 8 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
« no previous file with comments | « Source/platform/graphics/Canvas2DLayerBridge.h ('k') | Source/platform/graphics/ImageBuffer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 28 matching lines...) Expand all
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 setRateLimitingEnabled(false); 137 setRateLimitingEnabled(false);
137 m_canvas->silentFlush(); 138 m_canvas->silentFlush();
139 m_imageBuffer = 0;
138 freeTransientResources(); 140 freeTransientResources();
139 setIsHidden(true); 141 setIsHidden(true);
140 m_destructionInProgress = true; 142 m_destructionInProgress = true;
141 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); 143 GraphicsLayer::unregisterContentsLayer(m_layer->layer());
142 m_canvas->setNotificationClient(0); 144 m_canvas->setNotificationClient(0);
143 m_canvas.clear(); 145 m_canvas.clear();
144 m_layer->clearTexture(); 146 m_layer->clearTexture();
145 // Orphaning the layer is required to trigger the recration of a new layer 147 // Orphaning the layer is required to trigger the recration of a new layer
146 // in the case where destruction is caused by a canvas resize. Test: 148 // in the case where destruction is caused by a canvas resize. Test:
147 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html 149 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 ++m_framesSinceMailboxRelease; 202 ++m_framesSinceMailboxRelease;
201 if (releasedMailboxHasExpired()) { 203 if (releasedMailboxHasExpired()) {
202 freeReleasedMailbox(); 204 freeReleasedMailbox();
203 } 205 }
204 } 206 }
205 207
206 void Canvas2DLayerBridge::prepareForDraw() 208 void Canvas2DLayerBridge::prepareForDraw()
207 { 209 {
208 ASSERT(!m_destructionInProgress); 210 ASSERT(!m_destructionInProgress);
209 ASSERT(m_layer); 211 ASSERT(m_layer);
210 if (!surfaceIsValid() && !recoverSurface()) { 212 if (!checkSurfaceValid()) {
211 if (m_canvas) { 213 if (m_canvas) {
212 // drop pending commands because there is no surface to draw to 214 // drop pending commands because there is no surface to draw to
213 m_canvas->silentFlush(); 215 m_canvas->silentFlush();
214 } 216 }
215 return; 217 return;
216 } 218 }
217 context()->makeContextCurrent(); 219 context()->makeContextCurrent();
218 } 220 }
219 221
220 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted) 222 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted)
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0; 290 return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0;
289 } 291 }
290 292
291 bool Canvas2DLayerBridge::hasReleasedMailbox() const 293 bool Canvas2DLayerBridge::hasReleasedMailbox() const
292 { 294 {
293 return m_releasedMailboxInfoIndex != InvalidMailboxIndex; 295 return m_releasedMailboxInfoIndex != InvalidMailboxIndex;
294 } 296 }
295 297
296 void Canvas2DLayerBridge::freeReleasedMailbox() 298 void Canvas2DLayerBridge::freeReleasedMailbox()
297 { 299 {
298 if (m_contextProvider->context3d()->isContextLost() || !m_surfaceIsValid) 300 if (m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid)
299 return; 301 return;
300 MailboxInfo* mailboxInfo = releasedMailboxInfo(); 302 MailboxInfo* mailboxInfo = releasedMailboxInfo();
301 if (!mailboxInfo) 303 if (!mailboxInfo)
302 return; 304 return;
303 305
304 ASSERT(mailboxInfo->m_status == MailboxReleased); 306 ASSERT(mailboxInfo->m_status == MailboxReleased);
305 if (mailboxInfo->m_mailbox.syncPoint) { 307 if (mailboxInfo->m_mailbox.syncPoint) {
306 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); 308 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
307 mailboxInfo->m_mailbox.syncPoint = 0; 309 mailboxInfo->m_mailbox.syncPoint = 0;
308 } 310 }
309 // Invalidate texture state in case the compositor altered it since the copy -on-write. 311 // Invalidate texture state in case the compositor altered it since the copy -on-write.
310 if (mailboxInfo->m_image) { 312 if (mailboxInfo->m_image) {
311 if (isHidden() || releasedMailboxHasExpired()) 313 if (isHidden() || releasedMailboxHasExpired())
312 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF lags>(GrTexture::kReturnToCache_FlagBit)); 314 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF lags>(GrTexture::kReturnToCache_FlagBit));
313 mailboxInfo->m_image->getTexture()->invalidateCachedState(); 315 mailboxInfo->m_image->getTexture()->invalidateCachedState();
314 mailboxInfo->m_image.clear(); 316 mailboxInfo->m_image.clear();
315 } 317 }
316 mailboxInfo->m_status = MailboxAvailable; 318 mailboxInfo->m_status = MailboxAvailable;
317 m_releasedMailboxInfoIndex = InvalidMailboxIndex; 319 m_releasedMailboxInfoIndex = InvalidMailboxIndex;
318 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); 320 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
319 } 321 }
320 322
321 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() 323 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context()
322 { 324 {
323 // Check on m_layer is necessary because context() may be called during 325 // Check on m_layer is necessary because context() may be called during
324 // the destruction of m_layer 326 // the destruction of m_layer
325 if (m_layer && !m_destructionInProgress && !surfaceIsValid()) { 327 if (m_layer && !m_destructionInProgress)
326 recoverSurface(); // To ensure rate limiter is disabled if context is lo st. 328 checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost.
327 }
328 return m_contextProvider->context3d(); 329 return m_contextProvider->context3d();
329 } 330 }
330 331
331 bool Canvas2DLayerBridge::surfaceIsValid() 332 bool Canvas2DLayerBridge::checkSurfaceValid()
332 { 333 {
333 ASSERT(!m_destructionInProgress); 334 ASSERT(!m_destructionInProgress);
334 return !m_destructionInProgress && !m_contextProvider->context3d()->isContex tLost() && m_surfaceIsValid; 335 if (m_destructionInProgress || !m_isSurfaceValid)
336 return false;
337 if (m_contextProvider->context3d()->isContextLost()) {
338 m_isSurfaceValid = false;
339 if (m_imageBuffer)
340 m_imageBuffer->notifySurfaceInvalid();
341 setRateLimitingEnabled(false);
342 }
343 return m_isSurfaceValid;
335 } 344 }
336 345
337 bool Canvas2DLayerBridge::recoverSurface() 346 bool Canvas2DLayerBridge::restoreSurface()
338 { 347 {
339 ASSERT(!m_destructionInProgress); 348 ASSERT(!m_destructionInProgress);
340 ASSERT(m_layer && !surfaceIsValid());
341 if (m_destructionInProgress) 349 if (m_destructionInProgress)
342 return false; 350 return false;
351 ASSERT(m_layer && !m_isSurfaceValid);
343 352
344 blink::WebGraphicsContext3D* sharedContext = 0; 353 blink::WebGraphicsContext3D* sharedContext = 0;
345 // We must clear the mailboxes before calling m_layer->clearTexture() to pre vent 354 // We must clear the mailboxes before calling m_layer->clearTexture() to pre vent
346 // re-entry via mailboxReleased from operating on defunct GrContext objects. 355 // re-entry via mailboxReleased from operating on defunct GrContext objects.
347 m_mailboxes.clear(); 356 m_mailboxes.clear();
348 m_releasedMailboxInfoIndex = InvalidMailboxIndex; 357 m_releasedMailboxInfoIndex = InvalidMailboxIndex;
349 m_layer->clearTexture(); 358 m_layer->clearTexture();
350 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre enGraphicsContext3DProvider()); 359 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre enGraphicsContext3DProvider());
351 if (m_contextProvider) 360 if (m_contextProvider)
352 sharedContext = m_contextProvider->context3d(); 361 sharedContext = m_contextProvider->context3d();
353 362
354 if (!sharedContext || sharedContext->isContextLost()) { 363 if (sharedContext && !sharedContext->isContextLost()) {
355 m_surfaceIsValid = false;
356 } else {
357 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice() ->height()); 364 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice() ->height());
358 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext() , size, m_msaaSampleCount)); 365 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext() , size, m_msaaSampleCount));
359 if (surface.get()) { 366 if (surface.get()) {
360 m_canvas->setSurface(surface.get()); 367 m_canvas->setSurface(surface.get());
361 m_surfaceIsValid = true; 368 m_isSurfaceValid = true;
362 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 369 // FIXME: draw sad canvas picture into new buffer crbug.com/243842
363 } else {
364 // Surface allocation failed. Set m_surfaceIsValid to false to
365 // trigger subsequent retry.
366 m_surfaceIsValid = false;
367 } 370 }
368 } 371 }
369 if (!m_surfaceIsValid)
370 setRateLimitingEnabled(false);
371 372
372 return m_surfaceIsValid; 373 return m_isSurfaceValid;
373 } 374 }
374 375
375 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa ilbox, blink::WebExternalBitmap* bitmap) 376 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa ilbox, blink::WebExternalBitmap* bitmap)
376 { 377 {
377 ASSERT(!m_destructionInProgress); 378 ASSERT(!m_destructionInProgress);
378 if (bitmap) { 379 if (bitmap) {
379 // Using accelerated 2d canvas with software renderer, which 380 // Using accelerated 2d canvas with software renderer, which
380 // should only happen in tests that use fake graphics contexts 381 // should only happen in tests that use fake graphics contexts
381 // or in Android WebView in software mode. In this case, we do 382 // or in Android WebView in software mode. In this case, we do
382 // not care about producing any results for this canvas. 383 // not care about producing any results for this canvas.
383 m_canvas->silentFlush(); 384 m_canvas->silentFlush();
384 m_lastImageId = 0; 385 m_lastImageId = 0;
385 return false; 386 return false;
386 } 387 }
387 if (!surfaceIsValid() && !recoverSurface()) 388 if (!checkSurfaceValid())
388 return false; 389 return false;
389 390
390 blink::WebGraphicsContext3D* webContext = context(); 391 blink::WebGraphicsContext3D* webContext = context();
391 392
392 // Release to skia textures that were previouosly released by the 393 // Release to skia textures that were previouosly released by the
393 // compositor. We do this before acquiring the next snapshot in 394 // compositor. We do this before acquiring the next snapshot in
394 // order to cap maximum gpu memory consumption. 395 // order to cap maximum gpu memory consumption.
395 webContext->makeContextCurrent(); 396 webContext->makeContextCurrent();
396 flush(); 397 flush();
397 398
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 void Canvas2DLayerBridge::willUse() 504 void Canvas2DLayerBridge::willUse()
504 { 505 {
505 ASSERT(!m_destructionInProgress); 506 ASSERT(!m_destructionInProgress);
506 Canvas2DLayerManager::get().layerDidDraw(this); 507 Canvas2DLayerManager::get().layerDidDraw(this);
507 m_didRecordDrawCommand = true; 508 m_didRecordDrawCommand = true;
508 } 509 }
509 510
510 Platform3DObject Canvas2DLayerBridge::getBackingTexture() 511 Platform3DObject Canvas2DLayerBridge::getBackingTexture()
511 { 512 {
512 ASSERT(!m_destructionInProgress); 513 ASSERT(!m_destructionInProgress);
513 if (!surfaceIsValid() && !recoverSurface()) 514 if (!checkSurfaceValid())
514 return 0; 515 return 0;
515 willUse(); 516 willUse();
516 m_canvas->flush(); 517 m_canvas->flush();
517 context()->flush(); 518 context()->flush();
518 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( ); 519 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( );
519 if (renderTarget) { 520 if (renderTarget) {
520 return renderTarget->asTexture()->getTextureHandle(); 521 return renderTarget->asTexture()->getTextureHandle();
521 } 522 }
522 return 0; 523 return 0;
523 } 524 }
524 525
525 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { 526 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
526 // This copy constructor should only be used for Vector reallocation 527 // This copy constructor should only be used for Vector reallocation
527 // Assuming 'other' is to be destroyed, we transfer m_image ownership 528 // Assuming 'other' is to be destroyed, we transfer m_image ownership
528 // rather than do a refcount dance. 529 // rather than do a refcount dance.
529 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 530 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
530 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); 531 m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
531 m_status = other.m_status; 532 m_status = other.m_status;
532 } 533 }
533 534
534 } 535 }
OLDNEW
« no previous file with comments | « Source/platform/graphics/Canvas2DLayerBridge.h ('k') | Source/platform/graphics/ImageBuffer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698