gfx/layers/composite/TextureHost.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/composite/TextureHost.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,731 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     1.5 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/layers/TextureHost.h"
    1.10 +#include "CompositableHost.h"           // for CompositableHost
    1.11 +#include "LayersLogging.h"              // for AppendToString
    1.12 +#include "gfx2DGlue.h"                  // for ToIntSize
    1.13 +#include "mozilla/gfx/2D.h"             // for DataSourceSurface, Factory
    1.14 +#include "mozilla/ipc/Shmem.h"          // for Shmem
    1.15 +#include "mozilla/layers/Compositor.h"  // for Compositor
    1.16 +#include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
    1.17 +#include "mozilla/layers/ImageDataSerializer.h"
    1.18 +#include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor, etc
    1.19 +#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
    1.20 +#ifdef MOZ_X11
    1.21 +#include "mozilla/layers/X11TextureHost.h"
    1.22 +#endif
    1.23 +#include "mozilla/layers/YCbCrImageDataSerializer.h"
    1.24 +#include "nsAString.h"
    1.25 +#include "nsAutoPtr.h"                  // for nsRefPtr
    1.26 +#include "nsPrintfCString.h"            // for nsPrintfCString
    1.27 +#include "mozilla/layers/PTextureParent.h"
    1.28 +#include "mozilla/unused.h"
    1.29 +#include <limits>
    1.30 +
    1.31 +#if 0
    1.32 +#define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
    1.33 +#else
    1.34 +#define RECYCLE_LOG(...) do { } while (0)
    1.35 +#endif
    1.36 +
    1.37 +struct nsIntPoint;
    1.38 +
    1.39 +namespace mozilla {
    1.40 +namespace layers {
    1.41 +
    1.42 +/**
    1.43 + * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
    1.44 + * It is an IPDL actor just like LayerParent, CompositableParent, etc.
    1.45 + */
    1.46 +class TextureParent : public PTextureParent
    1.47 +{
    1.48 +public:
    1.49 +  TextureParent(ISurfaceAllocator* aAllocator);
    1.50 +
    1.51 +  ~TextureParent();
    1.52 +
    1.53 +  bool Init(const SurfaceDescriptor& aSharedData,
    1.54 +            const TextureFlags& aFlags);
    1.55 +
    1.56 +  void CompositorRecycle();
    1.57 +  virtual bool RecvClientRecycle() MOZ_OVERRIDE;
    1.58 +
    1.59 +  virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
    1.60 +
    1.61 +  virtual bool RecvRemoveTextureSync() MOZ_OVERRIDE;
    1.62 +
    1.63 +  TextureHost* GetTextureHost() { return mTextureHost; }
    1.64 +
    1.65 +  void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
    1.66 +
    1.67 +  ISurfaceAllocator* mAllocator;
    1.68 +  RefPtr<TextureHost> mWaitForClientRecycle;
    1.69 +  RefPtr<TextureHost> mTextureHost;
    1.70 +};
    1.71 +
    1.72 +// static
    1.73 +PTextureParent*
    1.74 +TextureHost::CreateIPDLActor(ISurfaceAllocator* aAllocator,
    1.75 +                             const SurfaceDescriptor& aSharedData,
    1.76 +                             TextureFlags aFlags)
    1.77 +{
    1.78 +  if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory &&
    1.79 +      !aAllocator->IsSameProcess())
    1.80 +  {
    1.81 +    NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
    1.82 +    return nullptr;
    1.83 +  }
    1.84 +  TextureParent* actor = new TextureParent(aAllocator);
    1.85 +  if (!actor->Init(aSharedData, aFlags)) {
    1.86 +    delete actor;
    1.87 +    return nullptr;
    1.88 +  }
    1.89 +  return actor;
    1.90 +}
    1.91 +
    1.92 +// static
    1.93 +bool
    1.94 +TextureHost::DestroyIPDLActor(PTextureParent* actor)
    1.95 +{
    1.96 +  delete actor;
    1.97 +  return true;
    1.98 +}
    1.99 +
   1.100 +// static
   1.101 +bool
   1.102 +TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
   1.103 +{
   1.104 +  return PTextureParent::Send__delete__(actor);
   1.105 +}
   1.106 +
   1.107 +// static
   1.108 +TextureHost*
   1.109 +TextureHost::AsTextureHost(PTextureParent* actor)
   1.110 +{
   1.111 +  return actor? static_cast<TextureParent*>(actor)->mTextureHost : nullptr;
   1.112 +}
   1.113 +
   1.114 +PTextureParent*
   1.115 +TextureHost::GetIPDLActor()
   1.116 +{
   1.117 +  return mActor;
   1.118 +}
   1.119 +
   1.120 +// implemented in TextureHostOGL.cpp
   1.121 +TemporaryRef<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
   1.122 +                                               ISurfaceAllocator* aDeallocator,
   1.123 +                                               TextureFlags aFlags);
   1.124 +
   1.125 +// implemented in TextureHostBasic.cpp
   1.126 +TemporaryRef<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
   1.127 +                                                 ISurfaceAllocator* aDeallocator,
   1.128 +                                                 TextureFlags aFlags);
   1.129 +
   1.130 +// implemented in TextureD3D11.cpp
   1.131 +TemporaryRef<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
   1.132 +                                                 ISurfaceAllocator* aDeallocator,
   1.133 +                                                 TextureFlags aFlags);
   1.134 +
   1.135 +// implemented in TextureD3D9.cpp
   1.136 +TemporaryRef<TextureHost> CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
   1.137 +                                                ISurfaceAllocator* aDeallocator,
   1.138 +                                                TextureFlags aFlags);
   1.139 +
   1.140 +// static
   1.141 +TemporaryRef<TextureHost>
   1.142 +TextureHost::Create(const SurfaceDescriptor& aDesc,
   1.143 +                    ISurfaceAllocator* aDeallocator,
   1.144 +                    TextureFlags aFlags)
   1.145 +{
   1.146 +  switch (aDesc.type()) {
   1.147 +    case SurfaceDescriptor::TSurfaceDescriptorShmem:
   1.148 +    case SurfaceDescriptor::TSurfaceDescriptorMemory:
   1.149 +      return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
   1.150 +    case SurfaceDescriptor::TSharedTextureDescriptor:
   1.151 +    case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
   1.152 +    case SurfaceDescriptor::TSurfaceStreamDescriptor:
   1.153 +      return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
   1.154 +    case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
   1.155 +      if (Compositor::GetBackend() == LayersBackend::LAYERS_OPENGL) {
   1.156 +        return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
   1.157 +      } else {
   1.158 +        return CreateTextureHostBasic(aDesc, aDeallocator, aFlags);
   1.159 +      }
   1.160 +#ifdef MOZ_X11
   1.161 +    case SurfaceDescriptor::TSurfaceDescriptorX11: {
   1.162 +      const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11();
   1.163 +      RefPtr<TextureHost> result = new X11TextureHost(aFlags, desc);
   1.164 +      return result;
   1.165 +    }
   1.166 +#endif
   1.167 +#ifdef XP_WIN
   1.168 +    case SurfaceDescriptor::TSurfaceDescriptorD3D9:
   1.169 +    case SurfaceDescriptor::TSurfaceDescriptorDIB:
   1.170 +      return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
   1.171 +    case SurfaceDescriptor::TSurfaceDescriptorD3D10:
   1.172 +      if (Compositor::GetBackend() == LayersBackend::LAYERS_D3D9) {
   1.173 +        return CreateTextureHostD3D9(aDesc, aDeallocator, aFlags);
   1.174 +      } else {
   1.175 +        return CreateTextureHostD3D11(aDesc, aDeallocator, aFlags);
   1.176 +      }
   1.177 +#endif
   1.178 +    default:
   1.179 +      MOZ_CRASH("Unsupported Surface type");
   1.180 +  }
   1.181 +}
   1.182 +
   1.183 +TemporaryRef<TextureHost>
   1.184 +CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
   1.185 +                                    ISurfaceAllocator* aDeallocator,
   1.186 +                                    TextureFlags aFlags)
   1.187 +{
   1.188 +  RefPtr<TextureHost> result;
   1.189 +  switch (aDesc.type()) {
   1.190 +    case SurfaceDescriptor::TSurfaceDescriptorShmem: {
   1.191 +      const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem();
   1.192 +      result = new ShmemTextureHost(descriptor.data(),
   1.193 +                                    descriptor.format(),
   1.194 +                                    aDeallocator,
   1.195 +                                    aFlags);
   1.196 +      break;
   1.197 +    }
   1.198 +    case SurfaceDescriptor::TSurfaceDescriptorMemory: {
   1.199 +      const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory();
   1.200 +      result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()),
   1.201 +                                     descriptor.format(),
   1.202 +                                     aFlags);
   1.203 +      break;
   1.204 +    }
   1.205 +    default: {
   1.206 +      NS_WARNING("No backend independent TextureHost for this descriptor type");
   1.207 +    }
   1.208 +  }
   1.209 +  return result;
   1.210 +}
   1.211 +
   1.212 +void
   1.213 +TextureHost::CompositorRecycle()
   1.214 +{
   1.215 +  if (!mActor) {
   1.216 +    return;
   1.217 +  }
   1.218 +  static_cast<TextureParent*>(mActor)->CompositorRecycle();
   1.219 +}
   1.220 +
   1.221 +void
   1.222 +TextureHost::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
   1.223 +{
   1.224 +    mCompositableBackendData = aBackendData;
   1.225 +}
   1.226 +
   1.227 +
   1.228 +TextureHost::TextureHost(TextureFlags aFlags)
   1.229 +    : mActor(nullptr)
   1.230 +    , mFlags(aFlags)
   1.231 +{}
   1.232 +
   1.233 +TextureHost::~TextureHost()
   1.234 +{
   1.235 +}
   1.236 +
   1.237 +void TextureHost::Finalize()
   1.238 +{
   1.239 +  if (!(GetFlags() & TEXTURE_DEALLOCATE_CLIENT)) {
   1.240 +    DeallocateSharedData();
   1.241 +    DeallocateDeviceData();
   1.242 +  }
   1.243 +}
   1.244 +
   1.245 +void
   1.246 +TextureHost::PrintInfo(nsACString& aTo, const char* aPrefix)
   1.247 +{
   1.248 +  aTo += aPrefix;
   1.249 +  aTo += nsPrintfCString("%s (0x%p)", Name(), this);
   1.250 +  // Note: the TextureHost needs to be locked before it is safe to call
   1.251 +  //       GetSize() and GetFormat() on it.
   1.252 +  if (Lock()) {
   1.253 +    AppendToString(aTo, GetSize(), " [size=", "]");
   1.254 +    AppendToString(aTo, GetFormat(), " [format=", "]");
   1.255 +    Unlock();
   1.256 +  }
   1.257 +  AppendToString(aTo, mFlags, " [flags=", "]");
   1.258 +}
   1.259 +
   1.260 +void
   1.261 +TextureSource::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
   1.262 +{
   1.263 +    mCompositableBackendData = aBackendData;
   1.264 +}
   1.265 +
   1.266 +TextureSource::TextureSource()
   1.267 +{
   1.268 +    MOZ_COUNT_CTOR(TextureSource);
   1.269 +}
   1.270 +TextureSource::~TextureSource()
   1.271 +{
   1.272 +    MOZ_COUNT_DTOR(TextureSource);
   1.273 +}
   1.274 +
   1.275 +BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
   1.276 +                                     TextureFlags aFlags)
   1.277 +: TextureHost(aFlags)
   1.278 +, mCompositor(nullptr)
   1.279 +, mFormat(aFormat)
   1.280 +, mUpdateSerial(1)
   1.281 +, mLocked(false)
   1.282 +, mPartialUpdate(false)
   1.283 +{}
   1.284 +
   1.285 +BufferTextureHost::~BufferTextureHost()
   1.286 +{}
   1.287 +
   1.288 +void
   1.289 +BufferTextureHost::Updated(const nsIntRegion* aRegion)
   1.290 +{
   1.291 +  ++mUpdateSerial;
   1.292 +  if (aRegion) {
   1.293 +    mPartialUpdate = true;
   1.294 +    mMaybeUpdatedRegion = *aRegion;
   1.295 +  } else {
   1.296 +    mPartialUpdate = false;
   1.297 +  }
   1.298 +  if (GetFlags() & TEXTURE_IMMEDIATE_UPLOAD) {
   1.299 +    DebugOnly<bool> result = MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr);
   1.300 +    NS_WARN_IF_FALSE(result, "Failed to upload a texture");
   1.301 +  }
   1.302 +}
   1.303 +
   1.304 +void
   1.305 +BufferTextureHost::SetCompositor(Compositor* aCompositor)
   1.306 +{
   1.307 +  if (mCompositor == aCompositor) {
   1.308 +    return;
   1.309 +  }
   1.310 +  RefPtr<NewTextureSource> it = mFirstSource;
   1.311 +  while (it) {
   1.312 +    it->SetCompositor(aCompositor);
   1.313 +    it = it->GetNextSibling();
   1.314 +  }
   1.315 +  mCompositor = aCompositor;
   1.316 +}
   1.317 +
   1.318 +void
   1.319 +BufferTextureHost::DeallocateDeviceData()
   1.320 +{
   1.321 +  RefPtr<NewTextureSource> it = mFirstSource;
   1.322 +  while (it) {
   1.323 +    it->DeallocateDeviceData();
   1.324 +    it = it->GetNextSibling();
   1.325 +  }
   1.326 +}
   1.327 +
   1.328 +bool
   1.329 +BufferTextureHost::Lock()
   1.330 +{
   1.331 +  mLocked = true;
   1.332 +  return true;
   1.333 +}
   1.334 +
   1.335 +void
   1.336 +BufferTextureHost::Unlock()
   1.337 +{
   1.338 +  mLocked = false;
   1.339 +}
   1.340 +
   1.341 +NewTextureSource*
   1.342 +BufferTextureHost::GetTextureSources()
   1.343 +{
   1.344 +  MOZ_ASSERT(mLocked, "should never be called while not locked");
   1.345 +  if (!MaybeUpload(mPartialUpdate ? &mMaybeUpdatedRegion : nullptr)) {
   1.346 +      return nullptr;
   1.347 +  }
   1.348 +  return mFirstSource;
   1.349 +}
   1.350 +
   1.351 +gfx::SurfaceFormat
   1.352 +BufferTextureHost::GetFormat() const
   1.353 +{
   1.354 +  // mFormat is the format of the data that we share with the content process.
   1.355 +  // GetFormat, on the other hand, expects the format that we present to the
   1.356 +  // Compositor (it is used to choose the effect type).
   1.357 +  // if the compositor does not support YCbCr effects, we give it a RGBX texture
   1.358 +  // instead (see BufferTextureHost::Upload)
   1.359 +  if (mFormat == gfx::SurfaceFormat::YUV &&
   1.360 +    mCompositor &&
   1.361 +    !mCompositor->SupportsEffect(EFFECT_YCBCR)) {
   1.362 +    return gfx::SurfaceFormat::R8G8B8X8;
   1.363 +  }
   1.364 +  return mFormat;
   1.365 +}
   1.366 +
   1.367 +bool
   1.368 +BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
   1.369 +{
   1.370 +  if (mFirstSource && mFirstSource->GetUpdateSerial() == mUpdateSerial) {
   1.371 +    return true;
   1.372 +  }
   1.373 +  if (!Upload(aRegion)) {
   1.374 +    return false;
   1.375 +  }
   1.376 +  mFirstSource->SetUpdateSerial(mUpdateSerial);
   1.377 +  return true;
   1.378 +}
   1.379 +
   1.380 +bool
   1.381 +BufferTextureHost::Upload(nsIntRegion *aRegion)
   1.382 +{
   1.383 +  if (!GetBuffer()) {
   1.384 +    // We don't have a buffer; a possible cause is that the IPDL actor
   1.385 +    // is already dead. This inevitably happens as IPDL actors can die
   1.386 +    // at any time, so we want to silently return in this case.
   1.387 +    return false;
   1.388 +  }
   1.389 +  if (!mCompositor) {
   1.390 +    NS_WARNING("Tried to upload without a compositor. Skipping texture upload...");
   1.391 +    // If we are in this situation it means we should have called SetCompositor
   1.392 +    // earlier. It is conceivable that on certain rare conditions with async-video
   1.393 +    // we may end up here for the first frame, but this should not happen repeatedly.
   1.394 +    return false;
   1.395 +  }
   1.396 +  if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
   1.397 +    NS_WARNING("BufferTextureHost: unsupported format!");
   1.398 +    return false;
   1.399 +  } else if (mFormat == gfx::SurfaceFormat::YUV) {
   1.400 +    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
   1.401 +    MOZ_ASSERT(yuvDeserializer.IsValid());
   1.402 +
   1.403 +    if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) {
   1.404 +      RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
   1.405 +      if (!mFirstSource) {
   1.406 +        mFirstSource = mCompositor->CreateDataTextureSource(mFlags);
   1.407 +      }
   1.408 +      mFirstSource->Update(surf, aRegion);
   1.409 +      return true;
   1.410 +    }
   1.411 +
   1.412 +    RefPtr<DataTextureSource> srcY;
   1.413 +    RefPtr<DataTextureSource> srcU;
   1.414 +    RefPtr<DataTextureSource> srcV;
   1.415 +    if (!mFirstSource) {
   1.416 +      // We don't support BigImages for YCbCr compositing.
   1.417 +      srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   1.418 +      srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   1.419 +      srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE);
   1.420 +      mFirstSource = srcY;
   1.421 +      srcY->SetNextSibling(srcU);
   1.422 +      srcU->SetNextSibling(srcV);
   1.423 +    } else {
   1.424 +      // mFormat never changes so if this was created as a YCbCr host and already
   1.425 +      // contains a source it should already have 3 sources.
   1.426 +      // BufferTextureHost only uses DataTextureSources so it is safe to assume
   1.427 +      // all 3 sources are DataTextureSource.
   1.428 +      MOZ_ASSERT(mFirstSource->GetNextSibling());
   1.429 +      MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
   1.430 +      srcY = mFirstSource;
   1.431 +      srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
   1.432 +      srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
   1.433 +    }
   1.434 +
   1.435 +
   1.436 +    RefPtr<gfx::DataSourceSurface> tempY =
   1.437 +      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
   1.438 +                                                    yuvDeserializer.GetYStride(),
   1.439 +                                                    yuvDeserializer.GetYSize(),
   1.440 +                                                    gfx::SurfaceFormat::A8);
   1.441 +    RefPtr<gfx::DataSourceSurface> tempCb =
   1.442 +      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
   1.443 +                                                    yuvDeserializer.GetCbCrStride(),
   1.444 +                                                    yuvDeserializer.GetCbCrSize(),
   1.445 +                                                    gfx::SurfaceFormat::A8);
   1.446 +    RefPtr<gfx::DataSourceSurface> tempCr =
   1.447 +      gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
   1.448 +                                                    yuvDeserializer.GetCbCrStride(),
   1.449 +                                                    yuvDeserializer.GetCbCrSize(),
   1.450 +                                                    gfx::SurfaceFormat::A8);
   1.451 +    // We don't support partial updates for Y U V textures
   1.452 +    NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
   1.453 +    if (!srcY->Update(tempY) ||
   1.454 +        !srcU->Update(tempCb) ||
   1.455 +        !srcV->Update(tempCr)) {
   1.456 +      NS_WARNING("failed to update the DataTextureSource");
   1.457 +      return false;
   1.458 +    }
   1.459 +  } else {
   1.460 +    // non-YCbCr case
   1.461 +    if (!mFirstSource) {
   1.462 +      mFirstSource = mCompositor->CreateDataTextureSource();
   1.463 +    }
   1.464 +    ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
   1.465 +    if (!deserializer.IsValid()) {
   1.466 +      NS_ERROR("Failed to deserialize image!");
   1.467 +      return false;
   1.468 +    }
   1.469 +
   1.470 +    RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface();
   1.471 +    if (!surf) {
   1.472 +      return false;
   1.473 +    }
   1.474 +
   1.475 +    if (!mFirstSource->Update(surf.get(), aRegion)) {
   1.476 +      NS_WARNING("failed to update the DataTextureSource");
   1.477 +      return false;
   1.478 +    }
   1.479 +  }
   1.480 +  return true;
   1.481 +}
   1.482 +
   1.483 +TemporaryRef<gfx::DataSourceSurface>
   1.484 +BufferTextureHost::GetAsSurface()
   1.485 +{
   1.486 +  RefPtr<gfx::DataSourceSurface> result;
   1.487 +  if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
   1.488 +    NS_WARNING("BufferTextureHost: unsupported format!");
   1.489 +    return nullptr;
   1.490 +  } else if (mFormat == gfx::SurfaceFormat::YUV) {
   1.491 +    YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
   1.492 +    if (!yuvDeserializer.IsValid()) {
   1.493 +      return nullptr;
   1.494 +    }
   1.495 +    result = yuvDeserializer.ToDataSourceSurface();
   1.496 +  } else {
   1.497 +    ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
   1.498 +    if (!deserializer.IsValid()) {
   1.499 +      NS_ERROR("Failed to deserialize image!");
   1.500 +      return nullptr;
   1.501 +    }
   1.502 +    result = deserializer.GetAsSurface();
   1.503 +  }
   1.504 +  return result.forget();
   1.505 +}
   1.506 +
   1.507 +ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
   1.508 +                                   gfx::SurfaceFormat aFormat,
   1.509 +                                   ISurfaceAllocator* aDeallocator,
   1.510 +                                   TextureFlags aFlags)
   1.511 +: BufferTextureHost(aFormat, aFlags)
   1.512 +, mShmem(new ipc::Shmem(aShmem))
   1.513 +, mDeallocator(aDeallocator)
   1.514 +{
   1.515 +  MOZ_COUNT_CTOR(ShmemTextureHost);
   1.516 +}
   1.517 +
   1.518 +ShmemTextureHost::~ShmemTextureHost()
   1.519 +{
   1.520 +  DeallocateDeviceData();
   1.521 +  delete mShmem;
   1.522 +  MOZ_COUNT_DTOR(ShmemTextureHost);
   1.523 +}
   1.524 +
   1.525 +void
   1.526 +ShmemTextureHost::DeallocateSharedData()
   1.527 +{
   1.528 +  if (mShmem) {
   1.529 +    MOZ_ASSERT(mDeallocator,
   1.530 +               "Shared memory would leak without a ISurfaceAllocator");
   1.531 +    mDeallocator->DeallocShmem(*mShmem);
   1.532 +    delete mShmem;
   1.533 +    mShmem = nullptr;
   1.534 +  }
   1.535 +}
   1.536 +
   1.537 +void
   1.538 +ShmemTextureHost::ForgetSharedData()
   1.539 +{
   1.540 +  if (mShmem) {
   1.541 +    delete mShmem;
   1.542 +    mShmem = nullptr;
   1.543 +  }
   1.544 +}
   1.545 +
   1.546 +void
   1.547 +ShmemTextureHost::OnShutdown()
   1.548 +{
   1.549 +  delete mShmem;
   1.550 +  mShmem = nullptr;
   1.551 +}
   1.552 +
   1.553 +uint8_t* ShmemTextureHost::GetBuffer()
   1.554 +{
   1.555 +  return mShmem ? mShmem->get<uint8_t>() : nullptr;
   1.556 +}
   1.557 +
   1.558 +size_t ShmemTextureHost::GetBufferSize()
   1.559 +{
   1.560 +  return mShmem ? mShmem->Size<uint8_t>() : 0;
   1.561 +}
   1.562 +
   1.563 +MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
   1.564 +                                     gfx::SurfaceFormat aFormat,
   1.565 +                                     TextureFlags aFlags)
   1.566 +: BufferTextureHost(aFormat, aFlags)
   1.567 +, mBuffer(aBuffer)
   1.568 +{
   1.569 +  MOZ_COUNT_CTOR(MemoryTextureHost);
   1.570 +}
   1.571 +
   1.572 +MemoryTextureHost::~MemoryTextureHost()
   1.573 +{
   1.574 +  DeallocateDeviceData();
   1.575 +  NS_ASSERTION(!mBuffer || (mFlags & TEXTURE_DEALLOCATE_CLIENT),
   1.576 +               "Leaking our buffer");
   1.577 +  MOZ_COUNT_DTOR(MemoryTextureHost);
   1.578 +}
   1.579 +
   1.580 +void
   1.581 +MemoryTextureHost::DeallocateSharedData()
   1.582 +{
   1.583 +  if (mBuffer) {
   1.584 +    GfxMemoryImageReporter::WillFree(mBuffer);
   1.585 +  }
   1.586 +  delete[] mBuffer;
   1.587 +  mBuffer = nullptr;
   1.588 +}
   1.589 +
   1.590 +void
   1.591 +MemoryTextureHost::ForgetSharedData()
   1.592 +{
   1.593 +  mBuffer = nullptr;
   1.594 +}
   1.595 +
   1.596 +uint8_t* MemoryTextureHost::GetBuffer()
   1.597 +{
   1.598 +  return mBuffer;
   1.599 +}
   1.600 +
   1.601 +size_t MemoryTextureHost::GetBufferSize()
   1.602 +{
   1.603 +  // MemoryTextureHost just trusts that the buffer size is large enough to read
   1.604 +  // anything we need to. That's because MemoryTextureHost has to trust the buffer
   1.605 +  // pointer anyway, so the security model here is just that MemoryTexture's
   1.606 +  // are restricted to same-process clients.
   1.607 +  return std::numeric_limits<size_t>::max();
   1.608 +}
   1.609 +
   1.610 +TextureParent::TextureParent(ISurfaceAllocator* aAllocator)
   1.611 +: mAllocator(aAllocator)
   1.612 +{
   1.613 +  MOZ_COUNT_CTOR(TextureParent);
   1.614 +}
   1.615 +
   1.616 +TextureParent::~TextureParent()
   1.617 +{
   1.618 +  MOZ_COUNT_DTOR(TextureParent);
   1.619 +  if (mTextureHost) {
   1.620 +    mTextureHost->ClearRecycleCallback();
   1.621 +  }
   1.622 +}
   1.623 +
   1.624 +static void RecycleCallback(TextureHost* textureHost, void* aClosure) {
   1.625 +  TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure);
   1.626 +  tp->CompositorRecycle();
   1.627 +}
   1.628 +
   1.629 +void
   1.630 +TextureParent::CompositorRecycle()
   1.631 +{
   1.632 +  mTextureHost->ClearRecycleCallback();
   1.633 +
   1.634 +  MaybeFenceHandle handle = null_t();
   1.635 +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   1.636 +  if (mTextureHost) {
   1.637 +    TextureHostOGL* hostOGL = mTextureHost->AsHostOGL();
   1.638 +    android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
   1.639 +    if (fence.get() && fence->isValid()) {
   1.640 +      handle = FenceHandle(fence);
   1.641 +      // HWC might not provide Fence.
   1.642 +      // In this case, HWC implicitly handles buffer's fence.
   1.643 +    }
   1.644 +  }
   1.645 +#endif
   1.646 +  mozilla::unused << SendCompositorRecycle(handle);
   1.647 +
   1.648 +  // Don't forget to prepare for the next reycle
   1.649 +  // if TextureClient request it.
   1.650 +  if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
   1.651 +    mWaitForClientRecycle = mTextureHost;
   1.652 +  }
   1.653 +}
   1.654 +
   1.655 +bool
   1.656 +TextureParent::RecvClientRecycle()
   1.657 +{
   1.658 +  // This will allow the RecycleCallback to be called once the compositor
   1.659 +  // releases any external references to TextureHost.
   1.660 +  mTextureHost->SetRecycleCallback(RecycleCallback, this);
   1.661 +  if (!mWaitForClientRecycle) {
   1.662 +    RECYCLE_LOG("Not a recycable tile");
   1.663 +  }
   1.664 +  mWaitForClientRecycle = nullptr;
   1.665 +  return true;
   1.666 +}
   1.667 +
   1.668 +bool
   1.669 +TextureParent::Init(const SurfaceDescriptor& aSharedData,
   1.670 +                    const TextureFlags& aFlags)
   1.671 +{
   1.672 +  mTextureHost = TextureHost::Create(aSharedData,
   1.673 +                                     mAllocator,
   1.674 +                                     aFlags);
   1.675 +  if (mTextureHost) {
   1.676 +    mTextureHost->mActor = this;
   1.677 +    if (aFlags & TEXTURE_RECYCLE) {
   1.678 +      mWaitForClientRecycle = mTextureHost;
   1.679 +      RECYCLE_LOG("Setup recycling for tile %p\n", this);
   1.680 +    }
   1.681 +  }
   1.682 +
   1.683 +  return !!mTextureHost;
   1.684 +}
   1.685 +
   1.686 +bool
   1.687 +TextureParent::RecvRemoveTexture()
   1.688 +{
   1.689 +  return PTextureParent::Send__delete__(this);
   1.690 +}
   1.691 +
   1.692 +bool
   1.693 +TextureParent::RecvRemoveTextureSync()
   1.694 +{
   1.695 +  // we don't need to send a reply in the synchronous case since the child side
   1.696 +  // has the guarantee that this message has been handled synchronously.
   1.697 +  return PTextureParent::Send__delete__(this);
   1.698 +}
   1.699 +
   1.700 +void
   1.701 +TextureParent::ActorDestroy(ActorDestroyReason why)
   1.702 +{
   1.703 +  if (!mTextureHost) {
   1.704 +    return;
   1.705 +  }
   1.706 +
   1.707 +  switch (why) {
   1.708 +  case AncestorDeletion:
   1.709 +  case Deletion:
   1.710 +  case NormalShutdown:
   1.711 +  case AbnormalShutdown:
   1.712 +    break;
   1.713 +  case FailedConstructor:
   1.714 +    NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   1.715 +  }
   1.716 +
   1.717 +  if (mTextureHost->GetFlags() & TEXTURE_RECYCLE) {
   1.718 +    RECYCLE_LOG("clear recycling for tile %p\n", this);
   1.719 +    mTextureHost->ClearRecycleCallback();
   1.720 +  }
   1.721 +  if (mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) {
   1.722 +    mTextureHost->ForgetSharedData();
   1.723 +  }
   1.724 +
   1.725 +  // Clear recycle callback.
   1.726 +  mTextureHost->ClearRecycleCallback();
   1.727 +  mWaitForClientRecycle = nullptr;
   1.728 +
   1.729 +  mTextureHost->mActor = nullptr;
   1.730 +  mTextureHost = nullptr;
   1.731 +}
   1.732 +
   1.733 +} // namespace
   1.734 +} // namespace

mercurial