Source code

Revision control

Other Tools

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 GFX_IMAGECONTAINER_H
8
#define GFX_IMAGECONTAINER_H
9
10
#include <stdint.h> // for uint32_t, uint8_t, uint64_t
11
#include <sys/types.h> // for int32_t
12
#include "gfxTypes.h"
13
#include "ImageTypes.h" // for ImageFormat, etc
14
#include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
15
#include "mozilla/Mutex.h" // for Mutex
16
#include "mozilla/RecursiveMutex.h" // for RecursiveMutex, etc
17
#include "mozilla/TimeStamp.h" // for TimeStamp
18
#include "mozilla/gfx/Point.h" // For IntSize
19
#include "mozilla/gfx/Types.h" // For ColorDepth
20
#include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc
21
#include "mozilla/layers/CompositorTypes.h"
22
#include "mozilla/mozalloc.h" // for operator delete, etc
23
#include "nsAutoRef.h" // for nsCountedRef
24
#include "nsCOMPtr.h" // for already_AddRefed
25
#include "nsDebug.h" // for NS_ASSERTION
26
#include "nsISupportsImpl.h" // for Image::Release, etc
27
#include "nsRect.h" // for mozilla::gfx::IntRect
28
#include "nsTArray.h" // for nsTArray
29
#include "mozilla/Atomics.h"
30
#include "mozilla/WeakPtr.h"
31
#include "nsThreadUtils.h"
32
#include "mozilla/gfx/2D.h"
33
#include "nsDataHashtable.h"
34
#include "mozilla/EnumeratedArray.h"
35
#include "mozilla/UniquePtr.h"
36
37
#ifndef XPCOM_GLUE_AVOID_NSPR
38
/**
39
* We need to be able to hold a reference to a Moz2D SourceSurface from Image
40
* subclasses. Whilst SourceSurface is atomic refcounted and thus safe to
41
* AddRef/Release on any thread, it is potentially a problem since clean up code
42
* may need to run on a the main thread.
43
*
44
* We use nsCountedRef<nsMainThreadSourceSurfaceRef> to reference the
45
* SourceSurface. When Releasing, if we're not on the main thread, we post an
46
* event to the main thread to do the actual release.
47
*/
48
class nsMainThreadSourceSurfaceRef;
49
50
template <>
51
class nsAutoRefTraits<nsMainThreadSourceSurfaceRef> {
52
public:
53
typedef mozilla::gfx::SourceSurface* RawRef;
54
55
/**
56
* The XPCOM event that will do the actual release on the main thread.
57
*/
58
class SurfaceReleaser : public mozilla::Runnable {
59
public:
60
explicit SurfaceReleaser(RawRef aRef)
61
: mozilla::Runnable(
62
"nsAutoRefTraits<nsMainThreadSourceSurfaceRef>::SurfaceReleaser"),
63
mRef(aRef) {}
64
NS_IMETHOD Run() override {
65
mRef->Release();
66
return NS_OK;
67
}
68
RawRef mRef;
69
};
70
71
static RawRef Void() { return nullptr; }
72
static void Release(RawRef aRawRef) {
73
if (NS_IsMainThread()) {
74
aRawRef->Release();
75
return;
76
}
77
nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
78
NS_DispatchToMainThread(runnable);
79
}
80
static void AddRef(RawRef aRawRef) { aRawRef->AddRef(); }
81
};
82
83
class nsOwningThreadSourceSurfaceRef;
84
85
template <>
86
class nsAutoRefTraits<nsOwningThreadSourceSurfaceRef> {
87
public:
88
typedef mozilla::gfx::SourceSurface* RawRef;
89
90
/**
91
* The XPCOM event that will do the actual release on the creation thread.
92
*/
93
class SurfaceReleaser : public mozilla::Runnable {
94
public:
95
explicit SurfaceReleaser(RawRef aRef)
96
: mozilla::Runnable(
97
"nsAutoRefTraits<nsOwningThreadSourceSurfaceRef>::"
98
"SurfaceReleaser"),
99
mRef(aRef) {}
100
NS_IMETHOD Run() override {
101
mRef->Release();
102
return NS_OK;
103
}
104
RawRef mRef;
105
};
106
107
static RawRef Void() { return nullptr; }
108
void Release(RawRef aRawRef) {
109
MOZ_ASSERT(mOwningEventTarget);
110
if (mOwningEventTarget->IsOnCurrentThread()) {
111
aRawRef->Release();
112
return;
113
}
114
nsCOMPtr<nsIRunnable> runnable = new SurfaceReleaser(aRawRef);
115
mOwningEventTarget->Dispatch(runnable, nsIThread::DISPATCH_NORMAL);
116
}
117
void AddRef(RawRef aRawRef) {
118
MOZ_ASSERT(!mOwningEventTarget);
119
mOwningEventTarget = mozilla::GetCurrentThreadSerialEventTarget();
120
aRawRef->AddRef();
121
}
122
123
private:
124
nsCOMPtr<nsISerialEventTarget> mOwningEventTarget;
125
};
126
127
#endif
128
129
#ifdef XP_WIN
130
struct ID3D10Texture2D;
131
struct ID3D10Device;
132
struct ID3D10ShaderResourceView;
133
#endif
134
135
typedef void* HANDLE;
136
137
namespace mozilla {
138
139
namespace layers {
140
141
class ImageClient;
142
class ImageCompositeNotification;
143
class ImageContainer;
144
class ImageContainerChild;
145
class SharedPlanarYCbCrImage;
146
class SharedSurfacesAnimation;
147
class PlanarYCbCrImage;
148
class TextureClient;
149
class TextureClientRecycleAllocator;
150
class KnowsCompositor;
151
class NVImage;
152
#ifdef XP_WIN
153
class D3D11YCbCrRecycleAllocator;
154
#endif
155
class SurfaceDescriptorBuffer;
156
157
struct ImageBackendData {
158
virtual ~ImageBackendData() = default;
159
160
protected:
161
ImageBackendData() = default;
162
};
163
164
/* Forward declarations for Image derivatives. */
165
class GLImage;
166
class SharedRGBImage;
167
#ifdef MOZ_WIDGET_ANDROID
168
class SurfaceTextureImage;
169
#elif defined(XP_MACOSX)
170
class MacIOSurfaceImage;
171
#elif MOZ_WAYLAND
172
class WaylandDMABUFSurfaceImage;
173
#endif
174
175
/**
176
* A class representing a buffer of pixel data. The data can be in one
177
* of various formats including YCbCr.
178
*
179
* Create an image using an ImageContainer. Fill the image with data, and
180
* then call ImageContainer::SetImage to display it. An image must not be
181
* modified after calling SetImage. Image implementations do not need to
182
* perform locking; when filling an Image, the Image client is responsible
183
* for ensuring only one thread accesses the Image at a time, and after
184
* SetImage the image is immutable.
185
*
186
* When resampling an Image, only pixels within the buffer should be
187
* sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
188
*/
189
class Image {
190
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
191
192
public:
193
ImageFormat GetFormat() const { return mFormat; }
194
void* GetImplData() const { return mImplData; }
195
196
virtual gfx::IntSize GetSize() const = 0;
197
virtual gfx::IntPoint GetOrigin() const { return gfx::IntPoint(0, 0); }
198
virtual gfx::IntRect GetPictureRect() const {
199
return gfx::IntRect(GetOrigin().x, GetOrigin().y, GetSize().width,
200
GetSize().height);
201
}
202
203
ImageBackendData* GetBackendData(LayersBackend aBackend) {
204
return mBackendData[aBackend].get();
205
}
206
void SetBackendData(LayersBackend aBackend, ImageBackendData* aData) {
207
mBackendData[aBackend] = mozilla::WrapUnique(aData);
208
}
209
210
int32_t GetSerial() const { return mSerial; }
211
212
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() = 0;
213
214
virtual bool IsValid() const { return true; }
215
216
/**
217
* For use with the TextureForwarder only (so that the later can
218
* synchronize the TextureClient with the TextureHost).
219
*/
220
virtual TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) {
221
return nullptr;
222
}
223
224
/* Access to derived classes. */
225
virtual GLImage* AsGLImage() { return nullptr; }
226
#ifdef MOZ_WIDGET_ANDROID
227
virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
228
#endif
229
#ifdef XP_MACOSX
230
virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
231
#endif
232
virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
233
#ifdef MOZ_WAYLAND
234
virtual WaylandDMABUFSurfaceImage* AsWaylandDMABUFSurfaceImage() {
235
return nullptr;
236
}
237
#endif
238
239
virtual NVImage* AsNVImage() { return nullptr; }
240
241
protected:
242
Image(void* aImplData, ImageFormat aFormat)
243
: mImplData(aImplData), mSerial(++sSerialCounter), mFormat(aFormat) {}
244
245
// Protected destructor, to discourage deletion outside of Release():
246
virtual ~Image() = default;
247
248
mozilla::EnumeratedArray<mozilla::layers::LayersBackend,
249
mozilla::layers::LayersBackend::LAYERS_LAST,
250
UniquePtr<ImageBackendData>>
251
mBackendData;
252
253
void* mImplData;
254
int32_t mSerial;
255
ImageFormat mFormat;
256
257
static mozilla::Atomic<int32_t> sSerialCounter;
258
};
259
260
/**
261
* A RecycleBin is owned by an ImageContainer. We store buffers in it that we
262
* want to recycle from one image to the next.It's a separate object from
263
* ImageContainer because images need to store a strong ref to their RecycleBin
264
* and we must avoid creating a reference loop between an ImageContainer and
265
* its active image.
266
*/
267
class BufferRecycleBin final {
268
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BufferRecycleBin)
269
270
// typedef mozilla::gl::GLContext GLContext;
271
272
public:
273
BufferRecycleBin();
274
275
void RecycleBuffer(mozilla::UniquePtr<uint8_t[]> aBuffer, uint32_t aSize);
276
// Returns a recycled buffer of the right size, or allocates a new buffer.
277
mozilla::UniquePtr<uint8_t[]> GetBuffer(uint32_t aSize);
278
virtual void ClearRecycledBuffers();
279
280
private:
281
typedef mozilla::Mutex Mutex;
282
283
// Private destructor, to discourage deletion outside of Release():
284
~BufferRecycleBin() = default;
285
286
// This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
287
// and mRecycledTextureSizes
288
Mutex mLock;
289
290
// We should probably do something to prune this list on a timer so we don't
291
// eat excess memory while video is paused...
292
nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers;
293
// This is only valid if mRecycledBuffers is non-empty
294
uint32_t mRecycledBufferSize;
295
};
296
297
/**
298
* A class that manages Image creation for a LayerManager. The only reason
299
* we need a separate class here is that LayerManagers aren't threadsafe
300
* (because layers can only be used on the main thread) and we want to
301
* be able to create images from any thread, to facilitate video playback
302
* without involving the main thread, for example.
303
* Different layer managers can implement child classes of this making it
304
* possible to create layer manager specific images.
305
* This class is not meant to be used directly but rather can be set on an
306
* image container. This is usually done by the layer system internally and
307
* not explicitly by users. For PlanarYCbCr or Cairo images the default
308
* implementation will creates images whose data lives in system memory, for
309
* MacIOSurfaces the default implementation will be a simple MacIOSurface
310
* wrapper.
311
*/
312
313
class ImageFactory {
314
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
315
protected:
316
friend class ImageContainer;
317
318
ImageFactory() = default;
319
virtual ~ImageFactory() = default;
320
321
virtual RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage(
322
const gfx::IntSize& aScaleHint, BufferRecycleBin* aRecycleBin);
323
};
324
325
// Used to notify ImageContainer::NotifyComposite()
326
class ImageContainerListener final {
327
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainerListener)
328
329
public:
330
explicit ImageContainerListener(ImageContainer* aImageContainer);
331
332
void NotifyComposite(const ImageCompositeNotification& aNotification);
333
void NotifyDropped(uint32_t aDropped);
334
void ClearImageContainer();
335
void DropImageClient();
336
337
private:
338
typedef mozilla::Mutex Mutex;
339
340
~ImageContainerListener();
341
342
Mutex mLock;
343
ImageContainer* mImageContainer;
344
};
345
346
/**
347
* A class that manages Images for an ImageLayer. The only reason
348
* we need a separate class here is that ImageLayers aren't threadsafe
349
* (because layers can only be used on the main thread) and we want to
350
* be able to set the current Image from any thread, to facilitate
351
* video playback without involving the main thread, for example.
352
*
353
* An ImageContainer can operate in one of these modes:
354
* 1) Normal. Triggered by constructing the ImageContainer with
355
* DISABLE_ASYNC or when compositing is happening on the main thread.
356
* SetCurrentImages changes ImageContainer state but nothing is sent to the
357
* compositor until the next layer transaction.
358
* 2) Asynchronous. Initiated by constructing the ImageContainer with
359
* ENABLE_ASYNC when compositing is happening on the main thread.
360
* SetCurrentImages sends a message through the ImageBridge to the compositor
361
* thread to update the image, without going through the main thread or
362
* a layer transaction.
363
* The ImageContainer uses a shared memory block containing a cross-process
364
* mutex to communicate with the compositor thread. SetCurrentImage
365
* synchronously updates the shared state to point to the new image and the old
366
* image is immediately released (not true in Normal or Asynchronous modes).
367
*/
368
class ImageContainer final : public SupportsWeakPtr<ImageContainer> {
369
friend class ImageContainerChild;
370
371
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
372
373
public:
374
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(ImageContainer)
375
376
enum Mode { SYNCHRONOUS = 0x0, ASYNCHRONOUS = 0x01 };
377
378
static const uint64_t sInvalidAsyncContainerId = 0;
379
380
explicit ImageContainer(ImageContainer::Mode flag = SYNCHRONOUS);
381
382
/**
383
* Create ImageContainer just to hold another ASYNCHRONOUS ImageContainer's
384
* async container ID.
385
* @param aAsyncContainerID async container ID for which we are a proxy
386
*/
387
explicit ImageContainer(const CompositableHandle& aHandle);
388
389
typedef ContainerFrameID FrameID;
390
typedef ContainerProducerID ProducerID;
391
392
RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage();
393
394
// Factory methods for shared image types.
395
RefPtr<SharedRGBImage> CreateSharedRGBImage();
396
397
struct NonOwningImage {
398
explicit NonOwningImage(Image* aImage = nullptr,
399
TimeStamp aTimeStamp = TimeStamp(),
400
FrameID aFrameID = 0, ProducerID aProducerID = 0)
401
: mImage(aImage),
402
mTimeStamp(aTimeStamp),
403
mFrameID(aFrameID),
404
mProducerID(aProducerID) {}
405
Image* mImage;
406
TimeStamp mTimeStamp;
407
FrameID mFrameID;
408
ProducerID mProducerID;
409
};
410
/**
411
* Set aImages as the list of timestamped to display. The Images must have
412
* been created by this ImageContainer.
413
* Can be called on any thread. This method takes mRecursiveMutex
414
* when accessing thread-shared state.
415
* aImages must be non-empty. The first timestamp in the list may be
416
* null but the others must not be, and the timestamps must increase.
417
* Every element of aImages must have non-null mImage.
418
* mFrameID can be zero, in which case you won't get meaningful
419
* painted/dropped frame counts. Otherwise you should use a unique and
420
* increasing ID for each decoded and submitted frame (but it's OK to
421
* pass the same frame to SetCurrentImages).
422
* mProducerID is a unique ID for the stream of images. A change in the
423
* mProducerID means changing to a new mFrameID namespace. All frames in
424
* aImages must have the same mProducerID.
425
*
426
* The Image data must not be modified after this method is called!
427
* Note that this must not be called if ENABLE_ASYNC has not been set.
428
*
429
* The implementation calls CurrentImageChanged() while holding
430
* mRecursiveMutex.
431
*
432
* If this ImageContainer has an ImageClient for async video:
433
* Schedule a task to send the image to the compositor using the
434
* PImageBridge protcol without using the main thread.
435
*/
436
void SetCurrentImages(const nsTArray<NonOwningImage>& aImages);
437
438
/**
439
* Clear all images. Let ImageClient release all TextureClients.
440
*/
441
void ClearAllImages();
442
443
/**
444
* Clear any resources that are not immediately necessary. This may be called
445
* in low-memory conditions.
446
*/
447
void ClearCachedResources();
448
449
/**
450
* Clear the current images.
451
* This function is expect to be called only from a CompositableClient
452
* that belongs to ImageBridgeChild. Created to prevent dead lock.
453
* See Bug 901224.
454
*/
455
void ClearImagesFromImageBridge();
456
457
/**
458
* Set an Image as the current image to display. The Image must have
459
* been created by this ImageContainer.
460
* Must be called on the main thread, within a layers transaction.
461
*
462
* This method takes mRecursiveMutex
463
* when accessing thread-shared state.
464
* aImage can be null. While it's null, nothing will be painted.
465
*
466
* The Image data must not be modified after this method is called!
467
* Note that this must not be called if ENABLE_ASYNC been set.
468
*
469
* You won't get meaningful painted/dropped counts when using this method.
470
*/
471
void SetCurrentImageInTransaction(Image* aImage);
472
void SetCurrentImagesInTransaction(const nsTArray<NonOwningImage>& aImages);
473
474
/**
475
* Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
476
*
477
* Can be called from any thread.
478
*/
479
bool IsAsync() const;
480
481
/**
482
* If this ImageContainer uses ImageBridge, returns the ID associated to
483
* this container, for use in the ImageBridge protocol.
484
* Returns 0 if this ImageContainer does not use ImageBridge. Note that
485
* 0 is always an invalid ID for asynchronous image containers.
486
*
487
* Can be called from any thread.
488
*/
489
CompositableHandle GetAsyncContainerHandle();
490
491
/**
492
* Returns if the container currently has an image.
493
* Can be called on any thread. This method takes mRecursiveMutex
494
* when accessing thread-shared state.
495
*/
496
bool HasCurrentImage();
497
498
struct OwningImage {
499
OwningImage() : mFrameID(0), mProducerID(0), mComposited(false) {}
500
RefPtr<Image> mImage;
501
TimeStamp mTimeStamp;
502
FrameID mFrameID;
503
ProducerID mProducerID;
504
bool mComposited;
505
};
506
/**
507
* Copy the current Image list to aImages.
508
* This has to add references since otherwise there are race conditions
509
* where the current image is destroyed before the caller can add
510
* a reference.
511
* Can be called on any thread.
512
* May return an empty list to indicate there is no current image.
513
* If aGenerationCounter is non-null, sets *aGenerationCounter to a value
514
* that's unique for this ImageContainer state.
515
*/
516
void GetCurrentImages(nsTArray<OwningImage>* aImages,
517
uint32_t* aGenerationCounter = nullptr);
518
519
/**
520
* Returns the size of the image in pixels.
521
* Can be called on any thread. This method takes mRecursiveMutex when
522
* accessing thread-shared state.
523
*/
524
gfx::IntSize GetCurrentSize();
525
526
/**
527
* Sets a size that the image is expected to be rendered at.
528
* This is a hint for image backends to optimize scaling.
529
* Default implementation in this class is to ignore the hint.
530
* Can be called on any thread. This method takes mRecursiveMutex
531
* when accessing thread-shared state.
532
*/
533
void SetScaleHint(const gfx::IntSize& aScaleHint) { mScaleHint = aScaleHint; }
534
535
const gfx::IntSize& GetScaleHint() const { return mScaleHint; }
536
537
void SetTransformHint(const gfx::Matrix& aTransformHint) {
538
mTransformHint = aTransformHint;
539
}
540
541
const gfx::Matrix& GetTransformHint() const { return mTransformHint; }
542
543
void SetImageFactory(ImageFactory* aFactory) {
544
RecursiveMutexAutoLock lock(mRecursiveMutex);
545
mImageFactory = aFactory ? aFactory : new ImageFactory();
546
}
547
548
ImageFactory* GetImageFactory() const { return mImageFactory; }
549
550
void EnsureRecycleAllocatorForRDD(KnowsCompositor* aKnowsCompositor);
551
552
#ifdef XP_WIN
553
D3D11YCbCrRecycleAllocator* GetD3D11YCbCrRecycleAllocator(
554
KnowsCompositor* aKnowsCompositor);
555
#endif
556
557
/**
558
* Returns the delay between the last composited image's presentation
559
* timestamp and when it was first composited. It's possible for the delay
560
* to be negative if the first image in the list passed to SetCurrentImages
561
* has a presentation timestamp greater than "now".
562
* Returns 0 if the composited image had a null timestamp, or if no
563
* image has been composited yet.
564
*/
565
TimeDuration GetPaintDelay() {
566
RecursiveMutexAutoLock lock(mRecursiveMutex);
567
return mPaintDelay;
568
}
569
570
/**
571
* Returns the number of images which have been contained in this container
572
* and painted at least once. Can be called from any thread.
573
*/
574
uint32_t GetPaintCount() {
575
RecursiveMutexAutoLock lock(mRecursiveMutex);
576
return mPaintCount;
577
}
578
579
/**
580
* An entry in the current image list "expires" when the entry has an
581
* non-null timestamp, and in a SetCurrentImages call the new image list is
582
* non-empty, the timestamp of the first new image is non-null and greater
583
* than the timestamp associated with the image, and the first new image's
584
* frameID is not the same as the entry's.
585
* Every expired image that is never composited is counted as dropped.
586
*/
587
uint32_t GetDroppedImageCount() { return mDroppedImageCount; }
588
589
void NotifyComposite(const ImageCompositeNotification& aNotification);
590
void NotifyDropped(uint32_t aDropped);
591
592
ImageContainerListener* GetImageContainerListener() {
593
return mNotifyCompositeListener;
594
}
595
596
/**
597
* Get the ImageClient associated with this container. Returns only after
598
* validating, and it will recreate the image client if that fails.
599
* Returns nullptr if not applicable.
600
*/
601
already_AddRefed<ImageClient> GetImageClient();
602
603
/**
604
* Main thread only.
605
*/
606
static ProducerID AllocateProducerID();
607
608
void DropImageClient();
609
610
SharedSurfacesAnimation* GetSharedSurfacesAnimation() const {
611
return mSharedAnimation;
612
}
613
614
SharedSurfacesAnimation* EnsureSharedSurfacesAnimation();
615
616
private:
617
typedef mozilla::RecursiveMutex RecursiveMutex;
618
619
// Private destructor, to discourage deletion outside of Release():
620
~ImageContainer();
621
622
void SetCurrentImageInternal(const nsTArray<NonOwningImage>& aImages);
623
624
// This is called to ensure we have an active image, this may not be true
625
// when we're storing image information in a RemoteImageData structure.
626
// NOTE: If we have remote data mRemoteDataMutex should be locked when
627
// calling this function!
628
void EnsureActiveImage();
629
630
void EnsureImageClient();
631
632
// RecursiveMutex to protect thread safe access to the "current
633
// image", and any other state which is shared between threads.
634
RecursiveMutex mRecursiveMutex;
635
636
RefPtr<TextureClientRecycleAllocator> mRecycleAllocator;
637
638
#ifdef XP_WIN
639
RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator;
640
#endif
641
642
nsTArray<OwningImage> mCurrentImages;
643
644
// Updates every time mActiveImage changes
645
uint32_t mGenerationCounter;
646
647
// Number of contained images that have been painted at least once. It's up
648
// to the ImageContainer implementation to ensure accesses to this are
649
// threadsafe.
650
uint32_t mPaintCount;
651
652
// See GetPaintDelay. Accessed only with mRecursiveMutex held.
653
TimeDuration mPaintDelay;
654
655
// See GetDroppedImageCount.
656
mozilla::Atomic<uint32_t> mDroppedImageCount;
657
658
// This is the image factory used by this container, layer managers using
659
// this container can set an alternative image factory that will be used to
660
// create images for this container.
661
RefPtr<ImageFactory> mImageFactory;
662
663
gfx::IntSize mScaleHint;
664
665
gfx::Matrix mTransformHint;
666
667
RefPtr<BufferRecycleBin> mRecycleBin;
668
669
// This member points to an ImageClient if this ImageContainer was
670
// sucessfully created with ENABLE_ASYNC, or points to null otherwise.
671
// 'unsuccessful' in this case only means that the ImageClient could not
672
// be created, most likely because off-main-thread compositing is not enabled.
673
// In this case the ImageContainer is perfectly usable, but it will forward
674
// frames to the compositor through transactions in the main thread rather
675
// than asynchronusly using the ImageBridge IPDL protocol.
676
RefPtr<ImageClient> mImageClient;
677
678
RefPtr<SharedSurfacesAnimation> mSharedAnimation;
679
680
bool mIsAsync;
681
CompositableHandle mAsyncContainerHandle;
682
683
// ProducerID for last current image(s)
684
ProducerID mCurrentProducerID;
685
686
RefPtr<ImageContainerListener> mNotifyCompositeListener;
687
688
static mozilla::Atomic<uint32_t> sGenerationCounter;
689
};
690
691
class AutoLockImage {
692
public:
693
explicit AutoLockImage(ImageContainer* aContainer) {
694
aContainer->GetCurrentImages(&mImages);
695
}
696
697
bool HasImage() const { return !mImages.IsEmpty(); }
698
Image* GetImage() const {
699
return mImages.IsEmpty() ? nullptr : mImages[0].mImage.get();
700
}
701
702
Image* GetImage(TimeStamp aTimeStamp) const {
703
if (mImages.IsEmpty()) {
704
return nullptr;
705
}
706
707
MOZ_ASSERT(!aTimeStamp.IsNull());
708
uint32_t chosenIndex = 0;
709
710
while (chosenIndex + 1 < mImages.Length() &&
711
mImages[chosenIndex + 1].mTimeStamp <= aTimeStamp) {
712
++chosenIndex;
713
}
714
715
return mImages[chosenIndex].mImage.get();
716
}
717
718
private:
719
AutoTArray<ImageContainer::OwningImage, 4> mImages;
720
};
721
722
struct PlanarYCbCrData {
723
// Luminance buffer
724
uint8_t* mYChannel = nullptr;
725
int32_t mYStride = 0;
726
gfx::IntSize mYSize = gfx::IntSize(0, 0);
727
int32_t mYSkip = 0;
728
// Chroma buffers
729
uint8_t* mCbChannel = nullptr;
730
uint8_t* mCrChannel = nullptr;
731
int32_t mCbCrStride = 0;
732
gfx::IntSize mCbCrSize = gfx::IntSize(0, 0);
733
int32_t mCbSkip = 0;
734
int32_t mCrSkip = 0;
735
// Picture region
736
uint32_t mPicX = 0;
737
uint32_t mPicY = 0;
738
gfx::IntSize mPicSize = gfx::IntSize(0, 0);
739
StereoMode mStereoMode = StereoMode::MONO;
740
gfx::ColorDepth mColorDepth = gfx::ColorDepth::COLOR_8;
741
gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
742
gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
743
744
gfx::IntRect GetPictureRect() const {
745
return gfx::IntRect(mPicX, mPicY, mPicSize.width, mPicSize.height);
746
}
747
};
748
749
/****** Image subtypes for the different formats ******/
750
751
/**
752
* We assume that the image data is in the REC 470M color space (see
753
* Theora specification, section 4.3.1).
754
*
755
* The YCbCr format can be:
756
*
757
* 4:4:4 - CbCr width/height are the same as Y.
758
* 4:2:2 - CbCr width is half that of Y. Height is the same.
759
* 4:2:0 - CbCr width and height is half that of Y.
760
*
761
* The color format is detected based on the height/width ratios
762
* defined above.
763
*
764
* The Image that is rendered is the picture region defined by
765
* mPicX, mPicY and mPicSize. The size of the rendered image is
766
* mPicSize, not mYSize or mCbCrSize.
767
*
768
* mYSkip, mCbSkip, mCrSkip are added to support various output
769
* formats from hardware decoder. They are per-pixel skips in the
770
* source image.
771
*
772
* For example when image width is 640, mYStride is 670, mYSkip is 3,
773
* the mYChannel buffer looks like:
774
*
775
* |<----------------------- mYStride ----------------------------->|
776
* |<----------------- mYSize.width --------------->|
777
* 0 3 6 9 12 15 18 21 659 669
778
* |----------------------------------------------------------------|
779
* |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%|
780
* |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%|
781
* |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%|
782
* | |<->|
783
* mYSkip
784
*/
785
class PlanarYCbCrImage : public Image {
786
public:
787
typedef PlanarYCbCrData Data;
788
789
enum { MAX_DIMENSION = 16384 };
790
791
virtual ~PlanarYCbCrImage() = default;
792
793
/**
794
* This makes a copy of the data buffers, in order to support functioning
795
* in all different layer managers.
796
*/
797
virtual bool CopyData(const Data& aData) = 0;
798
799
/**
800
* This doesn't make a copy of the data buffers.
801
*/
802
virtual bool AdoptData(const Data& aData);
803
804
/**
805
* Ask this Image to not convert YUV to RGB during SetData, and make
806
* the original data available through GetData. This is optional,
807
* and not all PlanarYCbCrImages will support it.
808
*/
809
virtual void SetDelayedConversion(bool aDelayed) {}
810
811
/**
812
* Grab the original YUV data. This is optional.
813
*/
814
virtual const Data* GetData() const { return &mData; }
815
816
/**
817
* Return the number of bytes of heap memory used to store this image.
818
*/
819
uint32_t GetDataSize() const { return mBufferSize; }
820
821
bool IsValid() const override { return !!mBufferSize; }
822
823
gfx::IntSize GetSize() const override { return mSize; }
824
825
gfx::IntPoint GetOrigin() const override { return mOrigin; }
826
827
PlanarYCbCrImage();
828
829
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
830
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
831
}
832
833
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const = 0;
834
835
PlanarYCbCrImage* AsPlanarYCbCrImage() override { return this; }
836
837
/**
838
* Build a SurfaceDescriptorBuffer with this image. The provided
839
* SurfaceDescriptorBuffer must already have a valid MemoryOrShmem set
840
* with a capacity large enough to hold |GetDataSize|.
841
*/
842
virtual nsresult BuildSurfaceDescriptorBuffer(
843
SurfaceDescriptorBuffer& aSdBuffer);
844
845
protected:
846
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
847
848
void SetOffscreenFormat(gfxImageFormat aFormat) {
849
mOffscreenFormat = aFormat;
850
}
851
gfxImageFormat GetOffscreenFormat() const;
852
853
Data mData;
854
gfx::IntPoint mOrigin;
855
gfx::IntSize mSize;
856
gfxImageFormat mOffscreenFormat;
857
nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
858
uint32_t mBufferSize;
859
};
860
861
class RecyclingPlanarYCbCrImage : public PlanarYCbCrImage {
862
public:
863
explicit RecyclingPlanarYCbCrImage(BufferRecycleBin* aRecycleBin)
864
: mRecycleBin(aRecycleBin) {}
865
virtual ~RecyclingPlanarYCbCrImage();
866
bool CopyData(const Data& aData) override;
867
size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
868
869
protected:
870
/**
871
* Return a buffer to store image data in.
872
*/
873
mozilla::UniquePtr<uint8_t[]> AllocateBuffer(uint32_t aSize);
874
875
RefPtr<BufferRecycleBin> mRecycleBin;
876
mozilla::UniquePtr<uint8_t[]> mBuffer;
877
};
878
879
/**
880
* NVImage is used to store YUV420SP_NV12 and YUV420SP_NV21 data natively, which
881
* are not supported by PlanarYCbCrImage. (PlanarYCbCrImage only stores YUV444P,
882
* YUV422P and YUV420P, it converts YUV420SP_NV12 and YUV420SP_NV21 data into
883
* YUV420P in its PlanarYCbCrImage::SetData() method.)
884
*
885
* PlanarYCbCrData is able to express all the YUV family and so we keep use it
886
* in NVImage.
887
*/
888
class NVImage final : public Image {
889
typedef PlanarYCbCrData Data;
890
891
public:
892
NVImage();
893
virtual ~NVImage();
894
895
// Methods inherited from layers::Image.
896
gfx::IntSize GetSize() const override;
897
gfx::IntRect GetPictureRect() const override;
898
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
899
bool IsValid() const override;
900
NVImage* AsNVImage() override;
901
902
// Methods mimic layers::PlanarYCbCrImage.
903
bool SetData(const Data& aData);
904
const Data* GetData() const;
905
uint32_t GetBufferSize() const;
906
907
protected:
908
/**
909
* Return a buffer to store image data in.
910
*/
911
mozilla::UniquePtr<uint8_t> AllocateBuffer(uint32_t aSize);
912
913
mozilla::UniquePtr<uint8_t> mBuffer;
914
uint32_t mBufferSize;
915
gfx::IntSize mSize;
916
Data mData;
917
nsCountedRef<nsMainThreadSourceSurfaceRef> mSourceSurface;
918
};
919
920
/**
921
* Currently, the data in a SourceSurfaceImage surface is treated as being in
922
* the device output color space. This class is very simple as all backends have
923
* to know about how to deal with drawing a cairo image.
924
*/
925
class SourceSurfaceImage final : public Image {
926
public:
927
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override {
928
RefPtr<gfx::SourceSurface> surface(mSourceSurface);
929
return surface.forget();
930
}
931
932
void SetTextureFlags(TextureFlags aTextureFlags) {
933
mTextureFlags = aTextureFlags;
934
}
935
TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override;
936
937
gfx::IntSize GetSize() const override { return mSize; }
938
939
SourceSurfaceImage(const gfx::IntSize& aSize,
940
gfx::SourceSurface* aSourceSurface);
941
explicit SourceSurfaceImage(gfx::SourceSurface* aSourceSurface);
942
virtual ~SourceSurfaceImage();
943
944
private:
945
gfx::IntSize mSize;
946
nsCountedRef<nsOwningThreadSourceSurfaceRef> mSourceSurface;
947
nsDataHashtable<nsUint32HashKey, RefPtr<TextureClient>> mTextureClients;
948
TextureFlags mTextureFlags;
949
};
950
951
} // namespace layers
952
} // namespace mozilla
953
954
#endif