Bug 1691109 [wpt PR 27513] - Increase timeout duration for wpt/fetch/api/basic/keepal...
[gecko.git] / gfx / layers / ImageContainer.h
bloba7f9fcffc04158d109a88de9d8473579afe5a69d
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/. */
7 #ifndef GFX_IMAGECONTAINER_H
8 #define GFX_IMAGECONTAINER_H
10 #include <stdint.h> // for int32_t, uint32_t, uint8_t, uint64_t
11 #include "ImageTypes.h" // for ImageFormat, etc
12 #include "mozilla/AlreadyAddRefed.h"
13 #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2
14 #include "mozilla/Mutex.h" // for Mutex
15 #include "mozilla/RecursiveMutex.h" // for RecursiveMutex, etc
16 #include "mozilla/ThreadSafeWeakPtr.h"
17 #include "mozilla/TimeStamp.h" // for TimeStamp
18 #include "mozilla/gfx/Point.h" // For IntSize
19 #include "mozilla/gfx/Rect.h"
20 #include "mozilla/gfx/Types.h" // For ColorDepth
21 #include "mozilla/layers/LayersTypes.h" // for LayersBackend, etc
22 #include "mozilla/layers/CompositorTypes.h"
23 #include "mozilla/mozalloc.h" // for operator delete, etc
24 #include "nsDebug.h" // for NS_ASSERTION
25 #include "nsISupportsImpl.h" // for Image::Release, etc
26 #include "nsTArray.h" // for nsTArray
27 #include "mozilla/Atomics.h"
28 #include "mozilla/gfx/2D.h"
29 #include "nsDataHashtable.h"
30 #include "mozilla/EnumeratedArray.h"
31 #include "mozilla/UniquePtr.h"
32 #include "MediaInfo.h"
34 #ifdef XP_WIN
35 struct ID3D10Texture2D;
36 struct ID3D10Device;
37 struct ID3D10ShaderResourceView;
38 #endif
40 typedef void* HANDLE;
42 namespace mozilla {
44 namespace layers {
46 class ImageClient;
47 class ImageCompositeNotification;
48 class ImageContainer;
49 class ImageContainerChild;
50 class SharedPlanarYCbCrImage;
51 class SharedSurfacesAnimation;
52 class SurfaceDescriptor;
53 class PlanarYCbCrImage;
54 class TextureClient;
55 class TextureClientRecycleAllocator;
56 class KnowsCompositor;
57 class NVImage;
58 #ifdef XP_WIN
59 class D3D11YCbCrRecycleAllocator;
60 #endif
61 #ifdef XP_MACOSX
62 class MacIOSurfaceRecycleAllocator;
63 #endif
64 class SurfaceDescriptorBuffer;
66 struct ImageBackendData {
67 virtual ~ImageBackendData() = default;
69 protected:
70 ImageBackendData() = default;
73 /* Forward declarations for Image derivatives. */
74 class GLImage;
75 class SharedRGBImage;
76 #ifdef MOZ_WIDGET_ANDROID
77 class SurfaceTextureImage;
78 #elif defined(XP_MACOSX)
79 class MacIOSurfaceImage;
80 #elif MOZ_WAYLAND
81 class DMABUFSurfaceImage;
82 #endif
84 /**
85 * A class representing a buffer of pixel data. The data can be in one
86 * of various formats including YCbCr.
88 * Create an image using an ImageContainer. Fill the image with data, and
89 * then call ImageContainer::SetImage to display it. An image must not be
90 * modified after calling SetImage. Image implementations do not need to
91 * perform locking; when filling an Image, the Image client is responsible
92 * for ensuring only one thread accesses the Image at a time, and after
93 * SetImage the image is immutable.
95 * When resampling an Image, only pixels within the buffer should be
96 * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
98 class Image {
99 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
101 public:
102 ImageFormat GetFormat() const { return mFormat; }
103 void* GetImplData() const { return mImplData; }
105 virtual gfx::IntSize GetSize() const = 0;
106 virtual gfx::IntPoint GetOrigin() const { return gfx::IntPoint(0, 0); }
107 virtual gfx::IntRect GetPictureRect() const {
108 return gfx::IntRect(GetOrigin().x, GetOrigin().y, GetSize().width,
109 GetSize().height);
112 ImageBackendData* GetBackendData(LayersBackend aBackend) {
113 return mBackendData[aBackend].get();
115 void SetBackendData(LayersBackend aBackend, ImageBackendData* aData) {
116 mBackendData[aBackend] = mozilla::WrapUnique(aData);
119 int32_t GetSerial() const { return mSerial; }
121 virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() = 0;
123 virtual bool IsValid() const { return true; }
126 * For use with the TextureForwarder only (so that the later can
127 * synchronize the TextureClient with the TextureHost).
129 virtual TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) {
130 return nullptr;
133 /* Access to derived classes. */
134 virtual GLImage* AsGLImage() { return nullptr; }
135 #ifdef MOZ_WIDGET_ANDROID
136 virtual SurfaceTextureImage* AsSurfaceTextureImage() { return nullptr; }
137 #endif
138 #ifdef XP_MACOSX
139 virtual MacIOSurfaceImage* AsMacIOSurfaceImage() { return nullptr; }
140 #endif
141 virtual PlanarYCbCrImage* AsPlanarYCbCrImage() { return nullptr; }
142 #ifdef MOZ_WAYLAND
143 virtual DMABUFSurfaceImage* AsDMABUFSurfaceImage() { return nullptr; }
144 #endif
146 virtual NVImage* AsNVImage() { return nullptr; }
148 virtual Maybe<SurfaceDescriptor> GetDesc();
150 protected:
151 Maybe<SurfaceDescriptor> GetDescFromTexClient(
152 TextureClient* tcOverride = nullptr);
154 Image(void* aImplData, ImageFormat aFormat)
155 : mImplData(aImplData), mSerial(++sSerialCounter), mFormat(aFormat) {}
157 // Protected destructor, to discourage deletion outside of Release():
158 virtual ~Image() = default;
160 mozilla::EnumeratedArray<mozilla::layers::LayersBackend,
161 mozilla::layers::LayersBackend::LAYERS_LAST,
162 UniquePtr<ImageBackendData>>
163 mBackendData;
165 void* mImplData;
166 int32_t mSerial;
167 ImageFormat mFormat;
169 static mozilla::Atomic<int32_t> sSerialCounter;
173 * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
174 * want to recycle from one image to the next.It's a separate object from
175 * ImageContainer because images need to store a strong ref to their RecycleBin
176 * and we must avoid creating a reference loop between an ImageContainer and
177 * its active image.
179 class BufferRecycleBin final {
180 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BufferRecycleBin)
182 // typedef mozilla::gl::GLContext GLContext;
184 public:
185 BufferRecycleBin();
187 void RecycleBuffer(mozilla::UniquePtr<uint8_t[]> aBuffer, uint32_t aSize);
188 // Returns a recycled buffer of the right size, or allocates a new buffer.
189 mozilla::UniquePtr<uint8_t[]> GetBuffer(uint32_t aSize);
190 virtual void ClearRecycledBuffers();
192 private:
193 typedef mozilla::Mutex Mutex;
195 // Private destructor, to discourage deletion outside of Release():
196 ~BufferRecycleBin() = default;
198 // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
199 // and mRecycledTextureSizes
200 Mutex mLock;
202 // We should probably do something to prune this list on a timer so we don't
203 // eat excess memory while video is paused...
204 nsTArray<mozilla::UniquePtr<uint8_t[]>> mRecycledBuffers;
205 // This is only valid if mRecycledBuffers is non-empty
206 uint32_t mRecycledBufferSize;
210 * A class that manages Image creation for a LayerManager. The only reason
211 * we need a separate class here is that LayerManagers aren't threadsafe
212 * (because layers can only be used on the main thread) and we want to
213 * be able to create images from any thread, to facilitate video playback
214 * without involving the main thread, for example.
215 * Different layer managers can implement child classes of this making it
216 * possible to create layer manager specific images.
217 * This class is not meant to be used directly but rather can be set on an
218 * image container. This is usually done by the layer system internally and
219 * not explicitly by users. For PlanarYCbCr or Cairo images the default
220 * implementation will creates images whose data lives in system memory, for
221 * MacIOSurfaces the default implementation will be a simple MacIOSurface
222 * wrapper.
225 class ImageFactory {
226 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
227 protected:
228 friend class ImageContainer;
230 ImageFactory() = default;
231 virtual ~ImageFactory() = default;
233 virtual RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage(
234 const gfx::IntSize& aScaleHint, BufferRecycleBin* aRecycleBin);
237 // Used to notify ImageContainer::NotifyComposite()
238 class ImageContainerListener final {
239 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainerListener)
241 public:
242 explicit ImageContainerListener(ImageContainer* aImageContainer);
244 void NotifyComposite(const ImageCompositeNotification& aNotification);
245 void NotifyDropped(uint32_t aDropped);
246 void ClearImageContainer();
247 void DropImageClient();
249 private:
250 typedef mozilla::Mutex Mutex;
252 ~ImageContainerListener();
254 Mutex mLock;
255 ImageContainer* mImageContainer;
259 * A class that manages Images for an ImageLayer. The only reason
260 * we need a separate class here is that ImageLayers aren't threadsafe
261 * (because layers can only be used on the main thread) and we want to
262 * be able to set the current Image from any thread, to facilitate
263 * video playback without involving the main thread, for example.
265 * An ImageContainer can operate in one of these modes:
266 * 1) Normal. Triggered by constructing the ImageContainer with
267 * DISABLE_ASYNC or when compositing is happening on the main thread.
268 * SetCurrentImages changes ImageContainer state but nothing is sent to the
269 * compositor until the next layer transaction.
270 * 2) Asynchronous. Initiated by constructing the ImageContainer with
271 * ENABLE_ASYNC when compositing is happening on the main thread.
272 * SetCurrentImages sends a message through the ImageBridge to the compositor
273 * thread to update the image, without going through the main thread or
274 * a layer transaction.
275 * The ImageContainer uses a shared memory block containing a cross-process
276 * mutex to communicate with the compositor thread. SetCurrentImage
277 * synchronously updates the shared state to point to the new image and the old
278 * image is immediately released (not true in Normal or Asynchronous modes).
280 class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
281 friend class ImageContainerChild;
283 public:
284 MOZ_DECLARE_THREADSAFEWEAKREFERENCE_TYPENAME(ImageContainer)
285 MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageContainer)
287 enum Mode { SYNCHRONOUS = 0x0, ASYNCHRONOUS = 0x01 };
289 static const uint64_t sInvalidAsyncContainerId = 0;
291 explicit ImageContainer(ImageContainer::Mode flag = SYNCHRONOUS);
294 * Create ImageContainer just to hold another ASYNCHRONOUS ImageContainer's
295 * async container ID.
296 * @param aAsyncContainerID async container ID for which we are a proxy
298 explicit ImageContainer(const CompositableHandle& aHandle);
300 ~ImageContainer();
302 typedef ContainerFrameID FrameID;
303 typedef ContainerProducerID ProducerID;
305 RefPtr<PlanarYCbCrImage> CreatePlanarYCbCrImage();
307 // Factory methods for shared image types.
308 RefPtr<SharedRGBImage> CreateSharedRGBImage();
310 struct NonOwningImage {
311 explicit NonOwningImage(Image* aImage = nullptr,
312 TimeStamp aTimeStamp = TimeStamp(),
313 FrameID aFrameID = 0, ProducerID aProducerID = 0)
314 : mImage(aImage),
315 mTimeStamp(aTimeStamp),
316 mFrameID(aFrameID),
317 mProducerID(aProducerID) {}
318 Image* mImage;
319 TimeStamp mTimeStamp;
320 FrameID mFrameID;
321 ProducerID mProducerID;
324 * Set aImages as the list of timestamped to display. The Images must have
325 * been created by this ImageContainer.
326 * Can be called on any thread. This method takes mRecursiveMutex
327 * when accessing thread-shared state.
328 * aImages must be non-empty. The first timestamp in the list may be
329 * null but the others must not be, and the timestamps must increase.
330 * Every element of aImages must have non-null mImage.
331 * mFrameID can be zero, in which case you won't get meaningful
332 * painted/dropped frame counts. Otherwise you should use a unique and
333 * increasing ID for each decoded and submitted frame (but it's OK to
334 * pass the same frame to SetCurrentImages).
335 * mProducerID is a unique ID for the stream of images. A change in the
336 * mProducerID means changing to a new mFrameID namespace. All frames in
337 * aImages must have the same mProducerID.
339 * The Image data must not be modified after this method is called!
340 * Note that this must not be called if ENABLE_ASYNC has not been set.
342 * The implementation calls CurrentImageChanged() while holding
343 * mRecursiveMutex.
345 * If this ImageContainer has an ImageClient for async video:
346 * Schedule a task to send the image to the compositor using the
347 * PImageBridge protcol without using the main thread.
349 void SetCurrentImages(const nsTArray<NonOwningImage>& aImages);
352 * Clear all images. Let ImageClient release all TextureClients.
354 void ClearAllImages();
357 * Clear any resources that are not immediately necessary. This may be called
358 * in low-memory conditions.
360 void ClearCachedResources();
363 * Clear the current images.
364 * This function is expect to be called only from a CompositableClient
365 * that belongs to ImageBridgeChild. Created to prevent dead lock.
366 * See Bug 901224.
368 void ClearImagesFromImageBridge();
371 * Set an Image as the current image to display. The Image must have
372 * been created by this ImageContainer.
373 * Must be called on the main thread, within a layers transaction.
375 * This method takes mRecursiveMutex
376 * when accessing thread-shared state.
377 * aImage can be null. While it's null, nothing will be painted.
379 * The Image data must not be modified after this method is called!
380 * Note that this must not be called if ENABLE_ASYNC been set.
382 * You won't get meaningful painted/dropped counts when using this method.
384 void SetCurrentImageInTransaction(Image* aImage);
385 void SetCurrentImagesInTransaction(const nsTArray<NonOwningImage>& aImages);
388 * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
390 * Can be called from any thread.
392 bool IsAsync() const;
395 * If this ImageContainer uses ImageBridge, returns the ID associated to
396 * this container, for use in the ImageBridge protocol.
397 * Returns 0 if this ImageContainer does not use ImageBridge. Note that
398 * 0 is always an invalid ID for asynchronous image containers.
400 * Can be called from any thread.
402 CompositableHandle GetAsyncContainerHandle();
405 * Returns if the container currently has an image.
406 * Can be called on any thread. This method takes mRecursiveMutex
407 * when accessing thread-shared state.
409 bool HasCurrentImage();
411 struct OwningImage {
412 OwningImage() : mFrameID(0), mProducerID(0), mComposited(false) {}
413 RefPtr<Image> mImage;
414 TimeStamp mTimeStamp;
415 FrameID mFrameID;
416 ProducerID mProducerID;
417 bool mComposited;
420 * Copy the current Image list to aImages.
421 * This has to add references since otherwise there are race conditions
422 * where the current image is destroyed before the caller can add
423 * a reference.
424 * Can be called on any thread.
425 * May return an empty list to indicate there is no current image.
426 * If aGenerationCounter is non-null, sets *aGenerationCounter to a value
427 * that's unique for this ImageContainer state.
429 void GetCurrentImages(nsTArray<OwningImage>* aImages,
430 uint32_t* aGenerationCounter = nullptr);
433 * Returns the size of the image in pixels.
434 * Can be called on any thread. This method takes mRecursiveMutex when
435 * accessing thread-shared state.
437 gfx::IntSize GetCurrentSize();
440 * Sets a size that the image is expected to be rendered at.
441 * This is a hint for image backends to optimize scaling.
442 * Default implementation in this class is to ignore the hint.
443 * Can be called on any thread. This method takes mRecursiveMutex
444 * when accessing thread-shared state.
446 void SetScaleHint(const gfx::IntSize& aScaleHint) { mScaleHint = aScaleHint; }
448 const gfx::IntSize& GetScaleHint() const { return mScaleHint; }
450 void SetTransformHint(const gfx::Matrix& aTransformHint) {
451 mTransformHint = aTransformHint;
454 const gfx::Matrix& GetTransformHint() const { return mTransformHint; }
456 void SetRotation(VideoInfo::Rotation aRotation) { mRotation = aRotation; }
458 VideoInfo::Rotation GetRotation() const { return mRotation; }
460 void SetImageFactory(ImageFactory* aFactory) {
461 RecursiveMutexAutoLock lock(mRecursiveMutex);
462 mImageFactory = aFactory ? aFactory : new ImageFactory();
465 ImageFactory* GetImageFactory() const { return mImageFactory; }
467 void EnsureRecycleAllocatorForRDD(KnowsCompositor* aKnowsCompositor);
469 #ifdef XP_WIN
470 D3D11YCbCrRecycleAllocator* GetD3D11YCbCrRecycleAllocator(
471 KnowsCompositor* aKnowsCompositor);
472 #endif
474 #ifdef XP_MACOSX
475 MacIOSurfaceRecycleAllocator* GetMacIOSurfaceRecycleAllocator();
476 #endif
479 * Returns the delay between the last composited image's presentation
480 * timestamp and when it was first composited. It's possible for the delay
481 * to be negative if the first image in the list passed to SetCurrentImages
482 * has a presentation timestamp greater than "now".
483 * Returns 0 if the composited image had a null timestamp, or if no
484 * image has been composited yet.
486 TimeDuration GetPaintDelay() {
487 RecursiveMutexAutoLock lock(mRecursiveMutex);
488 return mPaintDelay;
492 * Returns the number of images which have been contained in this container
493 * and painted at least once. Can be called from any thread.
495 uint32_t GetPaintCount() {
496 RecursiveMutexAutoLock lock(mRecursiveMutex);
497 return mPaintCount;
501 * An entry in the current image list "expires" when the entry has an
502 * non-null timestamp, and in a SetCurrentImages call the new image list is
503 * non-empty, the timestamp of the first new image is non-null and greater
504 * than the timestamp associated with the image, and the first new image's
505 * frameID is not the same as the entry's.
506 * Every expired image that is never composited is counted as dropped.
508 uint32_t GetDroppedImageCount() { return mDroppedImageCount; }
510 void NotifyComposite(const ImageCompositeNotification& aNotification);
511 void NotifyDropped(uint32_t aDropped);
513 ImageContainerListener* GetImageContainerListener() {
514 return mNotifyCompositeListener;
518 * Get the ImageClient associated with this container. Returns only after
519 * validating, and it will recreate the image client if that fails.
520 * Returns nullptr if not applicable.
522 already_AddRefed<ImageClient> GetImageClient();
525 * Main thread only.
527 static ProducerID AllocateProducerID();
529 void DropImageClient();
531 SharedSurfacesAnimation* GetSharedSurfacesAnimation() const {
532 return mSharedAnimation;
535 SharedSurfacesAnimation* EnsureSharedSurfacesAnimation();
537 private:
538 typedef mozilla::RecursiveMutex RecursiveMutex;
540 void SetCurrentImageInternal(const nsTArray<NonOwningImage>& aImages);
542 // This is called to ensure we have an active image, this may not be true
543 // when we're storing image information in a RemoteImageData structure.
544 // NOTE: If we have remote data mRemoteDataMutex should be locked when
545 // calling this function!
546 void EnsureActiveImage();
548 void EnsureImageClient();
550 // RecursiveMutex to protect thread safe access to the "current
551 // image", and any other state which is shared between threads.
552 RecursiveMutex mRecursiveMutex;
554 RefPtr<TextureClientRecycleAllocator> mRecycleAllocator;
556 #ifdef XP_WIN
557 RefPtr<D3D11YCbCrRecycleAllocator> mD3D11YCbCrRecycleAllocator;
558 #endif
559 #ifdef XP_MACOSX
560 RefPtr<MacIOSurfaceRecycleAllocator> mMacIOSurfaceRecycleAllocator;
561 #endif
563 nsTArray<OwningImage> mCurrentImages;
565 // Updates every time mActiveImage changes
566 uint32_t mGenerationCounter;
568 // Number of contained images that have been painted at least once. It's up
569 // to the ImageContainer implementation to ensure accesses to this are
570 // threadsafe.
571 uint32_t mPaintCount;
573 // See GetPaintDelay. Accessed only with mRecursiveMutex held.
574 TimeDuration mPaintDelay;
576 // See GetDroppedImageCount.
577 mozilla::Atomic<uint32_t> mDroppedImageCount;
579 // This is the image factory used by this container, layer managers using
580 // this container can set an alternative image factory that will be used to
581 // create images for this container.
582 RefPtr<ImageFactory> mImageFactory;
584 gfx::IntSize mScaleHint;
586 gfx::Matrix mTransformHint;
588 VideoInfo::Rotation mRotation = VideoInfo::Rotation::kDegree_0;
590 RefPtr<BufferRecycleBin> mRecycleBin;
592 // This member points to an ImageClient if this ImageContainer was
593 // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
594 // 'unsuccessful' in this case only means that the ImageClient could not
595 // be created, most likely because off-main-thread compositing is not enabled.
596 // In this case the ImageContainer is perfectly usable, but it will forward
597 // frames to the compositor through transactions in the main thread rather
598 // than asynchronusly using the ImageBridge IPDL protocol.
599 RefPtr<ImageClient> mImageClient;
601 RefPtr<SharedSurfacesAnimation> mSharedAnimation;
603 bool mIsAsync;
604 CompositableHandle mAsyncContainerHandle;
606 // ProducerID for last current image(s)
607 ProducerID mCurrentProducerID;
609 RefPtr<ImageContainerListener> mNotifyCompositeListener;
611 static mozilla::Atomic<uint32_t> sGenerationCounter;
614 class AutoLockImage {
615 public:
616 explicit AutoLockImage(ImageContainer* aContainer) {
617 aContainer->GetCurrentImages(&mImages);
620 bool HasImage() const { return !mImages.IsEmpty(); }
621 Image* GetImage() const {
622 return mImages.IsEmpty() ? nullptr : mImages[0].mImage.get();
625 Image* GetImage(TimeStamp aTimeStamp) const {
626 if (mImages.IsEmpty()) {
627 return nullptr;
630 MOZ_ASSERT(!aTimeStamp.IsNull());
631 uint32_t chosenIndex = 0;
633 while (chosenIndex + 1 < mImages.Length() &&
634 mImages[chosenIndex + 1].mTimeStamp <= aTimeStamp) {
635 ++chosenIndex;
638 return mImages[chosenIndex].mImage.get();
641 private:
642 AutoTArray<ImageContainer::OwningImage, 4> mImages;
645 struct PlanarYCbCrData {
646 // Luminance buffer
647 uint8_t* mYChannel = nullptr;
648 int32_t mYStride = 0;
649 gfx::IntSize mYSize = gfx::IntSize(0, 0);
650 int32_t mYSkip = 0;
651 // Chroma buffers
652 uint8_t* mCbChannel = nullptr;
653 uint8_t* mCrChannel = nullptr;
654 int32_t mCbCrStride = 0;
655 gfx::IntSize mCbCrSize = gfx::IntSize(0, 0);
656 int32_t mCbSkip = 0;
657 int32_t mCrSkip = 0;
658 // Picture region
659 uint32_t mPicX = 0;
660 uint32_t mPicY = 0;
661 gfx::IntSize mPicSize = gfx::IntSize(0, 0);
662 StereoMode mStereoMode = StereoMode::MONO;
663 gfx::ColorDepth mColorDepth = gfx::ColorDepth::COLOR_8;
664 gfx::YUVColorSpace mYUVColorSpace = gfx::YUVColorSpace::UNKNOWN;
665 gfx::ColorRange mColorRange = gfx::ColorRange::LIMITED;
667 gfx::IntRect GetPictureRect() const {
668 return gfx::IntRect(mPicX, mPicY, mPicSize.width, mPicSize.height);
672 // This type is currently only used for AVIF and therefore makes some
673 // AVIF-specific assumptions (e.g., Alpha's bpc and stride is equal to Y's one)
674 struct PlanarYCbCrAData : PlanarYCbCrData {
675 uint8_t* mAlphaChannel = nullptr;
676 gfx::IntSize mAlphaSize = gfx::IntSize(0, 0);
677 bool mPremultipliedAlpha = false;
679 bool hasAlpha() { return mAlphaChannel; }
682 /****** Image subtypes for the different formats ******/
685 * We assume that the image data is in the REC 470M color space (see
686 * Theora specification, section 4.3.1).
688 * The YCbCr format can be:
690 * 4:4:4 - CbCr width/height are the same as Y.
691 * 4:2:2 - CbCr width is half that of Y. Height is the same.
692 * 4:2:0 - CbCr width and height is half that of Y.
694 * The color format is detected based on the height/width ratios
695 * defined above.
697 * The Image that is rendered is the picture region defined by
698 * mPicX, mPicY and mPicSize. The size of the rendered image is
699 * mPicSize, not mYSize or mCbCrSize.
701 * mYSkip, mCbSkip, mCrSkip are added to support various output
702 * formats from hardware decoder. They are per-pixel skips in the
703 * source image.
705 * For example when image width is 640, mYStride is 670, mYSkip is 2,
706 * the mYChannel buffer looks like:
708 * |<----------------------- mYStride ----------------------------->|
709 * |<----------------- mYSize.width --------------->|
710 * 0 3 6 9 12 15 18 21 639 669
711 * |----------------------------------------------------------------|
712 * |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%%%%%%%|
713 * |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%%%%%%%|
714 * |Y___Y___Y___Y___Y___Y___Y___Y... |%%%%%%%%%%%%%%%|
715 * | |<->|
716 * mYSkip
718 class PlanarYCbCrImage : public Image {
719 public:
720 typedef PlanarYCbCrData Data;
722 enum { MAX_DIMENSION = 16384 };
724 virtual ~PlanarYCbCrImage();
727 * This makes a copy of the data buffers, in order to support functioning
728 * in all different layer managers.
730 virtual bool CopyData(const Data& aData) = 0;
733 * This doesn't make a copy of the data buffers.
735 virtual bool AdoptData(const Data& aData);
738 * Ask this Image to not convert YUV to RGB during SetData, and make
739 * the original data available through GetData. This is optional,
740 * and not all PlanarYCbCrImages will support it.
742 virtual void SetDelayedConversion(bool aDelayed) {}
745 * Grab the original YUV data. This is optional.
747 virtual const Data* GetData() const { return &mData; }
750 * Return the number of bytes of heap memory used to store this image.
752 uint32_t GetDataSize() const { return mBufferSize; }
754 bool IsValid() const override { return !!mBufferSize; }
756 gfx::IntSize GetSize() const override { return mSize; }
758 gfx::IntPoint GetOrigin() const override { return mOrigin; }
760 PlanarYCbCrImage();
762 virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
763 return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
766 virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const = 0;
768 PlanarYCbCrImage* AsPlanarYCbCrImage() override { return this; }
771 * Build a SurfaceDescriptorBuffer with this image. The provided
772 * SurfaceDescriptorBuffer must already have a valid MemoryOrShmem set
773 * with a capacity large enough to hold |GetDataSize|.
775 virtual nsresult BuildSurfaceDescriptorBuffer(
776 SurfaceDescriptorBuffer& aSdBuffer);
778 protected:
779 already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
781 void SetOffscreenFormat(gfxImageFormat aFormat) {
782 mOffscreenFormat = aFormat;
784 gfxImageFormat GetOffscreenFormat() const;
786 Data mData;
787 gfx::IntPoint mOrigin;
788 gfx::IntSize mSize;
789 gfxImageFormat mOffscreenFormat;
790 RefPtr<gfx::SourceSurface> mSourceSurface;
791 uint32_t mBufferSize;
794 class RecyclingPlanarYCbCrImage : public PlanarYCbCrImage {
795 public:
796 explicit RecyclingPlanarYCbCrImage(BufferRecycleBin* aRecycleBin)
797 : mRecycleBin(aRecycleBin) {}
798 virtual ~RecyclingPlanarYCbCrImage();
799 bool CopyData(const Data& aData) override;
800 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
802 protected:
804 * Return a buffer to store image data in.
806 mozilla::UniquePtr<uint8_t[]> AllocateBuffer(uint32_t aSize);
808 RefPtr<BufferRecycleBin> mRecycleBin;
809 mozilla::UniquePtr<uint8_t[]> mBuffer;
813 * NVImage is used to store YUV420SP_NV12 and YUV420SP_NV21 data natively, which
814 * are not supported by PlanarYCbCrImage. (PlanarYCbCrImage only stores YUV444P,
815 * YUV422P and YUV420P, it converts YUV420SP_NV12 and YUV420SP_NV21 data into
816 * YUV420P in its PlanarYCbCrImage::SetData() method.)
818 * PlanarYCbCrData is able to express all the YUV family and so we keep use it
819 * in NVImage.
821 class NVImage final : public Image {
822 typedef PlanarYCbCrData Data;
824 public:
825 NVImage();
826 virtual ~NVImage();
828 // Methods inherited from layers::Image.
829 gfx::IntSize GetSize() const override;
830 gfx::IntRect GetPictureRect() const override;
831 already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
832 bool IsValid() const override;
833 NVImage* AsNVImage() override;
835 // Methods mimic layers::PlanarYCbCrImage.
836 bool SetData(const Data& aData);
837 const Data* GetData() const;
838 uint32_t GetBufferSize() const;
840 protected:
842 * Return a buffer to store image data in.
844 mozilla::UniquePtr<uint8_t[]> AllocateBuffer(uint32_t aSize);
846 mozilla::UniquePtr<uint8_t[]> mBuffer;
847 uint32_t mBufferSize;
848 gfx::IntSize mSize;
849 Data mData;
850 RefPtr<gfx::SourceSurface> mSourceSurface;
854 * Currently, the data in a SourceSurfaceImage surface is treated as being in
855 * the device output color space. This class is very simple as all backends have
856 * to know about how to deal with drawing a cairo image.
858 class SourceSurfaceImage final : public Image {
859 public:
860 already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override {
861 RefPtr<gfx::SourceSurface> surface(mSourceSurface);
862 return surface.forget();
865 void SetTextureFlags(TextureFlags aTextureFlags) {
866 mTextureFlags = aTextureFlags;
868 TextureClient* GetTextureClient(KnowsCompositor* aKnowsCompositor) override;
870 gfx::IntSize GetSize() const override { return mSize; }
872 SourceSurfaceImage(const gfx::IntSize& aSize,
873 gfx::SourceSurface* aSourceSurface);
874 explicit SourceSurfaceImage(gfx::SourceSurface* aSourceSurface);
875 virtual ~SourceSurfaceImage();
877 private:
878 gfx::IntSize mSize;
879 RefPtr<gfx::SourceSurface> mSourceSurface;
880 nsDataHashtable<nsUint32HashKey, RefPtr<TextureClient>> mTextureClients;
881 TextureFlags mTextureFlags;
884 } // namespace layers
885 } // namespace mozilla
887 #endif