Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |