Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / ImageUtils.cpp
blob74b4c0b9cba97c86ec8d9f3f90ca73d03f3b1f54
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 "ImageUtils.h"
9 #include "ImageContainer.h"
10 #include "Intervals.h"
11 #include "mozilla/AlreadyAddRefed.h"
12 #include "mozilla/ErrorResult.h"
13 #include "mozilla/dom/ImageBitmapBinding.h"
15 using namespace mozilla::layers;
16 using namespace mozilla::gfx;
18 namespace mozilla::dom {
20 static ImageBitmapFormat GetImageBitmapFormatFromSurfaceFromat(
21 SurfaceFormat aSurfaceFormat) {
22 switch (aSurfaceFormat) {
23 case SurfaceFormat::B8G8R8A8:
24 case SurfaceFormat::B8G8R8X8:
25 return ImageBitmapFormat::BGRA32;
26 case SurfaceFormat::R8G8B8A8:
27 case SurfaceFormat::R8G8B8X8:
28 return ImageBitmapFormat::RGBA32;
29 case SurfaceFormat::R8G8B8:
30 return ImageBitmapFormat::RGB24;
31 case SurfaceFormat::B8G8R8:
32 return ImageBitmapFormat::BGR24;
33 case SurfaceFormat::HSV:
34 return ImageBitmapFormat::HSV;
35 case SurfaceFormat::Lab:
36 return ImageBitmapFormat::Lab;
37 case SurfaceFormat::Depth:
38 return ImageBitmapFormat::DEPTH;
39 case SurfaceFormat::A8:
40 return ImageBitmapFormat::GRAY8;
41 case SurfaceFormat::R5G6B5_UINT16:
42 case SurfaceFormat::YUV:
43 case SurfaceFormat::NV12:
44 case SurfaceFormat::P010:
45 case SurfaceFormat::P016:
46 case SurfaceFormat::UNKNOWN:
47 default:
48 return ImageBitmapFormat::EndGuard_;
52 static ImageBitmapFormat GetImageBitmapFormatFromPlanarYCbCrData(
53 layers::PlanarYCbCrData const* aData) {
54 MOZ_ASSERT(aData);
56 media::Interval<uintptr_t> YInterval(
57 uintptr_t(aData->mYChannel),
58 uintptr_t(aData->mYChannel) + aData->mYSize.height * aData->mYStride),
59 CbInterval(uintptr_t(aData->mCbChannel),
60 uintptr_t(aData->mCbChannel) +
61 aData->mCbCrSize.height * aData->mCbCrStride),
62 CrInterval(uintptr_t(aData->mCrChannel),
63 uintptr_t(aData->mCrChannel) +
64 aData->mCbCrSize.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 if (aData->mYSize.height == aData->mCbCrSize.height) {
70 if (aData->mYSize.width == aData->mCbCrSize.width) {
71 return ImageBitmapFormat::YUV444P;
73 if (((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
74 return ImageBitmapFormat::YUV422P;
76 } else if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height) {
77 if (((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
78 return ImageBitmapFormat::YUV420P;
82 } else if (aData->mYSkip == 0 && aData->mCbSkip == 1 &&
83 aData->mCrSkip == 1) { // Possibly two planes.
84 if (!YInterval.Intersects(CbInterval) &&
85 aData->mCbChannel == aData->mCrChannel - 1) { // Two planes.
86 if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height &&
87 ((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
88 return ImageBitmapFormat::YUV420SP_NV12; // Y-Cb-Cr
90 } else if (!YInterval.Intersects(CrInterval) &&
91 aData->mCrChannel == aData->mCbChannel - 1) { // Two planes.
92 if (((aData->mYSize.height + 1) / 2) == aData->mCbCrSize.height &&
93 ((aData->mYSize.width + 1) / 2) == aData->mCbCrSize.width) {
94 return ImageBitmapFormat::YUV420SP_NV21; // Y-Cr-Cb
99 return ImageBitmapFormat::EndGuard_;
102 // ImageUtils::Impl implements the _generic_ algorithm which always readback
103 // data in RGBA format into CPU memory.
104 // Since layers::CairoImage is just a warpper to a DataSourceSurface, the
105 // implementation of CairoSurfaceImpl is nothing different to the generic
106 // version.
107 class ImageUtils::Impl {
108 public:
109 explicit Impl(layers::Image* aImage) : mImage(aImage), mSurface(nullptr) {}
111 virtual ~Impl() = default;
113 virtual ImageBitmapFormat GetFormat() const {
114 return GetImageBitmapFormatFromSurfaceFromat(Surface()->GetFormat());
117 virtual uint32_t GetBufferLength() const {
118 DataSourceSurface::ScopedMap map(Surface(), DataSourceSurface::READ);
119 const uint32_t stride = map.GetStride();
120 const IntSize size = Surface()->GetSize();
121 return (uint32_t)(size.height * stride);
124 protected:
125 Impl() = default;
127 DataSourceSurface* Surface() const {
128 if (!mSurface) {
129 RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
130 MOZ_ASSERT(surface);
132 mSurface = surface->GetDataSurface();
133 MOZ_ASSERT(mSurface);
136 return mSurface.get();
139 RefPtr<layers::Image> mImage;
140 mutable RefPtr<DataSourceSurface> mSurface;
143 // YUVImpl is optimized for the layers::PlanarYCbCrImage and layers::NVImage.
144 // This implementation does not readback data in RGBA format but keep it in YUV
145 // format family.
146 class YUVImpl final : public ImageUtils::Impl {
147 public:
148 explicit YUVImpl(layers::Image* aImage) : Impl(aImage) {
149 MOZ_ASSERT(aImage->GetFormat() == ImageFormat::PLANAR_YCBCR ||
150 aImage->GetFormat() == ImageFormat::NV_IMAGE);
153 ImageBitmapFormat GetFormat() const override {
154 return GetImageBitmapFormatFromPlanarYCbCrData(GetPlanarYCbCrData());
157 uint32_t GetBufferLength() const override {
158 if (mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
159 return mImage->AsPlanarYCbCrImage()->GetDataSize();
161 return mImage->AsNVImage()->GetBufferSize();
164 private:
165 const PlanarYCbCrData* GetPlanarYCbCrData() const {
166 if (mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
167 return mImage->AsPlanarYCbCrImage()->GetData();
169 return mImage->AsNVImage()->GetData();
173 // TODO: optimize for other platforms.
174 // For Windows: implement D3D9RGB32TextureImpl and D3D11ShareHandleTextureImpl.
175 // Others: SharedBGRImpl, MACIOSrufaceImpl, GLImageImpl, SurfaceTextureImpl
176 // EGLImageImpl and OverlayImegImpl.
178 ImageUtils::ImageUtils(layers::Image* aImage) : mImpl(nullptr) {
179 MOZ_ASSERT(aImage, "Create ImageUtils with nullptr.");
180 switch (aImage->GetFormat()) {
181 case mozilla::ImageFormat::PLANAR_YCBCR:
182 case mozilla::ImageFormat::NV_IMAGE:
183 mImpl = new YUVImpl(aImage);
184 break;
185 case mozilla::ImageFormat::CAIRO_SURFACE:
186 default:
187 mImpl = new Impl(aImage);
191 ImageUtils::~ImageUtils() {
192 if (mImpl) {
193 delete mImpl;
194 mImpl = nullptr;
198 ImageBitmapFormat ImageUtils::GetFormat() const {
199 MOZ_ASSERT(mImpl);
200 return mImpl->GetFormat();
203 uint32_t ImageUtils::GetBufferLength() const {
204 MOZ_ASSERT(mImpl);
205 return mImpl->GetBufferLength();
208 } // namespace mozilla::dom