Coverage Report

Created: 2018-09-25 14:53

/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