forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			156 lines
		
	
	
	
		
			5.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			156 lines
		
	
	
	
		
			5.7 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 "SharedRGBImage.h"
 | |
| #include "ImageTypes.h"         // for ImageFormat::SHARED_RGB, etc
 | |
| #include "mozilla/ipc/Shmem.h"  // for Shmem
 | |
| #include "gfx2DGlue.h"          // for ImageFormatToSurfaceFormat, etc
 | |
| #include "gfxPlatform.h"        // for gfxPlatform, gfxImageFormat
 | |
| #include "mozilla/gfx/Point.h"  // for IntSIze
 | |
| #include "mozilla/layers/BufferTexture.h"
 | |
| #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator, etc
 | |
| #include "mozilla/layers/ImageClient.h"        // for ImageClient
 | |
| #include "mozilla/layers/LayersSurfaces.h"     // for SurfaceDescriptor, etc
 | |
| #include "mozilla/layers/TextureClient.h"      // for BufferTextureClient, etc
 | |
| #include "mozilla/layers/TextureClientRecycleAllocator.h"  // for ITextureClientAllocationHelper
 | |
| #include "mozilla/layers/ImageBridgeChild.h"  // for ImageBridgeChild
 | |
| #include "mozilla/mozalloc.h"                 // for operator delete, etc
 | |
| #include "nsDebug.h"                          // for NS_WARNING, NS_ASSERTION
 | |
| #include "nsISupportsImpl.h"                  // for Image::AddRef, etc
 | |
| #include "nsProxyRelease.h"
 | |
| #include "nsRect.h"  // for mozilla::gfx::IntRect
 | |
| 
 | |
| // Just big enough for a 1080p RGBA32 frame
 | |
| #define MAX_FRAME_SIZE (16 * 1024 * 1024)
 | |
| 
 | |
| namespace mozilla {
 | |
| namespace layers {
 | |
| 
 | |
| class TextureClientForRawBufferAccessAllocationHelper
 | |
|     : public ITextureClientAllocationHelper {
 | |
|  public:
 | |
|   TextureClientForRawBufferAccessAllocationHelper(gfx::SurfaceFormat aFormat,
 | |
|                                                   gfx::IntSize aSize,
 | |
|                                                   TextureFlags aTextureFlags)
 | |
|       : ITextureClientAllocationHelper(aFormat, aSize, BackendSelector::Content,
 | |
|                                        aTextureFlags, ALLOC_DEFAULT) {}
 | |
| 
 | |
|   bool IsCompatible(TextureClient* aTextureClient) override {
 | |
|     bool ret = aTextureClient->GetFormat() == mFormat &&
 | |
|                aTextureClient->GetSize() == mSize;
 | |
|     return ret;
 | |
|   }
 | |
| 
 | |
|   already_AddRefed<TextureClient> Allocate(
 | |
|       KnowsCompositor* aAllocator) override {
 | |
|     return TextureClient::CreateForRawBufferAccess(
 | |
|         aAllocator, mFormat, mSize, gfx::BackendType::NONE, mTextureFlags);
 | |
|   }
 | |
| };
 | |
| 
 | |
| SharedRGBImage::SharedRGBImage(ImageClient* aCompositable)
 | |
|     : Image(nullptr, ImageFormat::SHARED_RGB), mCompositable(aCompositable) {
 | |
|   MOZ_COUNT_CTOR(SharedRGBImage);
 | |
| }
 | |
| 
 | |
| SharedRGBImage::SharedRGBImage(TextureClientRecycleAllocator* aRecycleAllocator)
 | |
|     : Image(nullptr, ImageFormat::SHARED_RGB),
 | |
|       mRecycleAllocator(aRecycleAllocator) {
 | |
|   MOZ_COUNT_CTOR(SharedRGBImage);
 | |
| }
 | |
| 
 | |
| SharedRGBImage::~SharedRGBImage() {
 | |
|   MOZ_COUNT_DTOR(SharedRGBImage);
 | |
|   NS_ReleaseOnMainThread("SharedRGBImage::mSourceSurface",
 | |
|                          mSourceSurface.forget());
 | |
| }
 | |
| 
 | |
| TextureClientRecycleAllocator* SharedRGBImage::RecycleAllocator() {
 | |
|   static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
 | |
| 
 | |
|   if (!mRecycleAllocator && mCompositable) {
 | |
|     if (!mCompositable->HasTextureClientRecycler()) {
 | |
|       // Initialize TextureClientRecycler
 | |
|       mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(
 | |
|           MAX_POOLED_VIDEO_COUNT);
 | |
|     }
 | |
|     mRecycleAllocator = mCompositable->GetTextureClientRecycler();
 | |
|   }
 | |
|   return mRecycleAllocator;
 | |
| }
 | |
| 
 | |
| bool SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat) {
 | |
|   mSize = aSize;
 | |
| 
 | |
|   TextureFlags flags =
 | |
|       mCompositable ? mCompositable->GetTextureFlags() : TextureFlags::DEFAULT;
 | |
|   {
 | |
|     TextureClientForRawBufferAccessAllocationHelper helper(aFormat, aSize,
 | |
|                                                            flags);
 | |
|     mTextureClient = RecycleAllocator()->CreateOrRecycle(helper);
 | |
|   }
 | |
| 
 | |
|   return !!mTextureClient;
 | |
| }
 | |
| 
 | |
| gfx::IntSize SharedRGBImage::GetSize() const { return mSize; }
 | |
| 
 | |
| TextureClient* SharedRGBImage::GetTextureClient(
 | |
|     KnowsCompositor* aKnowsCompositor) {
 | |
|   return mTextureClient.get();
 | |
| }
 | |
| 
 | |
| static void ReleaseTextureClient(void* aData) {
 | |
|   RELEASE_MANUALLY(static_cast<TextureClient*>(aData));
 | |
| }
 | |
| 
 | |
| static gfx::UserDataKey sTextureClientKey;
 | |
| 
 | |
| already_AddRefed<gfx::SourceSurface> SharedRGBImage::GetAsSourceSurface() {
 | |
|   NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
 | |
| 
 | |
|   if (mSourceSurface) {
 | |
|     RefPtr<gfx::SourceSurface> surface(mSourceSurface);
 | |
|     return surface.forget();
 | |
|   }
 | |
| 
 | |
|   RefPtr<gfx::SourceSurface> surface;
 | |
|   {
 | |
|     // We are 'borrowing' the DrawTarget and retaining a permanent reference to
 | |
|     // the underlying data (via the surface). It is in this instance since we
 | |
|     // know that the TextureClient is always wrapping a BufferTextureData and
 | |
|     // therefore it won't go away underneath us.
 | |
|     BufferTextureData* decoded_buffer =
 | |
|         mTextureClient->GetInternalData()->AsBufferTextureData();
 | |
|     RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget();
 | |
| 
 | |
|     if (!drawTarget) {
 | |
|       return nullptr;
 | |
|     }
 | |
| 
 | |
|     surface = drawTarget->Snapshot();
 | |
|     if (!surface) {
 | |
|       return nullptr;
 | |
|     }
 | |
| 
 | |
|     // The surface may outlive the owning TextureClient. So, we need to ensure
 | |
|     // that the surface keeps the TextureClient alive via a reference held in
 | |
|     // user data. The TextureClient's DrawTarget only has a weak reference to
 | |
|     // the surface, so we won't create any cycles by just referencing the
 | |
|     // TextureClient.
 | |
|     if (!surface->GetUserData(&sTextureClientKey)) {
 | |
|       surface->AddUserData(&sTextureClientKey, mTextureClient,
 | |
|                            ReleaseTextureClient);
 | |
|       ADDREF_MANUALLY(mTextureClient);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   mSourceSurface = surface;
 | |
|   return surface.forget();
 | |
| }
 | |
| 
 | |
| }  // namespace layers
 | |
| }  // namespace mozilla
 | 
