| 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 21 matching lines...) Expand all Loading... |
| 32 #include "SkSurface.h" | 32 #include "SkSurface.h" |
| 33 #include "platform/TraceEvent.h" | 33 #include "platform/TraceEvent.h" |
| 34 #include "platform/graphics/Canvas2DLayerManager.h" | 34 #include "platform/graphics/Canvas2DLayerManager.h" |
| 35 #include "platform/graphics/GraphicsLayer.h" | 35 #include "platform/graphics/GraphicsLayer.h" |
| 36 #include "public/platform/Platform.h" | 36 #include "public/platform/Platform.h" |
| 37 #include "public/platform/WebCompositorSupport.h" | 37 #include "public/platform/WebCompositorSupport.h" |
| 38 #include "public/platform/WebGraphicsContext3D.h" | 38 #include "public/platform/WebGraphicsContext3D.h" |
| 39 #include "public/platform/WebGraphicsContext3DProvider.h" | 39 #include "public/platform/WebGraphicsContext3DProvider.h" |
| 40 #include "wtf/RefCountedLeakCounter.h" | 40 #include "wtf/RefCountedLeakCounter.h" |
| 41 | 41 |
| 42 using blink::WebExternalTextureLayer; | |
| 43 using blink::WebGraphicsContext3D; | |
| 44 | |
| 45 namespace { | 42 namespace { |
| 46 enum { | 43 enum { |
| 47 InvalidMailboxIndex = -1, | 44 InvalidMailboxIndex = -1, |
| 48 }; | 45 }; |
| 49 | 46 |
| 50 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstance
Counter, ("Canvas2DLayerBridge")); | 47 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstance
Counter, ("Canvas2DLayerBridge")); |
| 51 } | 48 } |
| 52 | 49 |
| 53 namespace blink { | 50 namespace blink { |
| 54 | 51 |
| 55 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size,
int msaaSampleCount = 0) | 52 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size,
int msaaSampleCount = 0) |
| 56 { | 53 { |
| 57 if (!gr) | 54 if (!gr) |
| 58 return nullptr; | 55 return nullptr; |
| 59 gr->resetContext(); | 56 gr->resetContext(); |
| 60 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); | 57 SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); |
| 61 return adoptRef(SkSurface::NewRenderTarget(gr, info, msaaSampleCount)); | 58 return adoptRef(SkSurface::NewRenderTarget(gr, info, msaaSampleCount)); |
| 62 } | 59 } |
| 63 | 60 |
| 64 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size,
OpacityMode opacityMode, int msaaSampleCount) | 61 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size,
OpacityMode opacityMode, int msaaSampleCount) |
| 65 { | 62 { |
| 66 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); | 63 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); |
| 67 OwnPtr<blink::WebGraphicsContext3DProvider> contextProvider = adoptPtr(blink
::Platform::current()->createSharedOffscreenGraphicsContext3DProvider()); | 64 OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::cu
rrent()->createSharedOffscreenGraphicsContext3DProvider()); |
| 68 if (!contextProvider) | 65 if (!contextProvider) |
| 69 return nullptr; | 66 return nullptr; |
| 70 RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size
, msaaSampleCount)); | 67 RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size
, msaaSampleCount)); |
| 71 if (!surface) | 68 if (!surface) |
| 72 return nullptr; | 69 return nullptr; |
| 73 RefPtr<Canvas2DLayerBridge> layerBridge; | 70 RefPtr<Canvas2DLayerBridge> layerBridge; |
| 74 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.
get())); | 71 OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.
get())); |
| 75 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), ca
nvas.release(), surface.release(), msaaSampleCount, opacityMode)); | 72 layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), ca
nvas.release(), surface.release(), msaaSampleCount, opacityMode)); |
| 76 return layerBridge.release(); | 73 return layerBridge.release(); |
| 77 } | 74 } |
| 78 | 75 |
| 79 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DP
rovider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, PassRefPtr<SkSurf
ace> surface, int msaaSampleCount, OpacityMode opacityMode) | 76 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider
> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, PassRefPtr<SkSurface> su
rface, int msaaSampleCount, OpacityMode opacityMode) |
| 80 : m_canvas(canvas) | 77 : m_canvas(canvas) |
| 81 , m_surface(surface) | 78 , m_surface(surface) |
| 82 , m_contextProvider(contextProvider) | 79 , m_contextProvider(contextProvider) |
| 83 , m_imageBuffer(0) | 80 , m_imageBuffer(0) |
| 84 , m_msaaSampleCount(msaaSampleCount) | 81 , m_msaaSampleCount(msaaSampleCount) |
| 85 , m_bytesAllocated(0) | 82 , m_bytesAllocated(0) |
| 86 , m_didRecordDrawCommand(false) | 83 , m_didRecordDrawCommand(false) |
| 87 , m_isSurfaceValid(true) | 84 , m_isSurfaceValid(true) |
| 88 , m_framesPending(0) | 85 , m_framesPending(0) |
| 89 , m_framesSinceMailboxRelease(0) | 86 , m_framesSinceMailboxRelease(0) |
| 90 , m_destructionInProgress(false) | 87 , m_destructionInProgress(false) |
| 91 , m_rateLimitingEnabled(false) | 88 , m_rateLimitingEnabled(false) |
| 92 , m_isHidden(false) | 89 , m_isHidden(false) |
| 93 , m_next(0) | 90 , m_next(0) |
| 94 , m_prev(0) | 91 , m_prev(0) |
| 95 , m_lastImageId(0) | 92 , m_lastImageId(0) |
| 96 , m_releasedMailboxInfoIndex(InvalidMailboxIndex) | 93 , m_releasedMailboxInfoIndex(InvalidMailboxIndex) |
| 97 { | 94 { |
| 98 ASSERT(m_canvas); | 95 ASSERT(m_canvas); |
| 99 ASSERT(m_surface); | 96 ASSERT(m_surface); |
| 100 ASSERT(m_contextProvider); | 97 ASSERT(m_contextProvider); |
| 101 // Used by browser tests to detect the use of a Canvas2DLayerBridge. | 98 // Used by browser tests to detect the use of a Canvas2DLayerBridge. |
| 102 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); | 99 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); |
| 103 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createEx
ternalTextureLayer(this)); | 100 m_layer = adoptPtr(Platform::current()->compositorSupport()->createExternalT
extureLayer(this)); |
| 104 m_layer->setOpaque(opacityMode == Opaque); | 101 m_layer->setOpaque(opacityMode == Opaque); |
| 105 m_layer->setBlendBackgroundColor(opacityMode != Opaque); | 102 m_layer->setBlendBackgroundColor(opacityMode != Opaque); |
| 106 GraphicsLayer::registerContentsLayer(m_layer->layer()); | 103 GraphicsLayer::registerContentsLayer(m_layer->layer()); |
| 107 m_layer->setRateLimitContext(m_rateLimitingEnabled); | 104 m_layer->setRateLimitContext(m_rateLimitingEnabled); |
| 108 m_canvas->setNotificationClient(this); | 105 m_canvas->setNotificationClient(this); |
| 109 #ifndef NDEBUG | 106 #ifndef NDEBUG |
| 110 canvas2DLayerBridgeInstanceCounter.increment(); | 107 canvas2DLayerBridgeInstanceCounter.increment(); |
| 111 #endif | 108 #endif |
| 112 } | 109 } |
| 113 | 110 |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 322 if (isHidden() || releasedMailboxHasExpired()) | 319 if (isHidden() || releasedMailboxHasExpired()) |
| 323 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF
lags>(GrTexture::kReturnToCache_FlagBit)); | 320 mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureF
lags>(GrTexture::kReturnToCache_FlagBit)); |
| 324 mailboxInfo->m_image->getTexture()->textureParamsModified(); | 321 mailboxInfo->m_image->getTexture()->textureParamsModified(); |
| 325 mailboxInfo->m_image.clear(); | 322 mailboxInfo->m_image.clear(); |
| 326 } | 323 } |
| 327 mailboxInfo->m_status = MailboxAvailable; | 324 mailboxInfo->m_status = MailboxAvailable; |
| 328 m_releasedMailboxInfoIndex = InvalidMailboxIndex; | 325 m_releasedMailboxInfoIndex = InvalidMailboxIndex; |
| 329 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); | 326 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this); |
| 330 } | 327 } |
| 331 | 328 |
| 332 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() | 329 WebGraphicsContext3D* Canvas2DLayerBridge::context() |
| 333 { | 330 { |
| 334 // Check on m_layer is necessary because context() may be called during | 331 // Check on m_layer is necessary because context() may be called during |
| 335 // the destruction of m_layer | 332 // the destruction of m_layer |
| 336 if (m_layer && !m_destructionInProgress) | 333 if (m_layer && !m_destructionInProgress) |
| 337 checkSurfaceValid(); // To ensure rate limiter is disabled if context is
lost. | 334 checkSurfaceValid(); // To ensure rate limiter is disabled if context is
lost. |
| 338 return m_contextProvider ? m_contextProvider->context3d() : 0; | 335 return m_contextProvider ? m_contextProvider->context3d() : 0; |
| 339 } | 336 } |
| 340 | 337 |
| 341 bool Canvas2DLayerBridge::checkSurfaceValid() | 338 bool Canvas2DLayerBridge::checkSurfaceValid() |
| 342 { | 339 { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 353 return m_isSurfaceValid; | 350 return m_isSurfaceValid; |
| 354 } | 351 } |
| 355 | 352 |
| 356 bool Canvas2DLayerBridge::restoreSurface() | 353 bool Canvas2DLayerBridge::restoreSurface() |
| 357 { | 354 { |
| 358 ASSERT(!m_destructionInProgress); | 355 ASSERT(!m_destructionInProgress); |
| 359 if (m_destructionInProgress) | 356 if (m_destructionInProgress) |
| 360 return false; | 357 return false; |
| 361 ASSERT(m_layer && !m_isSurfaceValid); | 358 ASSERT(m_layer && !m_isSurfaceValid); |
| 362 | 359 |
| 363 blink::WebGraphicsContext3D* sharedContext = 0; | 360 WebGraphicsContext3D* sharedContext = 0; |
| 364 // We must clear the mailboxes before calling m_layer->clearTexture() to pre
vent | 361 // We must clear the mailboxes before calling m_layer->clearTexture() to pre
vent |
| 365 // re-entry via mailboxReleased from operating on defunct GrContext objects. | 362 // re-entry via mailboxReleased from operating on defunct GrContext objects. |
| 366 m_mailboxes.clear(); | 363 m_mailboxes.clear(); |
| 367 m_releasedMailboxInfoIndex = InvalidMailboxIndex; | 364 m_releasedMailboxInfoIndex = InvalidMailboxIndex; |
| 368 m_layer->clearTexture(); | 365 m_layer->clearTexture(); |
| 369 m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscre
enGraphicsContext3DProvider()); | 366 m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraph
icsContext3DProvider()); |
| 370 if (m_contextProvider) | 367 if (m_contextProvider) |
| 371 sharedContext = m_contextProvider->context3d(); | 368 sharedContext = m_contextProvider->context3d(); |
| 372 | 369 |
| 373 if (sharedContext && !sharedContext->isContextLost()) { | 370 if (sharedContext && !sharedContext->isContextLost()) { |
| 374 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()
->height()); | 371 IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()
->height()); |
| 375 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext()
, size, m_msaaSampleCount)); | 372 RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext()
, size, m_msaaSampleCount)); |
| 376 if (surface.get()) { | 373 if (surface.get()) { |
| 377 m_surface = surface.release(); | 374 m_surface = surface.release(); |
| 378 m_canvas->setSurface(m_surface.get()); | 375 m_canvas->setSurface(m_surface.get()); |
| 379 m_isSurfaceValid = true; | 376 m_isSurfaceValid = true; |
| 380 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 | 377 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
| 381 } | 378 } |
| 382 } | 379 } |
| 383 | 380 |
| 384 return m_isSurfaceValid; | 381 return m_isSurfaceValid; |
| 385 } | 382 } |
| 386 | 383 |
| 387 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa
ilbox, blink::WebExternalBitmap* bitmap) | 384 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox,
WebExternalBitmap* bitmap) |
| 388 { | 385 { |
| 389 if (m_destructionInProgress) { | 386 if (m_destructionInProgress) { |
| 390 // It can be hit in the following sequence. | 387 // It can be hit in the following sequence. |
| 391 // 1. Canvas draws something. | 388 // 1. Canvas draws something. |
| 392 // 2. The compositor begins the frame. | 389 // 2. The compositor begins the frame. |
| 393 // 3. Javascript makes a context be lost. | 390 // 3. Javascript makes a context be lost. |
| 394 // 4. Here. | 391 // 4. Here. |
| 395 return false; | 392 return false; |
| 396 } | 393 } |
| 397 if (bitmap) { | 394 if (bitmap) { |
| 398 // Using accelerated 2d canvas with software renderer, which | 395 // Using accelerated 2d canvas with software renderer, which |
| 399 // should only happen in tests that use fake graphics contexts | 396 // should only happen in tests that use fake graphics contexts |
| 400 // or in Android WebView in software mode. In this case, we do | 397 // or in Android WebView in software mode. In this case, we do |
| 401 // not care about producing any results for this canvas. | 398 // not care about producing any results for this canvas. |
| 402 m_canvas->silentFlush(); | 399 m_canvas->silentFlush(); |
| 403 m_lastImageId = 0; | 400 m_lastImageId = 0; |
| 404 return false; | 401 return false; |
| 405 } | 402 } |
| 406 if (!checkSurfaceValid()) | 403 if (!checkSurfaceValid()) |
| 407 return false; | 404 return false; |
| 408 | 405 |
| 409 blink::WebGraphicsContext3D* webContext = context(); | 406 WebGraphicsContext3D* webContext = context(); |
| 410 | 407 |
| 411 // Release to skia textures that were previouosly released by the | 408 // Release to skia textures that were previouosly released by the |
| 412 // compositor. We do this before acquiring the next snapshot in | 409 // compositor. We do this before acquiring the next snapshot in |
| 413 // order to cap maximum gpu memory consumption. | 410 // order to cap maximum gpu memory consumption. |
| 414 webContext->makeContextCurrent(); | 411 webContext->makeContextCurrent(); |
| 415 flush(); | 412 flush(); |
| 416 | 413 |
| 417 RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot()); | 414 RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot()); |
| 418 | 415 |
| 419 // Early exit if canvas was not drawn to since last prepareMailbox | 416 // Early exit if canvas was not drawn to since last prepareMailbox |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 // means there is a problem. | 476 // means there is a problem. |
| 480 // For the single-threaded case, this value needs to be at least | 477 // For the single-threaded case, this value needs to be at least |
| 481 // kMaxSwapBuffersPending+1 (in render_widget.h). | 478 // kMaxSwapBuffersPending+1 (in render_widget.h). |
| 482 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. | 479 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. |
| 483 // TODO(piman): fix this. | 480 // TODO(piman): fix this. |
| 484 ASSERT(m_mailboxes.size() <= 4); | 481 ASSERT(m_mailboxes.size() <= 4); |
| 485 ASSERT(mailboxInfo < m_mailboxes.end()); | 482 ASSERT(mailboxInfo < m_mailboxes.end()); |
| 486 return mailboxInfo; | 483 return mailboxInfo; |
| 487 } | 484 } |
| 488 | 485 |
| 489 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox
& mailbox, bool lostResource) | 486 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb
ox, bool lostResource) |
| 490 { | 487 { |
| 491 freeReleasedMailbox(); // Never have more than one mailbox in the released s
tate. | 488 freeReleasedMailbox(); // Never have more than one mailbox in the released s
tate. |
| 492 bool contextLost = !m_isSurfaceValid || m_contextProvider->context3d()->isCo
ntextLost(); | 489 bool contextLost = !m_isSurfaceValid || m_contextProvider->context3d()->isCo
ntextLost(); |
| 493 Vector<MailboxInfo>::iterator mailboxInfo; | 490 Vector<MailboxInfo>::iterator mailboxInfo; |
| 494 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m
ailboxInfo) { | 491 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m
ailboxInfo) { |
| 495 if (nameEquals(mailboxInfo->m_mailbox, mailbox)) { | 492 if (nameEquals(mailboxInfo->m_mailbox, mailbox)) { |
| 496 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; | 493 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; |
| 497 ASSERT(mailboxInfo->m_status == MailboxInUse); | 494 ASSERT(mailboxInfo->m_status == MailboxInUse); |
| 498 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); | 495 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); |
| 499 | 496 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 } | 529 } |
| 533 // Trigger Canvas2DLayerBridge self-destruction if this is the | 530 // Trigger Canvas2DLayerBridge self-destruction if this is the |
| 534 // last live mailbox and the layer bridge is not externally | 531 // last live mailbox and the layer bridge is not externally |
| 535 // referenced. | 532 // referenced. |
| 536 mailboxInfo->m_parentLayerBridge.clear(); | 533 mailboxInfo->m_parentLayerBridge.clear(); |
| 537 return; | 534 return; |
| 538 } | 535 } |
| 539 } | 536 } |
| 540 } | 537 } |
| 541 | 538 |
| 542 blink::WebLayer* Canvas2DLayerBridge::layer() const | 539 WebLayer* Canvas2DLayerBridge::layer() const |
| 543 { | 540 { |
| 544 ASSERT(!m_destructionInProgress); | 541 ASSERT(!m_destructionInProgress); |
| 545 ASSERT(m_layer); | 542 ASSERT(m_layer); |
| 546 return m_layer->layer(); | 543 return m_layer->layer(); |
| 547 } | 544 } |
| 548 | 545 |
| 549 void Canvas2DLayerBridge::finalizeFrame() | 546 void Canvas2DLayerBridge::finalizeFrame() |
| 550 { | 547 { |
| 551 ASSERT(!m_destructionInProgress); | 548 ASSERT(!m_destructionInProgress); |
| 552 Canvas2DLayerManager::get().layerDidDraw(this); | 549 Canvas2DLayerManager::get().layerDidDraw(this); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 569 | 566 |
| 570 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { | 567 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { |
| 571 // This copy constructor should only be used for Vector reallocation | 568 // This copy constructor should only be used for Vector reallocation |
| 572 // Assuming 'other' is to be destroyed, we transfer m_image ownership | 569 // Assuming 'other' is to be destroyed, we transfer m_image ownership |
| 573 // rather than do a refcount dance. | 570 // rather than do a refcount dance. |
| 574 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); | 571 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); |
| 575 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); | 572 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); |
| 576 m_status = other.m_status; | 573 m_status = other.m_status; |
| 577 } | 574 } |
| 578 | 575 |
| 579 } | 576 } // namespace blink |
| OLD | NEW |