gfx/layers/composite/TextureHost.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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/. */
     6 #include "mozilla/layers/TextureHost.h"
     7 #include "CompositableHost.h"           // for CompositableHost
     8 #include "LayersLogging.h"              // for AppendToString
     9 #include "gfx2DGlue.h"                  // for ToIntSize
    10 #include "mozilla/gfx/2D.h"             // for DataSourceSurface, Factory
    11 #include "mozilla/ipc/Shmem.h"          // for Shmem
    12 #include "mozilla/layers/Compositor.h"  // for Compositor
    13 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
    14 #include "mozilla/layers/ImageDataSerializer.h"
    15 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
    16 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
    17 #ifdef MOZ_X11
    18 #include "mozilla/layers/X11TextureHost.h"
    19 #endif
    20 #include "mozilla/layers/YCbCrImageDataSerializer.h"
    21 #include "nsAString.h"
    22 #include "nsAutoPtr.h"                  // for nsRefPtr
    23 #include "nsPrintfCString.h"            // for nsPrintfCString
    24 #include "mozilla/layers/PTextureParent.h"
    25 #include "mozilla/unused.h"
    26 #include <limits>
    28 #if 0
    29 #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
    30 #else
    31 #define RECYCLE_LOG(...) do { } while (0)
    32 #endif
    34 struct nsIntPoint;
    36 namespace mozilla {
    37 namespace layers {
    39 /**
    40  * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
    41  * It is an IPDL actor just like LayerParent, CompositableParent, etc.
    42  */
    43 class TextureParent : public PTextureParent
    44 {
    45 public:
    46   TextureParent(ISurfaceAllocator* aAllocator);
    48   ~TextureParent();
    50   bool Init(const SurfaceDescriptor& aSharedData,
    51             const TextureFlags& aFlags);
    53   void CompositorRecycle();
    54   virtual bool RecvClientRecycle() MOZ_OVERRIDE;
    56   virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
    58   virtual bool RecvRemoveTextureSync() MOZ_OVERRIDE;
    60   TextureHost* GetTextureHost() { return mTextureHost; }
    62   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
    64   ISurfaceAllocator* mAllocator;
    65   RefPtr<TextureHost> mWaitForClientRecycle;
    66   RefPtr<TextureHost> mTextureHost;
    67 };
    69 // static
    70 PTextureParent*
    71 TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator,
    72                              const SurfaceDescriptor& aSharedData,
    73                              TextureFlags aFlags)
    74 {
    75   if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory &&
    76       !aAllocator->IsSameProcess())
    77   {
    78     NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
    79     return nullptr;
    80   }
    81   TextureParent* actor = new TextureParent(aAllocator);
    82   if (!actor->Init(aSharedData, aFlags)) {
    83     delete actor;
    84     return nullptr;
    85   }
    86   return actor;
    87 }
    89 // static
    90 bool
    91 TextureHost::DestroyIPDLActor(PTextureParent* actor)
    92 {
    93   delete actor;
    94   return true;
    95 }
    97 // static
    98 bool
    99 TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
   100 {
   101   return PTextureParent::Send__delete__(actor);
   102 }
   104 // static
   105 TextureHost*
   106 TextureHost::AsTextureHost(PTextureParent* actor)
   107 {
   108   return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
   109 }
   111 PTextureParent*
   112 TextureHost::GetIPDLActor()
   113 {
   114   return mActor;
   115 }
   117 // implemented in TextureHostOGL.cpp
   118 TemporaryRef<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
   119                                                ISurfaceAllocator* aDeallocator,
   120                                                TextureFlags aFlags);
   122 // implemented in TextureHostBasic.cpp
   123 TemporaryRef<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
   124                                                  ISurfaceAllocator* aDeallocator,
   125                                                  TextureFlags aFlags);
   127 // implemented in TextureD3D11.cpp
   128 TemporaryRef<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
   129                                                  ISurfaceAllocator* aDeallocator,
   130                                                  TextureFlags aFlags);
   132 // implemented in TextureD3D9.cpp
   133 TemporaryRef<TextureHost> CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
   134                                                 ISurfaceAllocator* aDeallocator,
   135                                                 TextureFlags aFlags);
   137 // static
   138 TemporaryRef<TextureHost>
   139 TextureHost::Create(const SurfaceDescriptor& aDesc,
   140                     ISurfaceAllocator* aDeallocator,
   141                     TextureFlags aFlags)
   142 {
   143   switch (aDesc.type()) {
   144     case SurfaceDescriptor::TSurfaceDescriptorShmem:
   145     case SurfaceDescriptor::TSurfaceDescriptorMemory:
   146       return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
   147     case SurfaceDescriptor::TSharedTextureDescriptor:
   148     case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
   149     case SurfaceDescriptor::TSurfaceStreamDescriptor:
   150       return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
   151     case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
   152       if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
   153         return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
   154       } else {
   155         return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
   156       }
   157 #ifdef MOZ_X11
   158     case SurfaceDescriptor::TSurfaceDescriptorX11: {
   159       const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11();
   160       RefPtr<TextureHost> result = new X11TextureHost(aFlags, desc);
   161       return result;
   162     }
   163 #endif
   164 #ifdef XP_WIN
   165     case SurfaceDescriptor::TSurfaceDescriptorD3D9:
   166     case SurfaceDescriptor::TSurfaceDescriptorDIB:
   167       return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
   168     case SurfaceDescriptor::TSurfaceDescriptorD3D10:
   169       if (Compositor::GetBackend() == LayersBackend::LAYERS_D3D9) {
   170         return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
   171       } else {
   172         return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags);
   173       }
   174 #endif
   175     default:
   176       MOZ_CRASH("Unsupported Surface type");
   177   }
   178 }
   180 TemporaryRef<TextureHost>
   181 CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
   182                                     ISurfaceAllocator* aDeallocator,
   183                                     TextureFlags aFlags)
   184 {
   185   RefPtr<TextureHost> result;
   186   switch (aDesc.type()) {
   187     case SurfaceDescriptor::TSurfaceDescriptorShmem: {
   188       const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem();
   189       result = new ShmemTextureHost(descriptor.data(),
   190                                     descriptor.format(),
   191                                     aDeallocator,
   192                                     aFlags);
   193       break;
   194     }
   195     case SurfaceDescriptor::TSurfaceDescriptorMemory: {
   196       const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory();
   197       result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()),
   198                                      descriptor.format(),
   199                                      aFlags);
   200       break;
   201     }
   202     default: {
   203       NS_WARNING("No backend independent TextureHost for this descriptor type");
   204     }
   205   }
   206   return result;
   207 }
   209 void
   210 TextureHost::CompositorRecycle()
   211 {
   212   if (!mActor) {
   213     return;
   214   }
   215   static_cast<TextureParent*>(mActor)->CompositorRecycle();
   216 }
   218 void
   219 TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
   220 {
   221     mCompositableBackendData = aBackendData;
   222 }
   225 TextureHost::TextureHost(TextureFlags aFlags)
   226     : mActor(nullptr)
   227     , mFlags(aFlags)
   228 {}
   230 TextureHost::~TextureHost()
   231 {
   232 }
   234 void TextureHost::Finalize()
   235 {
   236   if (!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) {
   237     DeallocateSharedData();
   238     DeallocateDeviceData();
   239   }
   240 }
   242 void
   243 TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix)
   244 {
   245   aTo += aPrefix;
   246   aTo += nsPrintfCString("%s (0x%p)", Name(), this);
   247   // Note: the TextureHost needs to be locked before it is safe to call
   248   //       GetSize() and GetFormat() on it.
   249   if (Lock()) {
   250     AppendToString(aTo, GetSize(), " [size=", "]");
   251     AppendToString(aTo, GetFormat(), " [format=", "]");
   252     Unlock();
   253   }
   254   AppendToString(aTo, mFlags, " [flags=", "]");
   255 }
   257 void
   258 TextureSource::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
   259 {
   260     mCompositableBackendData = aBackendData;
   261 }
   263 TextureSource::TextureSource()
   264 {
   265     MOZ_COUNT_CTOR(TextureSource);
   266 }
   267 TextureSource::~TextureSource()
   268 {
   269     MOZ_COUNT_DTOR(TextureSource);
   270 }
   272 BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
   273                                      TextureFlags aFlags)
   274 : TextureHost(aFlags)
   275 , mCompositor(nullptr)
   276 , mFormat(aFormat)
   277 , mUpdateSerial(1)
   278 , mLocked(false)
   279 , mPartialUpdate(false)
   280 {}
   282 BufferTextureHost::~BufferTextureHost()
   283 {}
   285 void
   286 BufferTextureHost::Updated(const nsIntRegion* aRegion)
   287 {
   288   ++mUpdateSerial;
   289   if (aRegion) {
   290     mPartialUpdate = true;
   291     mMaybeUpdatedRegion = *aRegion;
   292   } else {
   293     mPartialUpdate = false;
   294   }
   295   if (GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
   296     DebugOnly<bool> result = MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr);
   297     NS_WARN_IF_FALSE(result, "Failed to upload a texture");
   298   }
   299 }
   301 void
   302 BufferTextureHost::SetCompositor(Compositor* aCompositor)
   303 {
   304   if (mCompositor == aCompositor) {
   305     return;
   306   }
   307   RefPtr<NewTextureSource> it = mFirstSource;
   308   while (it) {
   309     it->SetCompositor(aCompositor);
   310     it = it->GetNextSibling();
   311   }
   312   mCompositor = aCompositor;
   313 }
   315 void
   316 BufferTextureHost::DeallocateDeviceData()
   317 {
   318   RefPtr<NewTextureSource> it = mFirstSource;
   319   while (it) {
   320     it->DeallocateDeviceData();
   321     it = it->GetNextSibling();
   322   }
   323 }
   325 bool
   326 BufferTextureHost::Lock()
   327 {
   328   mLocked = true;
   329   return true;
   330 }
   332 void
   333 BufferTextureHost::Unlock()
   334 {
   335   mLocked = false;
   336 }
   338 NewTextureSource*
   339 BufferTextureHost::GetTextureSources()
   340 {
   341   MOZ_ASSERT(mLocked, "should never be called while not locked");
   342   if (!MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr)) {
   343       return nullptr;
   344   }
   345   return mFirstSource;
   346 }
   348 gfx::SurfaceFormat
   349 BufferTextureHost::GetFormat() const
   350 {
   351   // mFormat is the format of the data that we share with the content process.
   352   // GetFormat, on the other hand, expects the format that we present to the
   353   // Compositor (it is used to choose the effect type).
   354   // if the compositor does not support YCbCr effects, we give it a RGBX texture
   355   // instead (see BufferTextureHost::Upload)
   356   if (mFormat == gfx::SurfaceFormat::YUV &&
   357     mCompositor &&
   358     !mCompositor->SupportsEffect(EFFECT_YCBCR)) {
   359     return gfx::SurfaceFormat::R8G8B8X8;
   360   }
   361   return mFormat;
   362 }
   364 bool
   365 BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
   366 {
   367   if (mFirstSource && mFirstSource->GetUpdateSerial() == mUpdateSerial) {
   368     return true;
   369   }
   370   if (!Upload(aRegion)) {
   371     return false;
   372   }
   373   mFirstSource->SetUpdateSerial(mUpdateSerial);
   374   return true;
   375 }
   377 bool
   378 BufferTextureHost::Upload(nsIntRegion *aRegion)
   379 {
   380   if (!GetBuffer()) {
   381     // We don't have a buffer; a possible cause is that the IPDL actor
   382     // is already dead. This inevitably happens as IPDL actors can die
   383     // at any time, so we want to silently return in this case.
   384     return false;
   385   }
   386   if (!mCompositor) {
   387     NS_WARNING("Tried to upload without a compositor. Skipping texture upload...");
   388     // If we are in this situation it means we should have called SetCompositor
   389     // earlier. It is conceivable that on certain rare conditions with async-video
   390     // we may end up here for the first frame, but this should not happen repeatedly.
   391     return false;
   392   }
   393   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
   394     NS_WARNING("BufferTextureHost: unsupported format!");
   395     return false;
   396   } else if (mFormat == gfx::SurfaceFormat::YUV) {
   397     YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
   398     MOZ_ASSERT(yuvDeserializer.IsValid());
   400     if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) {
   401       RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
   402       if (!mFirstSource) {
   403         mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
   404       }
   405       mFirstSource->Update(surf, aRegion);
   406       return true;
   407     }
   409     RefPtr<DataTextureSource> srcY;
   410     RefPtr<DataTextureSource> srcU;
   411     RefPtr<DataTextureSource> srcV;
   412     if (!mFirstSource) {
   413       // We don't support BigImages for YCbCr compositing.
   414       srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   415       srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   416       srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   417       mFirstSource = srcY;
   418       srcY->SetNextSibling(srcU);
   419       srcU->SetNextSibling(srcV);
   420     } else {
   421       // mFormat never changes so if this was created as a YCbCr host and already
   422       // contains a source it should already have 3 sources.
   423       // BufferTextureHost only uses DataTextureSources so it is safe to assume
   424       // all 3 sources are DataTextureSource.
   425       MOZ_ASSERT(mFirstSource->GetNextSibling());
   426       MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
   427       srcY = mFirstSource;
   428       srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
   429       srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
   430     }
   433     RefPtr<gfx::DataSourceSurface> tempY =
   434       gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
   435                                                     yuvDeserializer.GetYStride(),
   436                                                     yuvDeserializer.GetYSize(),
   437                                                     gfx::SurfaceFormat::A8);
   438     RefPtr<gfx::DataSourceSurface> tempCb =
   439       gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
   440                                                     yuvDeserializer.GetCbCrStride(),
   441                                                     yuvDeserializer.GetCbCrSize(),
   442                                                     gfx::SurfaceFormat::A8);
   443     RefPtr<gfx::DataSourceSurface> tempCr =
   444       gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
   445                                                     yuvDeserializer.GetCbCrStride(),
   446                                                     yuvDeserializer.GetCbCrSize(),
   447                                                     gfx::SurfaceFormat::A8);
   448     // We don't support partial updates for Y U V textures
   449     NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
   450     if (!srcY->Update(tempY) ||
   451         !srcU->Update(tempCb) ||
   452         !srcV->Update(tempCr)) {
   453       NS_WARNING("failed to update the DataTextureSource");
   454       return false;
   455     }
   456   } else {
   457     // non-YCbCr case
   458     if (!mFirstSource) {
   459       mFirstSource = mCompositor->CreateDataTextureSource();
   460     }
   461     ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
   462     if (!deserializer.IsValid()) {
   463       NS_ERROR("Failed to deserialize image!");
   464       return false;
   465     }
   467     RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface();
   468     if (!surf) {
   469       return false;
   470     }
   472     if (!mFirstSource->Update(surf.get(), aRegion)) {
   473       NS_WARNING("failed to update the DataTextureSource");
   474       return false;
   475     }
   476   }
   477   return true;
   478 }
   480 TemporaryRef<gfx::DataSourceSurface>
   481 BufferTextureHost::GetAsSurface()
   482 {
   483   RefPtr<gfx::DataSourceSurface> result;
   484   if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
   485     NS_WARNING("BufferTextureHost: unsupported format!");
   486     return nullptr;
   487   } else if (mFormat == gfx::SurfaceFormat::YUV) {
   488     YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
   489     if (!yuvDeserializer.IsValid()) {
   490       return nullptr;
   491     }
   492     result = yuvDeserializer.ToDataSourceSurface();
   493   } else {
   494     ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
   495     if (!deserializer.IsValid()) {
   496       NS_ERROR("Failed to deserialize image!");
   497       return nullptr;
   498     }
   499     result = deserializer.GetAsSurface();
   500   }
   501   return result.forget();
   502 }
   504 ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
   505                                    gfx::SurfaceFormat aFormat,
   506                                    ISurfaceAllocator* aDeallocator,
   507                                    TextureFlags aFlags)
   508 : BufferTextureHost(aFormat, aFlags)
   509 , mShmem(new ipc::Shmem(aShmem))
   510 , mDeallocator(aDeallocator)
   511 {
   512   MOZ_COUNT_CTOR(ShmemTextureHost);
   513 }
   515 ShmemTextureHost::~ShmemTextureHost()
   516 {
   517   DeallocateDeviceData();
   518   delete mShmem;
   519   MOZ_COUNT_DTOR(ShmemTextureHost);
   520 }
   522 void
   523 ShmemTextureHost::DeallocateSharedData()
   524 {
   525   if (mShmem) {
   526     MOZ_ASSERT(mDeallocator,
   527                "Shared memory would leak without a ISurfaceAllocator");
   528     mDeallocator->DeallocShmem(*mShmem);
   529     delete mShmem;
   530     mShmem = nullptr;
   531   }
   532 }
   534 void
   535 ShmemTextureHost::ForgetSharedData()
   536 {
   537   if (mShmem) {
   538     delete mShmem;
   539     mShmem = nullptr;
   540   }
   541 }
   543 void
   544 ShmemTextureHost::OnShutdown()
   545 {
   546   delete mShmem;
   547   mShmem = nullptr;
   548 }
   550 uint8_t* ShmemTextureHost::GetBuffer()
   551 {
   552   return mShmem ? mShmem->get<uint8_t>() : nullptr;
   553 }
   555 size_t ShmemTextureHost::GetBufferSize()
   556 {
   557   return mShmem ? mShmem->Size<uint8_t>() : 0;
   558 }
   560 MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
   561                                      gfx::SurfaceFormat aFormat,
   562                                      TextureFlags aFlags)
   563 : BufferTextureHost(aFormat, aFlags)
   564 , mBuffer(aBuffer)
   565 {
   566   MOZ_COUNT_CTOR(MemoryTextureHost);
   567 }
   569 MemoryTextureHost::~MemoryTextureHost()
   570 {
   571   DeallocateDeviceData();
   572   NS_ASSERTION(!mBuffer || (mFlags & TEXTURE_DEALLOCATE_CLIENT),
   573                "Leaking our buffer");
   574   MOZ_COUNT_DTOR(MemoryTextureHost);
   575 }
   577 void
   578 MemoryTextureHost::DeallocateSharedData()
   579 {
   580   if (mBuffer) {
   581     GfxMemoryImageReporter::WillFree(mBuffer);
   582   }
   583   delete[] mBuffer;
   584   mBuffer = nullptr;
   585 }
   587 void
   588 MemoryTextureHost::ForgetSharedData()
   589 {
   590   mBuffer = nullptr;
   591 }
   593 uint8_t* MemoryTextureHost::GetBuffer()
   594 {
   595   return mBuffer;
   596 }
   598 size_t MemoryTextureHost::GetBufferSize()
   599 {
   600   // MemoryTextureHost just trusts that the buffer size is large enough to read
   601   // anything we need to. That's because MemoryTextureHost has to trust the buffer
   602   // pointer anyway, so the security model here is just that MemoryTexture's
   603   // are restricted to same-process clients.
   604   return std::numeric_limits<size_t>::max();
   605 }
   607 TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
   608 : mAllocator(aAllocator)
   609 {
   610   MOZ_COUNT_CTOR(TextureParent);
   611 }
   613 TextureParent::~TextureParent()
   614 {
   615   MOZ_COUNT_DTOR(TextureParent);
   616   if (mTextureHost) {
   617     mTextureHost->ClearRecycleCallback();
   618   }
   619 }
   621 static void RecycleCallback(TextureHost* textureHost, void* aClosure) {
   622   TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure);
   623   tp->CompositorRecycle();
   624 }
   626 void
   627 TextureParent::CompositorRecycle()
   628 {
   629   mTextureHost->ClearRecycleCallback();
   631   MaybeFenceHandle handle = null_t();
   632 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   633   if (mTextureHost) {
   634     TextureHostOGL* hostOGL = mTextureHost->AsHostOGL();
   635     android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
   636     if (fence.get() && fence->isValid()) {
   637       handle = FenceHandle(fence);
   638       // HWC might not provide Fence.
   639       // In this case, HWC implicitly handles buffer's fence.
   640     }
   641   }
   642 #endif
   643   mozilla::unused << SendCompositorRecycle(handle);
   645   // Don't forget to prepare for the next reycle
   646   // if TextureClient request it.
   647   if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
   648     mWaitForClientRecycle = mTextureHost;
   649   }
   650 }
   652 bool
   653 TextureParent::RecvClientRecycle()
   654 {
   655   // This will allow the RecycleCallback to be called once the compositor
   656   // releases any external references to TextureHost.
   657   mTextureHost->SetRecycleCallback(RecycleCallback, this);
   658   if (!mWaitForClientRecycle) {
   659     RECYCLE_LOG("Not a recycable tile");
   660   }
   661   mWaitForClientRecycle = nullptr;
   662   return true;
   663 }
   665 bool
   666 TextureParent::Init(const SurfaceDescriptor& aSharedData,
   667                     const TextureFlags& aFlags)
   668 {
   669   mTextureHost = TextureHost::Create(aSharedData,
   670                                      mAllocator,
   671                                      aFlags);
   672   if (mTextureHost) {
   673     mTextureHost->mActor = this;
   674     if (aFlags & TEXTURE_RECYCLE) {
   675       mWaitForClientRecycle = mTextureHost;
   676       RECYCLE_LOG("Setup recycling for tile %p\n", this);
   677     }
   678   }
   680   return !!mTextureHost;
   681 }
   683 bool
   684 TextureParent::RecvRemoveTexture()
   685 {
   686   return PTextureParent::Send__delete__(this);
   687 }
   689 bool
   690 TextureParent::RecvRemoveTextureSync()
   691 {
   692   // we don't need to send a reply in the synchronous case since the child side
   693   // has the guarantee that this message has been handled synchronously.
   694   return PTextureParent::Send__delete__(this);
   695 }
   697 void
   698 TextureParent::ActorDestroy(ActorDestroyReason why)
   699 {
   700   if (!mTextureHost) {
   701     return;
   702   }
   704   switch (why) {
   705   case AncestorDeletion:
   706   case Deletion:
   707   case NormalShutdown:
   708   case AbnormalShutdown:
   709     break;
   710   case FailedConstructor:
   711     NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   712   }
   714   if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
   715     RECYCLE_LOG("clear recycling for tile %p\n", this);
   716     mTextureHost->ClearRecycleCallback();
   717   }
   718   if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
   719     mTextureHost->ForgetSharedData();
   720   }
   722   // Clear recycle callback.
   723   mTextureHost->ClearRecycleCallback();
   724   mWaitForClientRecycle = nullptr;
   726   mTextureHost->mActor = nullptr;
   727   mTextureHost = nullptr;
   728 }
   730 } // namespace
   731 } // namespace

mercurial