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