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_TEXTUREHOST_H 8 #define MOZILLA_GFX_TEXTUREHOST_H 9 10 #include <stddef.h> // for size_t 11 #include <stdint.h> // for uint64_t, uint32_t, uint8_t 12 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 13 #include "mozilla/Attributes.h" // for override 14 #include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed, etc 15 #include "mozilla/gfx/Logging.h" 16 #include "mozilla/gfx/Matrix.h" 17 #include "mozilla/gfx/Point.h" // for IntSize, IntPoint 18 #include "mozilla/gfx/Rect.h" 19 #include "mozilla/gfx/Types.h" // for SurfaceFormat, etc 20 #include "mozilla/ipc/FileDescriptor.h" 21 #include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc 22 #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc 23 #include "mozilla/layers/LayersSurfaces.h" 24 #include "mozilla/mozalloc.h" // for operator delete 25 #include "mozilla/Range.h" 26 #include "mozilla/UniquePtr.h" // for UniquePtr 27 #include "mozilla/webrender/WebRenderTypes.h" 28 #include "nsCOMPtr.h" // for already_AddRefed 29 #include "nsDebug.h" // for NS_WARNING 30 #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc 31 #include "nsRect.h" 32 #include "nsRegion.h" // for nsIntRegion 33 #include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc 34 #include "nscore.h" // for nsACString 35 #include "mozilla/layers/AtomicRefCountedWithFinalize.h" 36 37 class MacIOSurface; 38 namespace mozilla { 39 namespace gfx { 40 class DataSourceSurface; 41 } 42 43 namespace ipc { 44 class Shmem; 45 } // namespace ipc 46 47 namespace wr { 48 class DisplayListBuilder; 49 class TransactionBuilder; 50 } // namespace wr 51 52 namespace layers { 53 54 class AndroidHardwareBuffer; 55 class AndroidHardwareBufferTextureHost; 56 class BufferDescriptor; 57 class BufferTextureHost; 58 class Compositor; 59 class CompositableParentManager; 60 class ReadLockDescriptor; 61 class CompositorBridgeParent; 62 class SurfaceDescriptor; 63 class HostIPCAllocator; 64 class ISurfaceAllocator; 65 class MacIOSurfaceTextureHostOGL; 66 class SurfaceTextureHost; 67 class TextureHostOGL; 68 class TextureReadLock; 69 class TextureSourceOGL; 70 class TextureSourceD3D11; 71 class TextureSourceBasic; 72 class TextureSourceProvider; 73 class DataTextureSource; 74 class PTextureParent; 75 class TextureParent; 76 class WebRenderTextureHost; 77 class WrappingTextureSourceYCbCrBasic; 78 79 /** 80 * A view on a TextureHost where the texture is internally represented as tiles 81 * (contrast with a tiled buffer, where each texture is a tile). For iteration 82 * by the texture's buffer host. This is only useful when the underlying surface 83 * is too big to fit in one device texture, which forces us to split it in 84 * smaller parts. Tiled Compositable is a different thing. 85 */ 86 class BigImageIterator { 87 public: 88 virtual void BeginBigImageIteration() = 0; EndBigImageIteration()89 virtual void EndBigImageIteration(){}; 90 virtual gfx::IntRect GetTileRect() = 0; 91 virtual size_t GetTileCount() = 0; 92 virtual bool NextTile() = 0; 93 }; 94 95 /** 96 * TextureSource is the interface for texture objects that can be composited 97 * by a given compositor backend. Since the drawing APIs are different 98 * between backends, the TextureSource interface is split into different 99 * interfaces (TextureSourceOGL, etc.), and TextureSource mostly provide 100 * access to these interfaces. 101 * 102 * This class is used on the compositor side. 103 */ 104 class TextureSource : public RefCounted<TextureSource> { 105 public: 106 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(TextureSource) 107 108 TextureSource(); 109 110 virtual ~TextureSource(); 111 112 virtual const char* Name() const = 0; 113 114 /** 115 * Should be overridden in order to deallocate the data that is associated 116 * with the rendering backend, such as GL textures. 117 */ DeallocateDeviceData()118 virtual void DeallocateDeviceData() {} 119 120 /** 121 * Return the size of the texture in texels. 122 * If this is a tile iterator, GetSize must return the size of the current 123 * tile. 124 */ 125 virtual gfx::IntSize GetSize() const = 0; 126 127 /** 128 * Return the pixel format of this texture 129 */ GetFormat()130 virtual gfx::SurfaceFormat GetFormat() const { 131 return gfx::SurfaceFormat::UNKNOWN; 132 } 133 134 /** 135 * Cast to a TextureSource for for each backend.. 136 */ AsSourceOGL()137 virtual TextureSourceOGL* AsSourceOGL() { 138 gfxCriticalNote << "Failed to cast " << Name() 139 << " into a TextureSourceOGL"; 140 return nullptr; 141 } AsSourceD3D11()142 virtual TextureSourceD3D11* AsSourceD3D11() { return nullptr; } AsSourceBasic()143 virtual TextureSourceBasic* AsSourceBasic() { return nullptr; } 144 /** 145 * Cast to a DataTextureSurce. 146 */ AsDataTextureSource()147 virtual DataTextureSource* AsDataTextureSource() { return nullptr; } AsWrappingTextureSourceYCbCrBasic()148 virtual WrappingTextureSourceYCbCrBasic* AsWrappingTextureSourceYCbCrBasic() { 149 return nullptr; 150 } 151 152 /** 153 * Overload this if the TextureSource supports big textures that don't fit in 154 * one device texture and must be tiled internally. 155 */ AsBigImageIterator()156 virtual BigImageIterator* AsBigImageIterator() { return nullptr; } 157 SetTextureSourceProvider(TextureSourceProvider * aProvider)158 virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) {} 159 Unbind()160 virtual void Unbind() {} 161 SetNextSibling(TextureSource * aTexture)162 void SetNextSibling(TextureSource* aTexture) { mNextSibling = aTexture; } 163 GetNextSibling()164 TextureSource* GetNextSibling() const { return mNextSibling; } 165 166 /** 167 * In some rare cases we currently need to consider a group of textures as one 168 * TextureSource, that can be split in sub-TextureSources. 169 */ GetSubSource(int index)170 TextureSource* GetSubSource(int index) { 171 switch (index) { 172 case 0: 173 return this; 174 case 1: 175 return GetNextSibling(); 176 case 2: 177 return GetNextSibling() ? GetNextSibling()->GetNextSibling() : nullptr; 178 } 179 return nullptr; 180 } 181 AddCompositableRef()182 void AddCompositableRef() { ++mCompositableCount; } 183 ReleaseCompositableRef()184 void ReleaseCompositableRef() { 185 --mCompositableCount; 186 MOZ_ASSERT(mCompositableCount >= 0); 187 } 188 189 // When iterating as a BigImage, this creates temporary TextureSources 190 // wrapping individual tiles. ExtractCurrentTile()191 virtual RefPtr<TextureSource> ExtractCurrentTile() { 192 NS_WARNING("Implementation does not expose tile sources"); 193 return nullptr; 194 } 195 NumCompositableRefs()196 int NumCompositableRefs() const { return mCompositableCount; } 197 198 // Some texture sources could wrap the cpu buffer to gpu directly. Then, 199 // we could get better performance of texture uploading. IsDirectMap()200 virtual bool IsDirectMap() { return false; } 201 // The direct-map cpu buffer should be alive when gpu uses it. And it 202 // should not be updated while gpu reads it. This Sync() function 203 // implements this synchronized behavior by allowing us to check if 204 // the GPU is done with the texture, and block on it if aBlocking is 205 // true. Sync(bool aBlocking)206 virtual bool Sync(bool aBlocking) { return true; } 207 208 protected: 209 RefPtr<TextureSource> mNextSibling; 210 int mCompositableCount; 211 }; 212 213 /// Equivalent of a RefPtr<TextureSource>, that calls AddCompositableRef and 214 /// ReleaseCompositableRef in addition to the usual AddRef and Release. 215 /// 216 /// The semantoics of these CompositableTextureRefs are important because they 217 /// are used both as a synchronization/safety mechanism, and as an optimization 218 /// mechanism. They are also tricky and subtle because we use them in a very 219 /// implicit way (assigning to a CompositableTextureRef is less visible than 220 /// explicitly calling a method or whatnot). 221 /// It is Therefore important to be careful about the way we use this tool. 222 /// 223 /// CompositableTextureRef is a mechanism that lets us count how many 224 /// compositables are using a given texture (for TextureSource and TextureHost). 225 /// We use it to run specific code when a texture is not used anymore, and also 226 /// we trigger fast paths on some operations when we can see that the texture's 227 /// CompositableTextureRef counter is equal to 1 (the texture is not shared 228 /// between compositables). 229 /// This means that it is important to observe the following rules: 230 /// * CompositableHosts that receive UseTexture and similar messages *must* 231 /// store all of the TextureHosts they receive in CompositableTextureRef slots 232 /// for as long as they may be using them. 233 /// * CompositableHosts must store each texture in a *single* 234 /// CompositableTextureRef slot to ensure that the counter properly reflects how 235 /// many compositables are using the texture. If a compositable needs to hold 236 /// two references to a given texture (for example to have a pointer to the 237 /// current texture in a list of textures that may be used), it can hold its 238 /// extra references with RefPtr or whichever pointer type makes sense. 239 template <typename T> 240 class CompositableTextureRef { 241 public: 242 CompositableTextureRef() = default; 243 CompositableTextureRef(const CompositableTextureRef & aOther)244 explicit CompositableTextureRef(const CompositableTextureRef& aOther) { 245 *this = aOther; 246 } 247 CompositableTextureRef(T * aOther)248 explicit CompositableTextureRef(T* aOther) { *this = aOther; } 249 ~CompositableTextureRef()250 ~CompositableTextureRef() { 251 if (mRef) { 252 mRef->ReleaseCompositableRef(); 253 } 254 } 255 256 CompositableTextureRef& operator=(const CompositableTextureRef& aOther) { 257 if (aOther.get()) { 258 aOther->AddCompositableRef(); 259 } 260 if (mRef) { 261 mRef->ReleaseCompositableRef(); 262 } 263 mRef = aOther.get(); 264 return *this; 265 } 266 267 CompositableTextureRef& operator=(T* aOther) { 268 if (aOther) { 269 aOther->AddCompositableRef(); 270 } 271 if (mRef) { 272 mRef->ReleaseCompositableRef(); 273 } 274 mRef = aOther; 275 return *this; 276 } 277 get()278 T* get() const { return mRef; } 279 operator T*() const { return mRef; } 280 T* operator->() const { return mRef; } 281 T& operator*() const { return *mRef; } 282 283 private: 284 RefPtr<T> mRef; 285 }; 286 287 typedef CompositableTextureRef<TextureSource> CompositableTextureSourceRef; 288 typedef CompositableTextureRef<TextureHost> CompositableTextureHostRef; 289 290 /** 291 * Interface for TextureSources that can be updated from a DataSourceSurface. 292 * 293 * All backend should implement at least one DataTextureSource. 294 */ 295 class DataTextureSource : public TextureSource { 296 public: DataTextureSource()297 DataTextureSource() : mOwner(0), mUpdateSerial(0) {} 298 Name()299 const char* Name() const override { return "DataTextureSource"; } 300 AsDataTextureSource()301 DataTextureSource* AsDataTextureSource() override { return this; } 302 303 /** 304 * Upload a (portion of) surface to the TextureSource. 305 * 306 * The DataTextureSource doesn't own aSurface, although it owns and manage 307 * the device texture it uploads to internally. 308 */ 309 virtual bool Update(gfx::DataSourceSurface* aSurface, 310 nsIntRegion* aDestRegion = nullptr, 311 gfx::IntPoint* aSrcOffset = nullptr, 312 gfx::IntPoint* aDstOffset = nullptr) = 0; 313 314 /** 315 * A facility to avoid reuploading when it is not necessary. 316 * The caller of Update can use GetUpdateSerial to see if the number has 317 * changed since last update, and call SetUpdateSerial after each successful 318 * update. The caller is responsible for managing the update serial except 319 * when the texture data is deallocated in which case the TextureSource should 320 * always reset the update serial to zero. 321 */ GetUpdateSerial()322 uint32_t GetUpdateSerial() const { return mUpdateSerial; } SetUpdateSerial(uint32_t aValue)323 void SetUpdateSerial(uint32_t aValue) { mUpdateSerial = aValue; } 324 325 // By default at least set the update serial to zero. 326 // overloaded versions should do that too. DeallocateDeviceData()327 void DeallocateDeviceData() override { SetUpdateSerial(0); } 328 329 #ifdef DEBUG 330 /** 331 * Provide read access to the data as a DataSourceSurface. 332 * 333 * This is expected to be very slow and should be used for mostly debugging. 334 * XXX - implement everywhere and make it pure virtual. 335 */ ReadBack()336 virtual already_AddRefed<gfx::DataSourceSurface> ReadBack() { 337 return nullptr; 338 }; 339 #endif 340 SetOwner(TextureHost * aOwner)341 void SetOwner(TextureHost* aOwner) { 342 auto newOwner = (uintptr_t)aOwner; 343 if (newOwner != mOwner) { 344 mOwner = newOwner; 345 SetUpdateSerial(0); 346 } 347 } 348 IsOwnedBy(TextureHost * aOwner)349 bool IsOwnedBy(TextureHost* aOwner) const { 350 return mOwner == (uintptr_t)aOwner; 351 } 352 HasOwner()353 bool HasOwner() const { return !IsOwnedBy(nullptr); } 354 355 private: 356 // We store mOwner as an integer rather than as a pointer to make it clear 357 // it is not intended to be dereferenced. 358 uintptr_t mOwner; 359 uint32_t mUpdateSerial; 360 }; 361 362 /** 363 * TextureHost is a thin abstraction over texture data that need to be shared 364 * between the content process and the compositor process. It is the 365 * compositor-side half of a TextureClient/TextureHost pair. A corresponding 366 * TextureClient lives on the content-side. 367 * 368 * TextureHost only knows how to deserialize or synchronize generic image data 369 * (SurfaceDescriptor) and provide access to one or more TextureSource objects 370 * (these provide the necessary APIs for compositor backends to composite the 371 * image). 372 * 373 * A TextureHost implementation corresponds to one SurfaceDescriptor type, as 374 * opposed to TextureSource that corresponds to device textures. 375 * This means that for YCbCr planes, even though they are represented as 376 * 3 textures internally (3 TextureSources), we use 1 TextureHost and not 3, 377 * because the 3 planes are stored in the same buffer of shared memory, before 378 * they are uploaded separately. 379 * 380 * There is always one and only one TextureHost per TextureClient, and the 381 * TextureClient/Host pair only owns one buffer of image data through its 382 * lifetime. This means that the lifetime of the underlying shared data 383 * matches the lifetime of the TextureClient/Host pair. It also means 384 * TextureClient/Host do not implement double buffering, which is the 385 * reponsibility of the compositable (which would use two Texture pairs). 386 * 387 * The Lock/Unlock mecanism here mirrors Lock/Unlock in TextureClient. 388 * 389 */ 390 class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> { 391 /** 392 * Called once, just before the destructor. 393 * 394 * Here goes the shut-down code that uses virtual methods. 395 * Must only be called by Release(). 396 */ 397 void Finalize(); 398 399 friend class AtomicRefCountedWithFinalize<TextureHost>; 400 401 public: 402 explicit TextureHost(TextureFlags aFlags); 403 404 protected: 405 virtual ~TextureHost(); 406 407 public: 408 /** 409 * Factory method. 410 */ 411 static already_AddRefed<TextureHost> Create( 412 const SurfaceDescriptor& aDesc, const ReadLockDescriptor& aReadLock, 413 ISurfaceAllocator* aDeallocator, LayersBackend aBackend, 414 TextureFlags aFlags, wr::MaybeExternalImageId& aExternalImageId); 415 416 /** 417 * Lock the texture host for compositing. 418 */ Lock()419 virtual bool Lock() { return true; } 420 /** 421 * Unlock the texture host after compositing. Lock() and Unlock() should be 422 * called in pair. 423 */ Unlock()424 virtual void Unlock() {} 425 426 /** 427 * Lock the texture host for compositing without using compositor. 428 */ LockWithoutCompositor()429 virtual bool LockWithoutCompositor() { return true; } 430 /** 431 * Similar to Unlock(), but it should be called with LockWithoutCompositor(). 432 */ UnlockWithoutCompositor()433 virtual void UnlockWithoutCompositor() {} 434 435 /** 436 * Note that the texture host format can be different from its corresponding 437 * texture source's. For example a ShmemTextureHost can have the ycbcr 438 * format and produce 3 "alpha" textures sources. 439 */ 440 virtual gfx::SurfaceFormat GetFormat() const = 0; 441 /** 442 * Return the format used for reading the texture. 443 * Apple's YCBCR_422 is R8G8B8X8. 444 */ GetReadFormat()445 virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); } 446 GetYUVColorSpace()447 virtual gfx::YUVColorSpace GetYUVColorSpace() const { 448 return gfx::YUVColorSpace::Identity; 449 } 450 451 /** 452 * Return the color depth of the image. Used with YUV textures. 453 */ GetColorDepth()454 virtual gfx::ColorDepth GetColorDepth() const { 455 return gfx::ColorDepth::COLOR_8; 456 } 457 458 /** 459 * Return true if using full range values (0-255 if 8 bits YUV). Used with YUV 460 * textures. 461 */ GetColorRange()462 virtual gfx::ColorRange GetColorRange() const { 463 return gfx::ColorRange::LIMITED; 464 } 465 466 /** 467 * Called during the transaction. The TextureSource may or may not be 468 * composited. 469 * 470 * Note that this is called outside of lock/unlock. 471 */ PrepareTextureSource(CompositableTextureSourceRef & aTexture)472 virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) {} 473 474 /** 475 * Called at composition time, just before compositing the TextureSource 476 * composited. 477 * 478 * Note that this is called only withing lock/unlock. 479 */ 480 virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) = 0; 481 482 /** 483 * Called when preparing the rendering pipeline for advanced-layers. This is 484 * a lockless version of BindTextureSource. 485 */ AcquireTextureSource(CompositableTextureSourceRef & aTexture)486 virtual bool AcquireTextureSource(CompositableTextureSourceRef& aTexture) { 487 return false; 488 } 489 490 /** 491 * Called when another TextureHost will take over. 492 */ 493 virtual void UnbindTextureSource(); 494 IsValid()495 virtual bool IsValid() { return true; } 496 497 /** 498 * Is called before compositing if the shared data has changed since last 499 * composition. 500 * This method should be overload in cases like when we need to do a texture 501 * upload for example. 502 * 503 * @param aRegion The region that has been changed, if nil, it means that the 504 * entire surface should be updated. 505 */ 506 void Updated(const nsIntRegion* aRegion = nullptr); 507 508 /** 509 * Sets this TextureHost's compositor. A TextureHost can change compositor 510 * on certain occasions, in particular if it belongs to an async Compositable. 511 * aCompositor can be null, in which case the TextureHost must cleanup all 512 * of its device textures. 513 * 514 * Setting mProvider from this callback implicitly causes the texture to 515 * be locked for an extra frame after being detached from a compositable. 516 */ SetTextureSourceProvider(TextureSourceProvider * aProvider)517 virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) {} 518 519 /** 520 * Should be overridden in order to deallocate the data that is associated 521 * with the rendering backend, such as GL textures. 522 */ DeallocateDeviceData()523 virtual void DeallocateDeviceData() {} 524 525 /** 526 * Should be overridden in order to deallocate the data that is shared with 527 * the content side, such as shared memory. 528 */ DeallocateSharedData()529 virtual void DeallocateSharedData() {} 530 531 /** 532 * Should be overridden in order to force the TextureHost to drop all 533 * references to it's shared data. 534 * 535 * This is important to ensure the correctness of the deallocation protocol. 536 */ ForgetSharedData()537 virtual void ForgetSharedData() {} 538 539 virtual gfx::IntSize GetSize() const = 0; 540 541 /** 542 * Should be overridden if TextureHost supports crop rect. 543 */ SetCropRect(nsIntRect aCropRect)544 virtual void SetCropRect(nsIntRect aCropRect) {} 545 546 /** 547 * Debug facility. 548 * XXX - cool kids use Moz2D. See bug 882113. 549 */ 550 virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() = 0; 551 552 /** 553 * XXX - Flags should only be set at creation time, this will be removed. 554 */ SetFlags(TextureFlags aFlags)555 void SetFlags(TextureFlags aFlags) { mFlags = aFlags; } 556 557 /** 558 * XXX - Flags should only be set at creation time, this will be removed. 559 */ AddFlag(TextureFlags aFlag)560 void AddFlag(TextureFlags aFlag) { mFlags |= aFlag; } 561 GetFlags()562 TextureFlags GetFlags() { return mFlags; } 563 564 /** 565 * Allocate and deallocate a TextureParent actor. 566 * 567 * TextureParent< is an implementation detail of TextureHost that is not 568 * exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor 569 * are for use with the managing IPDL protocols only (so that they can 570 * implement AllocPTextureParent and DeallocPTextureParent). 571 */ 572 static PTextureParent* CreateIPDLActor( 573 HostIPCAllocator* aAllocator, const SurfaceDescriptor& aSharedData, 574 const ReadLockDescriptor& aDescriptor, LayersBackend aLayersBackend, 575 TextureFlags aFlags, uint64_t aSerial, 576 const wr::MaybeExternalImageId& aExternalImageId); 577 static bool DestroyIPDLActor(PTextureParent* actor); 578 579 /** 580 * Destroy the TextureChild/Parent pair. 581 */ 582 static bool SendDeleteIPDLActor(PTextureParent* actor); 583 584 static void ReceivedDestroy(PTextureParent* actor); 585 586 /** 587 * Get the TextureHost corresponding to the actor passed in parameter. 588 */ 589 static TextureHost* AsTextureHost(PTextureParent* actor); 590 591 static uint64_t GetTextureSerial(PTextureParent* actor); 592 593 /** 594 * Return a pointer to the IPDLActor. 595 * 596 * This is to be used with IPDL messages only. Do not store the returned 597 * pointer. 598 */ 599 PTextureParent* GetIPDLActor(); 600 601 // If a texture host holds a reference to shmem, it should override this 602 // method to forget about the shmem _without_ releasing it. OnShutdown()603 virtual void OnShutdown() {} 604 605 // Forget buffer actor. Used only for hacky fix for bug 966446. ForgetBufferActor()606 virtual void ForgetBufferActor() {} 607 Name()608 virtual const char* Name() { return "TextureHost"; } 609 virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); 610 611 /** 612 * Indicates whether the TextureHost implementation is backed by an 613 * in-memory buffer. The consequence of this is that locking the 614 * TextureHost does not contend with locking the texture on the client side. 615 */ HasIntermediateBuffer()616 virtual bool HasIntermediateBuffer() const { return false; } 617 618 /** 619 * Returns true if the TextureHost can be released before the rendering is 620 * completed, otherwise returns false. 621 */ NeedsDeferredDeletion()622 virtual bool NeedsDeferredDeletion() const { 623 return !HasIntermediateBuffer(); 624 } 625 AddCompositableRef()626 void AddCompositableRef() { 627 ++mCompositableCount; 628 if (mCompositableCount == 1) { 629 PrepareForUse(); 630 } 631 } 632 ReleaseCompositableRef()633 void ReleaseCompositableRef() { 634 --mCompositableCount; 635 MOZ_ASSERT(mCompositableCount >= 0); 636 if (mCompositableCount == 0) { 637 UnbindTextureSource(); 638 // Send mFwdTransactionId to client side if necessary. 639 NotifyNotUsed(); 640 } 641 } 642 NumCompositableRefs()643 int NumCompositableRefs() const { return mCompositableCount; } 644 645 void SetLastFwdTransactionId(uint64_t aTransactionId); 646 647 void DeserializeReadLock(const ReadLockDescriptor& aDesc, 648 ISurfaceAllocator* aAllocator); 649 void SetReadLocked(); 650 GetReadLock()651 TextureReadLock* GetReadLock() { return mReadLock; } 652 AsBufferTextureHost()653 virtual BufferTextureHost* AsBufferTextureHost() { return nullptr; } AsMacIOSurfaceTextureHost()654 virtual MacIOSurfaceTextureHostOGL* AsMacIOSurfaceTextureHost() { 655 return nullptr; 656 } AsWebRenderTextureHost()657 virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; } AsSurfaceTextureHost()658 virtual SurfaceTextureHost* AsSurfaceTextureHost() { return nullptr; } 659 virtual AndroidHardwareBufferTextureHost* AsAndroidHardwareBufferTextureHost()660 AsAndroidHardwareBufferTextureHost() { 661 return nullptr; 662 } 663 664 // Create the corresponding RenderTextureHost type of this texture, and 665 // register the RenderTextureHost into render thread. CreateRenderTexture(const wr::ExternalImageId & aExternalImageId)666 virtual void CreateRenderTexture( 667 const wr::ExternalImageId& aExternalImageId) { 668 MOZ_RELEASE_ASSERT( 669 false, 670 "No CreateRenderTexture() implementation for this TextureHost type."); 671 } 672 673 void EnsureRenderTexture(const wr::MaybeExternalImageId& aExternalImageId); 674 675 // Destroy RenderTextureHost when it was created by the TextureHost. 676 // It is called in TextureHost::Finalize(). 677 virtual void MaybeDestroyRenderTexture(); 678 679 static void DestroyRenderTexture(const wr::ExternalImageId& aExternalImageId); 680 681 /// Returns the number of actual textures that will be used to render this. 682 /// For example in a lot of YUV cases it will be 3 NumSubTextures()683 virtual uint32_t NumSubTextures() { return 1; } 684 685 enum ResourceUpdateOp { 686 ADD_IMAGE, 687 UPDATE_IMAGE, 688 }; 689 690 // Add all necessary TextureHost informations to the resource update queue. PushResourceUpdates(wr::TransactionBuilder & aResources,ResourceUpdateOp aOp,const Range<wr::ImageKey> & aImageKeys,const wr::ExternalImageId & aExtID)691 virtual void PushResourceUpdates(wr::TransactionBuilder& aResources, 692 ResourceUpdateOp aOp, 693 const Range<wr::ImageKey>& aImageKeys, 694 const wr::ExternalImageId& aExtID) { 695 MOZ_ASSERT_UNREACHABLE("Unimplemented"); 696 } 697 698 enum class PushDisplayItemFlag { 699 // Passed if the caller wants these display items to be promoted 700 // to compositor surfaces if possible. 701 PREFER_COMPOSITOR_SURFACE, 702 703 // Passed in the RenderCompositor supports BufferTextureHosts 704 // being used directly as external compositor surfaces. 705 SUPPORTS_EXTERNAL_BUFFER_TEXTURES, 706 }; 707 using PushDisplayItemFlagSet = EnumSet<PushDisplayItemFlag>; 708 709 // Put all necessary WR commands into DisplayListBuilder for this textureHost 710 // rendering. PushDisplayItems(wr::DisplayListBuilder & aBuilder,const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,wr::ImageRendering aFilter,const Range<wr::ImageKey> & aKeys,PushDisplayItemFlagSet aFlags)711 virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder, 712 const wr::LayoutRect& aBounds, 713 const wr::LayoutRect& aClip, 714 wr::ImageRendering aFilter, 715 const Range<wr::ImageKey>& aKeys, 716 PushDisplayItemFlagSet aFlags) { 717 MOZ_ASSERT_UNREACHABLE( 718 "No PushDisplayItems() implementation for this TextureHost type."); 719 } 720 721 /** 722 * Some API's can use the cross-process IOSurface directly, such as OpenVR 723 */ GetMacIOSurface()724 virtual MacIOSurface* GetMacIOSurface() { return nullptr; } 725 IsDirectMap()726 virtual bool IsDirectMap() { return false; } 727 728 virtual bool NeedsYFlip() const; 729 GetProvider()730 TextureSourceProvider* GetProvider() const { return mProvider; } 731 SetAcquireFence(mozilla::ipc::FileDescriptor && aFenceFd)732 virtual void SetAcquireFence(mozilla::ipc::FileDescriptor&& aFenceFd) {} 733 SetReleaseFence(mozilla::ipc::FileDescriptor && aFenceFd)734 virtual void SetReleaseFence(mozilla::ipc::FileDescriptor&& aFenceFd) {} 735 GetAndResetReleaseFence()736 virtual mozilla::ipc::FileDescriptor GetAndResetReleaseFence() { 737 return mozilla::ipc::FileDescriptor(); 738 } 739 GetAndroidHardwareBuffer()740 virtual AndroidHardwareBuffer* GetAndroidHardwareBuffer() const { 741 return nullptr; 742 } 743 SupportsExternalCompositing(WebRenderBackend aBackend)744 virtual bool SupportsExternalCompositing(WebRenderBackend aBackend) { 745 return false; 746 } 747 748 // Our WebRender backend may impose restrictions on whether textures are 749 // prepared as native textures or not, or it may have no restriction at 750 // all. This enumerates those possibilities. 751 enum NativeTexturePolicy { 752 REQUIRE, 753 FORBID, 754 DONT_CARE, 755 }; 756 BackendNativeTexturePolicy(layers::WebRenderBackend aBackend,gfx::IntSize aSize)757 static NativeTexturePolicy BackendNativeTexturePolicy( 758 layers::WebRenderBackend aBackend, gfx::IntSize aSize) { 759 static const int32_t SWGL_DIMENSION_MAX = 1 << 15; 760 if (aBackend == WebRenderBackend::SOFTWARE) { 761 return (aSize.width <= SWGL_DIMENSION_MAX && 762 aSize.height <= SWGL_DIMENSION_MAX) 763 ? REQUIRE 764 : FORBID; 765 } 766 return DONT_CARE; 767 } 768 769 protected: 770 virtual void ReadUnlock(); 771 772 void RecycleTexture(TextureFlags aFlags); 773 MaybeNotifyUnlocked()774 virtual void MaybeNotifyUnlocked() {} 775 UpdatedInternal(const nsIntRegion * Region)776 virtual void UpdatedInternal(const nsIntRegion* Region) {} 777 778 /** 779 * Called when mCompositableCount becomes from 0 to 1. 780 */ PrepareForUse()781 virtual void PrepareForUse() {} 782 783 /** 784 * Called when mCompositableCount becomes 0. 785 */ 786 virtual void NotifyNotUsed(); 787 788 // for Compositor. 789 void CallNotifyNotUsed(); 790 791 PTextureParent* mActor; 792 RefPtr<TextureSourceProvider> mProvider; 793 RefPtr<TextureReadLock> mReadLock; 794 TextureFlags mFlags; 795 int mCompositableCount; 796 uint64_t mFwdTransactionId; 797 bool mReadLocked; 798 wr::MaybeExternalImageId mExternalImageId; 799 800 friend class Compositor; 801 friend class TextureParent; 802 friend class TiledLayerBufferComposite; 803 friend class TextureSourceProvider; 804 friend class GPUVideoTextureHost; 805 friend class WebRenderTextureHost; 806 }; 807 808 /** 809 * TextureHost that wraps a random access buffer such as a Shmem or some raw 810 * memory. 811 * 812 * This TextureHost is backend-independent and the backend-specific bits are 813 * in the TextureSource. 814 * This class must be inherited to implement GetBuffer and DeallocSharedData 815 * (see ShmemTextureHost and MemoryTextureHost) 816 * 817 * Uploads happen when Lock is called. 818 * 819 * BufferTextureHost supports YCbCr and flavours of RGBA images (RGBX, A, etc.). 820 */ 821 class BufferTextureHost : public TextureHost { 822 public: 823 BufferTextureHost(const BufferDescriptor& aDescriptor, TextureFlags aFlags); 824 825 virtual ~BufferTextureHost(); 826 827 virtual uint8_t* GetBuffer() = 0; 828 829 virtual size_t GetBufferSize() = 0; 830 831 bool Lock() override; 832 833 void Unlock() override; 834 835 void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override; 836 837 bool BindTextureSource(CompositableTextureSourceRef& aTexture) override; 838 bool AcquireTextureSource(CompositableTextureSourceRef& aTexture) override; 839 840 void UnbindTextureSource() override; 841 842 void DeallocateDeviceData() override; 843 844 void SetTextureSourceProvider(TextureSourceProvider* aProvider) override; 845 846 /** 847 * Return the format that is exposed to the compositor when calling 848 * BindTextureSource. 849 * 850 * If the shared format is YCbCr and the compositor does not support it, 851 * GetFormat will be RGB32 (even though mFormat is SurfaceFormat::YUV). 852 */ 853 gfx::SurfaceFormat GetFormat() const override; 854 855 gfx::YUVColorSpace GetYUVColorSpace() const override; 856 857 gfx::ColorDepth GetColorDepth() const override; 858 859 gfx::ColorRange GetColorRange() const override; 860 GetSize()861 gfx::IntSize GetSize() const override { return mSize; } 862 863 already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override; 864 HasIntermediateBuffer()865 bool HasIntermediateBuffer() const override { return mHasIntermediateBuffer; } 866 NeedsDeferredDeletion()867 bool NeedsDeferredDeletion() const override { 868 return TextureHost::NeedsDeferredDeletion() || UseExternalTextures(); 869 } 870 AsBufferTextureHost()871 BufferTextureHost* AsBufferTextureHost() override { return this; } 872 GetBufferDescriptor()873 const BufferDescriptor& GetBufferDescriptor() const { return mDescriptor; } 874 875 void CreateRenderTexture( 876 const wr::ExternalImageId& aExternalImageId) override; 877 878 uint32_t NumSubTextures() override; 879 880 void PushResourceUpdates(wr::TransactionBuilder& aResources, 881 ResourceUpdateOp aOp, 882 const Range<wr::ImageKey>& aImageKeys, 883 const wr::ExternalImageId& aExtID) override; 884 885 void PushDisplayItems(wr::DisplayListBuilder& aBuilder, 886 const wr::LayoutRect& aBounds, 887 const wr::LayoutRect& aClip, wr::ImageRendering aFilter, 888 const Range<wr::ImageKey>& aImageKeys, 889 PushDisplayItemFlagSet aFlags) override; 890 891 void ReadUnlock() override; IsDirectMap()892 bool IsDirectMap() override { 893 return mFirstSource && mFirstSource->IsDirectMap(); 894 }; 895 CanUnlock()896 bool CanUnlock() { return !mFirstSource || mFirstSource->Sync(false); } DisableExternalTextures()897 void DisableExternalTextures() { mUseExternalTextures = false; } 898 899 protected: UseExternalTextures()900 bool UseExternalTextures() const { return mUseExternalTextures; } 901 bool Upload(nsIntRegion* aRegion = nullptr); 902 bool UploadIfNeeded(); 903 bool MaybeUpload(nsIntRegion* aRegion); 904 bool EnsureWrappingTextureSource(); 905 906 void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override; 907 void MaybeNotifyUnlocked() override; 908 909 BufferDescriptor mDescriptor; 910 RefPtr<Compositor> mCompositor; 911 RefPtr<DataTextureSource> mFirstSource; 912 nsIntRegion mMaybeUpdatedRegion; 913 gfx::IntSize mSize; 914 gfx::SurfaceFormat mFormat; 915 uint32_t mUpdateSerial; 916 bool mLocked; 917 bool mNeedsFullUpdate; 918 bool mHasIntermediateBuffer; 919 bool mUseExternalTextures; 920 921 class DataTextureSourceYCbCrBasic; 922 }; 923 924 /** 925 * TextureHost that wraps shared memory. 926 * the corresponding texture on the client side is ShmemTextureClient. 927 * This TextureHost is backend-independent. 928 */ 929 class ShmemTextureHost : public BufferTextureHost { 930 public: 931 ShmemTextureHost(const mozilla::ipc::Shmem& aShmem, 932 const BufferDescriptor& aDesc, 933 ISurfaceAllocator* aDeallocator, TextureFlags aFlags); 934 935 protected: 936 ~ShmemTextureHost(); 937 938 public: 939 void DeallocateSharedData() override; 940 941 void ForgetSharedData() override; 942 943 uint8_t* GetBuffer() override; 944 945 size_t GetBufferSize() override; 946 Name()947 const char* Name() override { return "ShmemTextureHost"; } 948 949 void OnShutdown() override; 950 951 protected: 952 UniquePtr<mozilla::ipc::Shmem> mShmem; 953 RefPtr<ISurfaceAllocator> mDeallocator; 954 }; 955 956 /** 957 * TextureHost that wraps raw memory. 958 * The corresponding texture on the client side is MemoryTextureClient. 959 * Can obviously not be used in a cross process setup. 960 * This TextureHost is backend-independent. 961 */ 962 class MemoryTextureHost : public BufferTextureHost { 963 public: 964 MemoryTextureHost(uint8_t* aBuffer, const BufferDescriptor& aDesc, 965 TextureFlags aFlags); 966 967 protected: 968 ~MemoryTextureHost(); 969 970 public: 971 void DeallocateSharedData() override; 972 973 void ForgetSharedData() override; 974 975 uint8_t* GetBuffer() override; 976 977 size_t GetBufferSize() override; 978 Name()979 const char* Name() override { return "MemoryTextureHost"; } 980 981 protected: 982 uint8_t* mBuffer; 983 }; 984 985 class MOZ_STACK_CLASS AutoLockTextureHost { 986 public: AutoLockTextureHost(TextureHost * aTexture)987 explicit AutoLockTextureHost(TextureHost* aTexture) : mTexture(aTexture) { 988 mLocked = mTexture ? mTexture->Lock() : false; 989 } 990 ~AutoLockTextureHost()991 ~AutoLockTextureHost() { 992 if (mTexture && mLocked) { 993 mTexture->Unlock(); 994 } 995 } 996 Failed()997 bool Failed() { return mTexture && !mLocked; } 998 999 private: 1000 RefPtr<TextureHost> mTexture; 1001 bool mLocked; 1002 }; 1003 1004 class MOZ_STACK_CLASS AutoLockTextureHostWithoutCompositor { 1005 public: AutoLockTextureHostWithoutCompositor(TextureHost * aTexture)1006 explicit AutoLockTextureHostWithoutCompositor(TextureHost* aTexture) 1007 : mTexture(aTexture) { 1008 mLocked = mTexture ? mTexture->LockWithoutCompositor() : false; 1009 } 1010 ~AutoLockTextureHostWithoutCompositor()1011 ~AutoLockTextureHostWithoutCompositor() { 1012 if (mTexture && mLocked) { 1013 mTexture->UnlockWithoutCompositor(); 1014 } 1015 } 1016 Failed()1017 bool Failed() { return mTexture && !mLocked; } 1018 1019 private: 1020 RefPtr<TextureHost> mTexture; 1021 bool mLocked; 1022 }; 1023 1024 /** 1025 * This can be used as an offscreen rendering target by the compositor, and 1026 * subsequently can be used as a source by the compositor. 1027 */ 1028 class CompositingRenderTarget : public TextureSource { 1029 public: CompositingRenderTarget(const gfx::IntPoint & aOrigin)1030 explicit CompositingRenderTarget(const gfx::IntPoint& aOrigin) 1031 : mClearOnBind(false), 1032 mOrigin(aOrigin), 1033 mZNear(0), 1034 mZFar(0), 1035 mHasComplexProjection(false), 1036 mEnableDepthBuffer(false) {} 1037 virtual ~CompositingRenderTarget() = default; 1038 Name()1039 const char* Name() const override { return "CompositingRenderTarget"; } 1040 1041 #ifdef MOZ_DUMP_PAINTING Dump(Compositor * aCompositor)1042 virtual already_AddRefed<gfx::DataSourceSurface> Dump( 1043 Compositor* aCompositor) { 1044 return nullptr; 1045 } 1046 #endif 1047 1048 /** 1049 * Perform a clear when recycling a non opaque surface. 1050 * The clear is deferred to when the render target is bound. 1051 */ ClearOnBind()1052 void ClearOnBind() { mClearOnBind = true; } 1053 GetOrigin()1054 const gfx::IntPoint& GetOrigin() const { return mOrigin; } GetRect()1055 gfx::IntRect GetRect() { return gfx::IntRect(GetOrigin(), GetSize()); } 1056 1057 /** 1058 * If a Projection matrix is set, then it is used for rendering to 1059 * this render target instead of generating one. If no explicit 1060 * projection is set, Compositors are expected to generate an 1061 * orthogonal maaping that maps 0..1 to the full size of the render 1062 * target. 1063 */ HasComplexProjection()1064 bool HasComplexProjection() const { return mHasComplexProjection; } ClearProjection()1065 void ClearProjection() { mHasComplexProjection = false; } SetProjection(const gfx::Matrix4x4 & aNewMatrix,bool aEnableDepthBuffer,float aZNear,float aZFar)1066 void SetProjection(const gfx::Matrix4x4& aNewMatrix, bool aEnableDepthBuffer, 1067 float aZNear, float aZFar) { 1068 mProjectionMatrix = aNewMatrix; 1069 mEnableDepthBuffer = aEnableDepthBuffer; 1070 mZNear = aZNear; 1071 mZFar = aZFar; 1072 mHasComplexProjection = true; 1073 } GetProjection(gfx::Matrix4x4 & aMatrix,bool & aEnableDepth,float & aZNear,float & aZFar)1074 void GetProjection(gfx::Matrix4x4& aMatrix, bool& aEnableDepth, float& aZNear, 1075 float& aZFar) { 1076 MOZ_ASSERT(mHasComplexProjection); 1077 aMatrix = mProjectionMatrix; 1078 aEnableDepth = mEnableDepthBuffer; 1079 aZNear = mZNear; 1080 aZFar = mZFar; 1081 } 1082 1083 protected: 1084 bool mClearOnBind; 1085 1086 private: 1087 gfx::IntPoint mOrigin; 1088 1089 gfx::Matrix4x4 mProjectionMatrix; 1090 float mZNear, mZFar; 1091 bool mHasComplexProjection; 1092 bool mEnableDepthBuffer; 1093 }; 1094 1095 /** 1096 * Creates a TextureHost that can be used with any of the existing backends 1097 * Not all SurfaceDescriptor types are supported 1098 */ 1099 already_AddRefed<TextureHost> CreateBackendIndependentTextureHost( 1100 const SurfaceDescriptor& aDesc, ISurfaceAllocator* aDeallocator, 1101 LayersBackend aBackend, TextureFlags aFlags); 1102 1103 } // namespace layers 1104 } // namespace mozilla 1105 1106 #endif 1107