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