| OLD | NEW | 
 | (Empty) | 
|    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 "core/platform/graphics/Canvas2DLayerBridge.h" |  | 
|   29  |  | 
|   30 #include "GrContext.h" |  | 
|   31 #include "SkDevice.h" |  | 
|   32 #include "SkSurface.h" |  | 
|   33 #include "core/platform/graphics/Canvas2DLayerManager.h" |  | 
|   34 #include "core/platform/graphics/GraphicsLayer.h" |  | 
|   35 #include "core/platform/graphics/gpu/SharedGraphicsContext3D.h" |  | 
|   36 #include "platform/TraceEvent.h" |  | 
|   37 #include "public/platform/Platform.h" |  | 
|   38 #include "public/platform/WebCompositorSupport.h" |  | 
|   39 #include "public/platform/WebGraphicsContext3D.h" |  | 
|   40  |  | 
|   41 using blink::WebExternalTextureLayer; |  | 
|   42 using blink::WebGraphicsContext3D; |  | 
|   43  |  | 
|   44 namespace WebCore { |  | 
|   45  |  | 
|   46 void Canvas2DLayerBridgePtr::clear() |  | 
|   47 { |  | 
|   48     if (m_ptr) { |  | 
|   49         m_ptr->destroy(); |  | 
|   50         m_ptr.clear(); |  | 
|   51     } |  | 
|   52 } |  | 
|   53  |  | 
|   54 Canvas2DLayerBridgePtr& Canvas2DLayerBridgePtr::operator=(const PassRefPtr<Canva
     s2DLayerBridge>& other) |  | 
|   55 { |  | 
|   56     clear(); |  | 
|   57     m_ptr = other; |  | 
|   58     return *this; |  | 
|   59 } |  | 
|   60  |  | 
|   61 static SkSurface* createSurface(GraphicsContext3D* context3D, const IntSize& siz
     e, int msaaSampleCount) |  | 
|   62 { |  | 
|   63     ASSERT(!context3D->webContext()->isContextLost()); |  | 
|   64     GrContext* gr = context3D->grContext(); |  | 
|   65     if (!gr) |  | 
|   66         return 0; |  | 
|   67     gr->resetContext(); |  | 
|   68     SkImageInfo info; |  | 
|   69     info.fWidth = size.width(); |  | 
|   70     info.fHeight = size.height(); |  | 
|   71     info.fColorType = kPMColor_SkColorType; |  | 
|   72     info.fAlphaType = kPremul_SkAlphaType; |  | 
|   73     return SkSurface::NewRenderTarget(gr, info,  msaaSampleCount); |  | 
|   74 } |  | 
|   75  |  | 
|   76 PassRefPtr<Canvas2DLayerBridge> Canvas2DLayerBridge::create(PassRefPtr<GraphicsC
     ontext3D> context, const IntSize& size, OpacityMode opacityMode, int msaaSampleC
     ount) |  | 
|   77 { |  | 
|   78     TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation"); |  | 
|   79     SkAutoTUnref<SkSurface> surface(createSurface(context.get(), size, msaaSampl
     eCount)); |  | 
|   80     if (!surface.get()) { |  | 
|   81         return PassRefPtr<Canvas2DLayerBridge>(); |  | 
|   82     } |  | 
|   83     RefPtr<SkDeferredCanvas> canvas = adoptRef(SkDeferredCanvas::Create(surface.
     get())); |  | 
|   84     RefPtr<Canvas2DLayerBridge> layerBridge = adoptRef(new Canvas2DLayerBridge(c
     ontext, canvas.release(), msaaSampleCount, opacityMode)); |  | 
|   85     return layerBridge.release(); |  | 
|   86 } |  | 
|   87  |  | 
|   88 Canvas2DLayerBridge::Canvas2DLayerBridge(PassRefPtr<GraphicsContext3D> context, 
     PassRefPtr<SkDeferredCanvas> canvas, int msaaSampleCount, OpacityMode opacityMod
     e) |  | 
|   89     : m_canvas(canvas) |  | 
|   90     , m_context(context) |  | 
|   91     , m_msaaSampleCount(msaaSampleCount) |  | 
|   92     , m_bytesAllocated(0) |  | 
|   93     , m_didRecordDrawCommand(false) |  | 
|   94     , m_surfaceIsValid(true) |  | 
|   95     , m_framesPending(0) |  | 
|   96     , m_destructionInProgress(false) |  | 
|   97     , m_rateLimitingEnabled(false) |  | 
|   98     , m_next(0) |  | 
|   99     , m_prev(0) |  | 
|  100     , m_lastImageId(0) |  | 
|  101 { |  | 
|  102     ASSERT(m_canvas); |  | 
|  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()->createEx
     ternalTextureLayer(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 } |  | 
|  112  |  | 
|  113 Canvas2DLayerBridge::~Canvas2DLayerBridge() |  | 
|  114 { |  | 
|  115     ASSERT(m_destructionInProgress); |  | 
|  116     m_layer.clear(); |  | 
|  117     Vector<MailboxInfo>::iterator mailboxInfo; |  | 
|  118     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai
     lboxInfo++) { |  | 
|  119         ASSERT(mailboxInfo->m_status != MailboxInUse); |  | 
|  120         if (mailboxInfo->m_status == MailboxReleased) { |  | 
|  121             if (mailboxInfo->m_mailbox.syncPoint) { |  | 
|  122                 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); |  | 
|  123                 mailboxInfo->m_mailbox.syncPoint = 0; |  | 
|  124             } |  | 
|  125             // Invalidate texture state in case the compositor altered it since 
     the copy-on-write. |  | 
|  126             mailboxInfo->m_image->getTexture()->invalidateCachedState(); |  | 
|  127         } |  | 
|  128     } |  | 
|  129     m_mailboxes.clear(); |  | 
|  130 } |  | 
|  131  |  | 
|  132 void Canvas2DLayerBridge::destroy() |  | 
|  133 { |  | 
|  134     ASSERT(!m_destructionInProgress); |  | 
|  135     m_destructionInProgress = true; |  | 
|  136     GraphicsLayer::unregisterContentsLayer(m_layer->layer()); |  | 
|  137     m_canvas->setNotificationClient(0); |  | 
|  138     m_layer->clearTexture(); |  | 
|  139     Canvas2DLayerManager::get().layerToBeDestroyed(this); |  | 
|  140     // Orphaning the layer is required to trigger the recration of a new layer |  | 
|  141     // in the case where destruction is caused by a canvas resize. Test: |  | 
|  142     // virtual/gpu/fast/canvas/canvas-resize-after-paint-without-layout.html |  | 
|  143     m_layer->layer()->removeFromParent(); |  | 
|  144 } |  | 
|  145  |  | 
|  146 void Canvas2DLayerBridge::limitPendingFrames() |  | 
|  147 { |  | 
|  148     ASSERT(!m_destructionInProgress); |  | 
|  149     if (m_didRecordDrawCommand) { |  | 
|  150         m_framesPending++; |  | 
|  151         m_didRecordDrawCommand = false; |  | 
|  152         if (m_framesPending > 1) { |  | 
|  153             // Turn on the rate limiter if this layer tends to accumulate a |  | 
|  154             // non-discardable multi-frame backlog of draw commands. |  | 
|  155             setRateLimitingEnabled(true); |  | 
|  156         } |  | 
|  157         if (m_rateLimitingEnabled) { |  | 
|  158             flush(); |  | 
|  159         } |  | 
|  160     } |  | 
|  161 } |  | 
|  162  |  | 
|  163 void Canvas2DLayerBridge::prepareForDraw() |  | 
|  164 { |  | 
|  165     ASSERT(!m_destructionInProgress); |  | 
|  166     ASSERT(m_layer); |  | 
|  167     if (!isValid()) { |  | 
|  168         if (m_canvas) { |  | 
|  169             // drop pending commands because there is no surface to draw to |  | 
|  170             m_canvas->silentFlush(); |  | 
|  171         } |  | 
|  172         return; |  | 
|  173     } |  | 
|  174     m_context->makeContextCurrent(); |  | 
|  175 } |  | 
|  176  |  | 
|  177 void Canvas2DLayerBridge::storageAllocatedForRecordingChanged(size_t bytesAlloca
     ted) |  | 
|  178 { |  | 
|  179     ASSERT(!m_destructionInProgress); |  | 
|  180     intptr_t delta = (intptr_t)bytesAllocated - (intptr_t)m_bytesAllocated; |  | 
|  181     m_bytesAllocated = bytesAllocated; |  | 
|  182     Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, delta); |  | 
|  183 } |  | 
|  184  |  | 
|  185 size_t Canvas2DLayerBridge::storageAllocatedForRecording() |  | 
|  186 { |  | 
|  187     ASSERT(!m_destructionInProgress); |  | 
|  188     return m_canvas->storageAllocatedForRecording(); |  | 
|  189 } |  | 
|  190  |  | 
|  191 void Canvas2DLayerBridge::flushedDrawCommands() |  | 
|  192 { |  | 
|  193     ASSERT(!m_destructionInProgress); |  | 
|  194     storageAllocatedForRecordingChanged(storageAllocatedForRecording()); |  | 
|  195     m_framesPending = 0; |  | 
|  196 } |  | 
|  197  |  | 
|  198 void Canvas2DLayerBridge::skippedPendingDrawCommands() |  | 
|  199 { |  | 
|  200     ASSERT(!m_destructionInProgress); |  | 
|  201     // Stop triggering the rate limiter if SkDeferredCanvas is detecting |  | 
|  202     // and optimizing overdraw. |  | 
|  203     setRateLimitingEnabled(false); |  | 
|  204     flushedDrawCommands(); |  | 
|  205 } |  | 
|  206  |  | 
|  207 void Canvas2DLayerBridge::setRateLimitingEnabled(bool enabled) |  | 
|  208 { |  | 
|  209     ASSERT(!m_destructionInProgress || !enabled); |  | 
|  210     if (m_rateLimitingEnabled != enabled) { |  | 
|  211         m_rateLimitingEnabled = enabled; |  | 
|  212         m_layer->setRateLimitContext(m_rateLimitingEnabled); |  | 
|  213     } |  | 
|  214 } |  | 
|  215  |  | 
|  216 size_t Canvas2DLayerBridge::freeMemoryIfPossible(size_t bytesToFree) |  | 
|  217 { |  | 
|  218     ASSERT(!m_destructionInProgress); |  | 
|  219     size_t bytesFreed = m_canvas->freeMemoryIfPossible(bytesToFree); |  | 
|  220     if (bytesFreed) |  | 
|  221         Canvas2DLayerManager::get().layerAllocatedStorageChanged(this, -((intptr
     _t)bytesFreed)); |  | 
|  222     m_bytesAllocated -= bytesFreed; |  | 
|  223     return bytesFreed; |  | 
|  224 } |  | 
|  225  |  | 
|  226 void Canvas2DLayerBridge::flush() |  | 
|  227 { |  | 
|  228     ASSERT(!m_destructionInProgress); |  | 
|  229     if (m_canvas->hasPendingCommands()) { |  | 
|  230         TRACE_EVENT0("cc", "Canvas2DLayerBridge::flush"); |  | 
|  231         m_canvas->flush(); |  | 
|  232     } |  | 
|  233 } |  | 
|  234  |  | 
|  235 WebGraphicsContext3D* Canvas2DLayerBridge::context() |  | 
|  236 { |  | 
|  237     // Check on m_layer is necessary because context() may be called during |  | 
|  238     // the destruction of m_layer |  | 
|  239     if (m_layer) { |  | 
|  240         isValid(); // To ensure rate limiter is disabled if context is lost. |  | 
|  241     } |  | 
|  242     return m_context->webContext(); |  | 
|  243 } |  | 
|  244  |  | 
|  245 bool Canvas2DLayerBridge::isValid() |  | 
|  246 { |  | 
|  247     ASSERT(m_layer); |  | 
|  248     if (m_destructionInProgress) |  | 
|  249         return false; |  | 
|  250     if (m_context->webContext()->isContextLost() || !m_surfaceIsValid) { |  | 
|  251         // Attempt to recover. |  | 
|  252         m_layer->clearTexture(); |  | 
|  253         m_mailboxes.clear(); |  | 
|  254         RefPtr<GraphicsContext3D> sharedContext = SharedGraphicsContext3D::get()
     ; |  | 
|  255         if (!sharedContext || sharedContext->webContext()->isContextLost()) { |  | 
|  256             m_surfaceIsValid = false; |  | 
|  257         } else { |  | 
|  258             m_context = sharedContext; |  | 
|  259             IntSize size(m_canvas->getTopDevice()->width(), m_canvas->getTopDevi
     ce()->height()); |  | 
|  260             SkAutoTUnref<SkSurface> surface(createSurface(m_context.get(), size,
      m_msaaSampleCount)); |  | 
|  261             if (surface.get()) { |  | 
|  262                 m_canvas->setSurface(surface.get()); |  | 
|  263                 m_surfaceIsValid = true; |  | 
|  264                 // FIXME: draw sad canvas picture into new buffer crbug.com/2438
     42 |  | 
|  265             } else { |  | 
|  266                 // Surface allocation failed. Set m_surfaceIsValid to false to |  | 
|  267                 // trigger subsequent retry. |  | 
|  268                 m_surfaceIsValid = false; |  | 
|  269             } |  | 
|  270         } |  | 
|  271     } |  | 
|  272     if (!m_surfaceIsValid) |  | 
|  273         setRateLimitingEnabled(false); |  | 
|  274     return m_surfaceIsValid; |  | 
|  275 } |  | 
|  276  |  | 
|  277 bool Canvas2DLayerBridge::prepareMailbox(blink::WebExternalTextureMailbox* outMa
     ilbox, blink::WebExternalBitmap* bitmap) |  | 
|  278 { |  | 
|  279     if (bitmap) { |  | 
|  280         // Using accelerated 2d canvas with software renderer, which |  | 
|  281         // should only happen in tests that use fake graphics contexts. |  | 
|  282         // In this case, we do not care about producing any results for |  | 
|  283         // compositing. |  | 
|  284         m_canvas->silentFlush(); |  | 
|  285         return false; |  | 
|  286     } |  | 
|  287     if (!isValid()) |  | 
|  288         return false; |  | 
|  289     // Release to skia textures that were previouosly released by the |  | 
|  290     // compositor. We do this before acquiring the next snapshot in |  | 
|  291     // order to cap maximum gpu memory consumption. |  | 
|  292     m_context->makeContextCurrent(); |  | 
|  293     flush(); |  | 
|  294     Vector<MailboxInfo>::iterator mailboxInfo; |  | 
|  295     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai
     lboxInfo++) { |  | 
|  296         if (mailboxInfo->m_status == MailboxReleased) { |  | 
|  297             if (mailboxInfo->m_mailbox.syncPoint) { |  | 
|  298                 context()->waitSyncPoint(mailboxInfo->m_mailbox.syncPoint); |  | 
|  299                 mailboxInfo->m_mailbox.syncPoint = 0; |  | 
|  300             } |  | 
|  301             // Invalidate texture state in case the compositor altered it since 
     the copy-on-write. |  | 
|  302             mailboxInfo->m_image->getTexture()->invalidateCachedState(); |  | 
|  303             mailboxInfo->m_image.reset(0); |  | 
|  304             mailboxInfo->m_status = MailboxAvailable; |  | 
|  305         } |  | 
|  306     } |  | 
|  307     SkAutoTUnref<SkImage> image(m_canvas->newImageSnapshot()); |  | 
|  308     // Early exit if canvas was not drawn to since last prepareMailbox |  | 
|  309     if (image->uniqueID() == m_lastImageId) |  | 
|  310         return false; |  | 
|  311     m_lastImageId = image->uniqueID(); |  | 
|  312  |  | 
|  313     mailboxInfo = createMailboxInfo(); |  | 
|  314     mailboxInfo->m_status = MailboxInUse; |  | 
|  315     mailboxInfo->m_image.swap(&image); |  | 
|  316     // Because of texture sharing with the compositor, we must invalidate |  | 
|  317     // the state cached in skia so that the deferred copy on write |  | 
|  318     // in SkSurface_Gpu does not make any false assumptions. |  | 
|  319     mailboxInfo->m_image->getTexture()->invalidateCachedState(); |  | 
|  320  |  | 
|  321     ASSERT(mailboxInfo->m_mailbox.syncPoint == 0); |  | 
|  322     ASSERT(mailboxInfo->m_image.get()); |  | 
|  323     ASSERT(mailboxInfo->m_image->getTexture()); |  | 
|  324  |  | 
|  325     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, mailboxInfo->m_image->
     getTexture()->getTextureHandle()); |  | 
|  326     m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T
     EXTURE_MAG_FILTER, GraphicsContext3D::LINEAR); |  | 
|  327     m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T
     EXTURE_MIN_FILTER, GraphicsContext3D::LINEAR); |  | 
|  328     m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T
     EXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE); |  | 
|  329     m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::T
     EXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE); |  | 
|  330     context()->produceTextureCHROMIUM(GraphicsContext3D::TEXTURE_2D, mailboxInfo
     ->m_mailbox.name); |  | 
|  331     context()->flush(); |  | 
|  332     mailboxInfo->m_mailbox.syncPoint = context()->insertSyncPoint(); |  | 
|  333     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); |  | 
|  334     // Because we are changing the texture binding without going through skia, |  | 
|  335     // we must dirty the context. |  | 
|  336     m_context->grContext()->resetContext(kTextureBinding_GrGLBackendState); |  | 
|  337  |  | 
|  338     // set m_parentLayerBridge to make sure 'this' stays alive as long as it has |  | 
|  339     // live mailboxes |  | 
|  340     ASSERT(!mailboxInfo->m_parentLayerBridge); |  | 
|  341     mailboxInfo->m_parentLayerBridge = this; |  | 
|  342     *outMailbox = mailboxInfo->m_mailbox; |  | 
|  343     return true; |  | 
|  344 } |  | 
|  345  |  | 
|  346 Canvas2DLayerBridge::MailboxInfo* Canvas2DLayerBridge::createMailboxInfo() { |  | 
|  347     ASSERT(!m_destructionInProgress); |  | 
|  348     MailboxInfo* mailboxInfo; |  | 
|  349     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai
     lboxInfo++) { |  | 
|  350         if (mailboxInfo->m_status == MailboxAvailable) { |  | 
|  351             return mailboxInfo; |  | 
|  352         } |  | 
|  353     } |  | 
|  354  |  | 
|  355     // No available mailbox: create one. |  | 
|  356     m_mailboxes.grow(m_mailboxes.size() + 1); |  | 
|  357     mailboxInfo = &m_mailboxes.last(); |  | 
|  358     context()->genMailboxCHROMIUM(mailboxInfo->m_mailbox.name); |  | 
|  359     // Worst case, canvas is triple buffered.  More than 3 active mailboxes |  | 
|  360     // means there is a problem. |  | 
|  361     // For the single-threaded case, this value needs to be at least |  | 
|  362     // kMaxSwapBuffersPending+1 (in render_widget.h). |  | 
|  363     // Because of crbug.com/247874, it needs to be kMaxSwapBuffersPending+2. |  | 
|  364     // TODO(piman): fix this. |  | 
|  365     ASSERT(m_mailboxes.size() <= 4); |  | 
|  366     ASSERT(mailboxInfo < m_mailboxes.end()); |  | 
|  367     return mailboxInfo; |  | 
|  368 } |  | 
|  369  |  | 
|  370 void Canvas2DLayerBridge::mailboxReleased(const blink::WebExternalTextureMailbox
     & mailbox) |  | 
|  371 { |  | 
|  372     Vector<MailboxInfo>::iterator mailboxInfo; |  | 
|  373     for (mailboxInfo = m_mailboxes.begin(); mailboxInfo < m_mailboxes.end(); mai
     lboxInfo++) { |  | 
|  374         if (!memcmp(mailboxInfo->m_mailbox.name, mailbox.name, sizeof(mailbox.na
     me))) { |  | 
|  375             mailboxInfo->m_mailbox.syncPoint = mailbox.syncPoint; |  | 
|  376             ASSERT(mailboxInfo->m_status == MailboxInUse); |  | 
|  377             mailboxInfo->m_status = MailboxReleased; |  | 
|  378             // Trigger Canvas2DLayerBridge self-destruction if this is the |  | 
|  379             // last live mailbox and the layer bridge is not externally |  | 
|  380             // referenced. |  | 
|  381             ASSERT(mailboxInfo->m_parentLayerBridge.get() == this); |  | 
|  382             mailboxInfo->m_parentLayerBridge.clear(); |  | 
|  383             return; |  | 
|  384         } |  | 
|  385     } |  | 
|  386 } |  | 
|  387  |  | 
|  388 blink::WebLayer* Canvas2DLayerBridge::layer() |  | 
|  389 { |  | 
|  390     ASSERT(m_layer); |  | 
|  391     return m_layer->layer(); |  | 
|  392 } |  | 
|  393  |  | 
|  394 void Canvas2DLayerBridge::contextAcquired() |  | 
|  395 { |  | 
|  396     ASSERT(!m_destructionInProgress); |  | 
|  397     Canvas2DLayerManager::get().layerDidDraw(this); |  | 
|  398     m_didRecordDrawCommand = true; |  | 
|  399 } |  | 
|  400  |  | 
|  401 unsigned Canvas2DLayerBridge::backBufferTexture() |  | 
|  402 { |  | 
|  403     ASSERT(!m_destructionInProgress); |  | 
|  404     if (!isValid()) |  | 
|  405         return 0; |  | 
|  406     contextAcquired(); |  | 
|  407     m_canvas->flush(); |  | 
|  408     m_context->flush(); |  | 
|  409     GrRenderTarget* renderTarget = reinterpret_cast<GrRenderTarget*>(m_canvas->g
     etDevice()->accessRenderTarget()); |  | 
|  410     if (renderTarget) { |  | 
|  411         return renderTarget->asTexture()->getTextureHandle(); |  | 
|  412     } |  | 
|  413     return 0; |  | 
|  414 } |  | 
|  415  |  | 
|  416 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) { |  | 
|  417     // This copy constructor should only be used for Vector reallocation |  | 
|  418     // Assuming 'other' is to be destroyed, we swap m_image ownership |  | 
|  419     // rather than do a refcount dance. |  | 
|  420     memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); |  | 
|  421     m_image.swap(const_cast<SkAutoTUnref<SkImage>*>(&other.m_image)); |  | 
|  422     m_status = other.m_status; |  | 
|  423 } |  | 
|  424  |  | 
|  425 } |  | 
| OLD | NEW |