LCOV - code coverage report
Current view: top level - gfx/layers/client - TextureClientRecycleAllocator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 122 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 24 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 "gfxPlatform.h"
       7             : #include "ImageContainer.h"
       8             : #include "mozilla/layers/BufferTexture.h"
       9             : #include "mozilla/layers/ISurfaceAllocator.h"
      10             : #include "mozilla/layers/TextureForwarder.h"
      11             : #include "TextureClientRecycleAllocator.h"
      12             : 
      13             : namespace mozilla {
      14             : namespace layers {
      15             : 
      16             : // Used to keep TextureClient's reference count stable as not to disrupt recycling.
      17             : class TextureClientHolder
      18             : {
      19           0 :   ~TextureClientHolder() {}
      20             : public:
      21           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder)
      22             : 
      23           0 :   explicit TextureClientHolder(TextureClient* aClient)
      24           0 :     : mTextureClient(aClient)
      25           0 :     , mWillRecycle(true)
      26           0 :   {}
      27             : 
      28           0 :   TextureClient* GetTextureClient()
      29             :   {
      30           0 :     return mTextureClient;
      31             :   }
      32             : 
      33           0 :   bool WillRecycle()
      34             :   {
      35           0 :     return mWillRecycle;
      36             :   }
      37             : 
      38           0 :   void ClearWillRecycle()
      39             :   {
      40           0 :     mWillRecycle = false;
      41           0 :   }
      42             : 
      43           0 :   void ClearTextureClient() { mTextureClient = nullptr; }
      44             : protected:
      45             :   RefPtr<TextureClient> mTextureClient;
      46             :   bool mWillRecycle;
      47             : };
      48             : 
      49             : class DefaultTextureClientAllocationHelper : public ITextureClientAllocationHelper
      50             : {
      51             : public:
      52           0 :   DefaultTextureClientAllocationHelper(TextureClientRecycleAllocator* aAllocator,
      53             :                                        gfx::SurfaceFormat aFormat,
      54             :                                        gfx::IntSize aSize,
      55             :                                        BackendSelector aSelector,
      56             :                                        TextureFlags aTextureFlags,
      57             :                                        TextureAllocationFlags aAllocationFlags)
      58           0 :     : ITextureClientAllocationHelper(aFormat,
      59             :                                      aSize,
      60             :                                      aSelector,
      61             :                                      aTextureFlags,
      62             :                                      aAllocationFlags)
      63           0 :     , mAllocator(aAllocator)
      64           0 :   {}
      65             : 
      66           0 :   bool IsCompatible(TextureClient* aTextureClient) override
      67             :   {
      68           0 :     if (aTextureClient->GetFormat() != mFormat ||
      69           0 :         aTextureClient->GetSize() != mSize) {
      70           0 :       return false;
      71             :     }
      72           0 :     return true;
      73             :   }
      74             : 
      75           0 :   already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
      76             :   {
      77           0 :     return mAllocator->Allocate(mFormat,
      78             :                                 mSize,
      79           0 :                                 mSelector,
      80           0 :                                 mTextureFlags,
      81           0 :                                 mAllocationFlags);
      82             :   }
      83             : 
      84             : protected:
      85             :   TextureClientRecycleAllocator* mAllocator;
      86             : };
      87             : 
      88           0 : YCbCrTextureClientAllocationHelper::YCbCrTextureClientAllocationHelper(const PlanarYCbCrData& aData,
      89           0 :                                                                        TextureFlags aTextureFlags)
      90             :   : ITextureClientAllocationHelper(gfx::SurfaceFormat::YUV,
      91             :                                    aData.mYSize,
      92             :                                    BackendSelector::Content,
      93             :                                    aTextureFlags,
      94             :                                    ALLOC_DEFAULT)
      95           0 :   , mData(aData)
      96             : {
      97           0 : }
      98             : 
      99             : bool
     100           0 : YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient)
     101             : {
     102           0 :   MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV);
     103             : 
     104           0 :   BufferTextureData* bufferData = aTextureClient->GetInternalData()->AsBufferTextureData();
     105           0 :   if (!bufferData ||
     106           0 :       aTextureClient->GetSize() != mData.mYSize ||
     107           0 :       bufferData->GetCbCrSize().isNothing() ||
     108           0 :       bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
     109           0 :       bufferData->GetYUVColorSpace().isNothing() ||
     110           0 :       bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
     111           0 :       bufferData->GetStereoMode().isNothing() ||
     112           0 :       bufferData->GetStereoMode().ref() != mData.mStereoMode) {
     113           0 :     return false;
     114             :   }
     115           0 :   return true;
     116             : }
     117             : 
     118             : already_AddRefed<TextureClient>
     119           0 : YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
     120             : {
     121             :   return TextureClient::CreateForYCbCr(aAllocator,
     122           0 :                                        mData.mYSize, mData.mCbCrSize,
     123           0 :                                        mData.mStereoMode,
     124           0 :                                        mData.mYUVColorSpace,
     125           0 :                                        mTextureFlags);
     126             : }
     127             : 
     128           0 : TextureClientRecycleAllocator::TextureClientRecycleAllocator(KnowsCompositor* aAllocator)
     129             :   : mSurfaceAllocator(aAllocator)
     130             :   , mMaxPooledSize(kMaxPooledSized)
     131             :   , mLock("TextureClientRecycleAllocatorImp.mLock")
     132           0 :   , mIsDestroyed(false)
     133             : {
     134           0 : }
     135             : 
     136           0 : TextureClientRecycleAllocator::~TextureClientRecycleAllocator()
     137             : {
     138           0 :   MutexAutoLock lock(mLock);
     139           0 :   while (!mPooledClients.empty()) {
     140           0 :     mPooledClients.pop();
     141             :   }
     142           0 :   MOZ_ASSERT(mInUseClients.empty());
     143           0 : }
     144             : 
     145             : void
     146           0 : TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax)
     147             : {
     148           0 :   mMaxPooledSize = aMax;
     149           0 : }
     150             : 
     151             : already_AddRefed<TextureClient>
     152           0 : TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
     153             :                                                gfx::IntSize aSize,
     154             :                                                BackendSelector aSelector,
     155             :                                                TextureFlags aTextureFlags,
     156             :                                                TextureAllocationFlags aAllocFlags)
     157             : {
     158           0 :   MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE));
     159             :   DefaultTextureClientAllocationHelper helper(this,
     160             :                                               aFormat,
     161             :                                               aSize,
     162             :                                               aSelector,
     163             :                                               aTextureFlags,
     164           0 :                                               aAllocFlags);
     165           0 :   return CreateOrRecycle(helper);
     166             : }
     167             : 
     168             : already_AddRefed<TextureClient>
     169           0 : TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& aHelper)
     170             : {
     171           0 :   MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);
     172             : 
     173           0 :   RefPtr<TextureClientHolder> textureHolder;
     174             : 
     175             :   {
     176           0 :     MutexAutoLock lock(mLock);
     177           0 :     if (mIsDestroyed) {
     178           0 :       return nullptr;
     179             :     }
     180           0 :     if (!mPooledClients.empty()) {
     181           0 :       textureHolder = mPooledClients.top();
     182           0 :       mPooledClients.pop();
     183             :       // If the texture's allocator is not open or a pooled TextureClient is
     184             :       // not compatible, release it.
     185           0 :       if (!textureHolder->GetTextureClient()->GetAllocator()->IPCOpen() ||
     186           0 :           !aHelper.IsCompatible(textureHolder->GetTextureClient())) {
     187             :         // Release TextureClient.
     188           0 :         RefPtr<Runnable> task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
     189           0 :         textureHolder->ClearTextureClient();
     190           0 :         textureHolder = nullptr;
     191           0 :         mSurfaceAllocator->GetTextureForwarder()->GetMessageLoop()->PostTask(task.forget());
     192             :       } else {
     193           0 :         textureHolder->GetTextureClient()->RecycleTexture(aHelper.mTextureFlags);
     194             :       }
     195             :     }
     196             :   }
     197             : 
     198           0 :   if (!textureHolder) {
     199             :     // Allocate new TextureClient
     200           0 :     RefPtr<TextureClient> texture = aHelper.Allocate(mSurfaceAllocator);
     201           0 :     if (!texture) {
     202           0 :       return nullptr;
     203             :     }
     204           0 :     textureHolder = new TextureClientHolder(texture);
     205             :   }
     206             : 
     207             :   {
     208           0 :     MutexAutoLock lock(mLock);
     209           0 :     MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end());
     210             :     // Register TextureClient
     211           0 :     mInUseClients[textureHolder->GetTextureClient()] = textureHolder;
     212             :   }
     213           0 :   RefPtr<TextureClient> client(textureHolder->GetTextureClient());
     214             : 
     215             :   // Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its
     216             :   // ref count drops to 1.
     217           0 :   client->SetRecycleAllocator(this);
     218           0 :   return client.forget();
     219             : }
     220             : 
     221             : already_AddRefed<TextureClient>
     222           0 : TextureClientRecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
     223             :                                         gfx::IntSize aSize,
     224             :                                         BackendSelector aSelector,
     225             :                                         TextureFlags aTextureFlags,
     226             :                                         TextureAllocationFlags aAllocFlags)
     227             : {
     228             :   return TextureClient::CreateForDrawing(mSurfaceAllocator, aFormat, aSize,
     229           0 :                                          aSelector, aTextureFlags, aAllocFlags);
     230             : }
     231             : 
     232             : void
     233           0 : TextureClientRecycleAllocator::ShrinkToMinimumSize()
     234             : {
     235           0 :   MutexAutoLock lock(mLock);
     236           0 :   while (!mPooledClients.empty()) {
     237           0 :     mPooledClients.pop();
     238             :   }
     239             :   // We can not clear using TextureClients safely.
     240             :   // Just clear WillRecycle here.
     241           0 :   std::map<TextureClient*, RefPtr<TextureClientHolder> >::iterator it;
     242           0 :   for (it = mInUseClients.begin(); it != mInUseClients.end(); it++) {
     243           0 :     RefPtr<TextureClientHolder> holder = it->second;
     244           0 :     holder->ClearWillRecycle();
     245             :   }
     246           0 : }
     247             : 
     248             : void
     249           0 : TextureClientRecycleAllocator::Destroy()
     250             : {
     251           0 :   MutexAutoLock lock(mLock);
     252           0 :   while (!mPooledClients.empty()) {
     253           0 :     mPooledClients.pop();
     254             :   }
     255           0 :   mIsDestroyed = true;
     256           0 : }
     257             : 
     258             : void
     259           0 : TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
     260             : {
     261             :   // Clearing the recycle allocator drops a reference, so make sure we stay alive
     262             :   // for the duration of this function.
     263           0 :   RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
     264           0 :   aClient->SetRecycleAllocator(nullptr);
     265             : 
     266           0 :   RefPtr<TextureClientHolder> textureHolder;
     267             :   {
     268           0 :     MutexAutoLock lock(mLock);
     269           0 :     if (mInUseClients.find(aClient) != mInUseClients.end()) {
     270           0 :       textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock.
     271           0 :       if (textureHolder->WillRecycle() &&
     272           0 :           !mIsDestroyed && mPooledClients.size() < mMaxPooledSize) {
     273           0 :         mPooledClients.push(textureHolder);
     274             :       }
     275           0 :       mInUseClients.erase(aClient);
     276             :     }
     277             :   }
     278           0 : }
     279             : 
     280             : } // namespace layers
     281             : } // namespace mozilla

Generated by: LCOV version 1.13