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