1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "render/rs_pixel_map_util.h"
17 #include <memory>
18 
19 #include "pixel_map.h"
20 #include "platform/common/rs_log.h"
21 #include "platform/common/rs_system_properties.h"
22 #include "drawing/engine_adapter/impl_interface/bitmap_impl.h"
23 #include "image/yuv_info.h"
24 
25 namespace OHOS {
26 namespace Rosen {
27 using namespace Media;
28 namespace {
29     constexpr float HALF_F = 2;
30 }
31 
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)32 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(
33     ColorManager::ColorSpaceName colorSpaceName)
34 {
35     switch (colorSpaceName) {
36         case ColorManager::ColorSpaceName::DCI_P3:
37         case ColorManager::ColorSpaceName::DISPLAY_P3:
38             return Drawing::ColorSpace::CreateRGB(
39                 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
40         case ColorManager::ColorSpaceName::LINEAR_SRGB:
41             return Drawing::ColorSpace::CreateSRGBLinear();
42         case ColorManager::ColorSpaceName::SRGB:
43             return Drawing::ColorSpace::CreateSRGB();
44         default:
45             return Drawing::ColorSpace::CreateSRGB();
46     }
47 }
48 
PixelFormatToDrawingColorType(PixelFormat pixelFormat)49 static Drawing::ColorType PixelFormatToDrawingColorType(PixelFormat pixelFormat)
50 {
51     switch (pixelFormat) {
52         case PixelFormat::RGB_565:
53             return Drawing::ColorType::COLORTYPE_RGB_565;
54         case PixelFormat::RGBA_8888:
55             return Drawing::ColorType::COLORTYPE_RGBA_8888;
56         case PixelFormat::BGRA_8888:
57             return Drawing::ColorType::COLORTYPE_BGRA_8888;
58         case PixelFormat::ALPHA_8:
59             return Drawing::ColorType::COLORTYPE_ALPHA_8;
60         case PixelFormat::RGBA_F16:
61             return Drawing::ColorType::COLORTYPE_RGBA_F16;
62         case PixelFormat::RGBA_1010102:
63             return Drawing::ColorType::COLORTYPE_RGBA_1010102;
64         case PixelFormat::UNKNOWN:
65         case PixelFormat::ARGB_8888:
66         case PixelFormat::RGB_888:
67         case PixelFormat::NV21:
68         case PixelFormat::NV12:
69         case PixelFormat::CMYK:
70         default:
71             return Drawing::ColorType::COLORTYPE_UNKNOWN;
72     }
73 }
74 
AlphaTypeToDrawingAlphaType(AlphaType alphaType)75 static Drawing::AlphaType AlphaTypeToDrawingAlphaType(AlphaType alphaType)
76 {
77     switch (alphaType) {
78         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
79             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
80         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
81             return Drawing::AlphaType::ALPHATYPE_OPAQUE;
82         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
83             return Drawing::AlphaType::ALPHATYPE_PREMUL;
84         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
85             return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
86         default:
87             return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
88     }
89 }
90 
91 
92 struct PixelMapReleaseContext {
PixelMapReleaseContextOHOS::Rosen::PixelMapReleaseContext93     explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
94 
~PixelMapReleaseContextOHOS::Rosen::PixelMapReleaseContext95     ~PixelMapReleaseContext()
96     {
97         pixelMap_ = nullptr;
98     }
99 
100 private:
101     std::shared_ptr<PixelMap> pixelMap_;
102 };
103 
PixelMapReleaseProc(const void *,void * context)104 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
105 {
106     PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
107     if (ctx) {
108         delete ctx;
109         ctx = nullptr;
110     }
111 }
112 
GetPixelmapColorSpace(const std::shared_ptr<Media::PixelMap> & pixelMap)113 std::shared_ptr<Drawing::ColorSpace> RSPixelMapUtil::GetPixelmapColorSpace(
114     const std::shared_ptr<Media::PixelMap>& pixelMap)
115 {
116     if (!pixelMap) {
117         return Drawing::ColorSpace::CreateSRGB();
118     }
119     return ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName());
120 }
121 
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)122 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ExtractDrawingImage(
123     std::shared_ptr<Media::PixelMap> pixelMap)
124 {
125     if (!pixelMap) {
126         return nullptr;
127     }
128     ImageInfo imageInfo;
129     pixelMap->GetImageInfo(imageInfo);
130     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
131         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
132         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
133         ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName()) };
134     Drawing::Pixmap imagePixmap(drawingImageInfo,
135         reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowStride());
136     PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
137     auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
138     if (!image) {
139         RS_LOGE("RSPixelMapUtil::ExtractDrawingImage fail");
140         delete releaseContext;
141         releaseContext = nullptr;
142     }
143     return image;
144 }
145 
146 
TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Rect & src,Drawing::Rect & dst,Drawing::Canvas & canvas)147 void RSPixelMapUtil::TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,
148                                              Drawing::Rect& src, Drawing::Rect& dst, Drawing::Canvas& canvas)
149 {
150     TransformData transformData;
151     pixelMap->GetTransformData(transformData);
152     Size realSize;
153     pixelMap->GetAstcRealSize(realSize);
154     dst.SetLeft(dst.GetLeft() - (realSize.width - src.GetRight()) / HALF_F);
155     dst.SetTop(dst.GetTop() - (realSize.height - src.GetBottom()) / HALF_F);
156     dst.SetRight(dst.GetRight() + (realSize.width - src.GetRight()) / HALF_F);
157     dst.SetBottom(dst.GetBottom() + (realSize.height - src.GetBottom()) / HALF_F);
158     if (transformData.scaleX != 0 && transformData.scaleY != 0) {
159         src.SetRight(src.GetRight() / abs(transformData.scaleX));
160         src.SetBottom(src.GetBottom() / abs(transformData.scaleY));
161     }
162     Drawing::Matrix matrix;
163     matrix.PostScale(transformData.scaleX, transformData.scaleY, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
164                      dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
165     matrix.PostRotate(transformData.rotateD, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
166                       dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
167     if (transformData.flipX) {
168         matrix.PostScale(-1, 1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
169                          dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
170     }
171     if (transformData.flipY) {
172         matrix.PostScale(1, -1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
173                          dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
174     }
175     canvas.ConcatMatrix(matrix);
176     if (transformData.cropLeft >= 0 && transformData.cropTop >= 0 && transformData.cropWidth > 0 &&
177         transformData.cropHeight > 0 && transformData.cropLeft + transformData.cropWidth <= realSize.width &&
178         transformData.cropTop + transformData.cropHeight <= realSize.height) {
179         float rightMinus = src.GetRight() - transformData.cropLeft - transformData.cropWidth;
180         float bottomMinus = src.GetBottom() - transformData.cropTop - transformData.cropHeight;
181         src.SetLeft(src.GetLeft() + transformData.cropLeft);
182         src.SetTop(src.GetTop() + transformData.cropTop);
183         src.SetRight(src.GetRight() - rightMinus);
184         src.SetBottom(src.GetBottom() - bottomMinus);
185         dst.SetLeft(dst.GetLeft() + (realSize.width - transformData.cropWidth) / HALF_F);
186         dst.SetTop(dst.GetTop() + (realSize.height - transformData.cropHeight) / HALF_F);
187         dst.SetRight(dst.GetRight() - (realSize.width - transformData.cropWidth) / HALF_F);
188         dst.SetBottom(dst.GetBottom() - (realSize.height - transformData.cropHeight) / HALF_F);
189     }
190     if (transformData.scaleX != 0 && transformData.scaleY != 0) {
191         dst.SetLeft(dst.GetLeft() + transformData.translateX / HALF_F / abs(transformData.scaleX));
192         dst.SetTop(dst.GetTop() + transformData.translateY / HALF_F / abs(transformData.scaleY));
193         dst.SetRight(dst.GetRight() + transformData.translateX / HALF_F / abs(transformData.scaleX));
194         dst.SetBottom(dst.GetBottom() + transformData.translateY / HALF_F / abs(transformData.scaleY));
195     }
196 }
197 
DrawPixelMap(Drawing::Canvas & canvas,Media::PixelMap & pixelMap,const Drawing::scalar px,const Drawing::scalar py)198 void RSPixelMapUtil::DrawPixelMap(Drawing::Canvas& canvas, Media::PixelMap& pixelMap,
199                                   const Drawing::scalar px, const Drawing::scalar py)
200 {
201     ImageInfo imageInfo;
202     pixelMap.GetImageInfo(imageInfo);
203     Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
204         PixelFormatToDrawingColorType(imageInfo.pixelFormat),
205         AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
206         ColorSpaceToDrawingColorSpace(pixelMap.InnerGetGrColorSpace().GetColorSpaceName()) };
207     Drawing::Bitmap pixelBitmap;
208     pixelBitmap.InstallPixels(
209         drawingImageInfo, reinterpret_cast<void*>(pixelMap.GetWritablePixels()),
210         static_cast<uint32_t>(pixelMap.GetRowBytes()));
211     canvas.DrawBitmap(pixelBitmap, px, py);
212 }
213 
IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)214 bool RSPixelMapUtil::IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)
215 {
216     if (!pixelMap) {
217         return false;
218     }
219 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
220     if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
221         return false;
222     }
223 #endif
224     ImageInfo imageInfo;
225     pixelMap->GetImageInfo(imageInfo);
226     return imageInfo.pixelFormat == Media::PixelFormat::NV21 || imageInfo.pixelFormat == Media::PixelFormat::NV12;
227 }
228 
YUVPixelFormatToPlaneConfig(Media::PixelFormat pixelFormat)229 static Drawing::YUVInfo::PlaneConfig YUVPixelFormatToPlaneConfig(Media::PixelFormat pixelFormat)
230 {
231     switch (pixelFormat) {
232         case Media::PixelFormat::NV12:
233             return Drawing::YUVInfo::PlaneConfig::Y_UV;
234         case Media::PixelFormat::NV21:
235             return Drawing::YUVInfo::PlaneConfig::Y_VU;
236         default:
237             return Drawing::YUVInfo::PlaneConfig::UNKNOWN;
238     }
239 }
240 
YUVPixelFormatToSubSampling(Media::PixelFormat pixelFormat)241 static Drawing::YUVInfo::SubSampling YUVPixelFormatToSubSampling(Media::PixelFormat pixelFormat)
242 {
243     switch (pixelFormat) {
244         case Media::PixelFormat::NV12:
245         case Media::PixelFormat::NV21:
246             return Drawing::YUVInfo::SubSampling::K420;
247         default:
248             return Drawing::YUVInfo::SubSampling::UNKNOWN;
249     }
250 }
251 
YUVPixelFormatToYUVColorSpace(Media::PixelFormat pixelFormat)252 static Drawing::YUVInfo::YUVColorSpace YUVPixelFormatToYUVColorSpace(Media::PixelFormat pixelFormat)
253 {
254     switch (pixelFormat) {
255         case Media::PixelFormat::NV12:
256         case Media::PixelFormat::NV21:
257             return Drawing::YUVInfo::YUVColorSpace::JPEG_FULL_YUVCOLORSPACE;
258         default:
259             return Drawing::YUVInfo::YUVColorSpace::IDENTITY_YUVCOLORSPACE;
260     }
261 }
262 
ConvertYUVPixelMapToDrawingImage(std::shared_ptr<Drawing::GPUContext> gpuContext,std::shared_ptr<Media::PixelMap> pixelMap)263 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ConvertYUVPixelMapToDrawingImage(
264     std::shared_ptr<Drawing::GPUContext> gpuContext, std::shared_ptr<Media::PixelMap> pixelMap)
265 {
266     if (gpuContext && pixelMap && IsYUVFormat(pixelMap)) {
267         ImageInfo imageInfo;
268         pixelMap->GetImageInfo(imageInfo);
269         Drawing::YUVInfo info(pixelMap->GetWidth(), pixelMap->GetHeight(),
270             YUVPixelFormatToPlaneConfig(imageInfo.pixelFormat),
271             YUVPixelFormatToSubSampling(imageInfo.pixelFormat),
272             YUVPixelFormatToYUVColorSpace(imageInfo.pixelFormat));
273         return Drawing::Image::MakeFromYUVAPixmaps(*gpuContext, info,
274             const_cast<void *>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
275     }
276     return nullptr;
277 }
278 
IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,const Drawing::SamplingOptions & sampling)279 bool RSPixelMapUtil::IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,
280     const Drawing::SamplingOptions& sampling)
281 {
282     if (!(pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC)) {
283         return false;
284     }
285     ImageInfo imageInfo;
286     pixelMap->GetImageInfo(imageInfo);
287     if (imageInfo.pixelFormat == Media::PixelFormat::RGBA_8888) {
288         return sampling.GetMipmapMode() != Drawing::MipmapMode::LINEAR && RSSystemProperties::IsPhoneType();
289     }
290     return true;
291 }
292 } // namespace Rosen
293 } // namespace OHOS
294