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 {
95 #ifdef ROSEN_OHOS
96 if (pixelMap_) {
97 pixelMap_->IncreaseUseCount();
98 }
99 #endif
100 }
101
~PixelMapReleaseContextOHOS::Rosen::PixelMapReleaseContext102 ~PixelMapReleaseContext()
103 {
104 #ifdef ROSEN_OHOS
105 if (pixelMap_) {
106 pixelMap_->DecreaseUseCount();
107 }
108 #endif
109 pixelMap_ = nullptr;
110 }
111
112 private:
113 std::shared_ptr<PixelMap> pixelMap_;
114 };
115
PixelMapReleaseProc(const void *,void * context)116 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
117 {
118 PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
119 if (ctx) {
120 delete ctx;
121 ctx = nullptr;
122 }
123 }
124
GetPixelmapColorSpace(const std::shared_ptr<Media::PixelMap> & pixelMap)125 std::shared_ptr<Drawing::ColorSpace> RSPixelMapUtil::GetPixelmapColorSpace(
126 const std::shared_ptr<Media::PixelMap>& pixelMap)
127 {
128 if (!pixelMap) {
129 return Drawing::ColorSpace::CreateSRGB();
130 }
131 return ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName());
132 }
133
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)134 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ExtractDrawingImage(
135 std::shared_ptr<Media::PixelMap> pixelMap)
136 {
137 if (!pixelMap) {
138 return nullptr;
139 }
140 ImageInfo imageInfo;
141 pixelMap->GetImageInfo(imageInfo);
142 Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
143 PixelFormatToDrawingColorType(imageInfo.pixelFormat),
144 AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
145 ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName()) };
146 Drawing::Pixmap imagePixmap(drawingImageInfo,
147 reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowStride());
148 PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
149 auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
150 if (!image) {
151 RS_LOGE("RSPixelMapUtil::ExtractDrawingImage fail");
152 delete releaseContext;
153 releaseContext = nullptr;
154 }
155 return image;
156 }
157
158
TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Rect & src,Drawing::Rect & dst,Drawing::Canvas & canvas)159 void RSPixelMapUtil::TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,
160 Drawing::Rect& src, Drawing::Rect& dst, Drawing::Canvas& canvas)
161 {
162 TransformData transformData;
163 pixelMap->GetTransformData(transformData);
164 Size realSize;
165 pixelMap->GetAstcRealSize(realSize);
166 dst.SetLeft(dst.GetLeft() - (realSize.width - src.GetRight()) / HALF_F);
167 dst.SetTop(dst.GetTop() - (realSize.height - src.GetBottom()) / HALF_F);
168 dst.SetRight(dst.GetRight() + (realSize.width - src.GetRight()) / HALF_F);
169 dst.SetBottom(dst.GetBottom() + (realSize.height - src.GetBottom()) / HALF_F);
170 if (transformData.scaleX != 0 && transformData.scaleY != 0) {
171 src.SetRight(src.GetRight() / abs(transformData.scaleX));
172 src.SetBottom(src.GetBottom() / abs(transformData.scaleY));
173 }
174 Drawing::Matrix matrix;
175 matrix.PostScale(transformData.scaleX, transformData.scaleY, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
176 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
177 matrix.PostRotate(transformData.rotateD, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
178 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
179 if (transformData.flipX) {
180 matrix.PostScale(-1, 1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
181 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
182 }
183 if (transformData.flipY) {
184 matrix.PostScale(1, -1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
185 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
186 }
187 canvas.ConcatMatrix(matrix);
188 if (transformData.cropLeft >= 0 && transformData.cropTop >= 0 && transformData.cropWidth > 0 &&
189 transformData.cropHeight > 0 && transformData.cropLeft + transformData.cropWidth <= realSize.width &&
190 transformData.cropTop + transformData.cropHeight <= realSize.height) {
191 float rightMinus = src.GetRight() - transformData.cropLeft - transformData.cropWidth;
192 float bottomMinus = src.GetBottom() - transformData.cropTop - transformData.cropHeight;
193 src.SetLeft(src.GetLeft() + transformData.cropLeft);
194 src.SetTop(src.GetTop() + transformData.cropTop);
195 src.SetRight(src.GetRight() - rightMinus);
196 src.SetBottom(src.GetBottom() - bottomMinus);
197 dst.SetLeft(dst.GetLeft() + (realSize.width - transformData.cropWidth) / HALF_F);
198 dst.SetTop(dst.GetTop() + (realSize.height - transformData.cropHeight) / HALF_F);
199 dst.SetRight(dst.GetRight() - (realSize.width - transformData.cropWidth) / HALF_F);
200 dst.SetBottom(dst.GetBottom() - (realSize.height - transformData.cropHeight) / HALF_F);
201 }
202 if (transformData.scaleX != 0 && transformData.scaleY != 0) {
203 dst.SetLeft(dst.GetLeft() + transformData.translateX / HALF_F / abs(transformData.scaleX));
204 dst.SetTop(dst.GetTop() + transformData.translateY / HALF_F / abs(transformData.scaleY));
205 dst.SetRight(dst.GetRight() + transformData.translateX / HALF_F / abs(transformData.scaleX));
206 dst.SetBottom(dst.GetBottom() + transformData.translateY / HALF_F / abs(transformData.scaleY));
207 }
208 }
209
DrawPixelMap(Drawing::Canvas & canvas,Media::PixelMap & pixelMap,const Drawing::scalar px,const Drawing::scalar py)210 void RSPixelMapUtil::DrawPixelMap(Drawing::Canvas& canvas, Media::PixelMap& pixelMap,
211 const Drawing::scalar px, const Drawing::scalar py)
212 {
213 ImageInfo imageInfo;
214 pixelMap.GetImageInfo(imageInfo);
215 Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
216 PixelFormatToDrawingColorType(imageInfo.pixelFormat),
217 AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
218 ColorSpaceToDrawingColorSpace(pixelMap.InnerGetGrColorSpace().GetColorSpaceName()) };
219 Drawing::Bitmap pixelBitmap;
220 pixelBitmap.InstallPixels(
221 drawingImageInfo, reinterpret_cast<void*>(pixelMap.GetWritablePixels()),
222 static_cast<uint32_t>(pixelMap.GetRowBytes()));
223 canvas.DrawBitmap(pixelBitmap, px, py);
224 }
225
IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)226 bool RSPixelMapUtil::IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)
227 {
228 if (!pixelMap) {
229 return false;
230 }
231 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
232 if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
233 return false;
234 }
235 #endif
236 ImageInfo imageInfo;
237 pixelMap->GetImageInfo(imageInfo);
238 return imageInfo.pixelFormat == PixelFormat::NV21 || imageInfo.pixelFormat == PixelFormat::NV12
239 || imageInfo.pixelFormat == PixelFormat::YCBCR_P010
240 || imageInfo.pixelFormat == PixelFormat::YCRCB_P010;
241 }
242
YUVPixelFormatToPlaneConfig(PixelFormat pixelFormat)243 static Drawing::YUVInfo::PlaneConfig YUVPixelFormatToPlaneConfig(PixelFormat pixelFormat)
244 {
245 switch (pixelFormat) {
246 case PixelFormat::NV12:
247 case PixelFormat::YCBCR_P010:
248 return Drawing::YUVInfo::PlaneConfig::Y_UV;
249 case PixelFormat::NV21:
250 case PixelFormat::YCRCB_P010:
251 return Drawing::YUVInfo::PlaneConfig::Y_VU;
252 default:
253 return Drawing::YUVInfo::PlaneConfig::UNKNOWN;
254 }
255 }
256
YUVPixelFormatToSubSampling(PixelFormat pixelFormat)257 static Drawing::YUVInfo::SubSampling YUVPixelFormatToSubSampling(PixelFormat pixelFormat)
258 {
259 switch (pixelFormat) {
260 case PixelFormat::NV12:
261 case PixelFormat::NV21:
262 case PixelFormat::YCBCR_P010:
263 case PixelFormat::YCRCB_P010:
264 return Drawing::YUVInfo::SubSampling::K420;
265 default:
266 return Drawing::YUVInfo::SubSampling::UNKNOWN;
267 }
268 }
269
YUVPixelFormatToYUVColorSpace(PixelFormat pixelFormat)270 static Drawing::YUVInfo::YUVColorSpace YUVPixelFormatToYUVColorSpace(PixelFormat pixelFormat)
271 {
272 switch (pixelFormat) {
273 case PixelFormat::NV12:
274 case PixelFormat::NV21:
275 return Drawing::YUVInfo::YUVColorSpace::JPEG_FULL_YUVCOLORSPACE;
276 case PixelFormat::YCBCR_P010:
277 case PixelFormat::YCRCB_P010:
278 return Drawing::YUVInfo::YUVColorSpace::BT2020_10BIT_LIMITED_YUVCOLORSPACE;
279 default:
280 return Drawing::YUVInfo::YUVColorSpace::IDENTITY_YUVCOLORSPACE;
281 }
282 }
283
YUVPixelFormatToYUVDataType(PixelFormat pixelFormat)284 static Drawing::YUVInfo::YUVDataType YUVPixelFormatToYUVDataType(PixelFormat pixelFormat)
285 {
286 switch (pixelFormat) {
287 case PixelFormat::NV12:
288 case PixelFormat::NV21:
289 return Drawing::YUVInfo::YUVDataType::UNORM_8;
290 case PixelFormat::YCBCR_P010:
291 case PixelFormat::YCRCB_P010:
292 return Drawing::YUVInfo::YUVDataType::UNORM_16;
293 default:
294 return Drawing::YUVInfo::YUVDataType::UNORM_8;
295 }
296 }
297
ConvertYUVPixelMapToDrawingImage(std::shared_ptr<Drawing::GPUContext> gpuContext,std::shared_ptr<Media::PixelMap> pixelMap)298 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ConvertYUVPixelMapToDrawingImage(
299 std::shared_ptr<Drawing::GPUContext> gpuContext, std::shared_ptr<Media::PixelMap> pixelMap)
300 {
301 if (gpuContext && pixelMap && IsYUVFormat(pixelMap)) {
302 ImageInfo imageInfo;
303 pixelMap->GetImageInfo(imageInfo);
304 Drawing::YUVInfo info(pixelMap->GetWidth(), pixelMap->GetHeight(),
305 YUVPixelFormatToPlaneConfig(imageInfo.pixelFormat),
306 YUVPixelFormatToSubSampling(imageInfo.pixelFormat),
307 YUVPixelFormatToYUVColorSpace(imageInfo.pixelFormat),
308 YUVPixelFormatToYUVDataType(imageInfo.pixelFormat));
309 #ifdef RS_ENABLE_GPU
310 return Drawing::Image::MakeFromYUVAPixmaps(*gpuContext, info,
311 const_cast<void *>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
312 #endif
313 }
314 return nullptr;
315 }
316
IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,const Drawing::SamplingOptions & sampling)317 bool RSPixelMapUtil::IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,
318 const Drawing::SamplingOptions& sampling)
319 {
320 if (!(pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC)) {
321 return false;
322 }
323 return RSSystemProperties::GetGpuApiType() != GpuApiType::OPENGL;
324 }
325 } // namespace Rosen
326 } // namespace OHOS
327