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 28 matching lines...) Expand all Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |