1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef MOZILLA_GFX_TEXTURECLIENT_H 8 #define MOZILLA_GFX_TEXTURECLIENT_H 9 10 #include <stddef.h> // for size_t 11 #include <stdint.h> // for uint32_t, uint8_t, uint64_t 12 13 #include "GLTextureImage.h" // for TextureImage 14 #include "GfxTexturesReporter.h" 15 #include "ImageTypes.h" // for StereoMode 16 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 17 #include "mozilla/Atomics.h" 18 #include "mozilla/Attributes.h" // for override 19 #include "mozilla/DebugOnly.h" 20 #include "mozilla/RefPtr.h" // for RefPtr, RefCounted 21 #include "mozilla/gfx/2D.h" // for DrawTarget 22 #include "mozilla/gfx/CriticalSection.h" 23 #include "mozilla/gfx/Point.h" // for IntSize 24 #include "mozilla/gfx/Types.h" // for SurfaceFormat 25 #include "mozilla/ipc/FileDescriptor.h" 26 #include "mozilla/ipc/Shmem.h" // for Shmem 27 #include "mozilla/layers/AtomicRefCountedWithFinalize.h" 28 #include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc 29 #include "mozilla/layers/ISurfaceAllocator.h" 30 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor 31 #include "mozilla/layers/LayersTypes.h" 32 #include "mozilla/layers/SyncObject.h" 33 #include "mozilla/mozalloc.h" // for operator delete 34 #include "mozilla/webrender/WebRenderTypes.h" 35 #include "nsCOMPtr.h" // for already_AddRefed 36 #include "nsISupportsImpl.h" // for TextureImage::AddRef, etc 37 #include "nsThreadUtils.h" 38 #include "pratom.h" 39 40 class gfxImageSurface; 41 struct ID3D11Device; 42 43 namespace mozilla { 44 45 // When defined, we track which pool the tile came from and test for 46 // any inconsistencies. This can be defined in release build as well. 47 #ifdef DEBUG 48 # define GFX_DEBUG_TRACK_CLIENTS_IN_POOL 1 49 #endif 50 51 namespace layers { 52 53 class AndroidHardwareBufferTextureData; 54 class BufferTextureData; 55 class CompositableForwarder; 56 class KnowsCompositor; 57 class LayersIPCChannel; 58 class CompositableClient; 59 struct PlanarYCbCrData; 60 class Image; 61 class PTextureChild; 62 class TextureChild; 63 class TextureData; 64 class GPUVideoTextureData; 65 struct RawTextureBuffer; 66 class RawYCbCrTextureBuffer; 67 class TextureClient; 68 class ITextureClientRecycleAllocator; 69 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL 70 class TextureClientPool; 71 #endif 72 class TextureForwarder; 73 class KeepAlive; 74 75 /** 76 * TextureClient is the abstraction that allows us to share data between the 77 * content and the compositor side. 78 */ 79 80 enum TextureAllocationFlags { 81 ALLOC_DEFAULT = 0, 82 ALLOC_CLEAR_BUFFER = 83 1 << 1, // Clear the buffer to whatever is best for the draw target 84 ALLOC_CLEAR_BUFFER_WHITE = 1 << 2, // explicit all white 85 ALLOC_CLEAR_BUFFER_BLACK = 1 << 3, // explicit all black 86 ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4, 87 88 // Allocate the texture for out-of-band content updates. This is mostly for 89 // TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex 90 // surfaces when used on the main thread. 91 ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5, 92 93 // Disable any cross-device synchronization. This is also for 94 // TextureClientD3D11, and creates a texture without KeyedMutex. 95 ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6, 96 97 // The texture is going to be updated using UpdateFromSurface and needs to 98 // support that call. 99 ALLOC_UPDATE_FROM_SURFACE = 1 << 7, 100 101 // In practice, this means we support the APPLE_client_storage extension, 102 // meaning the buffer will not be internally copied by the graphics driver. 103 ALLOC_ALLOW_DIRECT_MAPPING = 1 << 8, 104 }; 105 106 /** 107 * This class may be used to asynchronously receive an update when the content 108 * drawn to this texture client is available for reading in CPU memory. This 109 * can only be used on texture clients that support draw target creation. 110 */ 111 class TextureReadbackSink { 112 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadbackSink) 113 public: 114 /** 115 * Callback function to implement in order to receive a DataSourceSurface 116 * containing the data read back from the texture client. This will always 117 * be called on the main thread, and this may not hold on to the 118 * DataSourceSurface beyond the execution of this function. 119 */ 120 virtual void ProcessReadback(gfx::DataSourceSurface* aSourceSurface) = 0; 121 122 protected: 123 virtual ~TextureReadbackSink() = default; 124 }; 125 126 enum class BackendSelector { Content, Canvas }; 127 128 /// Temporary object providing direct access to a Texture's memory. 129 /// 130 /// see TextureClient::CanExposeMappedData() and 131 /// TextureClient::BorrowMappedData(). 132 struct MappedTextureData { 133 uint8_t* data; 134 gfx::IntSize size; 135 int32_t stride; 136 gfx::SurfaceFormat format; 137 }; 138 139 struct MappedYCbCrChannelData { 140 uint8_t* data; 141 gfx::IntSize size; 142 int32_t stride; 143 int32_t skip; 144 uint32_t bytesPerPixel; 145 146 bool CopyInto(MappedYCbCrChannelData& aDst); 147 }; 148 149 struct MappedYCbCrTextureData { 150 MappedYCbCrChannelData y; 151 MappedYCbCrChannelData cb; 152 MappedYCbCrChannelData cr; 153 // Sad but because of how SharedPlanarYCbCrData is used we have to expose this 154 // for now. 155 uint8_t* metadata; 156 StereoMode stereoMode; 157 CopyIntoMappedYCbCrTextureData158 bool CopyInto(MappedYCbCrTextureData& aDst) { 159 return y.CopyInto(aDst.y) && cb.CopyInto(aDst.cb) && cr.CopyInto(aDst.cr); 160 } 161 }; 162 163 class ReadLockDescriptor; 164 class NonBlockingTextureReadLock; 165 166 // A class to help implement copy-on-write semantics for shared textures. 167 // 168 // A TextureClient/Host pair can opt into using a ReadLock by calling 169 // TextureClient::EnableReadLock. This will equip the TextureClient with a 170 // ReadLock object that will be automatically ReadLock()'ed by the texture 171 // itself when it is written into (see TextureClient::Unlock). A 172 // TextureReadLock's counter starts at 1 and is expected to be equal to 1 when 173 // the lock is destroyed. See ShmemTextureReadLock for explanations about why we 174 // use 1 instead of 0 as the initial state. TextureReadLock is mostly internally 175 // managed by the TextureClient/Host pair, and the compositable only has to 176 // forward it during updates. If an update message contains a null_t lock, it 177 // means that the texture was not written into on the content side, and there is 178 // no synchronization required on the compositor side (or it means that the 179 // texture pair did not opt into using ReadLocks). On the compositor side, the 180 // TextureHost can receive a ReadLock during a transaction, and will both 181 // ReadUnlock() it and drop it as soon as the shared data is available again for 182 // writing (the texture upload is done, or the compositor not reading the 183 // texture anymore). The lock is dropped to make sure it is ReadUnlock()'ed only 184 // once. 185 class TextureReadLock { 186 protected: 187 virtual ~TextureReadLock() = default; 188 189 public: 190 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadLock) 191 192 virtual bool ReadLock() = 0; TryReadLock(TimeDuration aTimeout)193 virtual bool TryReadLock(TimeDuration aTimeout) { return ReadLock(); } 194 virtual int32_t ReadUnlock() = 0; 195 virtual bool IsValid() const = 0; 196 197 static already_AddRefed<TextureReadLock> Deserialize( 198 const ReadLockDescriptor& aDescriptor, ISurfaceAllocator* aAllocator); 199 200 virtual bool Serialize(ReadLockDescriptor& aOutput, 201 base::ProcessId aOther) = 0; 202 203 enum LockType { 204 TYPE_NONBLOCKING_MEMORY, 205 TYPE_NONBLOCKING_SHMEM, 206 TYPE_CROSS_PROCESS_SEMAPHORE 207 }; 208 virtual LockType GetType() = 0; 209 AsNonBlockingLock()210 virtual NonBlockingTextureReadLock* AsNonBlockingLock() { return nullptr; } 211 212 protected: 213 NS_DECL_OWNINGTHREAD 214 }; 215 216 class NonBlockingTextureReadLock : public TextureReadLock { 217 public: 218 virtual int32_t GetReadCount() = 0; 219 220 static already_AddRefed<TextureReadLock> Create(LayersIPCChannel* aAllocator); 221 AsNonBlockingLock()222 NonBlockingTextureReadLock* AsNonBlockingLock() override { return this; } 223 }; 224 225 #ifdef XP_WIN 226 class D3D11TextureData; 227 class DXGIYCbCrTextureData; 228 #endif 229 230 class TextureData { 231 public: 232 struct Info { 233 gfx::IntSize size; 234 gfx::SurfaceFormat format; 235 bool hasIntermediateBuffer; 236 bool hasSynchronization; 237 bool supportsMoz2D; 238 bool canExposeMappedData; 239 bool canConcurrentlyReadLock; 240 InfoInfo241 Info() 242 : format(gfx::SurfaceFormat::UNKNOWN), 243 hasIntermediateBuffer(false), 244 hasSynchronization(false), 245 supportsMoz2D(false), 246 canExposeMappedData(false), 247 canConcurrentlyReadLock(true) {} 248 }; 249 250 static TextureData* Create(TextureForwarder* aAllocator, 251 gfx::SurfaceFormat aFormat, gfx::IntSize aSize, 252 KnowsCompositor* aKnowsCompositor, 253 BackendSelector aSelector, 254 TextureFlags aTextureFlags, 255 TextureAllocationFlags aAllocFlags); 256 257 static bool IsRemote(KnowsCompositor* aKnowsCompositor, 258 BackendSelector aSelector); 259 260 MOZ_COUNTED_DTOR_VIRTUAL(TextureData) 261 262 virtual void FillInfo(TextureData::Info& aInfo) const = 0; 263 264 virtual bool Lock(OpenMode aMode) = 0; 265 266 virtual void Unlock() = 0; 267 BorrowDrawTarget()268 virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { 269 return nullptr; 270 } 271 BorrowSnapshot()272 virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() { 273 return nullptr; 274 } 275 BorrowMappedData(MappedTextureData &)276 virtual bool BorrowMappedData(MappedTextureData&) { return false; } 277 BorrowMappedYCbCrData(MappedYCbCrTextureData &)278 virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; } 279 280 virtual void Deallocate(LayersIPCChannel* aAllocator) = 0; 281 282 /// Depending on the texture's flags either Deallocate or Forget is called. Forget(LayersIPCChannel * aAllocator)283 virtual void Forget(LayersIPCChannel* aAllocator) {} 284 285 virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0; GetSubDescriptor(RemoteDecoderVideoSubDescriptor * aOutDesc)286 virtual void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) {} 287 OnForwardedToHost()288 virtual void OnForwardedToHost() {} 289 290 virtual TextureData* CreateSimilar( 291 LayersIPCChannel* aAllocator, LayersBackend aLayersBackend, 292 TextureFlags aFlags = TextureFlags::DEFAULT, 293 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const { 294 return nullptr; 295 } 296 UpdateFromSurface(gfx::SourceSurface * aSurface)297 virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) { 298 return false; 299 }; 300 ReadBack(TextureReadbackSink * aReadbackSink)301 virtual bool ReadBack(TextureReadbackSink* aReadbackSink) { return false; } 302 SyncWithObject(RefPtr<SyncObjectClient> aSyncObject)303 virtual void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject){}; 304 GetTextureFlags()305 virtual TextureFlags GetTextureFlags() const { 306 return TextureFlags::NO_FLAGS; 307 } 308 309 #ifdef XP_WIN AsD3D11TextureData()310 virtual D3D11TextureData* AsD3D11TextureData() { return nullptr; } AsDXGIYCbCrTextureData()311 virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() { return nullptr; } 312 #endif 313 AsBufferTextureData()314 virtual BufferTextureData* AsBufferTextureData() { return nullptr; } 315 AsGPUVideoTextureData()316 virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; } 317 318 virtual AndroidHardwareBufferTextureData* AsAndroidHardwareBufferTextureData()319 AsAndroidHardwareBufferTextureData() { 320 return nullptr; 321 } 322 323 // It is used by AndroidHardwareBufferTextureData and 324 // SharedSurfaceTextureData. Returns buffer id when it owns 325 // AndroidHardwareBuffer. It is used only on android. GetBufferId()326 virtual Maybe<uint64_t> GetBufferId() const { return Nothing(); } 327 328 // The acquire fence is a fence that is used for waiting until rendering to 329 // its AHardwareBuffer is completed. 330 // It is used only on android. GetAcquireFence()331 virtual mozilla::ipc::FileDescriptor GetAcquireFence() { 332 return mozilla::ipc::FileDescriptor(); 333 } 334 335 protected: 336 MOZ_COUNTED_DEFAULT_CTOR(TextureData) 337 }; 338 339 /** 340 * TextureClient is a thin abstraction over texture data that need to be shared 341 * between the content process and the compositor process. It is the 342 * content-side half of a TextureClient/TextureHost pair. A corresponding 343 * TextureHost lives on the compositor-side. 344 * 345 * TextureClient's primary purpose is to present texture data in a way that is 346 * understood by the IPC system. There are two ways to use it: 347 * - Use it to serialize image data that is not IPC-friendly (most likely 348 * involving a copy into shared memory) 349 * - preallocate it and paint directly into it, which avoids copy but requires 350 * the painting code to be aware of TextureClient (or at least the underlying 351 * shared memory). 352 * 353 * There is always one and only one TextureClient per TextureHost, and the 354 * TextureClient/Host pair only owns one buffer of image data through its 355 * lifetime. This means that the lifetime of the underlying shared data 356 * matches the lifetime of the TextureClient/Host pair. It also means 357 * TextureClient/Host do not implement double buffering, which is the 358 * responsibility of the compositable (which would use pairs of Textures). 359 * In order to send several different buffers to the compositor side, use 360 * several TextureClients. 361 */ 362 class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> { 363 public: 364 TextureClient(TextureData* aData, TextureFlags aFlags, 365 LayersIPCChannel* aAllocator); 366 367 virtual ~TextureClient(); 368 369 static already_AddRefed<TextureClient> CreateWithData( 370 TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator); 371 372 // Creates and allocates a TextureClient usable with Moz2D. 373 static already_AddRefed<TextureClient> CreateForDrawing( 374 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, 375 gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags, 376 TextureAllocationFlags flags = ALLOC_DEFAULT); 377 378 static already_AddRefed<TextureClient> CreateFromSurface( 379 KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface, 380 BackendSelector aSelector, TextureFlags aTextureFlags, 381 TextureAllocationFlags aAllocFlags); 382 383 // Creates and allocates a TextureClient supporting the YCbCr format. 384 static already_AddRefed<TextureClient> CreateForYCbCr( 385 KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay, 386 const gfx::IntSize& aYSize, uint32_t aYStride, 387 const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride, 388 StereoMode aStereoMode, gfx::ColorDepth aColorDepth, 389 gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange, 390 TextureFlags aTextureFlags); 391 392 // Creates and allocates a TextureClient (can be accessed through raw 393 // pointers). 394 static already_AddRefed<TextureClient> CreateForRawBufferAccess( 395 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, 396 gfx::IntSize aSize, gfx::BackendType aMoz2dBackend, 397 TextureFlags aTextureFlags, TextureAllocationFlags flags = ALLOC_DEFAULT); 398 399 // Creates and allocates a TextureClient of the same type. 400 already_AddRefed<TextureClient> CreateSimilar( 401 LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE, 402 TextureFlags aFlags = TextureFlags::DEFAULT, 403 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const; 404 405 /** 406 * Locks the shared data, allowing the caller to get access to it. 407 * 408 * Please always lock/unlock when accessing the shared data. 409 * If Lock() returns false, you should not attempt to access the shared data. 410 */ 411 bool Lock(OpenMode aMode); 412 413 void Unlock(); 414 IsLocked()415 bool IsLocked() const { return mIsLocked; } 416 GetSize()417 gfx::IntSize GetSize() const { return mInfo.size; } 418 GetFormat()419 gfx::SurfaceFormat GetFormat() const { return mInfo.format; } 420 421 /** 422 * Returns true if this texture has a synchronization mechanism (mutex, fence, 423 * etc.). Textures that do not implement synchronization should be immutable 424 * or should use immediate uploads (see TextureFlags in CompositorTypes.h) 425 * Even if a texture does not implement synchronization, Lock and Unlock need 426 * to be used appropriately since the latter are also there to map/numap data. 427 */ HasSynchronization()428 bool HasSynchronization() const { return mInfo.hasSynchronization; } 429 430 /** 431 * Indicates whether the TextureClient implementation is backed by an 432 * in-memory buffer. The consequence of this is that locking the 433 * TextureClient does not contend with locking the texture on the host side. 434 */ HasIntermediateBuffer()435 bool HasIntermediateBuffer() const { return mInfo.hasIntermediateBuffer; } 436 CanExposeDrawTarget()437 bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; } 438 CanExposeMappedData()439 bool CanExposeMappedData() const { return mInfo.canExposeMappedData; } 440 441 /** 442 * Returns a DrawTarget to draw into the TextureClient. 443 * This function should never be called when not on the main thread! 444 * 445 * This must never be called on a TextureClient that is not sucessfully 446 * locked. When called several times within one Lock/Unlock pair, this method 447 * should return the same DrawTarget. The DrawTarget is automatically flushed 448 * by the TextureClient when the latter is unlocked, and the DrawTarget that 449 * will be returned within the next lock/unlock pair may or may not be the 450 * same object. Do not keep references to the DrawTarget outside of the 451 * lock/unlock pair. 452 * 453 * This is typically used as follows: 454 * 455 * if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) { 456 * return false; 457 * } 458 * { 459 * // Restrict this code's scope to ensure all references to dt are gone 460 * // when Unlock is called. 461 * DrawTarget* dt = texture->BorrowDrawTarget(); 462 * // use the draw target ... 463 * } 464 * texture->Unlock(); 465 * 466 */ 467 gfx::DrawTarget* BorrowDrawTarget(); 468 469 already_AddRefed<gfx::SourceSurface> BorrowSnapshot(); 470 471 /** 472 * Similar to BorrowDrawTarget but provides direct access to the texture's 473 * bits instead of a DrawTarget. 474 */ 475 bool BorrowMappedData(MappedTextureData&); 476 bool BorrowMappedYCbCrData(MappedYCbCrTextureData&); 477 478 /** 479 * This function can be used to update the contents of the TextureClient 480 * off the main thread. 481 */ 482 void UpdateFromSurface(gfx::SourceSurface* aSurface); 483 484 /** 485 * This method is strictly for debugging. It causes locking and 486 * needless copies. 487 */ 488 already_AddRefed<gfx::DataSourceSurface> GetAsSurface(); 489 490 virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); 491 492 /** 493 * Copies a rectangle from this texture client to a position in aTarget. 494 * It is assumed that the necessary locks are in place; so this should at 495 * least have a read lock and aTarget should at least have a write lock. 496 */ 497 bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect, 498 const gfx::IntPoint* aPoint); 499 500 /** 501 * Allocate and deallocate a TextureChild actor. 502 * 503 * TextureChild is an implementation detail of TextureClient that is not 504 * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor 505 * are for use with the managing IPDL protocols only (so that they can 506 * implement AllocPextureChild and DeallocPTextureChild). 507 */ 508 static PTextureChild* CreateIPDLActor(); 509 static bool DestroyIPDLActor(PTextureChild* actor); 510 511 /** 512 * Get the TextureClient corresponding to the actor passed in parameter. 513 */ 514 static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor); 515 516 /** 517 * TextureFlags contain important information about various aspects 518 * of the texture, like how its liferime is managed, and how it 519 * should be displayed. 520 * See TextureFlags in CompositorTypes.h. 521 */ GetFlags()522 TextureFlags GetFlags() const { return mFlags; } 523 HasFlags(TextureFlags aFlags)524 bool HasFlags(TextureFlags aFlags) const { 525 return (mFlags & aFlags) == aFlags; 526 } 527 528 void AddFlags(TextureFlags aFlags); 529 530 void RemoveFlags(TextureFlags aFlags); 531 532 // Must not be called when TextureClient is in use by CompositableClient. 533 void RecycleTexture(TextureFlags aFlags); 534 535 /** 536 * After being shared with the compositor side, an immutable texture is never 537 * modified, it can only be read. It is safe to not Lock/Unlock immutable 538 * textures. 539 */ IsImmutable()540 bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); } 541 MarkImmutable()542 void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); } 543 544 bool IsSharedWithCompositor() const; 545 546 /** 547 * If this method returns false users of TextureClient are not allowed 548 * to access the shared data. 549 */ IsValid()550 bool IsValid() const { return !!mData; } 551 552 /** 553 * Called when TextureClient is added to CompositableClient. 554 */ 555 void SetAddedToCompositableClient(); 556 557 /** 558 * If this method retuns false, TextureClient is already added to 559 * CompositableClient, since its creation or recycling. 560 */ IsAddedToCompositableClient()561 bool IsAddedToCompositableClient() const { 562 return mAddedToCompositableClient; 563 } 564 565 /** 566 * Create and init the TextureChild/Parent IPDL actor pair 567 * with a CompositableForwarder. 568 * 569 * Should be called only once per TextureClient. 570 * The TextureClient must not be locked when calling this method. 571 */ 572 bool InitIPDLActor(CompositableForwarder* aForwarder); 573 574 /** 575 * Create and init the TextureChild/Parent IPDL actor pair 576 * with a TextureForwarder. 577 * 578 * Should be called only once per TextureClient. 579 * The TextureClient must not be locked when calling this method. 580 */ 581 bool InitIPDLActor(KnowsCompositor* aKnowsCompositor); 582 583 /** 584 * Return a pointer to the IPDLActor. 585 * 586 * This is to be used with IPDL messages only. Do not store the returned 587 * pointer. 588 */ 589 PTextureChild* GetIPDLActor(); 590 591 /** 592 * Triggers the destruction of the shared data and the corresponding 593 * TextureHost. 594 * 595 * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the 596 * destruction will be synchronously coordinated with the compositor side, 597 * otherwise it will be done asynchronously. 598 */ 599 void Destroy(); 600 601 /** 602 * Track how much of this texture is wasted. 603 * For example we might allocate a 256x256 tile but only use 10x10. 604 */ SetWaste(int aWasteArea)605 void SetWaste(int aWasteArea) { 606 mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat())); 607 } 608 609 /** 610 * This sets the readback sink that this texture is to use. This will 611 * receive the data for this texture as soon as it becomes available after 612 * texture unlock. 613 */ SetReadbackSink(TextureReadbackSink * aReadbackSink)614 virtual void SetReadbackSink(TextureReadbackSink* aReadbackSink) { 615 mReadbackSink = aReadbackSink; 616 } 617 SyncWithObject(RefPtr<SyncObjectClient> aSyncObject)618 void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) { 619 mData->SyncWithObject(aSyncObject); 620 } 621 GetAllocator()622 LayersIPCChannel* GetAllocator() { return mAllocator; } 623 GetRecycleAllocator()624 ITextureClientRecycleAllocator* GetRecycleAllocator() { 625 return mRecycleAllocator; 626 } 627 void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator); 628 629 /// If you add new code that uses this method, you are probably doing 630 /// something wrong. GetInternalData()631 TextureData* GetInternalData() { return mData; } GetInternalData()632 const TextureData* GetInternalData() const { return mData; } 633 GetSerial()634 uint64_t GetSerial() const { return mSerial; } 635 void GetSurfaceDescriptorRemoteDecoder( 636 SurfaceDescriptorRemoteDecoder* aOutDesc); 637 638 void CancelWaitForNotifyNotUsed(); 639 640 /** 641 * Set last transaction id of CompositableForwarder. 642 * 643 * Called when TextureClient has TextureFlags::RECYCLE flag. 644 * When CompositableForwarder forwards the TextureClient with 645 * TextureFlags::RECYCLE, it holds TextureClient's ref until host side 646 * releases it. The host side sends TextureClient release message. 647 * The id is used to check if the message is for the last TextureClient 648 * forwarding. 649 */ SetLastFwdTransactionId(uint64_t aTransactionId)650 void SetLastFwdTransactionId(uint64_t aTransactionId) { 651 MOZ_ASSERT(mFwdTransactionId <= aTransactionId); 652 mFwdTransactionId = aTransactionId; 653 } 654 GetLastFwdTransactionId()655 uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; } 656 GetReadLock()657 TextureReadLock* GetReadLock() { return mReadLock; } 658 659 bool IsReadLocked() const; 660 661 bool TryReadLock(); 662 void ReadUnlock(); 663 SetUpdated()664 void SetUpdated() { mUpdated = true; } 665 666 bool OnForwardedToHost(); 667 668 // Mark that the TextureClient will be used by the paint thread, and should 669 // not free its underlying texture data. This must only be called from the 670 // main thread. 671 void AddPaintThreadRef(); 672 673 // Mark that the TextureClient is no longer in use by the PaintThread. This 674 // must only be called from the PaintThread. 675 void DropPaintThreadRef(); 676 GetExternalImageKey()677 wr::MaybeExternalImageId GetExternalImageKey() { return mExternalImageId; } 678 679 private: 680 static void TextureClientRecycleCallback(TextureClient* aClient, 681 void* aClosure); 682 683 // Internal helpers for creating texture clients using the actual forwarder 684 // instead of KnowsCompositor. TextureClientPool uses these to let it cache 685 // texture clients per-process instead of per ShadowLayerForwarder, but 686 // everyone else should use the public functions instead. 687 friend class TextureClientPool; 688 static already_AddRefed<TextureClient> CreateForDrawing( 689 TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat, 690 gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor, 691 BackendSelector aSelector, TextureFlags aTextureFlags, 692 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT); 693 694 static already_AddRefed<TextureClient> CreateForRawBufferAccess( 695 LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat, 696 gfx::IntSize aSize, gfx::BackendType aMoz2dBackend, 697 LayersBackend aLayersBackend, TextureFlags aTextureFlags, 698 TextureAllocationFlags flags = ALLOC_DEFAULT); 699 700 void EnableReadLock(); 701 void EnableBlockingReadLock(); 702 703 /** 704 * Called once, during the destruction of the Texture, on the thread in which 705 * texture's reference count reaches 0 (could be any thread). 706 * 707 * Here goes the shut-down code that uses virtual methods. 708 * Must only be called by Release(). 709 */ Finalize()710 void Finalize() {} 711 712 friend class AtomicRefCountedWithFinalize<TextureClient>; 713 714 protected: 715 /** 716 * Should only be called *once* per texture, in TextureClient::InitIPDLActor. 717 * Some texture implementations rely on the fact that the descriptor will be 718 * deserialized. 719 * Calling ToSurfaceDescriptor again after it has already returned true, 720 * or never constructing a TextureHost with aDescriptor may result in a memory 721 * leak (see TextureClientD3D9 for example). 722 */ 723 bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor); 724 725 void LockActor() const; 726 void UnlockActor() const; 727 728 TextureData::Info mInfo; 729 730 RefPtr<LayersIPCChannel> mAllocator; 731 RefPtr<TextureChild> mActor; 732 RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator; 733 RefPtr<TextureReadLock> mReadLock; 734 735 TextureData* mData; 736 RefPtr<gfx::DrawTarget> mBorrowedDrawTarget; 737 738 TextureFlags mFlags; 739 740 gl::GfxTextureWasteTracker mWasteTracker; 741 742 OpenMode mOpenMode; 743 #ifdef DEBUG 744 uint32_t mExpectedDtRefs; 745 #endif 746 bool mIsLocked; 747 bool mIsReadLocked; 748 // This member tracks that the texture was written into until the update 749 // is sent to the compositor. We need this remember to lock mReadLock on 750 // behalf of the compositor just before sending the notification. 751 bool mUpdated; 752 753 // Used when TextureClient is recycled with TextureFlags::RECYCLE flag. 754 bool mAddedToCompositableClient; 755 756 RefPtr<TextureReadbackSink> mReadbackSink; 757 758 uint64_t mFwdTransactionId; 759 760 // Serial id of TextureClient. It is unique in current process. 761 const uint64_t mSerial; 762 763 // When non-zero, texture data must not be freed. 764 mozilla::Atomic<uintptr_t> mPaintThreadRefs; 765 766 // External image id. It is unique if it is allocated. 767 // The id is allocated in TextureClient::InitIPDLActor(). 768 // Its allocation is supported by 769 // CompositorBridgeChild and ImageBridgeChild for now. 770 wr::MaybeExternalImageId mExternalImageId; 771 772 // Used to assign serial ids of TextureClient. 773 static mozilla::Atomic<uint64_t> sSerialCounter; 774 775 friend class TextureChild; 776 friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*); 777 friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&); 778 friend already_AddRefed<TextureHost> CreateTextureHostWithBackend( 779 TextureClient*, ISurfaceAllocator*, LayersBackend&); 780 781 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL 782 public: 783 // Pointer to the pool this tile came from. 784 TextureClientPool* mPoolTracker; 785 #endif 786 }; 787 788 /** 789 * Task that releases TextureClient pointer on a specified thread. 790 */ 791 class TextureClientReleaseTask : public Runnable { 792 public: TextureClientReleaseTask(TextureClient * aClient)793 explicit TextureClientReleaseTask(TextureClient* aClient) 794 : Runnable("layers::TextureClientReleaseTask"), mTextureClient(aClient) {} 795 Run()796 NS_IMETHOD Run() override { 797 mTextureClient = nullptr; 798 return NS_OK; 799 } 800 801 private: 802 RefPtr<TextureClient> mTextureClient; 803 }; 804 805 // Automatically lock and unlock a texture. Since texture locking is fallible, 806 // Succeeded() must be checked on the guard object before proceeding. 807 class MOZ_RAII TextureClientAutoLock { 808 public: TextureClientAutoLock(TextureClient * aTexture,OpenMode aMode)809 TextureClientAutoLock(TextureClient* aTexture, OpenMode aMode) 810 : mTexture(aTexture), mSucceeded(false) { 811 mSucceeded = mTexture->Lock(aMode); 812 #ifdef DEBUG 813 mChecked = false; 814 #endif 815 } ~TextureClientAutoLock()816 ~TextureClientAutoLock() { 817 MOZ_ASSERT(mChecked); 818 if (mSucceeded) { 819 mTexture->Unlock(); 820 } 821 } 822 Succeeded()823 bool Succeeded() { 824 #ifdef DEBUG 825 mChecked = true; 826 #endif 827 return mSucceeded; 828 } 829 830 private: 831 TextureClient* mTexture; 832 #ifdef DEBUG 833 bool mChecked; 834 #endif 835 bool mSucceeded; 836 }; 837 838 // Automatically locks and unlocks two texture clients, and exposes them as a 839 // a single draw target dual. Since texture locking is fallible, Succeeded() 840 // must be checked on the guard object before proceeding. 841 class MOZ_RAII DualTextureClientAutoLock { 842 public: DualTextureClientAutoLock(TextureClient * aTexture,TextureClient * aTextureOnWhite,OpenMode aMode)843 DualTextureClientAutoLock(TextureClient* aTexture, 844 TextureClient* aTextureOnWhite, OpenMode aMode) 845 : mTarget(nullptr), mTexture(aTexture), mTextureOnWhite(aTextureOnWhite) { 846 if (!mTexture->Lock(aMode)) { 847 return; 848 } 849 850 mTarget = mTexture->BorrowDrawTarget(); 851 852 if (!mTarget) { 853 mTexture->Unlock(); 854 return; 855 } 856 857 if (!mTextureOnWhite) { 858 return; 859 } 860 861 if (!mTextureOnWhite->Lock(aMode)) { 862 mTarget = nullptr; 863 mTexture->Unlock(); 864 return; 865 } 866 867 RefPtr<gfx::DrawTarget> targetOnWhite = mTextureOnWhite->BorrowDrawTarget(); 868 869 if (!targetOnWhite) { 870 mTarget = nullptr; 871 mTexture->Unlock(); 872 mTextureOnWhite->Unlock(); 873 return; 874 } 875 876 mTarget = gfx::Factory::CreateDualDrawTarget(mTarget, targetOnWhite); 877 878 if (!mTarget) { 879 mTarget = nullptr; 880 mTexture->Unlock(); 881 mTextureOnWhite->Unlock(); 882 } 883 } 884 ~DualTextureClientAutoLock()885 ~DualTextureClientAutoLock() { 886 if (Succeeded()) { 887 mTarget = nullptr; 888 889 mTexture->Unlock(); 890 if (mTextureOnWhite) { 891 mTextureOnWhite->Unlock(); 892 } 893 } 894 } 895 Succeeded()896 bool Succeeded() const { return !!mTarget; } 897 898 operator gfx::DrawTarget*() const { return mTarget; } 899 gfx::DrawTarget* operator->() const { return mTarget; } 900 901 RefPtr<gfx::DrawTarget> mTarget; 902 903 private: 904 RefPtr<TextureClient> mTexture; 905 RefPtr<TextureClient> mTextureOnWhite; 906 }; 907 908 class KeepAlive { 909 public: 910 virtual ~KeepAlive() = default; 911 }; 912 913 template <typename T> 914 class TKeepAlive : public KeepAlive { 915 public: TKeepAlive(T * aData)916 explicit TKeepAlive(T* aData) : mData(aData) {} 917 918 protected: 919 RefPtr<T> mData; 920 }; 921 922 /// Convenience function to set the content of ycbcr texture. 923 bool UpdateYCbCrTextureClient(TextureClient* aTexture, 924 const PlanarYCbCrData& aData); 925 926 TextureType PreferredCanvasTextureType(KnowsCompositor* aKnowsCompositor); 927 928 } // namespace layers 929 } // namespace mozilla 930 931 #endif 932