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