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