1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 #include "mozilla/dom/ImageUtils.h"
9 #include "ImageContainer.h"
10 #include "Intervals.h"
11 #include "mozilla/dom/ImageBitmapBinding.h"
13 using namespace mozilla::layers
;
14 using namespace mozilla::gfx
;
16 namespace mozilla::dom
{
18 static Maybe
<ImageBitmapFormat
> GetImageBitmapFormatFromSurfaceFromat(
19 SurfaceFormat aSurfaceFormat
) {
20 switch (aSurfaceFormat
) {
21 case SurfaceFormat::B8G8R8A8
:
22 case SurfaceFormat::B8G8R8X8
:
23 return Some(ImageBitmapFormat::BGRA32
);
24 case SurfaceFormat::R8G8B8A8
:
25 case SurfaceFormat::R8G8B8X8
:
26 return Some(ImageBitmapFormat::RGBA32
);
27 case SurfaceFormat::R8G8B8
:
28 return Some(ImageBitmapFormat::RGB24
);
29 case SurfaceFormat::B8G8R8
:
30 return Some(ImageBitmapFormat::BGR24
);
31 case SurfaceFormat::HSV
:
32 return Some(ImageBitmapFormat::HSV
);
33 case SurfaceFormat::Lab
:
34 return Some(ImageBitmapFormat::Lab
);
35 case SurfaceFormat::Depth
:
36 return Some(ImageBitmapFormat::DEPTH
);
37 case SurfaceFormat::A8
:
38 return Some(ImageBitmapFormat::GRAY8
);
39 case SurfaceFormat::R5G6B5_UINT16
:
40 case SurfaceFormat::YUV420
:
41 case SurfaceFormat::NV12
:
42 case SurfaceFormat::P010
:
43 case SurfaceFormat::P016
:
44 case SurfaceFormat::UNKNOWN
:
50 static Maybe
<ImageBitmapFormat
> GetImageBitmapFormatFromPlanarYCbCrData(
51 layers::PlanarYCbCrData
const* aData
) {
54 auto ySize
= aData
->YDataSize();
55 auto cbcrSize
= aData
->CbCrDataSize();
56 media::Interval
<uintptr_t> YInterval(
57 uintptr_t(aData
->mYChannel
),
58 uintptr_t(aData
->mYChannel
) + ySize
.height
* aData
->mYStride
),
60 uintptr_t(aData
->mCbChannel
),
61 uintptr_t(aData
->mCbChannel
) + cbcrSize
.height
* aData
->mCbCrStride
),
63 uintptr_t(aData
->mCrChannel
),
64 uintptr_t(aData
->mCrChannel
) + cbcrSize
.height
* aData
->mCbCrStride
);
65 if (aData
->mYSkip
== 0 && aData
->mCbSkip
== 0 &&
66 aData
->mCrSkip
== 0) { // Possibly three planes.
67 if (!YInterval
.Intersects(CbInterval
) &&
68 !CbInterval
.Intersects(CrInterval
)) { // Three planes.
69 switch (aData
->mChromaSubsampling
) {
70 case ChromaSubsampling::FULL
:
71 return Some(ImageBitmapFormat::YUV444P
);
72 case ChromaSubsampling::HALF_WIDTH
:
73 return Some(ImageBitmapFormat::YUV422P
);
74 case ChromaSubsampling::HALF_WIDTH_AND_HEIGHT
:
75 return Some(ImageBitmapFormat::YUV420P
);
80 } else if (aData
->mYSkip
== 0 && aData
->mCbSkip
== 1 && aData
->mCrSkip
== 1 &&
81 aData
->mChromaSubsampling
==
82 ChromaSubsampling::HALF_WIDTH_AND_HEIGHT
) { // Possibly two
84 if (!YInterval
.Intersects(CbInterval
) &&
85 aData
->mCbChannel
== aData
->mCrChannel
- 1) { // Two planes.
86 return Some(ImageBitmapFormat::YUV420SP_NV12
); // Y-Cb-Cr
87 } else if (!YInterval
.Intersects(CrInterval
) &&
88 aData
->mCrChannel
== aData
->mCbChannel
- 1) { // Two planes.
89 return Some(ImageBitmapFormat::YUV420SP_NV21
); // Y-Cr-Cb
96 // ImageUtils::Impl implements the _generic_ algorithm which always readback
97 // data in RGBA format into CPU memory.
98 // Since layers::CairoImage is just a warpper to a DataSourceSurface, the
99 // implementation of CairoSurfaceImpl is nothing different to the generic
101 class ImageUtils::Impl
{
103 explicit Impl(layers::Image
* aImage
) : mImage(aImage
), mSurface(nullptr) {}
105 virtual ~Impl() = default;
107 virtual Maybe
<ImageBitmapFormat
> GetFormat() const {
108 if (DataSourceSurface
* surface
= Surface()) {
109 return GetImageBitmapFormatFromSurfaceFromat(surface
->GetFormat());
114 virtual uint32_t GetBufferLength() const {
115 if (DataSourceSurface
* surface
= Surface()) {
116 DataSourceSurface::ScopedMap
map(surface
, DataSourceSurface::READ
);
117 const uint32_t stride
= map
.GetStride();
118 const IntSize size
= surface
->GetSize();
119 return (uint32_t)(size
.height
* stride
);
127 DataSourceSurface
* Surface() const {
129 return mSurface
.get();
132 RefPtr
<SourceSurface
> surface
= mImage
->GetAsSourceSurface();
133 if (NS_WARN_IF(!surface
)) {
137 mSurface
= surface
->GetDataSurface();
138 MOZ_ASSERT(mSurface
);
139 return mSurface
.get();
142 RefPtr
<layers::Image
> mImage
;
143 mutable RefPtr
<DataSourceSurface
> mSurface
;
146 // YUVImpl is optimized for the layers::PlanarYCbCrImage and layers::NVImage.
147 // This implementation does not readback data in RGBA format but keep it in YUV
149 class YUVImpl final
: public ImageUtils::Impl
{
151 explicit YUVImpl(layers::Image
* aImage
) : Impl(aImage
) {
152 MOZ_ASSERT(aImage
->GetFormat() == ImageFormat::PLANAR_YCBCR
||
153 aImage
->GetFormat() == ImageFormat::NV_IMAGE
);
156 Maybe
<ImageBitmapFormat
> GetFormat() const override
{
157 return GetImageBitmapFormatFromPlanarYCbCrData(GetPlanarYCbCrData());
160 uint32_t GetBufferLength() const override
{
161 if (mImage
->GetFormat() == ImageFormat::PLANAR_YCBCR
) {
162 return mImage
->AsPlanarYCbCrImage()->GetDataSize();
164 return mImage
->AsNVImage()->GetBufferSize();
168 const PlanarYCbCrData
* GetPlanarYCbCrData() const {
169 if (mImage
->GetFormat() == ImageFormat::PLANAR_YCBCR
) {
170 return mImage
->AsPlanarYCbCrImage()->GetData();
172 return mImage
->AsNVImage()->GetData();
176 // TODO: optimize for other platforms.
177 // For Windows: implement D3D9RGB32TextureImpl and D3D11ShareHandleTextureImpl.
178 // Others: SharedBGRImpl, MACIOSrufaceImpl, GLImageImpl, SurfaceTextureImpl
179 // EGLImageImpl and OverlayImegImpl.
181 ImageUtils::ImageUtils(layers::Image
* aImage
) : mImpl(nullptr) {
182 MOZ_ASSERT(aImage
, "Create ImageUtils with nullptr.");
183 switch (aImage
->GetFormat()) {
184 case mozilla::ImageFormat::PLANAR_YCBCR
:
185 case mozilla::ImageFormat::NV_IMAGE
:
186 mImpl
= new YUVImpl(aImage
);
188 case mozilla::ImageFormat::MOZ2D_SURFACE
:
190 mImpl
= new Impl(aImage
);
194 ImageUtils::~ImageUtils() {
201 Maybe
<ImageBitmapFormat
> ImageUtils::GetFormat() const {
203 return mImpl
->GetFormat();
206 uint32_t ImageUtils::GetBufferLength() const {
208 return mImpl
->GetBufferLength();
211 } // namespace mozilla::dom