| 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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 } | 197 } |
| 198 ++m_framesSinceMailboxRelease; | 198 ++m_framesSinceMailboxRelease; |
| 199 if (releasedMailboxHasExpired()) { | 199 if (releasedMailboxHasExpired()) { |
| 200 freeReleasedMailbox(); | 200 freeReleasedMailbox(); |
| 201 } | 201 } |
| 202 } | 202 } |
| 203 | 203 |
| 204 void Canvas2DLayerBridge::prepareForDraw() | 204 void Canvas2DLayerBridge::prepareForDraw() |
| 205 { | 205 { |
| 206 ASSERT(m_layer); | 206 ASSERT(m_layer); |
| 207 if (!isValid()) { | 207 if (!isValid() && !tryRecover()) { |
| 208 if (m_canvas) { | 208 if (m_canvas) { |
| 209 // drop pending commands because there is no surface to draw to | 209 // drop pending commands because there is no surface to draw to |
| 210 m_canvas->silentFlush(); | 210 m_canvas->silentFlush(); |
| 211 } | 211 } |
| 212 return; | 212 return; |
| 213 } | 213 } |
| 214 context()->makeContextCurrent(); | 214 context()->makeContextCurrent(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca
ted) | 217 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; | 280 return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0; |
| 281 } | 281 } |
| 282 | 282 |
| 283 bool Canvas2DLayerBridge::hasReleasedMailbox() const | 283 bool Canvas2DLayerBridge::hasReleasedMailbox() const |
| 284 { | 284 { |
| 285 return m_releasedMailboxInfoIndex != InvalidMailboxIndex; | 285 return m_releasedMailboxInfoIndex != InvalidMailboxIndex; |
| 286 } | 286 } |
| 287 | 287 |
| 288 void Canvas2DLayerBridge::freeReleasedMailbox() | 288 void Canvas2DLayerBridge::freeReleasedMailbox() |
| 289 { | 289 { |
| 290 if (m_contextProvider->context3d()->isContextLost() || !m_surfaceIsValid) |
| 291 return; |
| 290 MailboxInfo* mailboxInfo = releasedMailboxInfo(); | 292 MailboxInfo* mailboxInfo = releasedMailboxInfo(); |
| 291 if (!mailboxInfo) | 293 if (!mailboxInfo) |
| 292 return; | 294 return; |
| 293 | 295 |
| 294 ASSERT(mailboxInfo->m_status == MailboxReleased); | 296 ASSERT(mailboxInfo->m_status == MailboxReleased); |
| 295 if (mailboxInfo->m_mailbox.syncPoint) { | 297 if (mailboxInfo->m_mailbox.syncPoint) { |
| 296 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); | 298 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); |
| 297 mailboxInfo->m_mailbox.syncPoint = 0; | 299 mailboxInfo->m_mailbox.syncPoint = 0; |
| 298 } | 300 } |
| 299 // Invalidate texture state in case the compositor altered it since the copy
-on-write. | 301 // Invalidate texture state in case the compositor altered it since the copy
-on-write. |
| 300 if (mailboxInfo->m_image) { | 302 if (mailboxInfo->m_image) { |
| 301 if (isHidden() || releasedMailboxHasExpired()) | 303 if (isHidden() || releasedMailboxHasExpired()) |
| 302 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF
lags>(GrTexture::kReturnToCache_FlagBit)); | 304 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF
lags>(GrTexture::kReturnToCache_FlagBit)); |
| 303 mailboxInfo->m_image->getTexture()->invalidateCachedState(); | 305 mailboxInfo->m_image->getTexture()->invalidateCachedState(); |
| 304 mailboxInfo->m_image.clear(); | 306 mailboxInfo->m_image.clear(); |
| 305 } | 307 } |
| 306 mailboxInfo->m_status = MailboxAvailable; | 308 mailboxInfo->m_status = MailboxAvailable; |
| 307 m_releasedMailboxInfoIndex = InvalidMailboxIndex; | 309 m_releasedMailboxInfoIndex = InvalidMailboxIndex; |
| 308 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); | 310 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); |
| 309 } | 311 } |
| 310 | 312 |
| 311 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() | 313 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() |
| 312 { | 314 { |
| 313 // Check on m_layer is necessary because context() may be called during | 315 // Check on m_layer is necessary because context() may be called during |
| 314 // the destruction of m_layer | 316 // the destruction of m_layer |
| 315 if (m_layer) { | 317 if (m_layer && !isValid()) { |
| 316 isValid(); // To ensure rate limiter is disabled if context is lost. | 318 tryRecover(); // To ensure rate limiter is disabled if context is lost. |
| 317 } | 319 } |
| 318 return m_contextProvider->context3d(); | 320 return m_contextProvider->context3d(); |
| 319 } | 321 } |
| 320 | 322 |
| 321 bool Canvas2DLayerBridge::isValid() | 323 bool Canvas2DLayerBridge::isValid() |
| 322 { | 324 { |
| 323 ASSERT(m_layer); | 325 return !m_destructionInProgress && !m_contextProvider->context3d()->isContex
tLost() && m_surfaceIsValid; |
| 326 } |
| 327 |
| 328 bool Canvas2DLayerBridge::tryRecover() |
| 329 { |
| 330 ASSERT(m_layer && !isValid()); |
| 324 if (m_destructionInProgress) | 331 if (m_destructionInProgress) |
| 325 return false; | 332 return false; |
| 326 if (m_contextProvider->context3d()->isContextLost() || !m_surfaceIsValid) { | |
| 327 // Attempt to recover. | |
| 328 blink::WebGraphicsContext3D* sharedContext = 0; | |
| 329 m_layer->clearTexture(); | |
| 330 m_mailboxes.clear(); | |
| 331 m_releasedMailboxInfoIndex = InvalidMailboxIndex; | |
| 332 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOff
screenGraphicsContext3DProvider()); | |
| 333 if (m_contextProvider) | |
| 334 sharedContext = m_contextProvider->context3d(); | |
| 335 | 333 |
| 336 if (!sharedContext || sharedContext->isContextLost()) { | 334 blink::WebGraphicsContext3D* sharedContext = 0; |
| 335 m_layer->clearTexture(); |
| 336 m_mailboxes.clear(); |
| 337 m_releasedMailboxInfoIndex = InvalidMailboxIndex; |
| 338 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre
enGraphicsContext3DProvider()); |
| 339 if (m_contextProvider) |
| 340 sharedContext = m_contextProvider->context3d(); |
| 341 |
| 342 if (!sharedContext || sharedContext->isContextLost()) { |
| 343 m_surfaceIsValid = false; |
| 344 } else { |
| 345 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()
->height()); |
| 346 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext()
, size, m_msaaSampleCount)); |
| 347 if (surface.get()) { |
| 348 m_canvas->setSurface(surface.get()); |
| 349 m_surfaceIsValid = true; |
| 350 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
| 351 } else { |
| 352 // Surface allocation failed. Set m_surfaceIsValid to false to |
| 353 // trigger subsequent retry. |
| 337 m_surfaceIsValid = false; | 354 m_surfaceIsValid = false; |
| 338 } else { | |
| 339 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevi
ce()->height()); | |
| 340 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grConte
xt(), size, m_msaaSampleCount)); | |
| 341 if (surface.get()) { | |
| 342 m_canvas->setSurface(surface.get()); | |
| 343 m_surfaceIsValid = true; | |
| 344 // FIXME: draw sad canvas picture into new buffer crbug.com/2438
42 | |
| 345 } else { | |
| 346 // Surface allocation failed. Set m_surfaceIsValid to false to | |
| 347 // trigger subsequent retry. | |
| 348 m_surfaceIsValid = false; | |
| 349 } | |
| 350 } | 355 } |
| 351 } | 356 } |
| 352 if (!m_surfaceIsValid) | 357 if (!m_surfaceIsValid) |
| 353 setRateLimitingEnabled(false); | 358 setRateLimitingEnabled(false); |
| 359 |
| 354 return m_surfaceIsValid; | 360 return m_surfaceIsValid; |
| 355 } | 361 } |
| 356 | 362 |
| 357 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa
ilbox, blink::WebExternalBitmap* bitmap) | 363 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa
ilbox, blink::WebExternalBitmap* bitmap) |
| 358 { | 364 { |
| 359 if (bitmap) { | 365 if (bitmap) { |
| 360 // Using accelerated 2d canvas with software renderer, which | 366 // Using accelerated 2d canvas with software renderer, which |
| 361 // should only happen in tests that use fake graphics contexts | 367 // should only happen in tests that use fake graphics contexts |
| 362 // or in Android WebView in software mode. In this case, we do | 368 // or in Android WebView in software mode. In this case, we do |
| 363 // not care about producing any results for this canvas. | 369 // not care about producing any results for this canvas. |
| 364 m_canvas->silentFlush(); | 370 m_canvas->silentFlush(); |
| 365 m_lastImageId = 0; | 371 m_lastImageId = 0; |
| 366 return false; | 372 return false; |
| 367 } | 373 } |
| 368 if (!isValid()) | 374 if (!isValid() && !tryRecover()) |
| 369 return false; | 375 return false; |
| 370 | 376 |
| 371 blink::WebGraphicsContext3D* webContext = context(); | 377 blink::WebGraphicsContext3D* webContext = context(); |
| 372 | 378 |
| 373 // Release to skia textures that were previouosly released by the | 379 // Release to skia textures that were previouosly released by the |
| 374 // compositor. We do this before acquiring the next snapshot in | 380 // compositor. We do this before acquiring the next snapshot in |
| 375 // order to cap maximum gpu memory consumption. | 381 // order to cap maximum gpu memory consumption. |
| 376 webContext->makeContextCurrent(); | 382 webContext->makeContextCurrent(); |
| 377 flush(); | 383 flush(); |
| 378 | 384 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 void Canvas2DLayerBridge::willUse() | 489 void Canvas2DLayerBridge::willUse() |
| 484 { | 490 { |
| 485 ASSERT(!m_destructionInProgress); | 491 ASSERT(!m_destructionInProgress); |
| 486 Canvas2DLayerManager::get().layerDidDraw(this); | 492 Canvas2DLayerManager::get().layerDidDraw(this); |
| 487 m_didRecordDrawCommand = true; | 493 m_didRecordDrawCommand = true; |
| 488 } | 494 } |
| 489 | 495 |
| 490 Platform3DObject Canvas2DLayerBridge::getBackingTexture() | 496 Platform3DObject Canvas2DLayerBridge::getBackingTexture() |
| 491 { | 497 { |
| 492 ASSERT(!m_destructionInProgress); | 498 ASSERT(!m_destructionInProgress); |
| 493 if (!isValid()) | 499 if (!isValid() && !tryRecover()) |
| 494 return 0; | 500 return 0; |
| 495 willUse(); | 501 willUse(); |
| 496 m_canvas->flush(); | 502 m_canvas->flush(); |
| 497 context()->flush(); | 503 context()->flush(); |
| 498 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget(
); | 504 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget(
); |
| 499 if (renderTarget) { | 505 if (renderTarget) { |
| 500 return renderTarget->asTexture()->getTextureHandle(); | 506 return renderTarget->asTexture()->getTextureHandle(); |
| 501 } | 507 } |
| 502 return 0; | 508 return 0; |
| 503 } | 509 } |
| 504 | 510 |
| 505 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { | 511 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { |
| 506 // This copy constructor should only be used for Vector reallocation | 512 // This copy constructor should only be used for Vector reallocation |
| 507 // Assuming 'other' is to be destroyed, we transfer m_image ownership | 513 // Assuming 'other' is to be destroyed, we transfer m_image ownership |
| 508 // rather than do a refcount dance. | 514 // rather than do a refcount dance. |
| 509 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); | 515 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); |
| 510 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); | 516 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); |
| 511 m_status = other.m_status; | 517 m_status = other.m_status; |
| 512 } | 518 } |
| 513 | 519 |
| 514 } | 520 } |
| OLD | NEW |