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 23 matching lines...) Expand all Loading... | |
| 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 "platform/graphics/gpu/SharedGraphicsContext3D.h" | 36 #include "platform/graphics/gpu/SharedGraphicsContext3D.h" |
| 37 #include "public/platform/Platform.h" | 37 #include "public/platform/Platform.h" |
| 38 #include "public/platform/WebCompositorSupport.h" | 38 #include "public/platform/WebCompositorSupport.h" |
| 39 #include "public/platform/WebGraphicsContext3D.h" | 39 #include "public/platform/WebGraphicsContext3D.h" |
| 40 | 40 |
| 41 using blink::WebExternalTextureLayer; | 41 using blink::WebExternalTextureLayer; |
| 42 using blink::WebGraphicsContext3D; | 42 using blink::WebGraphicsContext3D; |
| 43 | 43 |
| 44 namespace { | |
| 45 const size_t MaxSize = ~static_cast<size_t>(0); | |
| 46 } | |
| 47 | |
| 44 namespace WebCore { | 48 namespace WebCore { |
| 45 | 49 |
| 46 static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount) | 50 static PassRefPtr<SkSurface> createSkSurface(GraphicsContext3D* context3D, const IntSize& size, int msaaSampleCount = 0) |
| 47 { | 51 { |
| 48 ASSERT(!context3D->webContext()->isContextLost()); | 52 ASSERT(!context3D->webContext()->isContextLost()); |
| 49 GrContext* gr = context3D->grContext(); | 53 GrContext* gr = context3D->grContext(); |
| 50 if (!gr) | 54 if (!gr) |
| 51 return 0; | 55 return 0; |
| 52 gr->resetContext(); | 56 gr->resetContext(); |
| 53 SkImageInfo info; | 57 SkImageInfo info; |
| 54 info.fWidth = size.width(); | 58 info.fWidth = size.width(); |
| 55 info.fHeight = size.height(); | 59 info.fHeight = size.height(); |
| 56 info.fColorType = kPMColor_SkColorType; | 60 info.fColorType = kPMColor_SkColorType; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 72 } | 76 } |
| 73 | 77 |
| 74 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMod e) | 78 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMod e) |
| 75 : m_canvas(canvas) | 79 : m_canvas(canvas) |
| 76 , m_context(context) | 80 , m_context(context) |
| 77 , m_msaaSampleCount(msaaSampleCount) | 81 , m_msaaSampleCount(msaaSampleCount) |
| 78 , m_bytesAllocated(0) | 82 , m_bytesAllocated(0) |
| 79 , m_didRecordDrawCommand(false) | 83 , m_didRecordDrawCommand(false) |
| 80 , m_surfaceIsValid(true) | 84 , m_surfaceIsValid(true) |
| 81 , m_framesPending(0) | 85 , m_framesPending(0) |
| 86 , m_framesSinceMailboxRelease(0) | |
| 82 , m_destructionInProgress(false) | 87 , m_destructionInProgress(false) |
| 83 , m_rateLimitingEnabled(false) | 88 , m_rateLimitingEnabled(false) |
| 89 , m_isHidden(false) | |
| 84 , m_next(0) | 90 , m_next(0) |
| 85 , m_prev(0) | 91 , m_prev(0) |
| 86 , m_lastImageId(0) | 92 , m_lastImageId(0) |
| 93 , m_releasedMailboxInfo(0) | |
| 87 { | 94 { |
| 88 ASSERT(m_canvas); | 95 ASSERT(m_canvas); |
| 89 // Used by browser tests to detect the use of a Canvas2DLayerBridge. | 96 // Used by browser tests to detect the use of a Canvas2DLayerBridge. |
| 90 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); | 97 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); |
| 91 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createEx ternalTextureLayer(this)); | 98 m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createEx ternalTextureLayer(this)); |
| 92 m_layer->setOpaque(opacityMode == Opaque); | 99 m_layer->setOpaque(opacityMode == Opaque); |
| 93 m_layer->setBlendBackgroundColor(opacityMode != Opaque); | 100 m_layer->setBlendBackgroundColor(opacityMode != Opaque); |
| 94 GraphicsLayer::registerContentsLayer(m_layer->layer()); | 101 GraphicsLayer::registerContentsLayer(m_layer->layer()); |
| 95 m_layer->setRateLimitContext(m_rateLimitingEnabled); | 102 m_layer->setRateLimitContext(m_rateLimitingEnabled); |
| 96 m_canvas->setNotificationClient(this); | 103 m_canvas->setNotificationClient(this); |
| 97 } | 104 } |
| 98 | 105 |
| 99 Canvas2DLayerBridge::~Canvas2DLayerBridge() | 106 Canvas2DLayerBridge::~Canvas2DLayerBridge() |
| 100 { | 107 { |
| 101 ASSERT(m_destructionInProgress); | 108 ASSERT(m_destructionInProgress); |
| 102 m_layer.clear(); | 109 m_layer.clear(); |
| 110 freeReleasedMailbox(); | |
| 111 #if !ASSERT_DISABLED | |
| 103 Vector<MailboxInfo>::iterator mailboxInfo; | 112 Vector<MailboxInfo>::iterator mailboxInfo; |
| 104 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m ailboxInfo) { | 113 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m ailboxInfo) { |
| 105 ASSERT(mailboxInfo->m_status != MailboxInUse); | 114 ASSERT(mailboxInfo->m_status != MailboxInUse); |
| 106 if (mailboxInfo->m_status == MailboxReleased) { | 115 ASSERT(mailboxInfo->m_status != MailboxReleased); |
| 107 if (mailboxInfo->m_mailbox.syncPoint) { | |
| 108 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); | |
| 109 mailboxInfo->m_mailbox.syncPoint = 0; | |
| 110 } | |
| 111 // Invalidate texture state in case the compositor altered it since the copy-on-write. | |
| 112 mailboxInfo->m_image->getTexture()->invalidateCachedState(); | |
| 113 } | |
| 114 } | 116 } |
| 117 #endif | |
| 115 m_mailboxes.clear(); | 118 m_mailboxes.clear(); |
| 116 } | 119 } |
| 117 | 120 |
| 118 void Canvas2DLayerBridge::beginDestruction() | 121 void Canvas2DLayerBridge::beginDestruction() |
| 119 { | 122 { |
| 120 ASSERT(!m_destructionInProgress); | 123 ASSERT(!m_destructionInProgress); |
| 121 m_destructionInProgress = true; | 124 m_destructionInProgress = true; |
| 125 freeTransientResources(); | |
| 126 setIsHidden(true); | |
| 122 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); | 127 GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |
| 123 m_canvas->setNotificationClient(0); | 128 m_canvas->setNotificationClient(0); |
| 124 m_layer->clearTexture(); | 129 m_layer->clearTexture(); |
| 125 Canvas2DLayerManager::get().layerToBeDestroyed(this); | |
| 126 // Orphaning the layer is required to trigger the recration of a new layer | 130 // Orphaning the layer is required to trigger the recration of a new layer |
| 127 // in the case where destruction is caused by a canvas resize. Test: | 131 // in the case where destruction is caused by a canvas resize. Test: |
| 128 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html | 132 // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html |
| 129 m_layer->layer()->removeFromParent(); | 133 m_layer->layer()->removeFromParent(); |
| 130 } | 134 } |
| 131 | 135 |
| 136 void Canvas2DLayerBridge::setIsHidden(bool hidden) | |
| 137 { | |
| 138 bool newHiddenValue = hidden || m_destructionInProgress; | |
| 139 if (m_isHidden == newHiddenValue) | |
| 140 return; | |
| 141 | |
| 142 m_isHidden = newHiddenValue; | |
| 143 if (isHidden()) { | |
| 144 freeTransientResources(); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 void Canvas2DLayerBridge::freeTransientResources() | |
| 149 { | |
| 150 freeReleasedMailbox(); | |
| 151 flush(); | |
| 152 freeMemoryIfPossible(MaxSize); | |
|
Stephen White
2014/01/24 18:52:35
Nit: Maybe there should just be a freeAllMemoryIfP
| |
| 153 ASSERT(!hasTransientResources()); | |
| 154 } | |
| 155 | |
| 156 bool Canvas2DLayerBridge::hasTransientResources() const | |
| 157 { | |
| 158 return hasReleasedMailbox() || bytesAllocated(); | |
| 159 } | |
| 160 | |
| 132 void Canvas2DLayerBridge::limitPendingFrames() | 161 void Canvas2DLayerBridge::limitPendingFrames() |
| 133 { | 162 { |
| 134 ASSERT(!m_destructionInProgress); | 163 ASSERT(!m_destructionInProgress); |
| 164 if (isHidden()) { | |
| 165 freeTransientResources(); | |
| 166 return; | |
| 167 } | |
| 135 if (m_didRecordDrawCommand) { | 168 if (m_didRecordDrawCommand) { |
| 136 m_framesPending++; | 169 m_framesPending++; |
| 137 m_didRecordDrawCommand = false; | 170 m_didRecordDrawCommand = false; |
| 138 if (m_framesPending > 1) { | 171 if (m_framesPending > 1) { |
| 139 // Turn on the rate limiter if this layer tends to accumulate a | 172 // Turn on the rate limiter if this layer tends to accumulate a |
| 140 // non-discardable multi-frame backlog of draw commands. | 173 // non-discardable multi-frame backlog of draw commands. |
| 141 setRateLimitingEnabled(true); | 174 setRateLimitingEnabled(true); |
| 142 } | 175 } |
| 143 if (m_rateLimitingEnabled) { | 176 if (m_rateLimitingEnabled) { |
| 144 flush(); | 177 flush(); |
| 145 } | 178 } |
| 146 } | 179 } |
| 180 ++m_framesSinceMailboxRelease; | |
| 181 if (releasedMailboxHasExpired()) { | |
| 182 freeReleasedMailbox(); | |
| 183 } | |
| 147 } | 184 } |
| 148 | 185 |
| 149 void Canvas2DLayerBridge::prepareForDraw() | 186 void Canvas2DLayerBridge::prepareForDraw() |
| 150 { | 187 { |
| 151 ASSERT(!m_destructionInProgress); | |
| 152 ASSERT(m_layer); | 188 ASSERT(m_layer); |
| 153 if (!isValid()) { | 189 if (!isValid()) { |
| 154 if (m_canvas) { | 190 if (m_canvas) { |
| 155 // drop pending commands because there is no surface to draw to | 191 // drop pending commands because there is no surface to draw to |
| 156 m_canvas->silentFlush(); | 192 m_canvas->silentFlush(); |
| 157 } | 193 } |
| 158 return; | 194 return; |
| 159 } | 195 } |
| 160 context()->makeContextCurrent(); | 196 context()->makeContextCurrent(); |
| 161 } | 197 } |
| 162 | 198 |
| 163 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted) | 199 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca ted) |
| 164 { | 200 { |
| 165 ASSERT(!m_destructionInProgress); | |
| 166 intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated; | 201 intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated; |
| 167 m_bytesAllocated = bytesAllocated; | 202 m_bytesAllocated = bytesAllocated; |
| 168 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta); | 203 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, de lta); |
| 169 } | 204 } |
| 170 | 205 |
| 171 size_t Canvas2DLayerBridge::storageAllocatedForRecording() | 206 size_t Canvas2DLayerBridge::storageAllocatedForRecording() |
| 172 { | 207 { |
| 173 ASSERT(!m_destructionInProgress); | |
| 174 return m_canvas->storageAllocatedForRecording(); | 208 return m_canvas->storageAllocatedForRecording(); |
| 175 } | 209 } |
| 176 | 210 |
| 177 void Canvas2DLayerBridge::flushedDrawCommands() | 211 void Canvas2DLayerBridge::flushedDrawCommands() |
| 178 { | 212 { |
| 179 ASSERT(!m_destructionInProgress); | |
| 180 storageAllocatedForRecordingChanged(storageAllocatedForRecording()); | 213 storageAllocatedForRecordingChanged(storageAllocatedForRecording()); |
| 181 m_framesPending = 0; | 214 m_framesPending = 0; |
| 182 } | 215 } |
| 183 | 216 |
| 184 void Canvas2DLayerBridge::skippedPendingDrawCommands() | 217 void Canvas2DLayerBridge::skippedPendingDrawCommands() |
| 185 { | 218 { |
| 186 ASSERT(!m_destructionInProgress); | |
| 187 // Stop triggering the rate limiter if SkDeferredCanvas is detecting | 219 // Stop triggering the rate limiter if SkDeferredCanvas is detecting |
| 188 // and optimizing overdraw. | 220 // and optimizing overdraw. |
| 189 setRateLimitingEnabled(false); | 221 setRateLimitingEnabled(false); |
| 190 flushedDrawCommands(); | 222 flushedDrawCommands(); |
| 191 } | 223 } |
| 192 | 224 |
| 193 void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled) | 225 void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled) |
| 194 { | 226 { |
| 195 ASSERT(!m_destructionInProgress || !enabled); | 227 ASSERT(!m_destructionInProgress || !enabled); |
| 196 if (m_rateLimitingEnabled != enabled) { | 228 if (m_rateLimitingEnabled != enabled) { |
| 197 m_rateLimitingEnabled = enabled; | 229 m_rateLimitingEnabled = enabled; |
| 198 m_layer->setRateLimitContext(m_rateLimitingEnabled); | 230 m_layer->setRateLimitContext(m_rateLimitingEnabled); |
| 199 } | 231 } |
| 200 } | 232 } |
| 201 | 233 |
| 202 size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) | 234 size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) |
| 203 { | 235 { |
| 204 ASSERT(!m_destructionInProgress); | |
| 205 size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree); | 236 size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree); |
| 237 m_bytesAllocated -= bytesFreed; | |
| 206 if (bytesFreed) | 238 if (bytesFreed) |
| 207 Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr _t)bytesFreed)); | 239 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this , -((intptr_t)bytesFreed)); |
| 208 m_bytesAllocated -= bytesFreed; | |
| 209 return bytesFreed; | 240 return bytesFreed; |
| 210 } | 241 } |
| 211 | 242 |
| 212 void Canvas2DLayerBridge::flush() | 243 void Canvas2DLayerBridge::flush() |
| 213 { | 244 { |
| 214 ASSERT(!m_destructionInProgress); | |
| 215 if (m_canvas->hasPendingCommands()) { | 245 if (m_canvas->hasPendingCommands()) { |
| 216 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); | 246 TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); |
| 247 freeReleasedMailbox(); // To avoid unnecessary triple-buffering | |
| 217 m_canvas->flush(); | 248 m_canvas->flush(); |
| 218 } | 249 } |
| 219 } | 250 } |
| 220 | 251 |
| 252 bool Canvas2DLayerBridge::releasedMailboxHasExpired() | |
| 253 { | |
| 254 return m_releasedMailboxInfo && m_framesSinceMailboxRelease > 2; | |
|
Stephen White
2014/01/24 18:52:35
A comment to explain this heuristic might be usefu
| |
| 255 } | |
| 256 | |
| 257 void Canvas2DLayerBridge::freeReleasedMailbox() | |
| 258 { | |
| 259 if (m_releasedMailboxInfo) { | |
| 260 ASSERT(m_releasedMailboxInfo->m_status == MailboxReleased); | |
| 261 if (m_releasedMailboxInfo->m_mailbox.syncPoint) { | |
| 262 context()->waitSyncPoint(m_releasedMailboxInfo->m_mailbox.syncPoint) ; | |
| 263 m_releasedMailboxInfo->m_mailbox.syncPoint = 0; | |
| 264 } | |
| 265 // Invalidate texture state in case the compositor altered it since the copy-on-write. | |
| 266 if (m_releasedMailboxInfo->m_image) { | |
| 267 if (isHidden() || releasedMailboxHasExpired()) | |
| 268 m_releasedMailboxInfo->m_image->getTexture()->resetFlag(static_c ast<GrTextureFlags>(GrTexture::kReturnToCache_FlagBit)); | |
| 269 m_releasedMailboxInfo->m_image->getTexture()->invalidateCachedState( ); | |
| 270 m_releasedMailboxInfo->m_image.clear(); | |
| 271 } | |
| 272 m_releasedMailboxInfo->m_status = MailboxAvailable; | |
| 273 m_releasedMailboxInfo = 0; | |
| 274 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this ); | |
| 275 } | |
| 276 } | |
| 277 | |
| 221 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() | 278 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context() |
| 222 { | 279 { |
| 223 // Check on m_layer is necessary because context() may be called during | 280 // Check on m_layer is necessary because context() may be called during |
| 224 // the destruction of m_layer | 281 // the destruction of m_layer |
| 225 if (m_layer) { | 282 if (m_layer) { |
| 226 isValid(); // To ensure rate limiter is disabled if context is lost. | 283 isValid(); // To ensure rate limiter is disabled if context is lost. |
| 227 } | 284 } |
| 228 return m_context->webContext(); | 285 return m_context->webContext(); |
| 229 } | 286 } |
| 230 | 287 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 273 if (!isValid()) | 330 if (!isValid()) |
| 274 return false; | 331 return false; |
| 275 | 332 |
| 276 blink::WebGraphicsContext3D* webContext = context(); | 333 blink::WebGraphicsContext3D* webContext = context(); |
| 277 | 334 |
| 278 // Release to skia textures that were previouosly released by the | 335 // Release to skia textures that were previouosly released by the |
| 279 // compositor. We do this before acquiring the next snapshot in | 336 // compositor. We do this before acquiring the next snapshot in |
| 280 // order to cap maximum gpu memory consumption. | 337 // order to cap maximum gpu memory consumption. |
| 281 webContext->makeContextCurrent(); | 338 webContext->makeContextCurrent(); |
| 282 flush(); | 339 flush(); |
| 283 Vector<MailboxInfo>::iterator mailboxInfo; | 340 |
| 284 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m ailboxInfo) { | 341 RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot()); |
| 285 if (mailboxInfo->m_status == MailboxReleased) { | 342 |
| 286 if (mailboxInfo->m_mailbox.syncPoint) { | |
| 287 webContext->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); | |
| 288 mailboxInfo->m_mailbox.syncPoint = 0; | |
| 289 } | |
| 290 // Invalidate texture state in case the compositor altered it since the copy-on-write. | |
| 291 mailboxInfo->m_image->getTexture()->invalidateCachedState(); | |
| 292 mailboxInfo->m_image.reset(0); | |
| 293 mailboxInfo->m_status = MailboxAvailable; | |
| 294 } | |
| 295 } | |
| 296 SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot()); | |
| 297 // Early exit if canvas was not drawn to since last prepareMailbox | 343 // Early exit if canvas was not drawn to since last prepareMailbox |
| 298 if (image->uniqueID() == m_lastImageId) | 344 if (image->uniqueID() == m_lastImageId) |
| 299 return false; | 345 return false; |
| 300 m_lastImageId = image->uniqueID(); | 346 m_lastImageId = image->uniqueID(); |
| 301 | 347 |
| 302 mailboxInfo = createMailboxInfo(); | 348 MailboxInfo* mailboxInfo = createMailboxInfo(); |
| 303 mailboxInfo->m_status = MailboxInUse; | 349 mailboxInfo->m_status = MailboxInUse; |
| 304 mailboxInfo->m_image.swap(&image); | 350 mailboxInfo->m_image = image; |
| 351 | |
| 305 // Because of texture sharing with the compositor, we must invalidate | 352 // Because of texture sharing with the compositor, we must invalidate |
| 306 // the state cached in skia so that the deferred copy on write | 353 // the state cached in skia so that the deferred copy on write |
| 307 // in SkSurface_Gpu does not make any false assumptions. | 354 // in SkSurface_Gpu does not make any false assumptions. |
| 308 mailboxInfo->m_image->getTexture()->invalidateCachedState(); | 355 mailboxInfo->m_image->getTexture()->invalidateCachedState(); |
| 309 | 356 |
| 310 ASSERT(mailboxInfo->m_mailbox.syncPoint == 0); | 357 ASSERT(mailboxInfo->m_mailbox.syncPoint == 0); |
| 311 ASSERT(mailboxInfo->m_image.get()); | 358 ASSERT(mailboxInfo->m_image.get()); |
| 312 ASSERT(mailboxInfo->m_image->getTexture()); | 359 ASSERT(mailboxInfo->m_image->getTexture()); |
| 313 | 360 |
| 314 webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->g etTextureHandle()); | 361 webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->g etTextureHandle()); |
| 315 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 362 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| 316 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 363 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| 317 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); | 364 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); |
| 318 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); | 365 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); |
| 319 webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.nam e); | 366 webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.nam e); |
| 320 webContext->flush(); | 367 if (!isHidden()) { |
| 321 mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint(); | 368 // With hidden canvases, we release the SkImage immediately because |
|
Stephen White
2014/01/24 18:52:35
I don't understand this comment. This seems to be
Justin Novosad
2014/01/27 18:43:26
Holy s***. This is a major bug. Thanks for spottin
| |
| 369 // there is no need for animations to be double buffered. | |
| 370 mailboxInfo->m_image.clear(); | |
| 371 } else { | |
| 372 webContext->flush(); | |
| 373 mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint(); | |
| 374 } | |
| 322 webContext->bindTexture(GL_TEXTURE_2D, 0); | 375 webContext->bindTexture(GL_TEXTURE_2D, 0); |
| 323 // Because we are changing the texture binding without going through skia, | 376 // Because we are changing the texture binding without going through skia, |
| 324 // we must dirty the context. | 377 // we must dirty the context. |
| 325 m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState); | 378 m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState); |
| 326 | 379 |
| 327 // set m_parentLayerBridge to make sure 'this' stays alive as long as it has | 380 // set m_parentLayerBridge to make sure 'this' stays alive as long as it has |
| 328 // live mailboxes | 381 // live mailboxes |
| 329 ASSERT(!mailboxInfo->m_parentLayerBridge); | 382 ASSERT(!mailboxInfo->m_parentLayerBridge); |
| 330 mailboxInfo->m_parentLayerBridge = this; | 383 mailboxInfo->m_parentLayerBridge = this; |
| 331 *outMailbox = mailboxInfo->m_mailbox; | 384 *outMailbox = mailboxInfo->m_mailbox; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 351 // kMaxSwapBuffersPending+1 (in render_widget.h). | 404 // kMaxSwapBuffersPending+1 (in render_widget.h). |
| 352 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. | 405 // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. |
| 353 // TODO(piman): fix this. | 406 // TODO(piman): fix this. |
| 354 ASSERT(m_mailboxes.size() <= 4); | 407 ASSERT(m_mailboxes.size() <= 4); |
| 355 ASSERT(mailboxInfo < m_mailboxes.end()); | 408 ASSERT(mailboxInfo < m_mailboxes.end()); |
| 356 return mailboxInfo; | 409 return mailboxInfo; |
| 357 } | 410 } |
| 358 | 411 |
| 359 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox & mailbox) | 412 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox & mailbox) |
| 360 { | 413 { |
| 414 freeReleasedMailbox(); // Never have more than one mailbox in the released s tate. | |
| 361 Vector<MailboxInfo>::iterator mailboxInfo; | 415 Vector<MailboxInfo>::iterator mailboxInfo; |
| 362 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m ailboxInfo) { | 416 for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++m ailboxInfo) { |
| 363 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na me))) { | 417 if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na me))) { |
| 364 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; | 418 mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; |
| 365 ASSERT(mailboxInfo->m_status == MailboxInUse); | 419 ASSERT(mailboxInfo->m_status == MailboxInUse); |
| 366 mailboxInfo->m_status = MailboxReleased; | 420 mailboxInfo->m_status = MailboxReleased; |
| 367 // Trigger Canvas2DLayerBridge self-destruction if this is the | 421 // Trigger Canvas2DLayerBridge self-destruction if this is the |
| 368 // last live mailbox and the layer bridge is not externally | 422 // last live mailbox and the layer bridge is not externally |
| 369 // referenced. | 423 // referenced. |
| 424 m_releasedMailboxInfo = mailboxInfo; | |
| 425 m_framesSinceMailboxRelease = 0; | |
| 426 if (isHidden()) { | |
| 427 freeReleasedMailbox(); | |
| 428 } else { | |
| 429 ASSERT(!m_destructionInProgress); | |
| 430 Canvas2DLayerManager::get().layerTransientResourceAllocationChan ged(this); | |
| 431 } | |
| 370 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); | 432 ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); |
| 371 mailboxInfo->m_parentLayerBridge.clear(); | 433 mailboxInfo->m_parentLayerBridge.clear(); |
| 372 return; | 434 return; |
| 373 } | 435 } |
| 374 } | 436 } |
| 375 } | 437 } |
| 376 | 438 |
| 377 blink::WebLayer* Canvas2DLayerBridge::layer() const | 439 blink::WebLayer* Canvas2DLayerBridge::layer() const |
| 378 { | 440 { |
| 379 ASSERT(m_layer); | 441 ASSERT(m_layer); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 397 context()->flush(); | 459 context()->flush(); |
| 398 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( ); | 460 GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget( ); |
| 399 if (renderTarget) { | 461 if (renderTarget) { |
| 400 return renderTarget->asTexture()->getTextureHandle(); | 462 return renderTarget->asTexture()->getTextureHandle(); |
| 401 } | 463 } |
| 402 return 0; | 464 return 0; |
| 403 } | 465 } |
| 404 | 466 |
| 405 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { | 467 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { |
| 406 // This copy constructor should only be used for Vector reallocation | 468 // This copy constructor should only be used for Vector reallocation |
| 407 // Assuming 'other' is to be destroyed, we swap m_image ownership | 469 // Assuming 'other' is to be destroyed, we transfer m_image ownership |
| 408 // rather than do a refcount dance. | 470 // rather than do a refcount dance. |
| 409 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); | 471 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); |
| 410 m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image)); | 472 m_image = const_cast<MailboxInfo*>(&other)->m_image.release(); |
| 411 m_status = other.m_status; | 473 m_status = other.m_status; |
| 412 } | 474 } |
| 413 | 475 |
| 414 } | 476 } |
| OLD | NEW |