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