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