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