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