• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include "render/rs_colorspace_convert.h"
16 
17 #include <dlfcn.h>
18 
19 #include "display_engine/rs_color_temperature.h"
20 #include "display_engine/rs_luminance_control.h"
21 #include "effect/image_filter.h"
22 #include "metadata_helper.h"
23 #include "platform/common/rs_log.h"
24 #include "rs_trace.h"
25 
26 namespace OHOS {
27 namespace Rosen {
28 
29 namespace {
30 constexpr float DEFAULT_SCALER = 1000.0f / 203.0f;
31 constexpr uint32_t DEFAULT_DYNAMIC_METADATA_SIZE = 50;
32 constexpr size_t MATRIX_SIZE = 9;
33 }; // namespace
34 
RSColorSpaceConvert()35 RSColorSpaceConvert::RSColorSpaceConvert()
36 {
37     handle_ = dlopen("libvideoprocessingengine.z.so", RTLD_LAZY);
38     if (handle_ == nullptr) {
39         RS_LOGW("[%{public}s]:load library failed, reason: %{public}s", __func__, dlerror());
40         return;
41     }
42     colorSpaceConvertDisplayCreate_ = reinterpret_cast<VPEColorSpaceConvertDisplayCreate>(
43         dlsym(handle_, "ColorSpaceConvertDisplayCreate"));
44     if (colorSpaceConvertDisplayCreate_ == nullptr) {
45         RS_LOGW("[%{public}s]:load Create failed, reason: %{public}s", __func__, dlerror());
46         CloseLibraryHandle();
47         return;
48     }
49     colorSpaceConvertDisplayDestroy_ = reinterpret_cast<VPEColorSpaceConvertDisplayDestroy>(
50         dlsym(handle_, "ColorSpaceConvertDisplayDestroy"));
51     if (colorSpaceConvertDisplayDestroy_ == nullptr) {
52         RS_LOGW("[%{public}s]:load Destroy failed, reason: %{public}s", __func__, dlerror());
53         CloseLibraryHandle();
54         return;
55     }
56     colorSpaceConvertDisplayHandle_ = colorSpaceConvertDisplayCreate_();
57     if (colorSpaceConvertDisplayHandle_ == nullptr) {
58         RS_LOGE("ColorSpaceConvertDisplayCreate failed, return nullptr");
59         CloseLibraryHandle();
60         return;
61     }
62     colorSpaceConverterDisplay_ = static_cast<ColorSpaceConvertDisplayHandleImpl *>(
63         colorSpaceConvertDisplayHandle_)->obj;
64 }
65 
~RSColorSpaceConvert()66 RSColorSpaceConvert::~RSColorSpaceConvert()
67 {
68     if (colorSpaceConvertDisplayHandle_) {
69         colorSpaceConvertDisplayDestroy_(colorSpaceConvertDisplayHandle_);
70         colorSpaceConvertDisplayHandle_ = nullptr;
71     }
72     if (handle_) {
73         CloseLibraryHandle();
74     }
75 }
76 
Instance()77 RSColorSpaceConvert& RSColorSpaceConvert::Instance()
78 {
79     static RSColorSpaceConvert instance;
80     return instance;
81 }
82 
ColorSpaceConvertor(std::shared_ptr<Drawing::ShaderEffect> inputShader,const sptr<SurfaceBuffer> & surfaceBuffer,Drawing::Paint & paint,GraphicColorGamut targetColorSpace,ScreenId screenId,uint32_t dynamicRangeMode)83 bool RSColorSpaceConvert::ColorSpaceConvertor(std::shared_ptr<Drawing::ShaderEffect> inputShader,
84     const sptr<SurfaceBuffer>& surfaceBuffer, Drawing::Paint& paint, GraphicColorGamut targetColorSpace,
85     ScreenId screenId, uint32_t dynamicRangeMode)
86 {
87     RS_LOGD("RSColorSpaceConvertor HDRDraw targetColorSpace: %{public}d, screenId: %{public}" PRIu64 ""
88         ", dynamicRangeMode: %{public}u", targetColorSpace, screenId, dynamicRangeMode);
89     RS_TRACE_NAME_FMT("RSColorSpaceConvertor HDRDraw targetColorSpace: %d, screenId: %" PRIu64 ""
90         ", dynamicRangeMode: %u", targetColorSpace, screenId, dynamicRangeMode);
91     VPEParameter parameter;
92 
93     if (inputShader == nullptr) {
94         RS_LOGE("bhdr imageShader is nullptr.");
95         return false;
96     }
97 
98     if (!SetColorSpaceConverterDisplayParameter(surfaceBuffer, parameter, targetColorSpace, screenId,
99         dynamicRangeMode)) {
100         return false;
101     }
102 
103     std::shared_ptr<Drawing::ShaderEffect> outputShader;
104 
105     if (colorSpaceConverterDisplay_ == nullptr) {
106         RS_LOGE("colorSpaceConverterDisplay_ is nullptr.");
107         return false;
108     }
109     auto convRet = colorSpaceConverterDisplay_->Process(inputShader, outputShader, parameter);
110     if (convRet != Media::VideoProcessingEngine::VPE_ALGO_ERR_OK) {
111         RS_LOGE("bhdr failed with %{public}u.", convRet);
112         return false;
113     }
114     if (outputShader == nullptr) {
115         RS_LOGE("bhdr outputShader is nullptr.");
116         return false;
117     }
118     paint.SetShaderEffect(outputShader);
119     return true;
120 }
121 
GetHDRStaticMetadata(const sptr<SurfaceBuffer> & surfaceBuffer,std::vector<uint8_t> & hdrStaticMetadata,GSError & ret)122 void RSColorSpaceConvert::GetHDRStaticMetadata(const sptr<SurfaceBuffer>& surfaceBuffer,
123     std::vector<uint8_t>& hdrStaticMetadata, GSError& ret)
124 {
125     ret = MetadataHelper::GetHDRStaticMetadata(surfaceBuffer, hdrStaticMetadata);
126     if (ret != GSERROR_OK) {
127         RS_LOGD("RSColorSpaceConvert::GetHDRStaticMetadata failed with ret: %{public}u.", ret);
128     }
129 }
130 
GetHDRDynamicMetadata(const sptr<SurfaceBuffer> & surfaceBuffer,std::vector<uint8_t> & hdrDynamicMetadata,GSError & ret)131 void RSColorSpaceConvert::GetHDRDynamicMetadata(const sptr<SurfaceBuffer>& surfaceBuffer,
132     std::vector<uint8_t>& hdrDynamicMetadata, GSError& ret)
133 {
134     ret = MetadataHelper::GetHDRDynamicMetadata(surfaceBuffer, hdrDynamicMetadata);
135     if (ret != GSERROR_OK) {
136         RS_LOGD("RSColorSpaceConvert::GetHDRDynamicMetadata failed with ret: %{public}u.", ret);
137     }
138 }
139 
GetFOVMetadata(const sptr<SurfaceBuffer> & surfaceBuffer,std::vector<uint8_t> & adaptiveFOVMetadata,GSError & ret)140 void RSColorSpaceConvert::GetFOVMetadata(const sptr<SurfaceBuffer>& surfaceBuffer,
141     std::vector<uint8_t>& adaptiveFOVMetadata, GSError& ret)
142 {
143     if (surfaceBuffer == nullptr) {
144         RS_LOGE("surfaceBuffer is nullptr. Failed to get FOV metadata.");
145         ret = GSERROR_INVALID_ARGUMENTS;
146         return;
147     }
148     ret = MetadataHelper::GetAdaptiveFOVMetadata(surfaceBuffer, adaptiveFOVMetadata);
149     if (ret != GSERROR_OK) {
150         RS_LOGD("RSColorSpaceConvert::GetFOVMetadata( failed with ret: %{public}u.", ret);
151     }
152 }
153 
SetColorSpaceConverterDisplayParameter(const sptr<SurfaceBuffer> & surfaceBuffer,VPEParameter & parameter,GraphicColorGamut targetColorSpace,ScreenId screenId,uint32_t dynamicRangeMode)154 bool RSColorSpaceConvert::SetColorSpaceConverterDisplayParameter(const sptr<SurfaceBuffer>& surfaceBuffer,
155     VPEParameter& parameter, GraphicColorGamut targetColorSpace, ScreenId screenId, uint32_t dynamicRangeMode)
156 {
157     using namespace HDIV;
158 
159     GSError ret = MetadataHelper::GetColorSpaceInfo(surfaceBuffer, parameter.inputColorSpace.colorSpaceInfo);
160     if (ret != GSERROR_OK) {
161         RS_LOGE("bhdr GetColorSpaceInfo failed with %{public}u.", ret);
162         return false;
163     }
164     if (!ConvertColorGamutToSpaceInfo(targetColorSpace, parameter.outputColorSpace.colorSpaceInfo)) {
165         return false;
166     }
167     CM_HDR_Metadata_Type hdrMetadataType = CM_METADATA_NONE;
168     ret = MetadataHelper::GetHDRMetadataType(surfaceBuffer, hdrMetadataType);
169     if (ret != GSERROR_OK) {
170         RS_LOGD("bhdr GetHDRMetadataType failed with %{public}u.", ret);
171     }
172     parameter.inputColorSpace.metadataType = hdrMetadataType;
173     parameter.outputColorSpace.metadataType = hdrMetadataType;
174 
175     GetHDRStaticMetadata(surfaceBuffer, parameter.staticMetadata, ret);
176     GetHDRDynamicMetadata(surfaceBuffer, parameter.dynamicMetadata, ret);
177     GetFOVMetadata(surfaceBuffer, parameter.adaptiveFOVMetadata, ret);
178 
179     float scaler = DEFAULT_SCALER;
180     auto& rsLuminance = RSLuminanceControl::Get();
181     if (parameter.staticMetadata.size() != sizeof(HdrStaticMetadata)) {
182         RS_LOGD("bhdr parameter.staticMetadata size is invalid");
183     } else {
184         const auto& data = *reinterpret_cast<HdrStaticMetadata*>(parameter.staticMetadata.data());
185         scaler = rsLuminance.CalScaler(data.cta861.maxContentLightLevel,
186             ret == GSERROR_OK ? parameter.dynamicMetadata.size() : DEFAULT_DYNAMIC_METADATA_SIZE);
187     }
188 
189     if (!rsLuminance.IsHdrPictureOn() || dynamicRangeMode == DynamicRangeMode::STANDARD) {
190         scaler = 1.0f;
191     }
192 
193     float sdrNits = rsLuminance.GetSdrDisplayNits(screenId);
194     float displayNits = rsLuminance.GetDisplayNits(screenId);
195     parameter.tmoNits = std::clamp(sdrNits * scaler, sdrNits, displayNits);
196     parameter.currentDisplayNits = displayNits;
197     parameter.sdrNits = sdrNits;
198     // color temperature
199     parameter.layerLinearMatrix = RSColorTemperature::Get().GetLayerLinearCct(screenId, ret == GSERROR_OK ?
200         parameter.dynamicMetadata : std::vector<uint8_t>(), parameter.inputColorSpace.colorSpaceInfo.matrix);
201     if (parameter.layerLinearMatrix.size() >= MATRIX_SIZE) {
202         // main diagonal indices of a 3x3 matrix are 0, 4 and 8
203         RS_LOGD("bhdr Matrix[0]:%{public}.2f. Matrix[4]:%{public}.2f. Matrix[8]:%{public}.2f",
204             parameter.layerLinearMatrix[0], parameter.layerLinearMatrix[4], parameter.layerLinearMatrix[8]);
205     }
206     RS_LOGD("bhdr TmoNits:%{public}.2f. DisplayNits:%{public}.2f. SdrNits:%{public}.2f. DynamicRangeMode:%{public}u",
207         parameter.tmoNits, parameter.currentDisplayNits, parameter.sdrNits, dynamicRangeMode);
208     return true;
209 }
210 
ConvertColorGamutToSpaceInfo(const GraphicColorGamut & colorGamut,HDIV::CM_ColorSpaceInfo & colorSpaceInfo)211 bool RSColorSpaceConvert::ConvertColorGamutToSpaceInfo(const GraphicColorGamut& colorGamut,
212     HDIV::CM_ColorSpaceInfo& colorSpaceInfo)
213 {
214     using namespace HDIV;
215     static const std::map<GraphicColorGamut, CM_ColorSpaceType> RS_TO_COMMON_COLOR_SPACE_TYPE_MAP {
216         {GRAPHIC_COLOR_GAMUT_STANDARD_BT601, CM_BT601_EBU_FULL},
217         {GRAPHIC_COLOR_GAMUT_STANDARD_BT709, CM_BT709_FULL},
218         {GRAPHIC_COLOR_GAMUT_SRGB, CM_SRGB_FULL},
219         {GRAPHIC_COLOR_GAMUT_ADOBE_RGB, CM_ADOBERGB_FULL},
220         {GRAPHIC_COLOR_GAMUT_DISPLAY_P3, CM_P3_FULL},
221         {GRAPHIC_COLOR_GAMUT_BT2020, CM_DISPLAY_BT2020_SRGB},
222         {GRAPHIC_COLOR_GAMUT_BT2100_PQ, CM_BT2020_PQ_FULL},
223         {GRAPHIC_COLOR_GAMUT_BT2100_HLG, CM_BT2020_HLG_FULL},
224         {GRAPHIC_COLOR_GAMUT_DISPLAY_BT2020, CM_DISPLAY_BT2020_SRGB},
225     };
226 
227     CM_ColorSpaceType colorSpaceType = CM_COLORSPACE_NONE;
228     if (RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.find(colorGamut) != RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.end()) {
229         colorSpaceType = RS_TO_COMMON_COLOR_SPACE_TYPE_MAP.at(colorGamut);
230     }
231 
232     GSError ret = MetadataHelper::ConvertColorSpaceTypeToInfo(colorSpaceType, colorSpaceInfo);
233     if (ret != GSERROR_OK) {
234         RS_LOGE("bhdr ConvertColorSpaceTypeToInfo failed with %{public}u.", ret);
235         return false;
236     }
237 
238     return true;
239 }
240 
CloseLibraryHandle()241 void RSColorSpaceConvert::CloseLibraryHandle()
242 {
243     colorSpaceConvertDisplayCreate_ = nullptr;
244     colorSpaceConvertDisplayDestroy_ = nullptr;
245     colorSpaceConverterDisplay_ = nullptr;
246     if (dlclose(handle_) != 0) {
247         ROSEN_LOGE("Could not close the handle. This indicates a leak. %{public}s", dlerror());
248     }
249     handle_ = nullptr;
250 }
251 
252 } // namespace Rosen
253 } // namespace OHOS
254