Home | History | Annotate | Download | only in graphics
      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 using blink::WebExternalTextureLayer;
     43 using blink::WebGraphicsContext3D;
     44 
     45 namespace {
     46 enum {
     47     InvalidMailboxIndex = -1,
     48 };
     49 
     50 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, canvas2DLayerBridgeInstanceCounter, ("Canvas2DLayerBridge"));
     51 }
     52 
     53 namespace WebCore {
     54 
     55 static PassRefPtr<SkSurface> createSkSurface(GrContext* gr, const IntSize& size, int msaaSampleCount = 0)
     56 {
     57     if (!gr)
     58         return nullptr;
     59     gr->resetContext();
     60     SkImageInfo info;
     61     info.fWidth = size.width();
     62     info.fHeight = size.height();
     63     info.fColorType = kPMColor_SkColorType;
     64     info.fAlphaType = kPremul_SkAlphaType;
     65     return adoptRef(SkSurface::NewRenderTarget(gr, info,  msaaSampleCount));
     66 }
     67 
     68 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(const IntSize& size, OpacityMode opacityMode, int msaaSampleCount)
     69 {
     70     TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
     71     OwnPtr<blink::WebGraphicsContext3DProvider> contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
     72     if (!contextProvider)
     73         return nullptr;
     74     RefPtr<SkSurface> surface(createSkSurface(contextProvider->grContext(), size, msaaSampleCount));
     75     if (!surface)
     76         return nullptr;
     77     RefPtr<Canvas2DLayerBridge> layerBridge;
     78     OwnPtr<SkDeferredCanvas> canvas = adoptPtr(SkDeferredCanvas::Create(surface.get()));
     79     layerBridge = adoptRef(new Canvas2DLayerBridge(contextProvider.release(), canvas.release(), msaaSampleCount, opacityMode));
     80     return layerBridge.release();
     81 }
     82 
     83 Canvas2DLayerBridge::Canvas2DLayerBridge(PassOwnPtr<blink::WebGraphicsContext3DProvider> contextProvider, PassOwnPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMode)
     84     : m_canvas(canvas)
     85     , m_contextProvider(contextProvider)
     86     , m_imageBuffer(0)
     87     , m_msaaSampleCount(msaaSampleCount)
     88     , m_bytesAllocated(0)
     89     , m_didRecordDrawCommand(false)
     90     , m_isSurfaceValid(true)
     91     , m_framesPending(0)
     92     , m_framesSinceMailboxRelease(0)
     93     , m_destructionInProgress(false)
     94     , m_rateLimitingEnabled(false)
     95     , m_isHidden(false)
     96     , m_next(0)
     97     , m_prev(0)
     98     , m_lastImageId(0)
     99     , m_releasedMailboxInfoIndex(InvalidMailboxIndex)
    100 {
    101     ASSERT(m_canvas);
    102     ASSERT(m_contextProvider);
    103     // Used by browser tests to detect the use of a Canvas2DLayerBridge.
    104     TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation");
    105     m_layer = adoptPtr(blink::Platform::current()->compositorSupport()->createExternalTextureLayer(this));
    106     m_layer->setOpaque(opacityMode == Opaque);
    107     m_layer->setBlendBackgroundColor(opacityMode != Opaque);
    108     GraphicsLayer::registerContentsLayer(m_layer->layer());
    109     m_layer->setRateLimitContext(m_rateLimitingEnabled);
    110     m_canvas->setNotificationClient(this);
    111 #ifndef NDEBUG
    112     canvas2DLayerBridgeInstanceCounter.increment();
    113 #endif
    114 }
    115 
    116 Canvas2DLayerBridge::~Canvas2DLayerBridge()
    117 {
    118     ASSERT(m_destructionInProgress);
    119     ASSERT(!Canvas2DLayerManager::get().isInList(this));
    120     m_layer.clear();
    121     freeReleasedMailbox();
    122 #if ASSERT_ENABLED
    123     Vector<MailboxInfo>::iterator mailboxInfo;
    124     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
    125         ASSERT(mailboxInfo->m_status != MailboxInUse);
    126         ASSERT(mailboxInfo->m_status != MailboxReleased || m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid);
    127     }
    128 #endif
    129     m_mailboxes.clear();
    130 #ifndef NDEBUG
    131     canvas2DLayerBridgeInstanceCounter.decrement();
    132 #endif
    133 }
    134 
    135 void Canvas2DLayerBridge::beginDestruction()
    136 {
    137     ASSERT(!m_destructionInProgress);
    138     setRateLimitingEnabled(false);
    139     m_canvas->silentFlush();
    140     m_imageBuffer = 0;
    141     freeTransientResources();
    142     setIsHidden(true);
    143     m_destructionInProgress = true;
    144     GraphicsLayer::unregisterContentsLayer(m_layer->layer());
    145     m_canvas->setNotificationClient(0);
    146     m_canvas.clear();
    147     m_layer->clearTexture();
    148     // Orphaning the layer is required to trigger the recration of a new layer
    149     // in the case where destruction is caused by a canvas resize. Test:
    150     // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html
    151     m_layer->layer()->removeFromParent();
    152     // To anyone who ever hits this assert: Please update crbug.com/344666
    153     // with repro steps.
    154     ASSERT(!m_bytesAllocated);
    155 }
    156 
    157 void Canvas2DLayerBridge::setIsHidden(bool hidden)
    158 {
    159     ASSERT(!m_destructionInProgress);
    160     bool newHiddenValue = hidden || m_destructionInProgress;
    161     if (m_isHidden == newHiddenValue)
    162         return;
    163 
    164     m_isHidden = newHiddenValue;
    165     if (isHidden()) {
    166         freeTransientResources();
    167     }
    168 }
    169 
    170 void Canvas2DLayerBridge::freeTransientResources()
    171 {
    172     ASSERT(!m_destructionInProgress);
    173     freeReleasedMailbox();
    174     flush();
    175     freeMemoryIfPossible(bytesAllocated());
    176     ASSERT(!hasTransientResources());
    177 }
    178 
    179 bool Canvas2DLayerBridge::hasTransientResources() const
    180 {
    181     return !m_destructionInProgress && (hasReleasedMailbox() || bytesAllocated());
    182 }
    183 
    184 void Canvas2DLayerBridge::limitPendingFrames()
    185 {
    186     ASSERT(!m_destructionInProgress);
    187     if (isHidden()) {
    188         freeTransientResources();
    189         return;
    190     }
    191     if (m_didRecordDrawCommand) {
    192         m_framesPending++;
    193         m_didRecordDrawCommand = false;
    194         if (m_framesPending > 1) {
    195             // Turn on the rate limiter if this layer tends to accumulate a
    196             // non-discardable multi-frame backlog of draw commands.
    197             setRateLimitingEnabled(true);
    198         }
    199         if (m_rateLimitingEnabled) {
    200             flush();
    201         }
    202     }
    203     ++m_framesSinceMailboxRelease;
    204     if (releasedMailboxHasExpired()) {
    205         freeReleasedMailbox();
    206     }
    207 }
    208 
    209 void Canvas2DLayerBridge::prepareForDraw()
    210 {
    211     ASSERT(!m_destructionInProgress);
    212     ASSERT(m_layer);
    213     if (!checkSurfaceValid()) {
    214         if (m_canvas) {
    215             // drop pending commands because there is no surface to draw to
    216             m_canvas->silentFlush();
    217         }
    218         return;
    219     }
    220     context()->makeContextCurrent();
    221 }
    222 
    223 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAllocated)
    224 {
    225     ASSERT(!m_destructionInProgress);
    226     intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated;
    227     m_bytesAllocated = bytesAllocated;
    228     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, delta);
    229 }
    230 
    231 size_t Canvas2DLayerBridge::storageAllocatedForRecording()
    232 {
    233     return m_canvas->storageAllocatedForRecording();
    234 }
    235 
    236 void Canvas2DLayerBridge::flushedDrawCommands()
    237 {
    238     ASSERT(!m_destructionInProgress);
    239     storageAllocatedForRecordingChanged(storageAllocatedForRecording());
    240     m_framesPending = 0;
    241 }
    242 
    243 void Canvas2DLayerBridge::skippedPendingDrawCommands()
    244 {
    245     ASSERT(!m_destructionInProgress);
    246     // Stop triggering the rate limiter if SkDeferredCanvas is detecting
    247     // and optimizing overdraw.
    248     setRateLimitingEnabled(false);
    249     flushedDrawCommands();
    250 }
    251 
    252 void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled)
    253 {
    254     ASSERT(!m_destructionInProgress);
    255     if (m_rateLimitingEnabled != enabled) {
    256         m_rateLimitingEnabled = enabled;
    257         m_layer->setRateLimitContext(m_rateLimitingEnabled);
    258     }
    259 }
    260 
    261 size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree)
    262 {
    263     ASSERT(!m_destructionInProgress);
    264     size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree);
    265     m_bytesAllocated -= bytesFreed;
    266     if (bytesFreed)
    267         Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this, -((intptr_t)bytesFreed));
    268     return bytesFreed;
    269 }
    270 
    271 void Canvas2DLayerBridge::flush()
    272 {
    273     ASSERT(!m_destructionInProgress);
    274     if (m_canvas->hasPendingCommands()) {
    275         TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush");
    276         freeReleasedMailbox(); // To avoid unnecessary triple-buffering
    277         m_canvas->flush();
    278     }
    279 }
    280 
    281 bool Canvas2DLayerBridge::releasedMailboxHasExpired()
    282 {
    283     // This heuristic indicates that the canvas is not being
    284     // actively presented by the compositor (3 frames rendered since
    285     // last mailbox release), suggesting that double buffering is not required.
    286     return hasReleasedMailbox() && m_framesSinceMailboxRelease > 2;
    287 }
    288 
    289 Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::releasedMailboxInfo()
    290 {
    291     return hasReleasedMailbox() ? &m_mailboxes[m_releasedMailboxInfoIndex] : 0;
    292 }
    293 
    294 bool Canvas2DLayerBridge::hasReleasedMailbox() const
    295 {
    296     return m_releasedMailboxInfoIndex != InvalidMailboxIndex;
    297 }
    298 
    299 void Canvas2DLayerBridge::freeReleasedMailbox()
    300 {
    301     if (m_contextProvider->context3d()->isContextLost() || !m_isSurfaceValid)
    302         return;
    303     MailboxInfo* mailboxInfo = releasedMailboxInfo();
    304     if (!mailboxInfo)
    305         return;
    306 
    307     ASSERT(mailboxInfo->m_status == MailboxReleased);
    308     if (mailboxInfo->m_mailbox.syncPoint) {
    309         context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint);
    310         mailboxInfo->m_mailbox.syncPoint = 0;
    311     }
    312     // Invalidate texture state in case the compositor altered it since the copy-on-write.
    313     if (mailboxInfo->m_image) {
    314         if (isHidden() || releasedMailboxHasExpired())
    315             mailboxInfo->m_image->getTexture()->resetFlag(static_cast<GrTextureFlags>(GrTexture::kReturnToCache_FlagBit));
    316         mailboxInfo->m_image->getTexture()->textureParamsModified();
    317         mailboxInfo->m_image.clear();
    318     }
    319     mailboxInfo->m_status = MailboxAvailable;
    320     m_releasedMailboxInfoIndex = InvalidMailboxIndex;
    321     Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
    322 }
    323 
    324 blink::WebGraphicsContext3D* Canvas2DLayerBridge::context()
    325 {
    326     // Check on m_layer is necessary because context() may be called during
    327     // the destruction of m_layer
    328     if (m_layer && !m_destructionInProgress)
    329         checkSurfaceValid(); // To ensure rate limiter is disabled if context is lost.
    330     return m_contextProvider->context3d();
    331 }
    332 
    333 bool Canvas2DLayerBridge::checkSurfaceValid()
    334 {
    335     ASSERT(!m_destructionInProgress);
    336     if (m_destructionInProgress || !m_isSurfaceValid)
    337         return false;
    338     if (m_contextProvider->context3d()->isContextLost()) {
    339         m_isSurfaceValid = false;
    340         if (m_imageBuffer)
    341             m_imageBuffer->notifySurfaceInvalid();
    342         setRateLimitingEnabled(false);
    343     }
    344     return m_isSurfaceValid;
    345 }
    346 
    347 bool Canvas2DLayerBridge::restoreSurface()
    348 {
    349     ASSERT(!m_destructionInProgress);
    350     if (m_destructionInProgress)
    351         return false;
    352     ASSERT(m_layer && !m_isSurfaceValid);
    353 
    354     blink::WebGraphicsContext3D* sharedContext = 0;
    355     // We must clear the mailboxes before calling m_layer->clearTexture() to prevent
    356     // re-entry via mailboxReleased from operating on defunct GrContext objects.
    357     m_mailboxes.clear();
    358     m_releasedMailboxInfoIndex = InvalidMailboxIndex;
    359     m_layer->clearTexture();
    360     m_contextProvider = adoptPtr(blink::Platform::current()->createSharedOffscreenGraphicsContext3DProvider());
    361     if (m_contextProvider)
    362         sharedContext = m_contextProvider->context3d();
    363 
    364     if (sharedContext && !sharedContext->isContextLost()) {
    365         IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevice()->height());
    366         RefPtr<SkSurface> surface(createSkSurface(m_contextProvider->grContext(), size, m_msaaSampleCount));
    367         if (surface.get()) {
    368             m_canvas->setSurface(surface.get());
    369             m_isSurfaceValid = true;
    370             // FIXME: draw sad canvas picture into new buffer crbug.com/243842
    371         }
    372     }
    373 
    374     return m_isSurfaceValid;
    375 }
    376 
    377 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMailbox, blink::WebExternalBitmap* bitmap)
    378 {
    379     if (m_destructionInProgress) {
    380         // It can be hit in the following sequence.
    381         // 1. Canvas draws something.
    382         // 2. The compositor begins the frame.
    383         // 3. Javascript makes a context be lost.
    384         // 4. Here.
    385         return false;
    386     }
    387     if (bitmap) {
    388         // Using accelerated 2d canvas with software renderer, which
    389         // should only happen in tests that use fake graphics contexts
    390         // or in Android WebView in software mode. In this case, we do
    391         // not care about producing any results for this canvas.
    392         m_canvas->silentFlush();
    393         m_lastImageId = 0;
    394         return false;
    395     }
    396     if (!checkSurfaceValid())
    397         return false;
    398 
    399     blink::WebGraphicsContext3D* webContext = context();
    400 
    401     // Release to skia textures that were previouosly released by the
    402     // compositor. We do this before acquiring the next snapshot in
    403     // order to cap maximum gpu memory consumption.
    404     webContext->makeContextCurrent();
    405     flush();
    406 
    407     RefPtr<SkImage> image = adoptRef(m_canvas->newImageSnapshot());
    408 
    409     // Early exit if canvas was not drawn to since last prepareMailbox
    410     if (image->uniqueID() == m_lastImageId)
    411         return false;
    412     m_lastImageId = image->uniqueID();
    413 
    414     MailboxInfo* mailboxInfo = createMailboxInfo();
    415     mailboxInfo->m_status = MailboxInUse;
    416     mailboxInfo->m_image = image;
    417 
    418     ASSERT(mailboxInfo->m_mailbox.syncPoint == 0);
    419     ASSERT(mailboxInfo->m_image.get());
    420     ASSERT(mailboxInfo->m_image->getTexture());
    421 
    422     // Because of texture sharing with the compositor, we must invalidate
    423     // the state cached in skia so that the deferred copy on write
    424     // in SkSurface_Gpu does not make any false assumptions.
    425     mailboxInfo->m_image->getTexture()->textureParamsModified();
    426 
    427     webContext->bindTexture(GL_TEXTURE_2D, mailboxInfo->m_image->getTexture()->getTextureHandle());
    428     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    429     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    430     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    431     webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    432     webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo->m_mailbox.name);
    433     if (isHidden()) {
    434         // With hidden canvases, we release the SkImage immediately because
    435         // there is no need for animations to be double buffered.
    436         mailboxInfo->m_image.clear();
    437     } else {
    438         webContext->flush();
    439         mailboxInfo->m_mailbox.syncPoint = webContext->insertSyncPoint();
    440     }
    441     webContext->bindTexture(GL_TEXTURE_2D, 0);
    442     // Because we are changing the texture binding without going through skia,
    443     // we must dirty the context.
    444     m_contextProvider->grContext()->resetContext(kTextureBinding_GrGLBackendState);
    445 
    446     // set m_parentLayerBridge to make sure 'this' stays alive as long as it has
    447     // live mailboxes
    448     ASSERT(!mailboxInfo->m_parentLayerBridge);
    449     mailboxInfo->m_parentLayerBridge = this;
    450     *outMailbox = mailboxInfo->m_mailbox;
    451     return true;
    452 }
    453 
    454 Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() {
    455     ASSERT(!m_destructionInProgress);
    456     MailboxInfo* mailboxInfo;
    457     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mailboxInfo++) {
    458         if (mailboxInfo->m_status == MailboxAvailable) {
    459             return mailboxInfo;
    460         }
    461     }
    462 
    463     // No available mailbox: create one.
    464     m_mailboxes.grow(m_mailboxes.size() + 1);
    465     mailboxInfo = &m_mailboxes.last();
    466     context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name);
    467     // Worst case, canvas is triple buffered.  More than 3 active mailboxes
    468     // means there is a problem.
    469     // For the single-threaded case, this value needs to be at least
    470     // kMaxSwapBuffersPending+1 (in render_widget.h).
    471     // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2.
    472     // TODO(piman): fix this.
    473     ASSERT(m_mailboxes.size() <= 4);
    474     ASSERT(mailboxInfo < m_mailboxes.end());
    475     return mailboxInfo;
    476 }
    477 
    478 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox& mailbox)
    479 {
    480     freeReleasedMailbox(); // Never have more than one mailbox in the released state.
    481     Vector<MailboxInfo>::iterator mailboxInfo;
    482     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); ++mailboxInfo) {
    483         if (nameEquals(mailboxInfo->m_mailbox, mailbox)) {
    484             mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint;
    485             ASSERT(mailboxInfo->m_status == MailboxInUse);
    486             mailboxInfo->m_status = MailboxReleased;
    487             // Trigger Canvas2DLayerBridge self-destruction if this is the
    488             // last live mailbox and the layer bridge is not externally
    489             // referenced.
    490             m_releasedMailboxInfoIndex = mailboxInfo - m_mailboxes.begin();
    491             m_framesSinceMailboxRelease = 0;
    492             if (isHidden()) {
    493                 freeReleasedMailbox();
    494             } else {
    495                 ASSERT(!m_destructionInProgress);
    496                 Canvas2DLayerManager::get().layerTransientResourceAllocationChanged(this);
    497             }
    498             ASSERT(mailboxInfo->m_parentLayerBridge.get() == this);
    499             mailboxInfo->m_parentLayerBridge.clear();
    500             return;
    501         }
    502     }
    503 }
    504 
    505 blink::WebLayer* Canvas2DLayerBridge::layer() const
    506 {
    507     ASSERT(!m_destructionInProgress);
    508     ASSERT(m_layer);
    509     return m_layer->layer();
    510 }
    511 
    512 void Canvas2DLayerBridge::willUse()
    513 {
    514     ASSERT(!m_destructionInProgress);
    515     Canvas2DLayerManager::get().layerDidDraw(this);
    516     m_didRecordDrawCommand = true;
    517 }
    518 
    519 Platform3DObject Canvas2DLayerBridge::getBackingTexture()
    520 {
    521     ASSERT(!m_destructionInProgress);
    522     if (!checkSurfaceValid())
    523         return 0;
    524     willUse();
    525     m_canvas->flush();
    526     context()->flush();
    527     GrRenderTarget* renderTarget = m_canvas->getTopDevice()->accessRenderTarget();
    528     if (renderTarget) {
    529         return renderTarget->asTexture()->getTextureHandle();
    530     }
    531     return 0;
    532 }
    533 
    534 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) {
    535     // This copy constructor should only be used for Vector reallocation
    536     // Assuming 'other' is to be destroyed, we transfer m_image ownership
    537     // rather than do a refcount dance.
    538     memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
    539     m_image = const_cast<MailboxInfo*>(&other)->m_image.release();
    540     m_status = other.m_status;
    541 }
    542 
    543 }
    544