LCOV - code coverage report
Current view: top level - gfx/layers/composite - TextureHost.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 229 557 41.1 %
Date: 2017-07-14 16:53:18 Functions: 45 76 59.2 %
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 "TextureHost.h"
       7             : 
       8             : #include "CompositableHost.h"           // for CompositableHost
       9             : #include "LayerScope.h"
      10             : #include "LayersLogging.h"              // for AppendToString
      11             : #include "mozilla/gfx/2D.h"             // for DataSourceSurface, Factory
      12             : #include "mozilla/gfx/gfxVars.h"
      13             : #include "mozilla/ipc/Shmem.h"          // for Shmem
      14             : #include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
      15             : #include "mozilla/layers/CompositorBridgeParent.h"
      16             : #include "mozilla/layers/Compositor.h"  // for Compositor
      17             : #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
      18             : #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
      19             : #include "mozilla/layers/TextureHostBasic.h"
      20             : #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
      21             : #include "mozilla/layers/ImageDataSerializer.h"
      22             : #include "mozilla/layers/TextureClient.h"
      23             : #include "mozilla/layers/GPUVideoTextureHost.h"
      24             : #include "mozilla/layers/WebRenderTextureHost.h"
      25             : #include "mozilla/webrender/RenderBufferTextureHost.h"
      26             : #include "mozilla/webrender/RenderThread.h"
      27             : #include "mozilla/webrender/WebRenderAPI.h"
      28             : #include "nsAString.h"
      29             : #include "mozilla/RefPtr.h"                   // for nsRefPtr
      30             : #include "nsPrintfCString.h"            // for nsPrintfCString
      31             : #include "mozilla/layers/PTextureParent.h"
      32             : #include "mozilla/Unused.h"
      33             : #include <limits>
      34             : #include "../opengl/CompositorOGL.h"
      35             : #include "gfxPrefs.h"
      36             : #include "gfxUtils.h"
      37             : #include "IPDLActor.h"
      38             : 
      39             : #ifdef MOZ_ENABLE_D3D10_LAYER
      40             : #include "../d3d11/CompositorD3D11.h"
      41             : #endif
      42             : 
      43             : #ifdef MOZ_X11
      44             : #include "mozilla/layers/X11TextureHost.h"
      45             : #endif
      46             : 
      47             : #ifdef XP_MACOSX
      48             : #include "../opengl/MacIOSurfaceTextureHostOGL.h"
      49             : #endif
      50             : 
      51             : #ifdef XP_WIN
      52             : #include "mozilla/layers/TextureDIB.h"
      53             : #endif
      54             : 
      55             : #if 0
      56             : #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
      57             : #else
      58             : #define RECYCLE_LOG(...) do { } while (0)
      59             : #endif
      60             : 
      61             : namespace mozilla {
      62             : namespace layers {
      63             : 
      64             : /**
      65             :  * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
      66             :  * It is an IPDL actor just like LayerParent, CompositableParent, etc.
      67             :  */
      68             : class TextureParent : public ParentActor<PTextureParent>
      69             : {
      70             : public:
      71             :   explicit TextureParent(HostIPCAllocator* aAllocator, uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId);
      72             : 
      73             :   ~TextureParent();
      74             : 
      75             :   bool Init(const SurfaceDescriptor& aSharedData,
      76             :             const LayersBackend& aLayersBackend,
      77             :             const TextureFlags& aFlags);
      78             : 
      79             :   void NotifyNotUsed(uint64_t aTransactionId);
      80             : 
      81             :   virtual mozilla::ipc::IPCResult RecvRecycleTexture(const TextureFlags& aTextureFlags) override;
      82             : 
      83             :   TextureHost* GetTextureHost() { return mTextureHost; }
      84             : 
      85             :   virtual void Destroy() override;
      86             : 
      87             :   uint64_t GetSerial() const { return mSerial; }
      88             : 
      89             :   HostIPCAllocator* mSurfaceAllocator;
      90             :   RefPtr<TextureHost> mTextureHost;
      91             :   // mSerial is unique in TextureClient's process.
      92             :   const uint64_t mSerial;
      93             :   wr::MaybeExternalImageId mExternalImageId;
      94             : };
      95             : 
      96             : static bool
      97           9 : WrapWithWebRenderTextureHost(ISurfaceAllocator* aDeallocator,
      98             :                              LayersBackend aBackend,
      99             :                              TextureFlags aFlags)
     100             : {
     101          36 :   if (!gfxVars::UseWebRender() ||
     102           9 :       (aFlags & TextureFlags::SNAPSHOT) ||
     103          27 :       (aBackend != LayersBackend::LAYERS_WR) ||
     104           0 :       (!aDeallocator->UsesImageBridge() && !aDeallocator->AsCompositorBridgeParentBase())) {
     105           9 :     return false;
     106             :   }
     107           0 :   return true;
     108             : }
     109             : 
     110             : ////////////////////////////////////////////////////////////////////////////////
     111             : PTextureParent*
     112           9 : TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
     113             :                              const SurfaceDescriptor& aSharedData,
     114             :                              LayersBackend aLayersBackend,
     115             :                              TextureFlags aFlags,
     116             :                              uint64_t aSerial,
     117             :                              const wr::MaybeExternalImageId& aExternalImageId)
     118             : {
     119          27 :   if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
     120          17 :       aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
     121           8 :       !aAllocator->IsSameProcess())
     122             :   {
     123           0 :     NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
     124           0 :     return nullptr;
     125             :   }
     126           9 :   TextureParent* actor = new TextureParent(aAllocator, aSerial, aExternalImageId);
     127           9 :   if (!actor->Init(aSharedData, aLayersBackend, aFlags)) {
     128           0 :     delete actor;
     129           0 :     return nullptr;
     130             :   }
     131           9 :   return actor;
     132             : }
     133             : 
     134             : // static
     135             : bool
     136           6 : TextureHost::DestroyIPDLActor(PTextureParent* actor)
     137             : {
     138           6 :   delete actor;
     139           6 :   return true;
     140             : }
     141             : 
     142             : // static
     143             : bool
     144           0 : TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
     145             : {
     146           0 :   return PTextureParent::Send__delete__(actor);
     147             : }
     148             : 
     149             : // static
     150             : TextureHost*
     151          66 : TextureHost::AsTextureHost(PTextureParent* actor)
     152             : {
     153          66 :   if (!actor) {
     154           0 :     return nullptr;
     155             :   }
     156          66 :   return static_cast<TextureParent*>(actor)->mTextureHost;
     157             : }
     158             : 
     159             : // static
     160             : uint64_t
     161           0 : TextureHost::GetTextureSerial(PTextureParent* actor)
     162             : {
     163           0 :   if (!actor) {
     164           0 :     return UINT64_MAX;
     165             :   }
     166           0 :   return static_cast<TextureParent*>(actor)->mSerial;
     167             : }
     168             : 
     169             : PTextureParent*
     170           0 : TextureHost::GetIPDLActor()
     171             : {
     172           0 :   return mActor;
     173             : }
     174             : 
     175             : void
     176          33 : TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId)
     177             : {
     178          33 :   MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
     179          33 :   mFwdTransactionId = aTransactionId;
     180          33 : }
     181             : 
     182             : // implemented in TextureHostOGL.cpp
     183             : already_AddRefed<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
     184             :                                                    ISurfaceAllocator* aDeallocator,
     185             :                                                    LayersBackend aBackend,
     186             :                                                    TextureFlags aFlags);
     187             : 
     188             : // implemented in TextureHostBasic.cpp
     189             : already_AddRefed<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
     190             :                                                      ISurfaceAllocator* aDeallocator,
     191             :                                                      LayersBackend aBackend,
     192             :                                                      TextureFlags aFlags);
     193             : 
     194             : // implemented in TextureD3D11.cpp
     195             : already_AddRefed<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
     196             :                                                      ISurfaceAllocator* aDeallocator,
     197             :                                                      LayersBackend aBackend,
     198             :                                                      TextureFlags aFlags);
     199             : 
     200             : already_AddRefed<TextureHost>
     201           9 : TextureHost::Create(const SurfaceDescriptor& aDesc,
     202             :                     ISurfaceAllocator* aDeallocator,
     203             :                     LayersBackend aBackend,
     204             :                     TextureFlags aFlags,
     205             :                     wr::MaybeExternalImageId& aExternalImageId)
     206             : {
     207          18 :   RefPtr<TextureHost> result;
     208             : 
     209           9 :   switch (aDesc.type()) {
     210             :     case SurfaceDescriptor::TSurfaceDescriptorBuffer:
     211             :     case SurfaceDescriptor::TSurfaceDescriptorDIB:
     212             :     case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
     213             :     case SurfaceDescriptor::TSurfaceDescriptorGPUVideo:
     214           9 :       result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
     215           9 :       break;
     216             : 
     217             :     case SurfaceDescriptor::TEGLImageDescriptor:
     218             :     case SurfaceDescriptor::TSurfaceTextureDescriptor:
     219             :     case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
     220           0 :       result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
     221           0 :       break;
     222             : 
     223             :     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
     224           0 :       if (aBackend == LayersBackend::LAYERS_OPENGL ||
     225             :           aBackend == LayersBackend::LAYERS_WR) {
     226           0 :         result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
     227           0 :         break;
     228             :       } else {
     229           0 :         result = CreateTextureHostBasic(aDesc, aDeallocator, aBackend, aFlags);
     230           0 :         break;
     231             :       }
     232             : 
     233             : #ifdef MOZ_X11
     234             :     case SurfaceDescriptor::TSurfaceDescriptorX11: {
     235           0 :       const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11();
     236           0 :       result = MakeAndAddRef<X11TextureHost>(aFlags, desc);
     237           0 :       break;
     238             :     }
     239             : #endif
     240             : 
     241             : #ifdef XP_WIN
     242             :     case SurfaceDescriptor::TSurfaceDescriptorD3D10:
     243             :     case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
     244             :       result = CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
     245             :       break;
     246             : #endif
     247             :     default:
     248           0 :       MOZ_CRASH("GFX: Unsupported Surface type host");
     249             :   }
     250             : 
     251           9 :   if (WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
     252           0 :     MOZ_ASSERT(aExternalImageId.isSome());
     253           0 :     result = new WebRenderTextureHost(aDesc, aFlags, result, aExternalImageId.ref());
     254             :   }
     255             : 
     256          18 :   return result.forget();
     257             : }
     258             : 
     259             : already_AddRefed<TextureHost>
     260           9 : CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
     261             :                                     ISurfaceAllocator* aDeallocator,
     262             :                                     LayersBackend aBackend,
     263             :                                     TextureFlags aFlags)
     264             : {
     265          18 :   RefPtr<TextureHost> result;
     266           9 :   switch (aDesc.type()) {
     267             :     case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
     268           9 :       const SurfaceDescriptorBuffer& bufferDesc = aDesc.get_SurfaceDescriptorBuffer();
     269           9 :       const MemoryOrShmem& data = bufferDesc.data();
     270           9 :       switch (data.type()) {
     271             :         case MemoryOrShmem::TShmem: {
     272             :           result = new ShmemTextureHost(data.get_Shmem(),
     273             :                                         bufferDesc.desc(),
     274             :                                         aDeallocator,
     275           2 :                                         aFlags);
     276           1 :           break;
     277             :         }
     278             :         case MemoryOrShmem::Tuintptr_t: {
     279           8 :           result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
     280             :                                          bufferDesc.desc(),
     281          16 :                                          aFlags);
     282           8 :           break;
     283             :         }
     284             :         default:
     285           0 :           gfxCriticalError() << "Failed texture host for backend " << (int)data.type();
     286           0 :           MOZ_CRASH("GFX: No texture host for backend");
     287             :       }
     288           9 :       break;
     289             :     }
     290             :     case SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
     291           0 :       result = new GPUVideoTextureHost(aFlags, aDesc.get_SurfaceDescriptorGPUVideo());
     292           0 :       break;
     293             :     }
     294             : #ifdef XP_WIN
     295             :     case SurfaceDescriptor::TSurfaceDescriptorDIB: {
     296             :       result = new DIBTextureHost(aFlags, aDesc);
     297             :       break;
     298             :     }
     299             :     case SurfaceDescriptor::TSurfaceDescriptorFileMapping: {
     300             :       result = new TextureHostFileMapping(aFlags, aDesc);
     301             :       break;
     302             :     }
     303             : #endif
     304             :     default: {
     305           0 :       NS_WARNING("No backend independent TextureHost for this descriptor type");
     306             :     }
     307             :   }
     308          18 :   return result.forget();
     309             : }
     310             : 
     311           9 : TextureHost::TextureHost(TextureFlags aFlags)
     312             :     : AtomicRefCountedWithFinalize("TextureHost")
     313             :     , mActor(nullptr)
     314             :     , mFlags(aFlags)
     315             :     , mCompositableCount(0)
     316           9 :     , mFwdTransactionId(0)
     317             : {
     318           9 : }
     319             : 
     320          12 : TextureHost::~TextureHost()
     321             : {
     322             :   // If we still have a ReadLock, unlock it. At this point we don't care about
     323             :   // the texture client being written into on the other side since it should be
     324             :   // destroyed by now. But we will hit assertions if we don't ReadUnlock before
     325             :   // destroying the lock itself.
     326           6 :   ReadUnlock();
     327           6 : }
     328             : 
     329           6 : void TextureHost::Finalize()
     330             : {
     331           6 :   if (!(GetFlags() & TextureFlags::DEALLOCATE_CLIENT)) {
     332           6 :     DeallocateSharedData();
     333           6 :     DeallocateDeviceData();
     334             :   }
     335           6 : }
     336             : 
     337             : void
     338           0 : TextureHost::UnbindTextureSource()
     339             : {
     340           0 :   if (mReadLock) {
     341             :     // This TextureHost is not used anymore. Since most compositor backends are
     342             :     // working asynchronously under the hood a compositor could still be using
     343             :     // this texture, so it is generally best to wait until the end of the next
     344             :     // composition before calling ReadUnlock. We ask the compositor to take care
     345             :     // of that for us.
     346           0 :     if (mProvider) {
     347           0 :       mProvider->UnlockAfterComposition(this);
     348             :     } else {
     349             :       // GetCompositor returned null which means no compositor can be using this
     350             :       // texture. We can ReadUnlock right away.
     351           0 :       ReadUnlock();
     352             :     }
     353             :   }
     354           0 : }
     355             : 
     356             : void
     357           0 : TextureHost::RecycleTexture(TextureFlags aFlags)
     358             : {
     359           0 :   MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
     360           0 :   MOZ_ASSERT(aFlags & TextureFlags::RECYCLE);
     361           0 :   mFlags = aFlags;
     362           0 : }
     363             : 
     364             : void
     365          31 : TextureHost::NotifyNotUsed()
     366             : {
     367          31 :   if (!mActor) {
     368           2 :     return;
     369             :   }
     370             : 
     371             :   // Do not need to call NotifyNotUsed() if TextureHost does not have
     372             :   // TextureFlags::RECYCLE flag.
     373          29 :   if (!(GetFlags() & TextureFlags::RECYCLE)) {
     374          29 :     return;
     375             :   }
     376             : 
     377             :   // The following cases do not need to defer NotifyNotUsed until next Composite.
     378             :   // - TextureHost does not have Compositor.
     379             :   // - Compositor is BasicCompositor.
     380             :   // - TextureHost has intermediate buffer.
     381             :   //   end of buffer usage.
     382           0 :   if (!mProvider ||
     383           0 :       HasIntermediateBuffer() ||
     384           0 :       !mProvider->NotifyNotUsedAfterComposition(this))
     385             :   {
     386           0 :     static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
     387           0 :     return;
     388             :   }
     389             : }
     390             : 
     391             : void
     392           0 : TextureHost::CallNotifyNotUsed()
     393             : {
     394           0 :   if (!mActor) {
     395           0 :     return;
     396             :   }
     397           0 :   static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
     398             : }
     399             : 
     400             : void
     401           0 : TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
     402             : {
     403           0 :   aStream << aPrefix;
     404           0 :   aStream << nsPrintfCString("%s (0x%p)", Name(), this).get();
     405             :   // Note: the TextureHost needs to be locked before it is safe to call
     406             :   //       GetSize() and GetFormat() on it.
     407           0 :   if (Lock()) {
     408           0 :     AppendToString(aStream, GetSize(), " [size=", "]");
     409           0 :     AppendToString(aStream, GetFormat(), " [format=", "]");
     410           0 :     Unlock();
     411             :   }
     412           0 :   AppendToString(aStream, mFlags, " [flags=", "]");
     413             : #ifdef MOZ_DUMP_PAINTING
     414           0 :   if (gfxPrefs::LayersDumpTexture() ||
     415           0 :       profiler_feature_active(ProfilerFeature::LayersDump)) {
     416           0 :     nsAutoCString pfx(aPrefix);
     417           0 :     pfx += "  ";
     418             : 
     419           0 :     aStream << "\n" << pfx.get() << "Surface: ";
     420           0 :     RefPtr<gfx::DataSourceSurface> dSurf = GetAsSurface();
     421           0 :     if (dSurf) {
     422           0 :       aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
     423             :     }
     424             :   }
     425             : #endif
     426           0 : }
     427             : 
     428             : void
     429          33 : TextureHost::Updated(const nsIntRegion* aRegion)
     430             : {
     431          33 :     LayerScope::ContentChanged(this);
     432          33 :     UpdatedInternal(aRegion);
     433          33 : }
     434             : 
     435          36 : TextureSource::TextureSource()
     436          36 : : mCompositableCount(0)
     437             : {
     438          36 : }
     439             : 
     440          33 : TextureSource::~TextureSource()
     441             : {
     442          33 : }
     443             : 
     444             : const char*
     445           0 : TextureSource::Name() const
     446             : {
     447           0 :   MOZ_CRASH("GFX: TextureSource without class name");
     448             :   return "TextureSource";
     449             : }
     450             :   
     451           9 : BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
     452           9 :                                      TextureFlags aFlags)
     453             : : TextureHost(aFlags)
     454             : , mUpdateSerial(1)
     455             : , mLocked(false)
     456           9 : , mNeedsFullUpdate(false)
     457             : {
     458           9 :   mDescriptor = aDesc;
     459           9 :   switch (mDescriptor.type()) {
     460             :     case BufferDescriptor::TYCbCrDescriptor: {
     461           0 :       const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
     462           0 :       mSize = ycbcr.ySize();
     463           0 :       mFormat = gfx::SurfaceFormat::YUV;
     464           0 :       mHasIntermediateBuffer = ycbcr.hasIntermediateBuffer();
     465           0 :       break;
     466             :     }
     467             :     case BufferDescriptor::TRGBDescriptor: {
     468           9 :       const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
     469           9 :       mSize = rgb.size();
     470           9 :       mFormat = rgb.format();
     471           9 :       mHasIntermediateBuffer = rgb.hasIntermediateBuffer();
     472           9 :       break;
     473             :     }
     474             :     default:
     475           0 :       gfxCriticalError() << "Bad buffer host descriptor " << (int)mDescriptor.type();
     476           0 :       MOZ_CRASH("GFX: Bad descriptor");
     477             :   }
     478           9 :   if (aFlags & TextureFlags::COMPONENT_ALPHA) {
     479             :     // One texture of a component alpha texture pair will start out all white.
     480             :     // This hack allows us to easily make sure that white will be uploaded.
     481             :     // See bug 1138934
     482           0 :     mNeedsFullUpdate = true;
     483             :   }
     484           9 : }
     485             : 
     486           6 : BufferTextureHost::~BufferTextureHost()
     487           6 : {}
     488             : 
     489             : void
     490          33 : BufferTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
     491             : {
     492          33 :   ++mUpdateSerial;
     493             :   // If the last frame wasn't uploaded yet, and we -don't- have a partial update,
     494             :   // we still need to update the full surface.
     495          33 :   if (aRegion && !mNeedsFullUpdate) {
     496           0 :     mMaybeUpdatedRegion.OrWith(*aRegion);
     497             :   } else {
     498          33 :     mNeedsFullUpdate = true;
     499             :   }
     500          33 :   if (GetFlags() & TextureFlags::IMMEDIATE_UPLOAD) {
     501          66 :     DebugOnly<bool> result = MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
     502          33 :     NS_WARNING_ASSERTION(result, "Failed to upload a texture");
     503             :   }
     504          33 : }
     505             : 
     506             : void
     507          33 : BufferTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
     508             : {
     509          33 :   if (mProvider == aProvider) {
     510          24 :     return;
     511             :   }
     512           9 :   if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
     513           0 :     mFirstSource->SetOwner(nullptr);
     514             :   }
     515           9 :   if (mFirstSource) {
     516           0 :     mFirstSource = nullptr;
     517           0 :     mNeedsFullUpdate = true;
     518             :   }
     519           9 :   mProvider = aProvider;
     520             : }
     521             : 
     522             : void
     523          12 : BufferTextureHost::DeallocateDeviceData()
     524             : {
     525          12 :   if (mFirstSource && mFirstSource->NumCompositableRefs() > 0) {
     526           6 :     return;
     527             :   }
     528             : 
     529          12 :   if (!mFirstSource || !mFirstSource->IsOwnedBy(this)) {
     530           6 :     mFirstSource = nullptr;
     531           6 :     return;
     532             :   }
     533             : 
     534           6 :   mFirstSource->SetOwner(nullptr);
     535             : 
     536          12 :   RefPtr<TextureSource> it = mFirstSource;
     537          18 :   while (it) {
     538           6 :     it->DeallocateDeviceData();
     539           6 :     it = it->GetNextSibling();
     540             :   }
     541             : }
     542             : 
     543             : bool
     544          56 : BufferTextureHost::Lock()
     545             : {
     546          56 :   MOZ_ASSERT(!mLocked);
     547          56 :   if (!UploadIfNeeded()) {
     548           0 :       return false;
     549             :   }
     550          56 :   mLocked = !!mFirstSource;
     551          56 :   return mLocked;
     552             : }
     553             : 
     554             : void
     555          56 : BufferTextureHost::Unlock()
     556             : {
     557          56 :   MOZ_ASSERT(mLocked);
     558          56 :   mLocked = false;
     559          56 : }
     560             : 
     561             : void
     562           0 : BufferTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
     563             : {
     564             :   RefPtr<wr::RenderTextureHost> texture =
     565           0 :       new wr::RenderBufferTextureHost(GetBuffer(), GetBufferDescriptor());
     566             : 
     567           0 :   wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
     568           0 : }
     569             : 
     570             : void
     571           0 : BufferTextureHost::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
     572             :                                   const std::function<wr::ImageKey()>& aImageKeyAllocator)
     573             : {
     574           0 :   MOZ_ASSERT(aImageKeys.IsEmpty());
     575             : 
     576           0 :   if (GetFormat() != gfx::SurfaceFormat::YUV) {
     577             :     // 1 image key
     578           0 :     aImageKeys.AppendElement(aImageKeyAllocator());
     579           0 :     MOZ_ASSERT(aImageKeys.Length() == 1);
     580             :   } else {
     581             :     // 3 image key
     582           0 :     aImageKeys.AppendElement(aImageKeyAllocator());
     583           0 :     aImageKeys.AppendElement(aImageKeyAllocator());
     584           0 :     aImageKeys.AppendElement(aImageKeyAllocator());
     585           0 :     MOZ_ASSERT(aImageKeys.Length() == 3);
     586             :   }
     587           0 : }
     588             : 
     589             : void
     590           0 : BufferTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
     591             :                               Range<const wr::ImageKey>& aImageKeys,
     592             :                               const wr::ExternalImageId& aExtID)
     593             : {
     594           0 :   if (GetFormat() != gfx::SurfaceFormat::YUV) {
     595           0 :     MOZ_ASSERT(aImageKeys.length() == 1);
     596             : 
     597           0 :     wr::ImageDescriptor descriptor(GetSize(),
     598           0 :                                    ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width),
     599           0 :                                    GetFormat());
     600           0 :     aAPI->AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID);
     601             :   } else {
     602           0 :     MOZ_ASSERT(aImageKeys.length() == 3);
     603             : 
     604           0 :     const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     605           0 :     wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8);
     606           0 :     wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8);
     607           0 :     aAPI->AddExternalImage(aImageKeys[0],
     608             :                            yDescriptor,
     609             :                            aExtID,
     610             :                            WrExternalImageBufferType::ExternalBuffer,
     611           0 :                            0);
     612           0 :     aAPI->AddExternalImage(aImageKeys[1],
     613             :                            cbcrDescriptor,
     614             :                            aExtID,
     615             :                            WrExternalImageBufferType::ExternalBuffer,
     616           0 :                            1);
     617           0 :     aAPI->AddExternalImage(aImageKeys[2],
     618             :                            cbcrDescriptor,
     619             :                            aExtID,
     620             :                            WrExternalImageBufferType::ExternalBuffer,
     621           0 :                            2);
     622             :   }
     623           0 : }
     624             : 
     625             : void
     626           0 : BufferTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder,
     627             :                                      const WrRect& aBounds,
     628             :                                      const WrRect& aClip,
     629             :                                      wr::ImageRendering aFilter,
     630             :                                      Range<const wr::ImageKey>& aImageKeys)
     631             : {
     632           0 :   if (GetFormat() != gfx::SurfaceFormat::YUV) {
     633           0 :     MOZ_ASSERT(aImageKeys.length() == 1);
     634           0 :     aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
     635             :   } else {
     636           0 :     MOZ_ASSERT(aImageKeys.length() == 3);
     637             :     aBuilder.PushYCbCrPlanarImage(aBounds,
     638             :                                   aClip,
     639           0 :                                   aImageKeys[0],
     640           0 :                                   aImageKeys[1],
     641           0 :                                   aImageKeys[2],
     642             :                                   WrYuvColorSpace::Rec601,
     643           0 :                                   aFilter);
     644             :   }
     645           0 : }
     646             : 
     647             : void
     648           0 : TextureHost::DeserializeReadLock(const ReadLockDescriptor& aDesc,
     649             :                                  ISurfaceAllocator* aAllocator)
     650             : {
     651           0 :   RefPtr<TextureReadLock> lock = TextureReadLock::Deserialize(aDesc, aAllocator);
     652           0 :   if (!lock) {
     653           0 :     return;
     654             :   }
     655             : 
     656             :   // If mReadLock is not null it means we haven't unlocked it yet and the content
     657             :   // side should not have been able to write into this texture and send a new lock!
     658           0 :   MOZ_ASSERT(!mReadLock);
     659           0 :   mReadLock = lock.forget();
     660             : }
     661             : 
     662             : void
     663          33 : TextureHost::SetReadLock(TextureReadLock* aReadLock)
     664             : {
     665          33 :   if (!aReadLock) {
     666           0 :     return;
     667             :   }
     668             :   // If mReadLock is not null it means we haven't unlocked it yet and the content
     669             :   // side should not have been able to write into this texture and send a new lock!
     670          33 :   MOZ_ASSERT(!mReadLock);
     671          33 :   mReadLock = aReadLock;
     672             : }
     673             : 
     674             : void
     675          43 : TextureHost::ReadUnlock()
     676             : {
     677          43 :   if (mReadLock) {
     678          31 :     mReadLock->ReadUnlock();
     679          31 :     mReadLock = nullptr;
     680             :   }
     681          43 : }
     682             : 
     683             : bool
     684          66 : BufferTextureHost::EnsureWrappingTextureSource()
     685             : {
     686          66 :   MOZ_ASSERT(!mHasIntermediateBuffer);
     687             : 
     688          66 :   if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
     689          57 :     return true;
     690             :   }
     691             :   // We don't own it, apparently.
     692           9 :   if (mFirstSource) {
     693           0 :     mNeedsFullUpdate = true;
     694           0 :     mFirstSource = nullptr;
     695             :   }
     696             : 
     697           9 :   if (!mProvider) {
     698           0 :     return false;
     699             :   }
     700             : 
     701           9 :   if (mFormat == gfx::SurfaceFormat::YUV) {
     702           0 :     mFirstSource = mProvider->CreateDataTextureSourceAroundYCbCr(this);
     703             :   } else {
     704             :     RefPtr<gfx::DataSourceSurface> surf =
     705          18 :       gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
     706          18 :         ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
     707           9 :     if (!surf) {
     708           0 :       return false;
     709             :     }
     710           9 :     mFirstSource = mProvider->CreateDataTextureSourceAround(surf);
     711             :   }
     712             : 
     713           9 :   if (!mFirstSource) {
     714             :     // BasicCompositor::CreateDataTextureSourceAround never returns null
     715             :     // and we don't expect to take this branch if we are using another backend.
     716             :     // Returning false is fine but if we get into this situation it probably
     717             :     // means something fishy is going on, like a texture being used with
     718             :     // several compositor backends.
     719           0 :     NS_WARNING("Failed to use a BufferTextureHost without intermediate buffer");
     720           0 :     return false;
     721             :   }
     722             : 
     723           9 :   mFirstSource->SetUpdateSerial(mUpdateSerial);
     724           9 :   mFirstSource->SetOwner(this);
     725             : 
     726           9 :   return true;
     727             : }
     728             : 
     729             : static
     730           0 : bool IsCompatibleTextureSource(TextureSource* aTexture,
     731             :                                const BufferDescriptor& aDescriptor,
     732             :                                TextureSourceProvider* aProvider)
     733             : {
     734           0 :   if (!aProvider) {
     735           0 :     return false;
     736             :   }
     737             : 
     738           0 :   switch (aDescriptor.type()) {
     739             :     case BufferDescriptor::TYCbCrDescriptor: {
     740           0 :       const YCbCrDescriptor& ycbcr = aDescriptor.get_YCbCrDescriptor();
     741             : 
     742           0 :       if (!aProvider->SupportsEffect(EffectTypes::YCBCR)) {
     743           0 :         return aTexture->GetFormat() == gfx::SurfaceFormat::B8G8R8X8
     744           0 :             && aTexture->GetSize() == ycbcr.ySize();
     745             :       }
     746             : 
     747           0 :       if (aTexture->GetFormat() != gfx::SurfaceFormat::A8
     748           0 :           || aTexture->GetSize() != ycbcr.ySize()) {
     749           0 :         return false;
     750             :       }
     751             : 
     752           0 :       auto cbTexture = aTexture->GetSubSource(1);
     753           0 :       if (!cbTexture
     754           0 :           || cbTexture->GetFormat() != gfx::SurfaceFormat::A8
     755           0 :           || cbTexture->GetSize() != ycbcr.cbCrSize()) {
     756           0 :         return false;
     757             :       }
     758             : 
     759           0 :       auto crTexture = aTexture->GetSubSource(2);
     760           0 :       if (!crTexture
     761           0 :           || crTexture->GetFormat() != gfx::SurfaceFormat::A8
     762           0 :           || crTexture->GetSize() != ycbcr.cbCrSize()) {
     763           0 :         return false;
     764             :       }
     765             : 
     766           0 :       return true;
     767             :     }
     768             :     case BufferDescriptor::TRGBDescriptor: {
     769           0 :       const RGBDescriptor& rgb = aDescriptor.get_RGBDescriptor();
     770           0 :       return aTexture->GetFormat() == rgb.format()
     771           0 :           && aTexture->GetSize() == rgb.size();
     772             :     }
     773             :     default: {
     774           0 :       return false;
     775             :     }
     776             :   }
     777             : }
     778             : 
     779             : void
     780          33 : BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
     781             : {
     782             :   // Reuse WrappingTextureSourceYCbCrBasic to reduce memory consumption.
     783         132 :   if (mFormat == gfx::SurfaceFormat::YUV &&
     784           0 :       !mHasIntermediateBuffer &&
     785           0 :       aTexture.get() &&
     786           0 :       aTexture->AsWrappingTextureSourceYCbCrBasic() &&
     787          66 :       aTexture->NumCompositableRefs() <= 1 &&
     788          33 :       aTexture->GetSize() == GetSize()) {
     789           0 :     aTexture->AsSourceBasic()->SetBufferTextureHost(this);
     790           0 :     aTexture->AsDataTextureSource()->SetOwner(this);
     791           0 :     mFirstSource = aTexture->AsDataTextureSource();
     792           0 :     mNeedsFullUpdate = true;
     793             :   }
     794             : 
     795          33 :   if (!mHasIntermediateBuffer) {
     796          33 :     EnsureWrappingTextureSource();
     797             :   }
     798             : 
     799          33 :   if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
     800             :     // We are already attached to a TextureSource, nothing to do except tell
     801             :     // the compositable to use it.
     802          33 :     aTexture = mFirstSource.get();
     803          33 :     return;
     804             :   }
     805             : 
     806             :   // We don't own it, apparently.
     807           0 :   if (mFirstSource) {
     808           0 :     mNeedsFullUpdate = true;
     809           0 :     mFirstSource = nullptr;
     810             :   }
     811             : 
     812           0 :   DataTextureSource* texture = aTexture.get() ? aTexture->AsDataTextureSource() : nullptr;
     813             : 
     814           0 :   bool compatibleFormats = texture && IsCompatibleTextureSource(texture,
     815             :                                                                 mDescriptor,
     816           0 :                                                                 mProvider);
     817             : 
     818           0 :   bool shouldCreateTexture = !compatibleFormats
     819           0 :                            || texture->NumCompositableRefs() > 1
     820           0 :                            || texture->HasOwner();
     821             : 
     822           0 :   if (!shouldCreateTexture) {
     823           0 :     mFirstSource = texture;
     824           0 :     mFirstSource->SetOwner(this);
     825           0 :     mNeedsFullUpdate = true;
     826             : 
     827             :     // It's possible that texture belonged to a different compositor,
     828             :     // so make sure we update it (and all of its siblings) to the
     829             :     // current one.
     830           0 :     RefPtr<TextureSource> it = mFirstSource;
     831           0 :     while (it) {
     832           0 :       it->SetTextureSourceProvider(mProvider);
     833           0 :       it = it->GetNextSibling();
     834             :     }
     835             :   }
     836             : }
     837             : 
     838             : bool
     839          56 : BufferTextureHost::BindTextureSource(CompositableTextureSourceRef& aTexture)
     840             : {
     841          56 :   MOZ_ASSERT(mLocked);
     842          56 :   MOZ_ASSERT(mFirstSource);
     843          56 :   aTexture = mFirstSource;
     844          56 :   return !!aTexture;
     845             : }
     846             : 
     847             : bool
     848           0 : BufferTextureHost::AcquireTextureSource(CompositableTextureSourceRef& aTexture)
     849             : {
     850           0 :   if (!UploadIfNeeded()) {
     851           0 :     return false;
     852             :   }
     853           0 :   aTexture = mFirstSource;
     854           0 :   return !!mFirstSource;
     855             : }
     856             : 
     857             : void
     858          31 : BufferTextureHost::UnbindTextureSource()
     859             : {
     860          31 :   if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
     861          31 :     mFirstSource->Unbind();
     862             :   }
     863             :   // This texture is not used by any layer anymore.
     864             :   // If the texture doesn't have an intermediate buffer, it means we are
     865             :   // compositing synchronously on the CPU, so we don't need to wait until
     866             :   // the end of the next composition to ReadUnlock (which other textures do
     867             :   // by default).
     868             :   // If the texture has an intermediate buffer we don't care either because
     869             :   // texture uploads are also performed synchronously for BufferTextureHost.
     870          31 :   ReadUnlock();
     871          31 : }
     872             : 
     873             : gfx::SurfaceFormat
     874           0 : BufferTextureHost::GetFormat() const
     875             : {
     876             :   // mFormat is the format of the data that we share with the content process.
     877             :   // GetFormat, on the other hand, expects the format that we present to the
     878             :   // Compositor (it is used to choose the effect type).
     879             :   // if the compositor does not support YCbCr effects, we give it a RGBX texture
     880             :   // instead (see BufferTextureHost::Upload)
     881           0 :   if (mFormat == gfx::SurfaceFormat::YUV &&
     882           0 :       mProvider &&
     883           0 :       !mProvider->SupportsEffect(EffectTypes::YCBCR)) {
     884           0 :     return gfx::SurfaceFormat::R8G8B8X8;
     885             :   }
     886           0 :   return mFormat;
     887             : }
     888             : 
     889             : YUVColorSpace
     890           0 : BufferTextureHost::GetYUVColorSpace() const
     891             : {
     892           0 :   if (mFormat == gfx::SurfaceFormat::YUV) {
     893           0 :     const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     894           0 :     return desc.yUVColorSpace();
     895             :   }
     896           0 :   return YUVColorSpace::UNKNOWN;
     897             : }
     898             : 
     899             : bool
     900          56 : BufferTextureHost::UploadIfNeeded()
     901             : {
     902          56 :   return MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
     903             : }
     904             : 
     905             : bool
     906          89 : BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
     907             : {
     908          89 :   auto serial = mFirstSource ? mFirstSource->GetUpdateSerial() : 0;
     909             : 
     910          89 :   if (serial == mUpdateSerial) {
     911          56 :     return true;
     912             :   }
     913             : 
     914          33 :   if (serial == 0) {
     915             :     // 0 means the source has no valid content
     916           9 :     aRegion = nullptr;
     917             :   }
     918             : 
     919          33 :   if (!Upload(aRegion)) {
     920           0 :     return false;
     921             :   }
     922             : 
     923          33 :   if (mHasIntermediateBuffer) {
     924             :     // We just did the texture upload, the content side can now freely write
     925             :     // into the shared buffer.
     926           0 :     ReadUnlock();
     927             :   }
     928             : 
     929             :   // We no longer have an invalid region.
     930          33 :   mNeedsFullUpdate = false;
     931          33 :   mMaybeUpdatedRegion.SetEmpty();
     932             : 
     933             :   // If upload returns true we know mFirstSource is not null
     934          33 :   mFirstSource->SetUpdateSerial(mUpdateSerial);
     935          33 :   return true;
     936             : }
     937             : 
     938             : bool
     939          33 : BufferTextureHost::Upload(nsIntRegion *aRegion)
     940             : {
     941          33 :   uint8_t* buf = GetBuffer();
     942          33 :   if (!buf) {
     943             :     // We don't have a buffer; a possible cause is that the IPDL actor
     944             :     // is already dead. This inevitably happens as IPDL actors can die
     945             :     // at any time, so we want to silently return in this case.
     946             :     // another possible cause is that IPDL failed to map the shmem when
     947             :     // deserializing it.
     948           0 :     return false;
     949             :   }
     950          33 :   if (!mProvider) {
     951             :     // This can happen if we send textures to a compositable that isn't yet
     952             :     // attached to a layer.
     953           0 :     return false;
     954             :   }
     955          33 :   if (!mHasIntermediateBuffer && EnsureWrappingTextureSource()) {
     956          33 :     return true;
     957             :   }
     958             : 
     959           0 :   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
     960           0 :     NS_WARNING("BufferTextureHost: unsupported format!");
     961           0 :     return false;
     962           0 :   } else if (mFormat == gfx::SurfaceFormat::YUV) {
     963           0 :     const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
     964             : 
     965           0 :     if (!mProvider->SupportsEffect(EffectTypes::YCBCR)) {
     966             :       RefPtr<gfx::DataSourceSurface> surf =
     967           0 :         ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor());
     968           0 :       if (NS_WARN_IF(!surf)) {
     969           0 :         return false;
     970             :       }
     971           0 :       if (!mFirstSource) {
     972           0 :         mFirstSource = mProvider->CreateDataTextureSource(mFlags|TextureFlags::RGB_FROM_YCBCR);
     973           0 :         mFirstSource->SetOwner(this);
     974             :       }
     975           0 :       mFirstSource->Update(surf, aRegion);
     976           0 :       return true;
     977             :     }
     978             : 
     979           0 :     RefPtr<DataTextureSource> srcY;
     980           0 :     RefPtr<DataTextureSource> srcU;
     981           0 :     RefPtr<DataTextureSource> srcV;
     982           0 :     if (!mFirstSource) {
     983             :       // We don't support BigImages for YCbCr compositing.
     984           0 :       srcY = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
     985           0 :       srcU = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
     986           0 :       srcV = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
     987           0 :       mFirstSource = srcY;
     988           0 :       mFirstSource->SetOwner(this);
     989           0 :       srcY->SetNextSibling(srcU);
     990           0 :       srcU->SetNextSibling(srcV);
     991             :     } else {
     992             :       // mFormat never changes so if this was created as a YCbCr host and already
     993             :       // contains a source it should already have 3 sources.
     994             :       // BufferTextureHost only uses DataTextureSources so it is safe to assume
     995             :       // all 3 sources are DataTextureSource.
     996           0 :       MOZ_ASSERT(mFirstSource->GetNextSibling());
     997           0 :       MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
     998           0 :       srcY = mFirstSource;
     999           0 :       srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
    1000           0 :       srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
    1001             :     }
    1002             : 
    1003             :     RefPtr<gfx::DataSourceSurface> tempY =
    1004           0 :       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
    1005           0 :                                                     desc.ySize().width,
    1006           0 :                                                     desc.ySize(),
    1007           0 :                                                     gfx::SurfaceFormat::A8);
    1008             :     RefPtr<gfx::DataSourceSurface> tempCb =
    1009           0 :       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
    1010           0 :                                                     desc.cbCrSize().width,
    1011           0 :                                                     desc.cbCrSize(),
    1012           0 :                                                     gfx::SurfaceFormat::A8);
    1013             :     RefPtr<gfx::DataSourceSurface> tempCr =
    1014           0 :       gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
    1015           0 :                                                     desc.cbCrSize().width,
    1016           0 :                                                     desc.cbCrSize(),
    1017           0 :                                                     gfx::SurfaceFormat::A8);
    1018             :     // We don't support partial updates for Y U V textures
    1019           0 :     NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
    1020           0 :     if (!tempY ||
    1021           0 :         !tempCb ||
    1022           0 :         !tempCr ||
    1023           0 :         !srcY->Update(tempY) ||
    1024           0 :         !srcU->Update(tempCb) ||
    1025           0 :         !srcV->Update(tempCr)) {
    1026           0 :       NS_WARNING("failed to update the DataTextureSource");
    1027           0 :       return false;
    1028             :     }
    1029             :   } else {
    1030             :     // non-YCbCr case
    1031           0 :     nsIntRegion* regionToUpdate = aRegion;
    1032           0 :     if (!mFirstSource) {
    1033           0 :       mFirstSource = mProvider->CreateDataTextureSource(mFlags);
    1034           0 :       mFirstSource->SetOwner(this);
    1035           0 :       if (mFlags & TextureFlags::COMPONENT_ALPHA) {
    1036             :         // Update the full region the first time for component alpha textures.
    1037           0 :         regionToUpdate = nullptr;
    1038             :       }
    1039             :     }
    1040             : 
    1041             :     RefPtr<gfx::DataSourceSurface> surf =
    1042           0 :       gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
    1043           0 :         ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
    1044           0 :     if (!surf) {
    1045           0 :       return false;
    1046             :     }
    1047             : 
    1048           0 :     if (!mFirstSource->Update(surf.get(), regionToUpdate)) {
    1049           0 :       NS_WARNING("failed to update the DataTextureSource");
    1050           0 :       return false;
    1051             :     }
    1052             :   }
    1053           0 :   MOZ_ASSERT(mFirstSource);
    1054           0 :   return true;
    1055             : }
    1056             : 
    1057             : already_AddRefed<gfx::DataSourceSurface>
    1058           0 : BufferTextureHost::GetAsSurface()
    1059             : {
    1060           0 :   RefPtr<gfx::DataSourceSurface> result;
    1061           0 :   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
    1062           0 :     NS_WARNING("BufferTextureHost: unsupported format!");
    1063           0 :     return nullptr;
    1064           0 :   } else if (mFormat == gfx::SurfaceFormat::YUV) {
    1065           0 :     result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
    1066           0 :       GetBuffer(), mDescriptor.get_YCbCrDescriptor());
    1067           0 :     if (NS_WARN_IF(!result)) {
    1068           0 :       return nullptr;
    1069             :     }
    1070             :   } else {
    1071             :     result =
    1072           0 :       gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
    1073           0 :         ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()),
    1074           0 :         mSize, mFormat);
    1075             :   }
    1076           0 :   return result.forget();
    1077             : }
    1078             : 
    1079           1 : ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
    1080             :                                    const BufferDescriptor& aDesc,
    1081             :                                    ISurfaceAllocator* aDeallocator,
    1082           1 :                                    TextureFlags aFlags)
    1083             : : BufferTextureHost(aDesc, aFlags)
    1084           1 : , mDeallocator(aDeallocator)
    1085             : {
    1086           1 :   if (aShmem.IsReadable()) {
    1087           1 :     mShmem = MakeUnique<ipc::Shmem>(aShmem);
    1088             :   } else {
    1089             :     // This can happen if we failed to map the shmem on this process, perhaps
    1090             :     // because it was big and we didn't have enough contiguous address space
    1091             :     // available, even though we did on the child process.
    1092             :     // As a result this texture will be in an invalid state and Lock will
    1093             :     // always fail.
    1094             : 
    1095           0 :     gfxCriticalNote << "Failed to create a valid ShmemTextureHost";
    1096             :   }
    1097             : 
    1098           1 :   MOZ_COUNT_CTOR(ShmemTextureHost);
    1099           1 : }
    1100             : 
    1101           0 : ShmemTextureHost::~ShmemTextureHost()
    1102             : {
    1103           0 :   MOZ_ASSERT(!mShmem || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
    1104             :              "Leaking our buffer");
    1105           0 :   DeallocateDeviceData();
    1106           0 :   MOZ_COUNT_DTOR(ShmemTextureHost);
    1107           0 : }
    1108             : 
    1109             : void
    1110           0 : ShmemTextureHost::DeallocateSharedData()
    1111             : {
    1112           0 :   if (mShmem) {
    1113           0 :     MOZ_ASSERT(mDeallocator,
    1114             :                "Shared memory would leak without a ISurfaceAllocator");
    1115           0 :     mDeallocator->AsShmemAllocator()->DeallocShmem(*mShmem);
    1116           0 :     mShmem = nullptr;
    1117             :   }
    1118           0 : }
    1119             : 
    1120             : void
    1121           0 : ShmemTextureHost::ForgetSharedData()
    1122             : {
    1123           0 :   if (mShmem) {
    1124           0 :     mShmem = nullptr;
    1125             :   }
    1126           0 : }
    1127             : 
    1128             : void
    1129           0 : ShmemTextureHost::OnShutdown()
    1130             : {
    1131           0 :   mShmem = nullptr;
    1132           0 : }
    1133             : 
    1134           2 : uint8_t* ShmemTextureHost::GetBuffer()
    1135             : {
    1136           2 :   return mShmem ? mShmem->get<uint8_t>() : nullptr;
    1137             : }
    1138             : 
    1139           0 : size_t ShmemTextureHost::GetBufferSize()
    1140             : {
    1141           0 :   return mShmem ? mShmem->Size<uint8_t>() : 0;
    1142             : }
    1143             : 
    1144           8 : MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
    1145             :                                      const BufferDescriptor& aDesc,
    1146           8 :                                      TextureFlags aFlags)
    1147             : : BufferTextureHost(aDesc, aFlags)
    1148           8 : , mBuffer(aBuffer)
    1149             : {
    1150           8 :   MOZ_COUNT_CTOR(MemoryTextureHost);
    1151           8 : }
    1152             : 
    1153          18 : MemoryTextureHost::~MemoryTextureHost()
    1154             : {
    1155           6 :   MOZ_ASSERT(!mBuffer || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
    1156             :              "Leaking our buffer");
    1157           6 :   DeallocateDeviceData();
    1158           6 :   MOZ_COUNT_DTOR(MemoryTextureHost);
    1159          18 : }
    1160             : 
    1161             : void
    1162           6 : MemoryTextureHost::DeallocateSharedData()
    1163             : {
    1164           6 :   if (mBuffer) {
    1165           6 :     GfxMemoryImageReporter::WillFree(mBuffer);
    1166             :   }
    1167           6 :   delete[] mBuffer;
    1168           6 :   mBuffer = nullptr;
    1169           6 : }
    1170             : 
    1171             : void
    1172           0 : MemoryTextureHost::ForgetSharedData()
    1173             : {
    1174           0 :   mBuffer = nullptr;
    1175           0 : }
    1176             : 
    1177          40 : uint8_t* MemoryTextureHost::GetBuffer()
    1178             : {
    1179          40 :   return mBuffer;
    1180             : }
    1181             : 
    1182           0 : size_t MemoryTextureHost::GetBufferSize()
    1183             : {
    1184             :   // MemoryTextureHost just trusts that the buffer size is large enough to read
    1185             :   // anything we need to. That's because MemoryTextureHost has to trust the buffer
    1186             :   // pointer anyway, so the security model here is just that MemoryTexture's
    1187             :   // are restricted to same-process clients.
    1188           0 :   return std::numeric_limits<size_t>::max();
    1189             : }
    1190             : 
    1191           9 : TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator, uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId)
    1192             : : mSurfaceAllocator(aSurfaceAllocator)
    1193             : , mSerial(aSerial)
    1194           9 : , mExternalImageId(aExternalImageId)
    1195             : {
    1196           9 :   MOZ_COUNT_CTOR(TextureParent);
    1197           9 : }
    1198             : 
    1199          18 : TextureParent::~TextureParent()
    1200             : {
    1201           6 :   MOZ_COUNT_DTOR(TextureParent);
    1202          18 : }
    1203             : 
    1204             : void
    1205           0 : TextureParent::NotifyNotUsed(uint64_t aTransactionId)
    1206             : {
    1207           0 :   if (!mTextureHost) {
    1208           0 :     return;
    1209             :   }
    1210           0 :   mSurfaceAllocator->NotifyNotUsed(this, aTransactionId);
    1211             : }
    1212             : 
    1213             : bool
    1214           9 : TextureParent::Init(const SurfaceDescriptor& aSharedData,
    1215             :                     const LayersBackend& aBackend,
    1216             :                     const TextureFlags& aFlags)
    1217             : {
    1218          27 :   mTextureHost = TextureHost::Create(aSharedData,
    1219           9 :                                      mSurfaceAllocator,
    1220             :                                      aBackend,
    1221             :                                      aFlags,
    1222           9 :                                      mExternalImageId);
    1223           9 :   if (mTextureHost) {
    1224           9 :     mTextureHost->mActor = this;
    1225             :   }
    1226             : 
    1227           9 :   return !!mTextureHost;
    1228             : }
    1229             : 
    1230             : void
    1231           6 : TextureParent::Destroy()
    1232             : {
    1233           6 :   if (!mTextureHost) {
    1234           0 :     return;
    1235             :   }
    1236             : 
    1237             :   // ReadUnlock here to make sure the ReadLock's shmem does not outlive the
    1238             :   // protocol that created it.
    1239           6 :   mTextureHost->ReadUnlock();
    1240             : 
    1241           6 :   if (mTextureHost->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
    1242           0 :     mTextureHost->ForgetSharedData();
    1243             :   }
    1244             : 
    1245           6 :   mTextureHost->mActor = nullptr;
    1246           6 :   mTextureHost = nullptr;
    1247             : }
    1248             : 
    1249             : void
    1250           2 : TextureHost::ReceivedDestroy(PTextureParent* aActor)
    1251             : {
    1252           2 :   static_cast<TextureParent*>(aActor)->RecvDestroy();
    1253           2 : }
    1254             : 
    1255             : mozilla::ipc::IPCResult
    1256           0 : TextureParent::RecvRecycleTexture(const TextureFlags& aTextureFlags)
    1257             : {
    1258           0 :   if (!mTextureHost) {
    1259           0 :     return IPC_OK();
    1260             :   }
    1261           0 :   mTextureHost->RecycleTexture(aTextureFlags);
    1262           0 :   return IPC_OK();
    1263             : }
    1264             : 
    1265             : ////////////////////////////////////////////////////////////////////////////////
    1266             : 
    1267             : } // namespace layers
    1268           9 : } // namespace mozilla

Generated by: LCOV version 1.13