Upstream version 10.38.208.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / Canvas2DLayerBridge.cpp
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "platform/graphics/Canvas2DLayerBridge.h"
29
30 #include "GrContext.h"
31 #include "SkDevice.h"
32 #include "SkSurface.h"
33 #include "platform/TraceEvent.h"
34 #include "platform/graphics/Canvas2DLayerManager.h"
35 #include "platform/graphics/GraphicsLayer.h"
36 #include "public/platform/Platform.h"
37 #include "public/platform/WebCompositorSupport.h"
38 #include "public/platform/WebGraphicsContext3D.h"
39 #include "public/platform/WebGraphicsContext3DProvider.h"
40 #include "wtf/RefCountedLeakCounter.h"
41
42 namespace {
43 enum {
44     InvalidMailboxIndex = -1,
45 };
46
47 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstanceCounter, ("Canvas2DLayerBridge"));
48 }
49
50 namespace blink {
51
52 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount = 0)
53 {
54     if (!gr)
55         return nullptr;
56     gr->resetContext();
57     SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
58     return adoptRef(SkSurface::NewRenderTarget(gr, info,  msaaSampleCount));
59 }
60
61 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount)
62 {
63     TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
64     OwnPtr<WebGraphicsContext3DProvider> contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
65     if (!contextProvider)
66         return nullptr;
67     RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size, msaaSampleCount));
68     if (!surface)
69         return nullptr;
70     RefPtr<Canvas2DLayerBridge> layerBridge;
71     OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.get()));
72     layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), canvas.release(), surface.release(), msaaSampleCount, opacityMode));
73     return layerBridge.release();
74 }
75
76 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<WebGraphicsContext3DProvider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, PassRefPtr<SkSurface> surface, int msaaSampleCount, OpacityMode opacityMode)
77     : m_canvas(canvas)
78     , m_surface(surface)
79     , m_contextProvider(contextProvider)
80     , m_imageBuffer(0)
81     , m_msaaSampleCount(msaaSampleCount)
82     , m_bytesAllocated(0)
83     , m_didRecordDrawCommand(false)
84     , m_isSurfaceValid(true)
85     , m_framesPending(0)
86     , m_framesSinceMailboxRelease(0)
87     , m_destructionInProgress(false)
88     , m_rateLimitingEnabled(false)
89     , m_isHidden(false)
90     , m_next(0)
91     , m_prev(0)
92     , m_lastImageId(0)
93     , m_releasedMailboxInfoIndex(InvalidMailboxIndex)
94 {
95     ASSERT(m_canvas);
96     ASSERT(m_surface);
97     ASSERT(m_contextProvider);
98     // Used by browser tests to detect the use of a Canvas2DLayerBridge.
99     TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
100     m_layer = adoptPtr(Platform::current()->compositorSupport()->createExternalTextureLayer(this));
101     m_layer->setOpaque(opacityMode == Opaque);
102     m_layer->setBlendBackgroundColor(opacityMode != Opaque);
103     GraphicsLayer::registerContentsLayer(m_layer->layer());
104     m_layer->setRateLimitContext(m_rateLimitingEnabled);
105     m_canvas->setNotificationClient(this);
106 #ifndef NDEBUG
107     canvas2DLayerBridgeInstanceCounter.increment();
108 #endif
109 }
110
111 Canvas2DLayerBridge::~Canvas2DLayerBridge()
112 {
113     ASSERT(m_destructionInProgress);
114     ASSERT(!Canvas2DLayerManager::get().isInList(this));
115     m_layer.clear();
116     freeReleasedMailbox();
117 #if ENABLE(ASSERT)
118     Vector<MailboxInfo>::iterator mailboxInfo;
119     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
120         ASSERT(mailboxInfo->m_status != MailboxInUse);
121         ASSERT(mailboxInfo->m_status != MailboxReleased || m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid);
122     }
123 #endif
124     m_mailboxes.clear();
125 #ifndef NDEBUG
126     canvas2DLayerBridgeInstanceCounter.decrement();
127 #endif
128 }
129
130 void Canvas2DLayerBridge::beginDestruction()
131 {
132     ASSERT(!m_destructionInProgress);
133     setRateLimitingEnabled(false);
134     m_canvas->silentFlush();
135     m_imageBuffer = 0;
136     freeTransientResources();
137     setIsHidden(true);
138     m_destructionInProgress = true;
139     GraphicsLayer::unregisterContentsLayer(m_layer->layer());
140     m_canvas->setNotificationClient(0);
141     m_surface.clear();
142     m_canvas.clear();
143     m_layer->clearTexture();
144     // Orphaning the layer is required to trigger the recration of a new layer
145     // in the case where destruction is caused by a canvas resize. Test:
146     // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
147     m_layer->layer()->removeFromParent();
148     // To anyone who ever hits this assert: Please update crbug.com/344666
149     // with repro steps.
150     ASSERT(!m_bytesAllocated);
151 }
152
153 void Canvas2DLayerBridge::setIsHidden(bool hidden)
154 {
155     ASSERT(!m_destructionInProgress);
156     bool newHiddenValue = hidden || m_destructionInProgress;
157     if (m_isHidden == newHiddenValue)
158         return;
159
160     m_isHidden = newHiddenValue;
161     if (isHidden()) {
162         freeTransientResources();
163     }
164 }
165
166 void Canvas2DLayerBridge::willAccessPixels()
167 {
168     // A readback operation may alter the texture parameters, which may affect
169     // the compositor's behavior. Therefore, we must trigger copy-on-write
170     // even though we are not technically writing to the texture, only to its
171     // parameters.
172     m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode);
173 }
174
175 void Canvas2DLayerBridge::freeTransientResources()
176 {
177     ASSERT(!m_destructionInProgress);
178     if (!m_isSurfaceValid)
179         return;
180     freeReleasedMailbox();
181     flush();
182     freeMemoryIfPossible(bytesAllocated());
183     ASSERT(!hasTransientResources());
184 }
185
186 bool Canvas2DLayerBridge::hasTransientResources() const
187 {
188     return !m_destructionInProgress && (hasReleasedMailbox() || bytesAllocated());
189 }
190
191 void Canvas2DLayerBridge::limitPendingFrames()
192 {
193     ASSERT(!m_destructionInProgress);
194     if (isHidden()) {
195         freeTransientResources();
196         return;
197     }
198     if (m_didRecordDrawCommand) {
199         m_framesPending++;
200         m_didRecordDrawCommand = false;
201         if (m_framesPending > 1) {
202             // Turn on the rate limiter if this layer tends to accumulate a
203             // non-discardable multi-frame backlog of draw commands.
204             setRateLimitingEnabled(true);
205         }
206         if (m_rateLimitingEnabled) {
207             flush();
208         }
209     }
210     ++m_framesSinceMailboxRelease;
211     if (releasedMailboxHasExpired()) {
212         freeReleasedMailbox();
213     }
214 }
215
216 void Canvas2DLayerBridge::prepareForDraw()
217 {
218     ASSERT(!m_destructionInProgress);
219     ASSERT(m_layer);
220     if (!checkSurfaceValid()) {
221         if (m_canvas) {
222             // drop pending commands because there is no surface to draw to
223             m_canvas->silentFlush();
224         }
225         return;
226     }
227     context()->makeContextCurrent();
228 }
229
230 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated)
231 {
232     ASSERT(!m_destructionInProgress);
233     intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
234     m_bytesAllocated = bytesAllocated;
235     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, delta);
236 }
237
238 size_t Canvas2DLayerBridge::storageAllocatedForRecording()
239 {
240     return m_canvas->storageAllocatedForRecording();
241 }
242
243 void Canvas2DLayerBridge::flushedDrawCommands()
244 {
245     ASSERT(!m_destructionInProgress);
246     storageAllocatedForRecordingChanged(storageAllocatedForRecording());
247     m_framesPending = 0;
248 }
249
250 void Canvas2DLayerBridge::skippedPendingDrawCommands()
251 {
252     ASSERT(!m_destructionInProgress);
253     // Stop triggering the rate limiter if SkDeferredCanvas is detecting
254     // and optimizing overdraw.
255     setRateLimitingEnabled(false);
256     flushedDrawCommands();
257 }
258
259 void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled)
260 {
261     ASSERT(!m_destructionInProgress);
262     if (m_rateLimitingEnabled != enabled) {
263         m_rateLimitingEnabled = enabled;
264         m_layer->setRateLimitContext(m_rateLimitingEnabled);
265     }
266 }
267
268 size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree)
269 {
270     ASSERT(!m_destructionInProgress);
271     size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree);
272     m_bytesAllocated -= bytesFreed;
273     if (bytesFreed)
274         Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, -((intptr_t)bytesFreed));
275     return bytesFreed;
276 }
277
278 void Canvas2DLayerBridge::flush()
279 {
280     ASSERT(!m_destructionInProgress);
281     if (m_canvas->hasPendingCommands()) {
282         TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
283         freeReleasedMailbox(); // To avoid unnecessary triple-buffering
284         m_canvas->flush();
285     }
286 }
287
288 bool Canvas2DLayerBridge::releasedMailboxHasExpired()
289 {
290     // This heuristic indicates that the canvas is not being
291     // actively presented by the compositor (3 frames rendered since
292     // last mailbox release), suggesting that double buffering is not required.
293     return hasReleasedMailbox() && m_framesSinceMailboxRelease > 2;
294 }
295
296 Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::releasedMailboxInfo()
297 {
298     return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0;
299 }
300
301 bool Canvas2DLayerBridge::hasReleasedMailbox() const
302 {
303     return m_releasedMailboxInfoIndex != InvalidMailboxIndex;
304 }
305
306 void Canvas2DLayerBridge::freeReleasedMailbox()
307 {
308     if (!m_isSurfaceValid || m_contextProvider->context3d()->isContextLost())
309         return;
310     MailboxInfo* mailboxInfo = releasedMailboxInfo();
311     if (!mailboxInfo)
312         return;
313
314     ASSERT(mailboxInfo->m_status == MailboxReleased);
315     if (mailboxInfo->m_mailbox.syncPoint) {
316         context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
317         mailboxInfo->m_mailbox.syncPoint = 0;
318     }
319     // Invalidate texture state in case the compositor altered it since the copy-on-write.
320     if (mailboxInfo->m_image) {
321         if (isHidden() || releasedMailboxHasExpired())
322             mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureFlags>(GrTexture::kReturnToCache_FlagBit));
323         mailboxInfo->m_image->getTexture()->textureParamsModified();
324         mailboxInfo->m_image.clear();
325     }
326     mailboxInfo->m_status = MailboxAvailable;
327     m_releasedMailboxInfoIndex = InvalidMailboxIndex;
328     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
329 }
330
331 WebGraphicsContext3D* Canvas2DLayerBridge::context()
332 {
333     // Check on m_layer is necessary because context() may be called during
334     // the destruction of m_layer
335     if (m_layer && !m_destructionInProgress)
336         checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost.
337     return m_contextProvider ? m_contextProvider->context3d() : 0;
338 }
339
340 bool Canvas2DLayerBridge::checkSurfaceValid()
341 {
342     ASSERT(!m_destructionInProgress);
343     if (m_destructionInProgress || !m_isSurfaceValid)
344         return false;
345     if (m_contextProvider->context3d()->isContextLost()) {
346         m_isSurfaceValid = false;
347         m_surface.clear();
348         if (m_imageBuffer)
349             m_imageBuffer->notifySurfaceInvalid();
350         setRateLimitingEnabled(false);
351     }
352     return m_isSurfaceValid;
353 }
354
355 bool Canvas2DLayerBridge::restoreSurface()
356 {
357     ASSERT(!m_destructionInProgress);
358     if (m_destructionInProgress)
359         return false;
360     ASSERT(m_layer && !m_isSurfaceValid);
361
362     WebGraphicsContext3D* sharedContext = 0;
363     // We must clear the mailboxes before calling m_layer->clearTexture() to prevent
364     // re-entry via mailboxReleased from operating on defunct GrContext objects.
365     m_mailboxes.clear();
366     m_releasedMailboxInfoIndex = InvalidMailboxIndex;
367     m_layer->clearTexture();
368     m_contextProvider = adoptPtr(Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
369     if (m_contextProvider)
370         sharedContext = m_contextProvider->context3d();
371
372     if (sharedContext && !sharedContext->isContextLost()) {
373         IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
374         RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount));
375         if (surface.get()) {
376             m_surface = surface.release();
377             m_canvas->setSurface(m_surface.get());
378             m_isSurfaceValid = true;
379             // FIXME: draw sad canvas picture into new buffer crbug.com/243842
380         }
381     }
382
383     return m_isSurfaceValid;
384 }
385
386 bool Canvas2DLayerBridge::prepareMailbox(WebExternalTextureMailbox* outMailbox, WebExternalBitmap* bitmap)
387 {
388     if (m_destructionInProgress) {
389         // It can be hit in the following sequence.
390         // 1. Canvas draws something.
391         // 2. The compositor begins the frame.
392         // 3. Javascript makes a context be lost.
393         // 4. Here.
394         return false;
395     }
396     if (bitmap) {
397         // Using accelerated 2d canvas with software renderer, which
398         // should only happen in tests that use fake graphics contexts
399         // or in Android WebView in software mode. In this case, we do
400         // not care about producing any results for this canvas.
401         m_canvas->silentFlush();
402         m_lastImageId = 0;
403         return false;
404     }
405     if (!checkSurfaceValid())
406         return false;
407
408     WebGraphicsContext3D* webContext = context();
409
410     // Release to skia textures that were previouosly released by the
411     // compositor. We do this before acquiring the next snapshot in
412     // order to cap maximum gpu memory consumption.
413     webContext->makeContextCurrent();
414     flush();
415
416     RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot());
417
418     // Early exit if canvas was not drawn to since last prepareMailbox
419     if (image->uniqueID() == m_lastImageId)
420         return false;
421     m_lastImageId = image->uniqueID();
422
423     MailboxInfo* mailboxInfo = createMailboxInfo();
424     mailboxInfo->m_status = MailboxInUse;
425     mailboxInfo->m_image = image;
426
427     ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
428     ASSERT(mailboxInfo->m_image.get());
429
430     // set m_parentLayerBridge to make sure 'this' stays alive as long as it has
431     // live mailboxes
432     ASSERT(!mailboxInfo->m_parentLayerBridge);
433     mailboxInfo->m_parentLayerBridge = this;
434     *outMailbox = mailboxInfo->m_mailbox;
435
436     GrContext* grContext = m_contextProvider->grContext();
437     if (!grContext)
438         return true; // for testing: skip gl stuff when using a mock graphics context.
439
440     ASSERT(mailboxInfo->m_image->getTexture());
441
442     // Because of texture sharing with the compositor, we must invalidate
443     // the state cached in skia so that the deferred copy on write
444     // in SkSurface_Gpu does not make any false assumptions.
445     mailboxInfo->m_image->getTexture()->textureParamsModified();
446
447     webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
448     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
449     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
450     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
451     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
452     webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.name);
453     if (isHidden()) {
454         // With hidden canvases, we release the SkImage immediately because
455         // there is no need for animations to be double buffered.
456         mailboxInfo->m_image.clear();
457     } else {
458         webContext->flush();
459         mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint();
460     }
461     webContext->bindTexture(GL_TEXTURE_2D, 0);
462     // Because we are changing the texture binding without going through skia,
463     // we must dirty the context.
464     grContext->resetContext(kTextureBinding_GrGLBackendState);
465
466     return true;
467 }
468
469 Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() {
470     ASSERT(!m_destructionInProgress);
471     MailboxInfo* mailboxInfo;
472     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
473         if (mailboxInfo->m_status == MailboxAvailable) {
474             return mailboxInfo;
475         }
476     }
477
478     // No available mailbox: create one.
479     m_mailboxes.grow(m_mailboxes.size() + 1);
480     mailboxInfo = &m_mailboxes.last();
481     context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name);
482     // Worst case, canvas is triple buffered.  More than 3 active mailboxes
483     // means there is a problem.
484     // For the single-threaded case, this value needs to be at least
485     // kMaxSwapBuffersPending+1 (in render_widget.h).
486     // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2.
487     // TODO(piman): fix this.
488     ASSERT(m_mailboxes.size() <= 4);
489     ASSERT(mailboxInfo < m_mailboxes.end());
490     return mailboxInfo;
491 }
492
493 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailbox, bool lostResource)
494 {
495     freeReleasedMailbox(); // Never have more than one mailbox in the released state.
496     bool contextLost = !m_isSurfaceValid || m_contextProvider->context3d()->isContextLost();
497     Vector<MailboxInfo>::iterator mailboxInfo;
498     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
499         if (nameEquals(mailboxInfo->m_mailbox, mailbox)) {
500             mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
501             ASSERT(mailboxInfo->m_status == MailboxInUse);
502             ASSERT(mailboxInfo->m_parentLayerBridge.get() == this);
503
504             if (contextLost) {
505                 // No need to clean up the mailbox resource, but make sure the
506                 // mailbox can also be reusable once the context is restored.
507                 mailboxInfo->m_status = MailboxAvailable;
508                 m_releasedMailboxInfoIndex = InvalidMailboxIndex;
509                 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
510             } else if (lostResource) {
511                 // In case of the resource is lost, we need to delete the backing
512                 // texture and remove the mailbox from list to avoid reusing it
513                 // in future.
514                 if (mailboxInfo->m_image) {
515                     GrTexture* texture = mailboxInfo->m_image->getTexture();
516                     if (texture) {
517                         texture->resetFlag(static_cast<GrTextureFlags>(GrTexture::kReturnToCache_FlagBit));
518                         texture->textureParamsModified();
519                     }
520                     mailboxInfo->m_image.clear();
521                 }
522                 if (m_destructionInProgress) {
523                     mailboxInfo->m_status = MailboxAvailable; // To satisfy assert in destructor
524
525                     // The following line may trigger self destruction. We do not care about
526                     // not cleaning up m_mailboxes during destruction sequence because
527                     // mailboxes will not be recycled after this point. Calling remove()
528                     // could trigger a memory use after free, so we just clear the self
529                     // reference to be safe, and we let the Canvas2DLayerBridge destructor
530                     // take care of freeing m_mailboxes.
531                     mailboxInfo->m_parentLayerBridge.clear();
532                 } else {
533                     size_t i = mailboxInfo - m_mailboxes.begin();
534                     m_mailboxes.remove(i); // indirectly clears mailboxInfo->m_parentLayerBridge
535                     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
536                 }
537                 // mailboxInfo is not valid from this point, so we return immediately.
538                 return;
539             } else {
540                 mailboxInfo->m_status = MailboxReleased;
541                 m_releasedMailboxInfoIndex = mailboxInfo - m_mailboxes.begin();
542                 m_framesSinceMailboxRelease = 0;
543                 if (isHidden()) {
544                     freeReleasedMailbox();
545                 } else {
546                     ASSERT(!m_destructionInProgress);
547                     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
548                 }
549             }
550             // Trigger Canvas2DLayerBridge self-destruction if this is the
551             // last live mailbox and the layer bridge is not externally
552             // referenced.
553             mailboxInfo->m_parentLayerBridge.clear();
554             return;
555         }
556     }
557 }
558
559 WebLayer* Canvas2DLayerBridge::layer() const
560 {
561     ASSERT(!m_destructionInProgress);
562     ASSERT(m_layer);
563     return m_layer->layer();
564 }
565
566 void Canvas2DLayerBridge::finalizeFrame(const FloatRect &dirtyRect)
567 {
568     ASSERT(!m_destructionInProgress);
569     Canvas2DLayerManager::get().layerDidDraw(this);
570     m_layer->layer()->invalidateRect(dirtyRect);
571     m_didRecordDrawCommand = true;
572 }
573
574 Platform3DObject Canvas2DLayerBridge::getBackingTexture()
575 {
576     ASSERT(!m_destructionInProgress);
577     if (!checkSurfaceValid())
578         return 0;
579     m_canvas->flush();
580     context()->flush();
581     GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget();
582     if (renderTarget) {
583         return renderTarget->asTexture()->getTextureHandle();
584     }
585     return 0;
586 }
587
588 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
589     // This copy constructor should only be used for Vector reallocation
590     // Assuming 'other' is to be destroyed, we transfer m_image and
591     // m_parentLayerBridge ownership rather than do a refcount dance.
592     memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
593     m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
594     m_parentLayerBridge = const_cast<MailboxInfo*>(&other)->m_parentLayerBridge.release();
595     m_status = other.m_status;
596 }
597
598 } // namespace blink