1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/TextureClient.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,533 @@ 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 +#ifndef MOZILLA_GFX_TEXTURECLIENT_H 1.10 +#define MOZILLA_GFX_TEXTURECLIENT_H 1.11 + 1.12 +#include <stddef.h> // for size_t 1.13 +#include <stdint.h> // for uint32_t, uint8_t, uint64_t 1.14 +#include "GLContextTypes.h" // for GLContext (ptr only), etc 1.15 +#include "GLTextureImage.h" // for TextureImage 1.16 +#include "ImageTypes.h" // for StereoMode 1.17 +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 1.18 +#include "mozilla/Attributes.h" // for MOZ_OVERRIDE 1.19 +#include "mozilla/RefPtr.h" // for RefPtr, RefCounted 1.20 +#include "mozilla/gfx/2D.h" // for DrawTarget 1.21 +#include "mozilla/gfx/Point.h" // for IntSize 1.22 +#include "mozilla/gfx/Types.h" // for SurfaceFormat 1.23 +#include "mozilla/layers/FenceUtils.h" // for FenceHandle 1.24 +#include "mozilla/ipc/Shmem.h" // for Shmem 1.25 +#include "mozilla/layers/AtomicRefCountedWithFinalize.h" 1.26 +#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc 1.27 +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor 1.28 +#include "mozilla/layers/PTextureChild.h" // for PTextureChild 1.29 +#include "mozilla/mozalloc.h" // for operator delete 1.30 +#include "nsAutoPtr.h" // for nsRefPtr 1.31 +#include "nsCOMPtr.h" // for already_AddRefed 1.32 +#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc 1.33 + 1.34 +class gfxReusableSurfaceWrapper; 1.35 +class gfxImageSurface; 1.36 + 1.37 +namespace mozilla { 1.38 +namespace layers { 1.39 + 1.40 +class ContentClient; 1.41 +class CompositableForwarder; 1.42 +class ISurfaceAllocator; 1.43 +class CompositableClient; 1.44 +class PlanarYCbCrImage; 1.45 +class PlanarYCbCrData; 1.46 +class Image; 1.47 +class PTextureChild; 1.48 +class TextureChild; 1.49 +class BufferTextureClient; 1.50 +class TextureClient; 1.51 + 1.52 +/** 1.53 + * TextureClient is the abstraction that allows us to share data between the 1.54 + * content and the compositor side. 1.55 + */ 1.56 + 1.57 +enum TextureAllocationFlags { 1.58 + ALLOC_DEFAULT = 0, 1.59 + ALLOC_CLEAR_BUFFER = 1 1.60 +}; 1.61 + 1.62 +/** 1.63 + * Interface for TextureClients that can be updated using YCbCr data. 1.64 + */ 1.65 +class TextureClientYCbCr 1.66 +{ 1.67 +public: 1.68 + /** 1.69 + * Copy aData into this texture client. 1.70 + * 1.71 + * This must never be called on a TextureClient that is not sucessfully locked. 1.72 + */ 1.73 + virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) = 0; 1.74 + 1.75 + /** 1.76 + * Allocates for a given surface size, taking into account the pixel format 1.77 + * which is part of the state of the TextureClient. 1.78 + * 1.79 + * Does not clear the surface, since we consider that the surface 1.80 + * be painted entirely with opaque content. 1.81 + */ 1.82 + virtual bool AllocateForYCbCr(gfx::IntSize aYSize, 1.83 + gfx::IntSize aCbCrSize, 1.84 + StereoMode aStereoMode) = 0; 1.85 +}; 1.86 + 1.87 +/** 1.88 + * Holds the shared data of a TextureClient, to be destroyed later. 1.89 + * 1.90 + * TextureClient's destructor initiates the destruction sequence of the 1.91 + * texture client/host pair. If the shared data is to be deallocated on the 1.92 + * host side, there is nothing to do. 1.93 + * On the other hand, if the client data must be deallocated on the client 1.94 + * side, the CompositableClient will ask the TextureClient to drop its shared 1.95 + * data in the form of a TextureClientData object. This data will be kept alive 1.96 + * until the host side confirms that it is not using the data anymore and that 1.97 + * it is completely safe to deallocate the shared data. 1.98 + * 1.99 + * See: 1.100 + * - The PTexture IPDL protocol 1.101 + * - CompositableChild in TextureClient.cpp 1.102 + */ 1.103 +class TextureClientData { 1.104 +public: 1.105 + virtual void DeallocateSharedData(ISurfaceAllocator* allocator) = 0; 1.106 + virtual ~TextureClientData() {} 1.107 +}; 1.108 + 1.109 +/** 1.110 + * TextureClient is a thin abstraction over texture data that need to be shared 1.111 + * between the content process and the compositor process. It is the 1.112 + * content-side half of a TextureClient/TextureHost pair. A corresponding 1.113 + * TextureHost lives on the compositor-side. 1.114 + * 1.115 + * TextureClient's primary purpose is to present texture data in a way that is 1.116 + * understood by the IPC system. There are two ways to use it: 1.117 + * - Use it to serialize image data that is not IPC-friendly (most likely 1.118 + * involving a copy into shared memory) 1.119 + * - preallocate it and paint directly into it, which avoids copy but requires 1.120 + * the painting code to be aware of TextureClient (or at least the underlying 1.121 + * shared memory). 1.122 + * 1.123 + * There is always one and only one TextureClient per TextureHost, and the 1.124 + * TextureClient/Host pair only owns one buffer of image data through its 1.125 + * lifetime. This means that the lifetime of the underlying shared data 1.126 + * matches the lifetime of the TextureClient/Host pair. It also means 1.127 + * TextureClient/Host do not implement double buffering, which is the 1.128 + * responsibility of the compositable (which would use two Texture pairs). 1.129 + * In order to send several different buffers to the compositor side, use 1.130 + * several TextureClients. 1.131 + */ 1.132 +class TextureClient 1.133 + : public AtomicRefCountedWithFinalize<TextureClient> 1.134 +{ 1.135 +public: 1.136 + TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT); 1.137 + virtual ~TextureClient(); 1.138 + 1.139 + static TemporaryRef<BufferTextureClient> 1.140 + CreateBufferTextureClient(ISurfaceAllocator* aAllocator, 1.141 + gfx::SurfaceFormat aFormat, 1.142 + TextureFlags aTextureFlags, 1.143 + gfx::BackendType aMoz2dBackend); 1.144 + 1.145 + static TemporaryRef<TextureClient> 1.146 + CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator, 1.147 + gfx::SurfaceFormat aFormat, 1.148 + TextureFlags aTextureFlags, 1.149 + gfx::BackendType aMoz2dBackend, 1.150 + const gfx::IntSize& aSizeHint); 1.151 + 1.152 + virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; } 1.153 + 1.154 + /** 1.155 + * Locks the shared data, allowing the caller to get access to it. 1.156 + * 1.157 + * Please always lock/unlock when accessing the shared data. 1.158 + * If Lock() returns false, you should not attempt to access the shared data. 1.159 + */ 1.160 + virtual bool Lock(OpenMode aMode) { return IsValid(); } 1.161 + 1.162 + virtual void Unlock() {} 1.163 + 1.164 + virtual bool IsLocked() const = 0; 1.165 + 1.166 + virtual bool CanExposeDrawTarget() const { return false; } 1.167 + 1.168 + /** 1.169 + * Returns a DrawTarget to draw into the TextureClient. 1.170 + * 1.171 + * This must never be called on a TextureClient that is not sucessfully locked. 1.172 + * When called several times within one Lock/Unlock pair, this method should 1.173 + * return the same DrawTarget. 1.174 + * The DrawTarget is automatically flushed by the TextureClient when the latter 1.175 + * is unlocked, and the DrawTarget that will be returned within the next 1.176 + * lock/unlock pair may or may not be the same object. 1.177 + * Do not keep references to the DrawTarget outside of the lock/unlock pair. 1.178 + * 1.179 + * This is typically used as follows: 1.180 + * 1.181 + * if (!texture->Lock(OPEN_READ_WRITE)) { 1.182 + * return false; 1.183 + * } 1.184 + * { 1.185 + * // Restrict this code's scope to ensure all references to dt are gone 1.186 + * // when Unlock is called. 1.187 + * RefPtr<DrawTarget> dt = texture->GetAsDrawTarget(); 1.188 + * // use the draw target ... 1.189 + * } 1.190 + * texture->Unlock(); 1.191 + * 1.192 + */ 1.193 + virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() { return nullptr; } 1.194 + 1.195 + // TextureClients that can expose a DrawTarget should override this method. 1.196 + virtual gfx::SurfaceFormat GetFormat() const 1.197 + { 1.198 + return gfx::SurfaceFormat::UNKNOWN; 1.199 + } 1.200 + 1.201 + /** 1.202 + * Allocates for a given surface size, taking into account the pixel format 1.203 + * which is part of the state of the TextureClient. 1.204 + * 1.205 + * Does not clear the surface by default, clearing the surface can be done 1.206 + * by passing the CLEAR_BUFFER flag. 1.207 + * 1.208 + * TextureClients that can expose a DrawTarget should override this method. 1.209 + */ 1.210 + virtual bool AllocateForSurface(gfx::IntSize aSize, 1.211 + TextureAllocationFlags flags = ALLOC_DEFAULT) 1.212 + { 1.213 + return false; 1.214 + } 1.215 + 1.216 + /** 1.217 + * Copies a rectangle from this texture client to a position in aTarget. 1.218 + * It is assumed that the necessary locks are in place; so this should at 1.219 + * least have a read lock and aTarget should at least have a write lock. 1.220 + */ 1.221 + virtual bool CopyToTextureClient(TextureClient* aTarget, 1.222 + const gfx::IntRect* aRect, 1.223 + const gfx::IntPoint* aPoint); 1.224 + 1.225 + /** 1.226 + * Returns true if this texture has a lock/unlock mechanism. 1.227 + * Textures that do not implement locking should be immutable or should 1.228 + * use immediate uploads (see TextureFlags in CompositorTypes.h) 1.229 + */ 1.230 + virtual bool ImplementsLocking() const { return false; } 1.231 + 1.232 + /** 1.233 + * Indicates whether the TextureClient implementation is backed by an 1.234 + * in-memory buffer. The consequence of this is that locking the 1.235 + * TextureClient does not contend with locking the texture on the host side. 1.236 + */ 1.237 + virtual bool HasInternalBuffer() const = 0; 1.238 + 1.239 + /** 1.240 + * Allocate and deallocate a TextureChild actor. 1.241 + * 1.242 + * TextureChild is an implementation detail of TextureClient that is not 1.243 + * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor 1.244 + * are for use with the managing IPDL protocols only (so that they can 1.245 + * implement AllocPextureChild and DeallocPTextureChild). 1.246 + */ 1.247 + static PTextureChild* CreateIPDLActor(); 1.248 + static bool DestroyIPDLActor(PTextureChild* actor); 1.249 + 1.250 + /** 1.251 + * Get the TextureClient corresponding to the actor passed in parameter. 1.252 + */ 1.253 + static TextureClient* AsTextureClient(PTextureChild* actor); 1.254 + 1.255 + virtual bool IsAllocated() const = 0; 1.256 + 1.257 + virtual gfx::IntSize GetSize() const = 0; 1.258 + 1.259 + /** 1.260 + * TextureFlags contain important information about various aspects 1.261 + * of the texture, like how its liferime is managed, and how it 1.262 + * should be displayed. 1.263 + * See TextureFlags in CompositorTypes.h. 1.264 + */ 1.265 + TextureFlags GetFlags() const { return mFlags; } 1.266 + 1.267 + /** 1.268 + * valid only for TEXTURE_RECYCLE TextureClient. 1.269 + * When called this texture client will grab a strong reference and release 1.270 + * it once the compositor notifies that it is done with the texture. 1.271 + * NOTE: In this stage the texture client can no longer be used by the 1.272 + * client in a transaction. 1.273 + */ 1.274 + void WaitForCompositorRecycle(); 1.275 + 1.276 + /** 1.277 + * After being shared with the compositor side, an immutable texture is never 1.278 + * modified, it can only be read. It is safe to not Lock/Unlock immutable 1.279 + * textures. 1.280 + */ 1.281 + bool IsImmutable() const { return mFlags & TEXTURE_IMMUTABLE; } 1.282 + 1.283 + void MarkImmutable() { AddFlags(TEXTURE_IMMUTABLE); } 1.284 + 1.285 + bool IsSharedWithCompositor() const { return mShared; } 1.286 + 1.287 + bool ShouldDeallocateInDestructor() const; 1.288 + 1.289 + /** 1.290 + * If this method returns false users of TextureClient are not allowed 1.291 + * to access the shared data. 1.292 + */ 1.293 + bool IsValid() const { return mValid; } 1.294 + 1.295 + /** 1.296 + * Create and init the TextureChild/Parent IPDL actor pair. 1.297 + * 1.298 + * Should be called only once per TextureClient. 1.299 + */ 1.300 + bool InitIPDLActor(CompositableForwarder* aForwarder); 1.301 + 1.302 + /** 1.303 + * Return a pointer to the IPDLActor. 1.304 + * 1.305 + * This is to be used with IPDL messages only. Do not store the returned 1.306 + * pointer. 1.307 + */ 1.308 + PTextureChild* GetIPDLActor(); 1.309 + 1.310 + /** 1.311 + * Triggers the destruction of the shared data and the corresponding TextureHost. 1.312 + * 1.313 + * If the texture flags contain TEXTURE_DEALLOCATE_CLIENT, the destruction 1.314 + * will be synchronously coordinated with the compositor side, otherwise it 1.315 + * will be done asynchronously. 1.316 + */ 1.317 + void ForceRemove(); 1.318 + 1.319 + virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) {} 1.320 + 1.321 + const FenceHandle& GetReleaseFenceHandle() const 1.322 + { 1.323 + return mReleaseFenceHandle; 1.324 + } 1.325 + 1.326 + /** 1.327 + * Wait until the current buffer is no longer being read. 1.328 + * 1.329 + * Platform support is necessary. gonk JB supports this function. 1.330 + */ 1.331 + virtual void WaitReleaseFence() {} 1.332 + 1.333 +private: 1.334 + /** 1.335 + * Called once, just before the destructor. 1.336 + * 1.337 + * Here goes the shut-down code that uses virtual methods. 1.338 + * Must only be called by Release(). 1.339 + */ 1.340 + void Finalize(); 1.341 + 1.342 + friend class AtomicRefCountedWithFinalize<TextureClient>; 1.343 + 1.344 +protected: 1.345 + /** 1.346 + * An invalid TextureClient cannot provide access to its shared data 1.347 + * anymore. This usually means it will soon be destroyed. 1.348 + */ 1.349 + void MarkInvalid() { mValid = false; } 1.350 + 1.351 + /** 1.352 + * Drop the shared data into a TextureClientData object and mark this 1.353 + * TextureClient as invalid. 1.354 + * 1.355 + * The TextureClient must not hold any reference to the shared data 1.356 + * after this method has been called. 1.357 + * The TextureClientData is owned by the caller. 1.358 + */ 1.359 + virtual TextureClientData* DropTextureData() = 0; 1.360 + 1.361 + /** 1.362 + * Should only be called *once* per texture, in TextureClient::InitIPDLActor. 1.363 + * Some texture implementations rely on the fact that the descriptor will be 1.364 + * deserialized. 1.365 + * Calling ToSurfaceDescriptor again after it has already returned true, 1.366 + * or never constructing a TextureHost with aDescriptor may result in a memory 1.367 + * leak (see CairoTextureClientD3D9 for example). 1.368 + */ 1.369 + virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0; 1.370 + 1.371 + void AddFlags(TextureFlags aFlags) 1.372 + { 1.373 + MOZ_ASSERT(!IsSharedWithCompositor()); 1.374 + mFlags |= aFlags; 1.375 + } 1.376 + 1.377 + RefPtr<TextureChild> mActor; 1.378 + TextureFlags mFlags; 1.379 + bool mShared; 1.380 + bool mValid; 1.381 + FenceHandle mReleaseFenceHandle; 1.382 + 1.383 + friend class TextureChild; 1.384 + friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*); 1.385 + friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&); 1.386 +}; 1.387 + 1.388 +/** 1.389 + * TextureClient that wraps a random access buffer such as a Shmem or raw memory. 1.390 + * This class must be inherited to implement the memory allocation and access bits. 1.391 + * (see ShmemTextureClient and MemoryTextureClient) 1.392 + */ 1.393 +class BufferTextureClient : public TextureClient 1.394 + , public TextureClientYCbCr 1.395 +{ 1.396 +public: 1.397 + BufferTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, 1.398 + gfx::BackendType aBackend, TextureFlags aFlags); 1.399 + 1.400 + virtual ~BufferTextureClient(); 1.401 + 1.402 + virtual bool IsAllocated() const = 0; 1.403 + 1.404 + virtual uint8_t* GetBuffer() const = 0; 1.405 + 1.406 + virtual gfx::IntSize GetSize() const { return mSize; } 1.407 + 1.408 + virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE; 1.409 + 1.410 + virtual void Unlock() MOZ_OVERRIDE; 1.411 + 1.412 + virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; } 1.413 + 1.414 + virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; } 1.415 + 1.416 + virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE; 1.417 + 1.418 + virtual bool AllocateForSurface(gfx::IntSize aSize, 1.419 + TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE; 1.420 + 1.421 + // TextureClientYCbCr 1.422 + 1.423 + virtual TextureClientYCbCr* AsTextureClientYCbCr() MOZ_OVERRIDE { return this; } 1.424 + 1.425 + virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) MOZ_OVERRIDE; 1.426 + 1.427 + virtual bool AllocateForYCbCr(gfx::IntSize aYSize, 1.428 + gfx::IntSize aCbCrSize, 1.429 + StereoMode aStereoMode) MOZ_OVERRIDE; 1.430 + 1.431 + virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; } 1.432 + 1.433 + // XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected. 1.434 + // these two methods should only be called by methods of BufferTextureClient 1.435 + // that are overridden in GrallocTextureClient (which does not implement the 1.436 + // two methods below) 1.437 + virtual bool Allocate(uint32_t aSize) = 0; 1.438 + 1.439 + virtual size_t GetBufferSize() const = 0; 1.440 + 1.441 + virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } 1.442 + 1.443 + ISurfaceAllocator* GetAllocator() const; 1.444 + 1.445 +protected: 1.446 + RefPtr<gfx::DrawTarget> mDrawTarget; 1.447 + RefPtr<ISurfaceAllocator> mAllocator; 1.448 + gfx::SurfaceFormat mFormat; 1.449 + gfx::IntSize mSize; 1.450 + gfx::BackendType mBackend; 1.451 + OpenMode mOpenMode; 1.452 + bool mUsingFallbackDrawTarget; 1.453 + bool mLocked; 1.454 +}; 1.455 + 1.456 +/** 1.457 + * TextureClient that wraps shared memory. 1.458 + * the corresponding texture on the host side is ShmemTextureHost. 1.459 + */ 1.460 +class ShmemTextureClient : public BufferTextureClient 1.461 +{ 1.462 +public: 1.463 + ShmemTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, 1.464 + gfx::BackendType aBackend, TextureFlags aFlags); 1.465 + 1.466 + ~ShmemTextureClient(); 1.467 + 1.468 + virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; 1.469 + 1.470 + virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE; 1.471 + 1.472 + virtual uint8_t* GetBuffer() const MOZ_OVERRIDE; 1.473 + 1.474 + virtual size_t GetBufferSize() const MOZ_OVERRIDE; 1.475 + 1.476 + virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; } 1.477 + 1.478 + virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; 1.479 + 1.480 + virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } 1.481 + 1.482 + mozilla::ipc::Shmem& GetShmem() { return mShmem; } 1.483 + 1.484 +protected: 1.485 + mozilla::ipc::Shmem mShmem; 1.486 + bool mAllocated; 1.487 +}; 1.488 + 1.489 +/** 1.490 + * TextureClient that wraps raw memory. 1.491 + * The corresponding texture on the host side is MemoryTextureHost. 1.492 + * Can obviously not be used in a cross process setup. 1.493 + */ 1.494 +class MemoryTextureClient : public BufferTextureClient 1.495 +{ 1.496 +public: 1.497 + MemoryTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat, 1.498 + gfx::BackendType aBackend, TextureFlags aFlags); 1.499 + 1.500 + ~MemoryTextureClient(); 1.501 + 1.502 + virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) MOZ_OVERRIDE; 1.503 + 1.504 + virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE; 1.505 + 1.506 + virtual uint8_t* GetBuffer() const MOZ_OVERRIDE { return mBuffer; } 1.507 + 1.508 + virtual size_t GetBufferSize() const MOZ_OVERRIDE { return mBufSize; } 1.509 + 1.510 + virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; } 1.511 + 1.512 + virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; } 1.513 + 1.514 + virtual TextureClientData* DropTextureData() MOZ_OVERRIDE; 1.515 + 1.516 +protected: 1.517 + uint8_t* mBuffer; 1.518 + size_t mBufSize; 1.519 +}; 1.520 + 1.521 +struct TextureClientAutoUnlock 1.522 +{ 1.523 + TextureClient* mTexture; 1.524 + 1.525 + TextureClientAutoUnlock(TextureClient* aTexture) 1.526 + : mTexture(aTexture) {} 1.527 + 1.528 + ~TextureClientAutoUnlock() 1.529 + { 1.530 + mTexture->Unlock(); 1.531 + } 1.532 +}; 1.533 + 1.534 +} 1.535 +} 1.536 +#endif