forked from mirrors/gecko-dev
		
	 126bd9e1a4
			
		
	
	
		126bd9e1a4
		
	
	
	
	
		
			
			This patch was generated automatically by the "modeline.py" script, available here: https://github.com/amccreight/moz-source-tools/blob/master/modeline.py For every file that is modified in this patch, the changes are as follows: (1) The patch changes the file to use the exact C++ mode lines from the Mozilla coding style guide, available here: https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style#Mode_Line (2) The patch deletes any blank lines between the mode line & the MPL boilerplate comment. (3) If the file previously had the mode lines and MPL boilerplate in a single contiguous C++ comment, then the patch splits them into separate C++ comments, to match the boilerplate in the coding style. MozReview-Commit-ID: 77D61xpSmIl --HG-- extra : rebase_source : c6162fa3cf539a07177a19838324bf368faa162b
		
			
				
	
	
		
			286 lines
		
	
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | |
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| #include "gfxPlatform.h"
 | |
| #include "ImageContainer.h"
 | |
| #include "mozilla/layers/BufferTexture.h"
 | |
| #include "mozilla/layers/ISurfaceAllocator.h"
 | |
| #include "mozilla/layers/TextureForwarder.h"
 | |
| #include "TextureClientRecycleAllocator.h"
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace layers {
 | |
| 
 | |
| // Used to keep TextureClient's reference count stable as not to disrupt recycling.
 | |
| class TextureClientHolder
 | |
| {
 | |
|   ~TextureClientHolder() {}
 | |
| public:
 | |
|   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder)
 | |
| 
 | |
|   explicit TextureClientHolder(TextureClient* aClient)
 | |
|     : mTextureClient(aClient)
 | |
|     , mWillRecycle(true)
 | |
|   {}
 | |
| 
 | |
|   TextureClient* GetTextureClient()
 | |
|   {
 | |
|     return mTextureClient;
 | |
|   }
 | |
| 
 | |
|   bool WillRecycle()
 | |
|   {
 | |
|     return mWillRecycle;
 | |
|   }
 | |
| 
 | |
|   void ClearWillRecycle()
 | |
|   {
 | |
|     mWillRecycle = false;
 | |
|   }
 | |
| 
 | |
|   void ClearTextureClient() { mTextureClient = nullptr; }
 | |
| protected:
 | |
|   RefPtr<TextureClient> mTextureClient;
 | |
|   bool mWillRecycle;
 | |
| };
 | |
| 
 | |
| class DefaultTextureClientAllocationHelper : public ITextureClientAllocationHelper
 | |
| {
 | |
| public:
 | |
|   DefaultTextureClientAllocationHelper(TextureClientRecycleAllocator* aAllocator,
 | |
|                                        gfx::SurfaceFormat aFormat,
 | |
|                                        gfx::IntSize aSize,
 | |
|                                        BackendSelector aSelector,
 | |
|                                        TextureFlags aTextureFlags,
 | |
|                                        TextureAllocationFlags aAllocationFlags)
 | |
|     : ITextureClientAllocationHelper(aFormat,
 | |
|                                      aSize,
 | |
|                                      aSelector,
 | |
|                                      aTextureFlags,
 | |
|                                      aAllocationFlags)
 | |
|     , mAllocator(aAllocator)
 | |
|   {}
 | |
| 
 | |
|   bool IsCompatible(TextureClient* aTextureClient) override
 | |
|   {
 | |
|     if (aTextureClient->GetFormat() != mFormat ||
 | |
|         aTextureClient->GetSize() != mSize) {
 | |
|       return false;
 | |
|     }
 | |
|     return true;
 | |
|   }
 | |
| 
 | |
|   already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
 | |
|   {
 | |
|     return mAllocator->Allocate(mFormat,
 | |
|                                 mSize,
 | |
|                                 mSelector,
 | |
|                                 mTextureFlags,
 | |
|                                 mAllocationFlags);
 | |
|   }
 | |
| 
 | |
| protected:
 | |
|   TextureClientRecycleAllocator* mAllocator;
 | |
| };
 | |
| 
 | |
| YCbCrTextureClientAllocationHelper::YCbCrTextureClientAllocationHelper(const PlanarYCbCrData& aData,
 | |
|                                                                        TextureFlags aTextureFlags)
 | |
|   : ITextureClientAllocationHelper(gfx::SurfaceFormat::YUV,
 | |
|                                    aData.mYSize,
 | |
|                                    BackendSelector::Content,
 | |
|                                    aTextureFlags,
 | |
|                                    ALLOC_DEFAULT)
 | |
|   , mData(aData)
 | |
| {
 | |
| }
 | |
| 
 | |
| bool
 | |
| YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient)
 | |
| {
 | |
|   MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV);
 | |
| 
 | |
|   BufferTextureData* bufferData = aTextureClient->GetInternalData()->AsBufferTextureData();
 | |
|   if (!bufferData ||
 | |
|       aTextureClient->GetSize() != mData.mYSize ||
 | |
|       bufferData->GetCbCrSize().isNothing() ||
 | |
|       bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
 | |
|       bufferData->GetYUVColorSpace().isNothing() ||
 | |
|       bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
 | |
|       bufferData->GetBitDepth().isNothing() ||
 | |
|       bufferData->GetBitDepth().ref() != mData.mBitDepth ||
 | |
|       bufferData->GetStereoMode().isNothing() ||
 | |
|       bufferData->GetStereoMode().ref() != mData.mStereoMode) {
 | |
|     return false;
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| already_AddRefed<TextureClient>
 | |
| YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
 | |
| {
 | |
|   return TextureClient::CreateForYCbCr(aAllocator,
 | |
|                                        mData.mYSize, mData.mYStride,
 | |
|                                        mData.mCbCrSize, mData.mCbCrStride,
 | |
|                                        mData.mStereoMode,
 | |
|                                        mData.mYUVColorSpace,
 | |
|                                        mData.mBitDepth,
 | |
|                                        mTextureFlags);
 | |
| }
 | |
| 
 | |
| TextureClientRecycleAllocator::TextureClientRecycleAllocator(KnowsCompositor* aAllocator)
 | |
|   : mSurfaceAllocator(aAllocator)
 | |
|   , mMaxPooledSize(kMaxPooledSized)
 | |
|   , mLock("TextureClientRecycleAllocatorImp.mLock")
 | |
|   , mIsDestroyed(false)
 | |
| {
 | |
| }
 | |
| 
 | |
| TextureClientRecycleAllocator::~TextureClientRecycleAllocator()
 | |
| {
 | |
|   MutexAutoLock lock(mLock);
 | |
|   while (!mPooledClients.empty()) {
 | |
|     mPooledClients.pop();
 | |
|   }
 | |
|   MOZ_ASSERT(mInUseClients.empty());
 | |
| }
 | |
| 
 | |
| void
 | |
| TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax)
 | |
| {
 | |
|   mMaxPooledSize = aMax;
 | |
| }
 | |
| 
 | |
| already_AddRefed<TextureClient>
 | |
| TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
 | |
|                                                gfx::IntSize aSize,
 | |
|                                                BackendSelector aSelector,
 | |
|                                                TextureFlags aTextureFlags,
 | |
|                                                TextureAllocationFlags aAllocFlags)
 | |
| {
 | |
|   MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE));
 | |
|   DefaultTextureClientAllocationHelper helper(this,
 | |
|                                               aFormat,
 | |
|                                               aSize,
 | |
|                                               aSelector,
 | |
|                                               aTextureFlags,
 | |
|                                               aAllocFlags);
 | |
|   return CreateOrRecycle(helper);
 | |
| }
 | |
| 
 | |
| already_AddRefed<TextureClient>
 | |
| TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& aHelper)
 | |
| {
 | |
|   MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);
 | |
| 
 | |
|   RefPtr<TextureClientHolder> textureHolder;
 | |
| 
 | |
|   {
 | |
|     MutexAutoLock lock(mLock);
 | |
|     if (mIsDestroyed) {
 | |
|       return nullptr;
 | |
|     }
 | |
|     if (!mPooledClients.empty()) {
 | |
|       textureHolder = mPooledClients.top();
 | |
|       mPooledClients.pop();
 | |
|       // If the texture's allocator is not open or a pooled TextureClient is
 | |
|       // not compatible, release it.
 | |
|       if (!textureHolder->GetTextureClient()->GetAllocator()->IPCOpen() ||
 | |
|           !aHelper.IsCompatible(textureHolder->GetTextureClient())) {
 | |
|         // Release TextureClient.
 | |
|         RefPtr<Runnable> task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
 | |
|         textureHolder->ClearTextureClient();
 | |
|         textureHolder = nullptr;
 | |
|         mSurfaceAllocator->GetTextureForwarder()->GetMessageLoop()->PostTask(task.forget());
 | |
|       } else {
 | |
|         textureHolder->GetTextureClient()->RecycleTexture(aHelper.mTextureFlags);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!textureHolder) {
 | |
|     // Allocate new TextureClient
 | |
|     RefPtr<TextureClient> texture = aHelper.Allocate(mSurfaceAllocator);
 | |
|     if (!texture) {
 | |
|       return nullptr;
 | |
|     }
 | |
|     textureHolder = new TextureClientHolder(texture);
 | |
|   }
 | |
| 
 | |
|   {
 | |
|     MutexAutoLock lock(mLock);
 | |
|     MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end());
 | |
|     // Register TextureClient
 | |
|     mInUseClients[textureHolder->GetTextureClient()] = textureHolder;
 | |
|   }
 | |
|   RefPtr<TextureClient> client(textureHolder->GetTextureClient());
 | |
| 
 | |
|   // Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its
 | |
|   // ref count drops to 1.
 | |
|   client->SetRecycleAllocator(this);
 | |
|   return client.forget();
 | |
| }
 | |
| 
 | |
| already_AddRefed<TextureClient>
 | |
| TextureClientRecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
 | |
|                                         gfx::IntSize aSize,
 | |
|                                         BackendSelector aSelector,
 | |
|                                         TextureFlags aTextureFlags,
 | |
|                                         TextureAllocationFlags aAllocFlags)
 | |
| {
 | |
|   return TextureClient::CreateForDrawing(mSurfaceAllocator, aFormat, aSize,
 | |
|                                          aSelector, aTextureFlags, aAllocFlags);
 | |
| }
 | |
| 
 | |
| void
 | |
| TextureClientRecycleAllocator::ShrinkToMinimumSize()
 | |
| {
 | |
|   MutexAutoLock lock(mLock);
 | |
|   while (!mPooledClients.empty()) {
 | |
|     mPooledClients.pop();
 | |
|   }
 | |
|   // We can not clear using TextureClients safely.
 | |
|   // Just clear WillRecycle here.
 | |
|   std::map<TextureClient*, RefPtr<TextureClientHolder> >::iterator it;
 | |
|   for (it = mInUseClients.begin(); it != mInUseClients.end(); it++) {
 | |
|     RefPtr<TextureClientHolder> holder = it->second;
 | |
|     holder->ClearWillRecycle();
 | |
|   }
 | |
| }
 | |
| 
 | |
| void
 | |
| TextureClientRecycleAllocator::Destroy()
 | |
| {
 | |
|   MutexAutoLock lock(mLock);
 | |
|   while (!mPooledClients.empty()) {
 | |
|     mPooledClients.pop();
 | |
|   }
 | |
|   mIsDestroyed = true;
 | |
| }
 | |
| 
 | |
| void
 | |
| TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
 | |
| {
 | |
|   // Clearing the recycle allocator drops a reference, so make sure we stay alive
 | |
|   // for the duration of this function.
 | |
|   RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
 | |
|   aClient->SetRecycleAllocator(nullptr);
 | |
| 
 | |
|   RefPtr<TextureClientHolder> textureHolder;
 | |
|   {
 | |
|     MutexAutoLock lock(mLock);
 | |
|     if (mInUseClients.find(aClient) != mInUseClients.end()) {
 | |
|       textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock.
 | |
|       if (textureHolder->WillRecycle() &&
 | |
|           !mIsDestroyed && mPooledClients.size() < mMaxPooledSize) {
 | |
|         mPooledClients.push(textureHolder);
 | |
|       }
 | |
|       mInUseClients.erase(aClient);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| } // namespace layers
 | |
| } // namespace mozilla
 |