LCOV - code coverage report
Current view: top level - gfx/layers/client - CanvasClient.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 255 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "CanvasClient.h"
       7             : 
       8             : #include "ClientCanvasLayer.h"          // for ClientCanvasLayer
       9             : #include "GLContext.h"                  // for GLContext
      10             : #include "GLScreenBuffer.h"             // for GLScreenBuffer
      11             : #include "ScopedGLHelpers.h"
      12             : #include "gfx2DGlue.h"                  // for ImageFormatToSurfaceFormat
      13             : #include "gfxPlatform.h"                // for gfxPlatform
      14             : #include "GLReadTexImageHelper.h"
      15             : #include "mozilla/gfx/BaseSize.h"       // for BaseSize
      16             : #include "mozilla/layers/BufferTexture.h"
      17             : #include "mozilla/layers/AsyncCanvasRenderer.h"
      18             : #include "mozilla/layers/CompositableForwarder.h"
      19             : #include "mozilla/layers/CompositorBridgeChild.h" // for CompositorBridgeChild
      20             : #include "mozilla/layers/LayersTypes.h"
      21             : #include "mozilla/layers/TextureClient.h"  // for TextureClient, etc
      22             : #include "mozilla/layers/TextureClientOGL.h"
      23             : #include "nsDebug.h"                    // for printf_stderr, NS_ASSERTION
      24             : #include "nsXULAppAPI.h"                // for XRE_GetProcessType, etc
      25             : #include "ShareableCanvasLayer.h"
      26             : #include "TextureClientSharedSurface.h"
      27             : 
      28             : using namespace mozilla::gfx;
      29             : using namespace mozilla::gl;
      30             : 
      31             : namespace mozilla {
      32             : namespace layers {
      33             : 
      34             : /* static */ already_AddRefed<CanvasClient>
      35           0 : CanvasClient::CreateCanvasClient(CanvasClientType aType,
      36             :                                  CompositableForwarder* aForwarder,
      37             :                                  TextureFlags aFlags)
      38             : {
      39           0 :   switch (aType) {
      40             :   case CanvasClientTypeShSurf:
      41           0 :     return MakeAndAddRef<CanvasClientSharedSurface>(aForwarder, aFlags);
      42             :   case CanvasClientAsync:
      43           0 :     return MakeAndAddRef<CanvasClientBridge>(aForwarder, aFlags);
      44             :   default:
      45           0 :     return MakeAndAddRef<CanvasClient2D>(aForwarder, aFlags);
      46             :     break;
      47             :   }
      48             : }
      49             : 
      50             : void
      51           0 : CanvasClientBridge::UpdateAsync(AsyncCanvasRenderer* aRenderer)
      52             : {
      53           0 :   if (!GetForwarder() || !mLayer || !aRenderer ||
      54           0 :       !aRenderer->GetCanvasClient()) {
      55           0 :     return;
      56             :   }
      57             : 
      58           0 :   CompositableHandle asyncID = aRenderer->GetCanvasClientAsyncHandle();
      59           0 :   if (!asyncID || mAsyncHandle == asyncID) {
      60           0 :     return;
      61             :   }
      62             : 
      63           0 :   static_cast<ShadowLayerForwarder*>(GetForwarder())
      64           0 :     ->AttachAsyncCompositable(asyncID, mLayer);
      65           0 :   mAsyncHandle = asyncID;
      66             : }
      67             : 
      68             : void
      69           0 : CanvasClient2D::UpdateFromTexture(TextureClient* aTexture)
      70             : {
      71           0 :   MOZ_ASSERT(aTexture);
      72             : 
      73           0 :   if (!aTexture->IsSharedWithCompositor()) {
      74           0 :     if (!AddTextureClient(aTexture)) {
      75           0 :       return;
      76             :     }
      77             :   }
      78             : 
      79           0 :   mBackBuffer = nullptr;
      80           0 :   mFrontBuffer = nullptr;
      81           0 :   mBufferProviderTexture = aTexture;
      82             : 
      83           0 :   AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
      84           0 :   CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
      85           0 :   t->mTextureClient = aTexture;
      86           0 :   t->mPictureRect = nsIntRect(nsIntPoint(0, 0), aTexture->GetSize());
      87           0 :   t->mFrameID = mFrameID;
      88             : 
      89           0 :   GetForwarder()->UseTextures(this, textures);
      90           0 :   aTexture->SyncWithObject(GetForwarder()->GetSyncObject());
      91             : }
      92             : 
      93             : void
      94           0 : CanvasClient2D::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
      95             : {
      96           0 :   mBufferProviderTexture = nullptr;
      97             : 
      98           0 :   AutoRemoveTexture autoRemove(this);
      99           0 :   if (mBackBuffer && (mBackBuffer->IsReadLocked() || mBackBuffer->GetSize() != aSize)) {
     100           0 :     autoRemove.mTexture = mBackBuffer;
     101           0 :     mBackBuffer = nullptr;
     102             :   }
     103             : 
     104           0 :   bool bufferCreated = false;
     105           0 :   if (!mBackBuffer) {
     106           0 :     bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
     107             :     gfxContentType contentType = isOpaque
     108           0 :                                                 ? gfxContentType::COLOR
     109           0 :                                                 : gfxContentType::COLOR_ALPHA;
     110             :     gfx::SurfaceFormat surfaceFormat
     111           0 :       = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType);
     112           0 :     TextureFlags flags = TextureFlags::DEFAULT;
     113           0 :     if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) {
     114           0 :       flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
     115             :     }
     116             : 
     117           0 :     mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
     118           0 :     if (!mBackBuffer) {
     119           0 :       NS_WARNING("Failed to allocate the TextureClient");
     120           0 :       return;
     121             :     }
     122           0 :     mBackBuffer->EnableReadLock();
     123           0 :     MOZ_ASSERT(mBackBuffer->CanExposeDrawTarget());
     124             : 
     125           0 :     bufferCreated = true;
     126             :   }
     127             : 
     128           0 :   bool updated = false;
     129             :   {
     130           0 :     TextureClientAutoLock autoLock(mBackBuffer, OpenMode::OPEN_WRITE_ONLY);
     131           0 :     if (!autoLock.Succeeded()) {
     132           0 :       mBackBuffer = nullptr;
     133           0 :       return;
     134             :     }
     135             : 
     136           0 :     RefPtr<DrawTarget> target = mBackBuffer->BorrowDrawTarget();
     137           0 :     if (target) {
     138           0 :       if (!aLayer->UpdateTarget(target)) {
     139           0 :         NS_WARNING("Failed to copy the canvas into a TextureClient.");
     140           0 :         return;
     141             :       }
     142           0 :       updated = true;
     143             :     }
     144             :   }
     145             : 
     146           0 :   if (bufferCreated && !AddTextureClient(mBackBuffer)) {
     147           0 :     mBackBuffer = nullptr;
     148           0 :     return;
     149             :   }
     150             : 
     151           0 :   if (updated) {
     152           0 :     AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
     153           0 :     CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
     154           0 :     t->mTextureClient = mBackBuffer;
     155           0 :     t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBackBuffer->GetSize());
     156           0 :     t->mFrameID = mFrameID;
     157           0 :     GetForwarder()->UseTextures(this, textures);
     158           0 :     mBackBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
     159             :   }
     160             : 
     161           0 :   mBackBuffer.swap(mFrontBuffer);
     162             : }
     163             : 
     164             : already_AddRefed<TextureClient>
     165           0 : CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat,
     166             :                                              gfx::IntSize aSize,
     167             :                                              TextureFlags aFlags,
     168             :                                              ShareableCanvasLayer* aLayer)
     169             : {
     170           0 :   if (aLayer->IsGLLayer()) {
     171             :     // We want a cairo backend here as we don't want to be copying into
     172             :     // an accelerated backend and we like LockBits to work. This is currently
     173             :     // the most effective way to make this work.
     174           0 :     return TextureClient::CreateForRawBufferAccess(GetForwarder(),
     175             :                                                    aFormat, aSize, BackendType::CAIRO,
     176           0 :                                                    mTextureFlags | aFlags);
     177             :   }
     178             : 
     179             : #ifdef XP_WIN
     180             :   return CreateTextureClientForDrawing(aFormat, aSize, BackendSelector::Canvas, aFlags);
     181             : #else
     182             :   // XXX - We should use CreateTextureClientForDrawing, but we first need
     183             :   // to use double buffering.
     184           0 :   gfx::BackendType backend = gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
     185           0 :   return TextureClient::CreateForRawBufferAccess(GetForwarder(),
     186             :                                                  aFormat, aSize, backend,
     187           0 :                                                  mTextureFlags | aFlags);
     188             : #endif
     189             : }
     190             : 
     191             : ////////////////////////////////////////////////////////////////////////
     192             : 
     193           0 : CanvasClientSharedSurface::CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
     194           0 :                                                      TextureFlags aFlags)
     195           0 :   : CanvasClient(aLayerForwarder, aFlags)
     196           0 : { }
     197             : 
     198           0 : CanvasClientSharedSurface::~CanvasClientSharedSurface()
     199             : {
     200           0 :   ClearSurfaces();
     201           0 : }
     202             : 
     203             : ////////////////////////////////////////
     204             : // Readback
     205             : 
     206             : // For formats compatible with R8G8B8A8.
     207           0 : static inline void SwapRB_R8G8B8A8(uint8_t* pixel) {
     208             :   // [RR, GG, BB, AA]
     209           0 :   Swap(pixel[0], pixel[2]);
     210           0 : }
     211             : 
     212             : class TexClientFactory
     213             : {
     214             :   CompositableForwarder* const mAllocator;
     215             :   const bool mHasAlpha;
     216             :   const gfx::IntSize mSize;
     217             :   const gfx::BackendType mBackendType;
     218             :   const TextureFlags mBaseTexFlags;
     219             :   const LayersBackend mLayersBackend;
     220             : 
     221             : public:
     222           0 :   TexClientFactory(CompositableForwarder* allocator, bool hasAlpha,
     223             :                    const gfx::IntSize& size, gfx::BackendType backendType,
     224             :                    TextureFlags baseTexFlags, LayersBackend layersBackend)
     225           0 :     : mAllocator(allocator)
     226             :     , mHasAlpha(hasAlpha)
     227             :     , mSize(size)
     228             :     , mBackendType(backendType)
     229             :     , mBaseTexFlags(baseTexFlags)
     230           0 :     , mLayersBackend(layersBackend)
     231             :   {
     232           0 :   }
     233             : 
     234             : protected:
     235           0 :   already_AddRefed<TextureClient> Create(gfx::SurfaceFormat format) {
     236           0 :     return TextureClient::CreateForRawBufferAccess(mAllocator, format,
     237           0 :                                                    mSize, mBackendType,
     238           0 :                                                    mBaseTexFlags);
     239             :   }
     240             : 
     241             : public:
     242           0 :   already_AddRefed<TextureClient> CreateB8G8R8AX8() {
     243           0 :     gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
     244           0 :                                           : gfx::SurfaceFormat::B8G8R8X8;
     245           0 :     return Create(format);
     246             :   }
     247             : 
     248           0 :   already_AddRefed<TextureClient> CreateR8G8B8AX8() {
     249           0 :     RefPtr<TextureClient> ret;
     250             : 
     251           0 :     bool areRGBAFormatsBroken = mLayersBackend == LayersBackend::LAYERS_BASIC;
     252           0 :     if (!areRGBAFormatsBroken) {
     253           0 :       gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
     254           0 :                                             : gfx::SurfaceFormat::R8G8B8X8;
     255           0 :       ret = Create(format);
     256             :     }
     257             : 
     258           0 :     if (!ret) {
     259           0 :       ret = CreateB8G8R8AX8();
     260           0 :       if (ret) {
     261           0 :         ret->AddFlags(TextureFlags::RB_SWAPPED);
     262             :       }
     263             :     }
     264             : 
     265           0 :     return ret.forget();
     266             :   }
     267             : };
     268             : 
     269             : static already_AddRefed<TextureClient>
     270           0 : TexClientFromReadback(SharedSurface* src, CompositableForwarder* allocator,
     271             :                       TextureFlags baseFlags, LayersBackend layersBackend)
     272             : {
     273           0 :   auto backendType = gfx::BackendType::CAIRO;
     274           0 :   TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType,
     275           0 :                            baseFlags, layersBackend);
     276             : 
     277           0 :   RefPtr<TextureClient> texClient;
     278             : 
     279             :   {
     280           0 :     gl::ScopedReadbackFB autoReadback(src);
     281             : 
     282             :     // We have a source FB, now we need a format.
     283           0 :     GLenum destFormat = LOCAL_GL_BGRA;
     284           0 :     GLenum destType = LOCAL_GL_UNSIGNED_BYTE;
     285             :     GLenum readFormat;
     286             :     GLenum readType;
     287             : 
     288             :     // We actually don't care if they match, since we can handle
     289             :     // any read{Format,Type} we get.
     290           0 :     auto gl = src->mGL;
     291           0 :     GetActualReadFormats(gl, destFormat, destType, &readFormat, &readType);
     292             : 
     293           0 :     MOZ_ASSERT(readFormat == LOCAL_GL_RGBA ||
     294             :                readFormat == LOCAL_GL_BGRA);
     295           0 :     MOZ_ASSERT(readType == LOCAL_GL_UNSIGNED_BYTE);
     296             : 
     297             :     // With a format and type, we can create texClient.
     298           0 :     if (readFormat == LOCAL_GL_BGRA &&
     299           0 :         readType == LOCAL_GL_UNSIGNED_BYTE)
     300             :     {
     301             :       // 0xAARRGGBB
     302             :       // In Lendian: [BB, GG, RR, AA]
     303           0 :       texClient = factory.CreateB8G8R8AX8();
     304             : 
     305           0 :     } else if (readFormat == LOCAL_GL_RGBA &&
     306           0 :                readType == LOCAL_GL_UNSIGNED_BYTE)
     307             :     {
     308             :       // [RR, GG, BB, AA]
     309           0 :       texClient = factory.CreateR8G8B8AX8();
     310             :     } else {
     311           0 :       MOZ_CRASH("GFX: Bad `read{Format,Type}`.");
     312             :     }
     313             : 
     314           0 :     MOZ_ASSERT(texClient);
     315           0 :     if (!texClient)
     316           0 :       return nullptr;
     317             : 
     318             :     // With a texClient, we can lock for writing.
     319           0 :     TextureClientAutoLock autoLock(texClient, OpenMode::OPEN_WRITE);
     320           0 :     DebugOnly<bool> succeeded = autoLock.Succeeded();
     321           0 :     MOZ_ASSERT(succeeded, "texture should have locked");
     322             : 
     323           0 :     MappedTextureData mapped;
     324           0 :     texClient->BorrowMappedData(mapped);
     325             : 
     326             :     // ReadPixels from the current FB into mapped.data.
     327           0 :     auto width = src->mSize.width;
     328           0 :     auto height = src->mSize.height;
     329             : 
     330             :     {
     331           0 :       ScopedPackState scopedPackState(gl);
     332             : 
     333           0 :       MOZ_ASSERT(mapped.stride/4 == mapped.size.width);
     334           0 :       gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, mapped.data);
     335             :     }
     336             : 
     337             :     // RB_SWAPPED doesn't work with D3D11. (bug 1051010)
     338             :     // RB_SWAPPED doesn't work with Basic. (bug ???????)
     339           0 :     bool layersNeedsManualSwap = layersBackend == LayersBackend::LAYERS_BASIC ||
     340           0 :                                  layersBackend == LayersBackend::LAYERS_D3D11;
     341           0 :     if (texClient->HasFlags(TextureFlags::RB_SWAPPED) &&
     342             :         layersNeedsManualSwap)
     343             :     {
     344           0 :       size_t pixels = width * height;
     345           0 :       uint8_t* itr = mapped.data;
     346           0 :       for (size_t i = 0; i < pixels; i++) {
     347           0 :         SwapRB_R8G8B8A8(itr);
     348           0 :         itr += 4;
     349             :       }
     350             : 
     351           0 :       texClient->RemoveFlags(TextureFlags::RB_SWAPPED);
     352             :     }
     353             :   }
     354             : 
     355           0 :   return texClient.forget();
     356             : }
     357             : 
     358             : ////////////////////////////////////////
     359             : 
     360             : static already_AddRefed<SharedSurfaceTextureClient>
     361           0 : CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory)
     362             : {
     363           0 :     RefPtr<SharedSurfaceTextureClient> dest = factory->NewTexClient(src->mSize);
     364           0 :     if (!dest) {
     365           0 :       return nullptr;
     366             :     }
     367             : 
     368           0 :     gl::SharedSurface* destSurf = dest->Surf();
     369             : 
     370           0 :     destSurf->ProducerAcquire();
     371           0 :     SharedSurface::ProdCopy(src, dest->Surf(), factory);
     372           0 :     destSurf->ProducerRelease();
     373             : 
     374           0 :     return dest.forget();
     375             : }
     376             : 
     377             : void
     378           0 : CanvasClientSharedSurface::Update(gfx::IntSize aSize, ShareableCanvasLayer* aLayer)
     379             : {
     380           0 :   Renderer renderer;
     381           0 :   renderer.construct<ShareableCanvasLayer*>(aLayer);
     382           0 :   UpdateRenderer(aSize, renderer);
     383           0 : }
     384             : 
     385             : void
     386           0 : CanvasClientSharedSurface::UpdateAsync(AsyncCanvasRenderer* aRenderer)
     387             : {
     388           0 :   Renderer renderer;
     389           0 :   renderer.construct<AsyncCanvasRenderer*>(aRenderer);
     390           0 :   UpdateRenderer(aRenderer->GetSize(), renderer);
     391           0 : }
     392             : 
     393             : void
     394           0 : CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRenderer)
     395             : {
     396           0 :   GLContext* gl = nullptr;
     397           0 :   ShareableCanvasLayer* layer = nullptr;
     398           0 :   AsyncCanvasRenderer* asyncRenderer = nullptr;
     399           0 :   if (aRenderer.constructed<ShareableCanvasLayer*>()) {
     400           0 :     layer = aRenderer.ref<ShareableCanvasLayer*>();
     401           0 :     gl = layer->mGLContext;
     402             :   } else {
     403           0 :     asyncRenderer = aRenderer.ref<AsyncCanvasRenderer*>();
     404           0 :     gl = asyncRenderer->mGLContext;
     405             :   }
     406           0 :   gl->MakeCurrent();
     407             : 
     408           0 :   RefPtr<TextureClient> newFront;
     409             : 
     410           0 :   if (layer && layer->mGLFrontbuffer) {
     411           0 :     mShSurfClient = CloneSurface(layer->mGLFrontbuffer.get(), layer->mFactory.get());
     412           0 :     if (!mShSurfClient) {
     413           0 :       gfxCriticalError() << "Invalid canvas front buffer";
     414           0 :       return;
     415             :     }
     416           0 :   } else if (layer && layer->mIsMirror) {
     417           0 :     mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), layer->mFactory.get());
     418           0 :     if (!mShSurfClient) {
     419           0 :       return;
     420             :     }
     421             :   } else {
     422           0 :     mShSurfClient = gl->Screen()->Front();
     423           0 :     if (mShSurfClient && mShSurfClient->GetAllocator() &&
     424           0 :         mShSurfClient->GetAllocator() != GetForwarder()->GetTextureForwarder()) {
     425           0 :       mShSurfClient = CloneSurface(mShSurfClient->Surf(), gl->Screen()->Factory());
     426             :     }
     427           0 :     if (!mShSurfClient) {
     428           0 :       return;
     429             :     }
     430             :   }
     431           0 :   MOZ_ASSERT(mShSurfClient);
     432             : 
     433           0 :   newFront = mShSurfClient;
     434             : 
     435           0 :   SharedSurface* surf = mShSurfClient->Surf();
     436             : 
     437             :   // Readback if needed.
     438           0 :   mReadbackClient = nullptr;
     439             : 
     440           0 :   auto forwarder = GetForwarder();
     441             : 
     442           0 :   bool needsReadback = (surf->mType == SharedSurfaceType::Basic);
     443           0 :   if (needsReadback) {
     444           0 :     TextureFlags flags = TextureFlags::IMMUTABLE;
     445             : 
     446           0 :     CompositableForwarder* shadowForwarder = nullptr;
     447           0 :     if (layer) {
     448           0 :       flags |= layer->Flags();
     449           0 :       shadowForwarder = layer->GetForwarder();
     450             :     } else {
     451           0 :       MOZ_ASSERT(asyncRenderer);
     452           0 :       flags |= mTextureFlags;
     453           0 :       shadowForwarder = GetForwarder();
     454             :     }
     455             : 
     456           0 :     auto layersBackend = shadowForwarder->GetCompositorBackendType();
     457           0 :     mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
     458             : 
     459           0 :     newFront = mReadbackClient;
     460             :   } else {
     461           0 :     mReadbackClient = nullptr;
     462             :   }
     463             : 
     464           0 :   surf->Commit();
     465             : 
     466           0 :   if (asyncRenderer) {
     467             :     // If surface type is Basic, above codes will readback
     468             :     // the GLContext to mReadbackClient in order to send frame to
     469             :     // compositor. We copy from this TextureClient directly by
     470             :     // calling CopyFromTextureClient().
     471             :     // Therefore, if main-thread want the content of GLContext,
     472             :     // it doesn't have to readback from GLContext again.
     473             :     //
     474             :     // Otherwise, if surface type isn't Basic, we will read from
     475             :     // SharedSurface directly from main-thread. We still pass
     476             :     // mReadbackClient which is nullptr here to tell
     477             :     // AsyncCanvasRenderer reset some properties.
     478           0 :     asyncRenderer->CopyFromTextureClient(mReadbackClient);
     479             :   }
     480             : 
     481           0 :   MOZ_ASSERT(newFront);
     482           0 :   if (!newFront) {
     483             :     // May happen in a release build in case of memory pressure.
     484           0 :     gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize;
     485           0 :     return;
     486             :   }
     487             : 
     488           0 :   mNewFront = newFront;
     489             : }
     490             : 
     491             : void
     492           0 : CanvasClientSharedSurface::Updated()
     493             : {
     494           0 :   if (!mNewFront) {
     495           0 :     return;
     496             :   }
     497             : 
     498           0 :   auto forwarder = GetForwarder();
     499             : 
     500           0 :   mFront = mNewFront;
     501           0 :   mNewFront = nullptr;
     502             : 
     503             :   // Add the new TexClient.
     504           0 :   if (!AddTextureClient(mFront)) {
     505           0 :     return;
     506             :   }
     507             : 
     508           0 :   AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
     509           0 :   CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
     510           0 :   t->mTextureClient = mFront;
     511           0 :   t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
     512           0 :   t->mFrameID = mFrameID;
     513           0 :   forwarder->UseTextures(this, textures);
     514             : }
     515             : 
     516             : void
     517           0 : CanvasClientSharedSurface::OnDetach() {
     518           0 :   ClearSurfaces();
     519           0 : }
     520             : 
     521             : void
     522           0 : CanvasClientSharedSurface::ClearSurfaces()
     523             : {
     524           0 :   if (mFront) {
     525           0 :     mFront->CancelWaitForRecycle();
     526             :   }
     527           0 :   mFront = nullptr;
     528           0 :   mNewFront = nullptr;
     529           0 :   mShSurfClient = nullptr;
     530           0 :   mReadbackClient = nullptr;
     531           0 : }
     532             : 
     533             : } // namespace layers
     534             : } // namespace mozilla

Generated by: LCOV version 1.13