1 /*
2 * Copyright (c) 2025 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 "rs_hdr_util.h"
17
18 #include <parameters.h>
19
20 #include "display_engine/rs_color_temperature.h"
21 #include "feature/uifirst/rs_uifirst_manager.h"
22 #include "hdi_layer_info.h"
23 #include "metadata_helper.h"
24 #include "pipeline/main_thread/rs_main_thread.h"
25 #include "platform/common/rs_log.h"
26 #include "utils/system_properties.h"
27 #include "v2_2/cm_color_space.h"
28 #ifdef USE_VIDEO_PROCESSING_ENGINE
29 #include "render/rs_colorspace_convert.h"
30 #endif
31
32 namespace OHOS {
33 namespace Rosen {
34 namespace {
35 constexpr float DEFAULT_HDR_RATIO = 1.0f;
36 constexpr float DEFAULT_SCALER = 1000.0f / 203.0f;
37 constexpr float GAMMA2_2 = 2.2f;
38 constexpr size_t MATRIX_SIZE = 9;
39 const std::vector<float> DEFAULT_MATRIX = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
40 const std::vector<uint8_t> HDR_VIVID_METADATA = {
41 1, 0, 23, 93, 111, 186, 221, 240, 26, 189, 83, 29, 128, 0, 82, 142, 25, 156, 3,
42 198, 204, 179, 47, 236, 32, 190, 143, 163, 252, 16, 93, 185, 106, 159, 0, 10,
43 81, 199, 178, 80, 255, 217, 150, 101, 201, 144, 114, 73, 65, 127, 160, 0, 0
44 };
45 }
46 static std::shared_ptr<Drawing::RuntimeEffect> hdrHeadroomShaderEffect_;
47 std::unordered_set<uint8_t> aihdrMetadataTypeSet = {
48 HDI::Display::Graphic::Common::V2_2::CM_VIDEO_AI_HDR,
49 HDI::Display::Graphic::Common::V2_2::CM_VIDEO_AI_HDR_HIGH_LIGHT,
50 HDI::Display::Graphic::Common::V2_2::CM_VIDEO_AI_HDR_COLOR_ENHANCE
51 };
52
CheckIsHdrSurface(const RSSurfaceRenderNode & surfaceNode)53 HdrStatus RSHdrUtil::CheckIsHdrSurface(const RSSurfaceRenderNode& surfaceNode)
54 {
55 if (!surfaceNode.IsOnTheTree()) {
56 return HdrStatus::NO_HDR;
57 }
58 if (!surfaceNode.GetRSSurfaceHandler()) {
59 return HdrStatus::NO_HDR;
60 }
61 return CheckIsHdrSurfaceBuffer(surfaceNode.GetRSSurfaceHandler()->GetBuffer());
62 }
63
CheckIsHdrSurfaceBuffer(const sptr<SurfaceBuffer> surfaceBuffer)64 HdrStatus RSHdrUtil::CheckIsHdrSurfaceBuffer(const sptr<SurfaceBuffer> surfaceBuffer)
65 {
66 if (surfaceBuffer == nullptr) {
67 return HdrStatus::NO_HDR;
68 }
69 if (!RSSystemProperties::GetHdrVideoEnabled()) {
70 RS_LOGD("RSHdrUtil::CheckIsHdrSurfaceBuffer HDRVideoEnabled false");
71 return HdrStatus::NO_HDR;
72 }
73 #ifdef USE_VIDEO_PROCESSING_ENGINE
74 std::vector<uint8_t> metadataType{};
75 if ((surfaceBuffer->GetMetadata(ATTRKEY_HDR_METADATA_TYPE, metadataType)
76 == GSERROR_OK) && (metadataType.size() > 0) &&
77 (aihdrMetadataTypeSet.find(metadataType[0]) != aihdrMetadataTypeSet.end())) {
78 return HdrStatus::AI_HDR_VIDEO;
79 }
80 #endif
81 if (surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_1010102 &&
82 surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_YCBCR_P010 &&
83 surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_YCRCB_P010) {
84 return HdrStatus::NO_HDR;
85 }
86 using namespace HDI::Display::Graphic::Common::V1_0;
87 CM_ColorSpaceInfo colorSpaceInfo;
88 if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, colorSpaceInfo) == GSERROR_OK) {
89 if (colorSpaceInfo.transfunc == TRANSFUNC_PQ || colorSpaceInfo.transfunc == TRANSFUNC_HLG) {
90 return HdrStatus::HDR_VIDEO;
91 }
92 }
93 return HdrStatus::NO_HDR;
94 }
95
CheckIsSurfaceWithMetadata(const RSSurfaceRenderNode & surfaceNode)96 bool RSHdrUtil::CheckIsSurfaceWithMetadata(const RSSurfaceRenderNode& surfaceNode)
97 {
98 if (!surfaceNode.IsOnTheTree()) {
99 return false;
100 }
101 if (!surfaceNode.GetRSSurfaceHandler()) {
102 return false;
103 }
104 if (!surfaceNode.IsYUVBufferFormat()) {
105 return false;
106 }
107 return CheckIsSurfaceBufferWithMetadata(surfaceNode.GetRSSurfaceHandler()->GetBuffer());
108 }
109
CheckIsSurfaceBufferWithMetadata(const sptr<SurfaceBuffer> surfaceBuffer)110 bool RSHdrUtil::CheckIsSurfaceBufferWithMetadata(const sptr<SurfaceBuffer> surfaceBuffer)
111 {
112 if (surfaceBuffer == nullptr) {
113 return false;
114 }
115 using namespace HDI::Display::Graphic::Common::V1_0;
116 CM_ColorSpaceInfo colorSpaceInfo;
117 if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, colorSpaceInfo) != GSERROR_OK) {
118 RS_LOGD("RSHdrUtil::CheckIsSurfaceBufferWithMetadata failed to get ColorSpaceInfo");
119 return false;
120 }
121 // only primaries P3_D65 and BT2020 has metadata
122 if (colorSpaceInfo.primaries != CM_ColorPrimaries::COLORPRIMARIES_P3_D65 &&
123 colorSpaceInfo.primaries != CM_ColorPrimaries::COLORPRIMARIES_BT2020) {
124 RS_LOGD("RSHdrUtil::CheckIsSurfaceBufferWithMetadata colorSpaceInfo.primaries not satisfied");
125 return false;
126 }
127 #ifdef USE_VIDEO_PROCESSING_ENGINE
128 std::vector<uint8_t> sdrDynamicMetadata{};
129 if (MetadataHelper::GetSDRDynamicMetadata(surfaceBuffer, sdrDynamicMetadata) ==
130 GSERROR_OK && sdrDynamicMetadata.size() > 0) {
131 return true;
132 }
133 #endif
134 return false;
135 }
136
UpdateSurfaceNodeNit(RSSurfaceRenderNode & surfaceNode,ScreenId screenId)137 void RSHdrUtil::UpdateSurfaceNodeNit(RSSurfaceRenderNode& surfaceNode, ScreenId screenId)
138 {
139 if (!surfaceNode.GetRSSurfaceHandler()) {
140 RS_LOGE("RSHdrUtil::UpdateSurfaceNodeNit surfaceHandler is NULL");
141 return;
142 }
143 const sptr<SurfaceBuffer>& surfaceBuffer = surfaceNode.GetRSSurfaceHandler()->GetBuffer();
144 if (surfaceBuffer == nullptr) {
145 RS_LOGE("surfaceNode.GetRSSurfaceHandler is NULL");
146 return;
147 }
148 auto& rsLuminance = RSLuminanceControl::Get();
149 if (surfaceNode.GetVideoHdrStatus() == HdrStatus::NO_HDR) {
150 surfaceNode.SetDisplayNit(rsLuminance.GetSdrDisplayNits(screenId));
151 surfaceNode.SetSdrNit(rsLuminance.GetSdrDisplayNits(screenId));
152 surfaceNode.SetBrightnessRatio(rsLuminance.GetHdrBrightnessRatio(screenId, 0));
153 surfaceNode.SetLayerLinearMatrix(DEFAULT_MATRIX);
154 // color temperature
155 if (surfaceNode.GetSdrHasMetadata()) {
156 UpdateSurfaceNodeLayerLinearMatrix(surfaceNode, screenId);
157 }
158 return;
159 }
160
161 using namespace HDI::Display::Graphic::Common::V1_0;
162 std::vector<uint8_t> hdrStaticMetadataVec;
163 std::vector<uint8_t> hdrDynamicMetadataVec;
164 GSError ret = GSERROR_OK;
165 #ifdef USE_VIDEO_PROCESSING_ENGINE
166 RSColorSpaceConvert::Instance().GetHDRStaticMetadata(surfaceBuffer, hdrStaticMetadataVec, ret);
167 RSColorSpaceConvert::Instance().GetHDRDynamicMetadata(surfaceBuffer, hdrDynamicMetadataVec, ret);
168 #endif
169 float scaler = DEFAULT_SCALER;
170 auto context = surfaceNode.GetContext().lock();
171 if (!context) {
172 RS_LOGE("RSHdrUtil::UpdateSurfaceNodeNit context is null");
173 return;
174 }
175 auto screenNode = context->GetNodeMap().GetRenderNode<RSScreenRenderNode>(surfaceNode.GetScreenNodeId());
176 if (!screenNode) {
177 RS_LOGE("RSHdrUtil::UpdateSurfaceNodeNit screenNode is null");
178 return;
179 }
180 float brightnessFactor = screenNode->GetRenderProperties().GetHDRBrightnessFactor();
181 if (ROSEN_NE(surfaceNode.GetHDRBrightnessFactor(), brightnessFactor)) {
182 RS_LOGD("RSHdrUtil::UpdateSurfaceNodeNit GetHDRBrightnessFactor: %{public}f, "
183 "screenNode brightnessFactor: %{public}f, nodeId: %{public}" PRIu64 "",
184 surfaceNode.GetHDRBrightnessFactor(), brightnessFactor, surfaceNode.GetId());
185 surfaceNode.SetHDRBrightnessFactor(brightnessFactor);
186 surfaceNode.SetContentDirty();
187 }
188 if (hdrStaticMetadataVec.size() != sizeof(HdrStaticMetadata) || hdrStaticMetadataVec.data() == nullptr) {
189 RS_LOGD("hdrStaticMetadataVec is invalid");
190 scaler = surfaceNode.GetHDRBrightness() * brightnessFactor * (scaler - 1.0f) + 1.0f;
191 } else {
192 const auto& data = *reinterpret_cast<HdrStaticMetadata*>(hdrStaticMetadataVec.data());
193 scaler = rsLuminance.CalScaler(data.cta861.maxContentLightLevel, ret == GSERROR_OK ?
194 hdrDynamicMetadataVec : std::vector<uint8_t>{}, surfaceNode.GetHDRBrightness() * brightnessFactor);
195 }
196
197 float sdrNits = rsLuminance.GetSdrDisplayNits(screenId);
198 float displayNits = rsLuminance.GetDisplayNits(screenId);
199
200 float layerNits = std::clamp(sdrNits * scaler, sdrNits, displayNits);
201 surfaceNode.SetDisplayNit(layerNits);
202 surfaceNode.SetSdrNit(sdrNits);
203 if (ROSEN_LE(displayNits, 0.0f)) {
204 surfaceNode.SetBrightnessRatio(DEFAULT_HDR_RATIO);
205 } else {
206 surfaceNode.SetBrightnessRatio(std::pow(layerNits / displayNits, 1.0f / GAMMA2_2)); // gamma 2.2
207 }
208 // color temperature
209 UpdateSurfaceNodeLayerLinearMatrix(surfaceNode, screenId);
210 RS_LOGD("RSHdrUtil::UpdateSurfaceNodeNit layerNits: %{public}.2f, displayNits: %{public}.2f,"
211 " sdrNits: %{public}.2f, scaler: %{public}.2f, HDRBrightness: %{public}f, brightnessFactor: %{public}f",
212 layerNits, displayNits, sdrNits, scaler, surfaceNode.GetHDRBrightness(), brightnessFactor);
213 }
214
UpdateSurfaceNodeLayerLinearMatrix(RSSurfaceRenderNode & surfaceNode,ScreenId screenId)215 void RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix(RSSurfaceRenderNode& surfaceNode, ScreenId screenId)
216 {
217 if (!surfaceNode.GetRSSurfaceHandler()) {
218 RS_LOGE("RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix surfaceHandler is NULL");
219 return;
220 }
221 const sptr<SurfaceBuffer>& surfaceBuffer = surfaceNode.GetRSSurfaceHandler()->GetBuffer();
222 if (surfaceBuffer == nullptr) {
223 RS_LOGE("surfaceNode.GetRSSurfaceHandler is NULL");
224 return;
225 }
226 using namespace HDI::Display::Graphic::Common::V1_0;
227 CM_ColorSpaceInfo srcColorSpaceInfo;
228 CM_Matrix srcColorMatrix = CM_Matrix::MATRIX_P3;
229 if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, srcColorSpaceInfo) == GSERROR_OK) {
230 srcColorMatrix = srcColorSpaceInfo.matrix;
231 }
232 std::vector<uint8_t> dynamicMetadataVec;
233 GSError ret = GSERROR_OK;
234 #ifdef USE_VIDEO_PROCESSING_ENGINE
235 if (srcColorMatrix == CM_Matrix::MATRIX_BT2020) {
236 RSColorSpaceConvert::Instance().GetHDRDynamicMetadata(surfaceBuffer, dynamicMetadataVec, ret);
237 } else {
238 RSColorSpaceConvert::Instance().GetSDRDynamicMetadata(surfaceBuffer, dynamicMetadataVec, ret);
239 }
240 #endif
241 std::vector<float> layerLinearMatrix = RSColorTemperature::Get().GetLayerLinearCct(screenId,
242 ret == GSERROR_OK ? dynamicMetadataVec : std::vector<uint8_t>(), srcColorMatrix);
243 surfaceNode.SetLayerLinearMatrix(layerLinearMatrix);
244 if (layerLinearMatrix.size() >= MATRIX_SIZE) {
245 // main diagonal indices of a 3x3 matrix are 0, 4 and 8
246 RS_LOGD("RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix "
247 "matrix[0]: %{public}.2f, matrix[4]: %{public}.2f, matrix[8]: %{public}.2f",
248 layerLinearMatrix[0], layerLinearMatrix[4], layerLinearMatrix[8]);
249 }
250 }
251
UpdatePixelFormatAfterHwcCalc(RSScreenRenderNode & node)252 void RSHdrUtil::UpdatePixelFormatAfterHwcCalc(RSScreenRenderNode& node)
253 {
254 const auto& selfDrawingNodes = RSMainThread::Instance()->GetSelfDrawingNodes();
255 for (const auto& selfDrawingNode : selfDrawingNodes) {
256 if (!selfDrawingNode) {
257 RS_LOGD("RSHdrUtil::UpdatePixelFormatAfterHwcCalc selfDrawingNode is nullptr");
258 continue;
259 }
260 auto ancestor = selfDrawingNode->GetAncestorScreenNode().lock();
261 if (!ancestor) {
262 RS_LOGD("RSHdrUtil::UpdatePixelFormatAfterHwcCalc ancestor is nullptr");
263 continue;
264 }
265 if (node.GetId() == ancestor->GetId()) {
266 CheckPixelFormatWithSelfDrawingNode(*selfDrawingNode, node);
267 bool needSetExistHWCNode = !node.GetExistHWCNode() && selfDrawingNode->IsOnTheTree() &&
268 !selfDrawingNode->IsHardwareForcedDisabled();
269 if (needSetExistHWCNode) {
270 RS_LOGD("RSHdrUtil::UpdatePixelFormatAfterHwcCalc there exist HWCNode");
271 node.SetExistHWCNode(true);
272 }
273 }
274 }
275 }
276
CheckPixelFormatWithSelfDrawingNode(RSSurfaceRenderNode & surfaceNode,RSScreenRenderNode & screenNode)277 void RSHdrUtil::CheckPixelFormatWithSelfDrawingNode(RSSurfaceRenderNode& surfaceNode,
278 RSScreenRenderNode& screenNode)
279 {
280 if (!surfaceNode.IsOnTheTree()) {
281 RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) is not on the tree",
282 surfaceNode.GetName().c_str());
283 return;
284 }
285 if (!surfaceNode.GetRSSurfaceHandler()) {
286 RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode surfaceHandler is null");
287 return;
288 }
289 auto screenId = screenNode.GetScreenId();
290 UpdateSurfaceNodeNit(surfaceNode, screenId);
291 screenNode.CollectHdrStatus(surfaceNode.GetVideoHdrStatus());
292 if (RSLuminanceControl::Get().IsForceCloseHdr()) {
293 RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) forceCloseHdr.",
294 surfaceNode.GetName().c_str());
295 return;
296 }
297 if (!surfaceNode.IsHardwareForcedDisabled()) {
298 RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) is hardware-enabled",
299 surfaceNode.GetName().c_str());
300 return;
301 }
302 if (surfaceNode.GetVideoHdrStatus() != HdrStatus::NO_HDR) {
303 SetHDRParam(screenNode, surfaceNode, true);
304 if (screenNode.GetIsLuminanceStatusChange()) {
305 surfaceNode.SetContentDirty();
306 }
307 RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode HDRService surfaceNode %{public}s is HDR",
308 surfaceNode.GetName().c_str());
309 }
310 }
311
GetRGBA1010108Enabled()312 bool RSHdrUtil::GetRGBA1010108Enabled()
313 {
314 static bool isDDGR = Drawing::SystemProperties::GetSystemGraphicGpuType() == GpuApiType::DDGR;
315 static bool rgba1010108 = system::GetBoolParameter("const.graphics.rgba_1010108_supported", false);
316 static bool debugSwitch = system::GetBoolParameter("persist.sys.graphic.rgba_1010108.enabled", true);
317 return isDDGR && rgba1010108 && debugSwitch;
318 }
319
SetHDRParam(RSScreenRenderNode & screenNode,RSSurfaceRenderNode & node,bool flag)320 void RSHdrUtil::SetHDRParam(RSScreenRenderNode& screenNode, RSSurfaceRenderNode& node, bool flag)
321 {
322 if (screenNode.GetForceCloseHdr()) {
323 RS_LOGD("RSHdrUtil::SetHDRParam curScreenNode forceclosehdr.");
324 return;
325 }
326 auto firstLevelNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetFirstLevelNode());
327 if (firstLevelNode != nullptr && node.GetFirstLevelNodeId() != node.GetId()) {
328 firstLevelNode->SetHDRPresent(flag);
329 RS_LOGD("RSHrdUtil::SetHDRParam HDRService FirstLevelNode: %{public}" PRIu64 "",
330 node.GetFirstLevelNodeId());
331 }
332 node.SetHDRPresent(flag);
333 }
334
LuminanceChangeSetDirty(RSScreenRenderNode & node)335 void RSHdrUtil::LuminanceChangeSetDirty(RSScreenRenderNode& node)
336 {
337 if (!node.GetIsLuminanceStatusChange()) {
338 return;
339 }
340 auto& hdrNodeList = node.GetHDRNodeList();
341 const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
342 for (const auto& nodeId : hdrNodeList) {
343 auto canvasNode = nodeMap.GetRenderNode(nodeId);
344 if (!canvasNode) {
345 RS_LOGE("RSHdrUtil::LuminanceChangeSetDirty get nullptr canvasNodeId: %{public}" PRIu64 "", nodeId);
346 continue;
347 }
348 canvasNode->SetContentDirty();
349 }
350 }
351
GetScreenColorGamut(RSScreenRenderNode & node,const sptr<RSScreenManager> & screenManager)352 ScreenColorGamut RSHdrUtil::GetScreenColorGamut(RSScreenRenderNode& node, const sptr<RSScreenManager>& screenManager)
353 {
354 ScreenColorGamut screenColorGamut;
355 if (screenManager->GetScreenColorGamut(node.GetScreenId(), screenColorGamut) != SUCCESS) {
356 RS_LOGD("RSHdrUtil::GetScreenColorGamut get screen color gamut failed.");
357 return COLOR_GAMUT_INVALID;
358 }
359 return screenColorGamut;
360 }
361
NeedUseF16Capture(const std::shared_ptr<RSSurfaceRenderNode> & surfaceNode)362 bool RSHdrUtil::NeedUseF16Capture(const std::shared_ptr<RSSurfaceRenderNode>& surfaceNode)
363 {
364 if (!surfaceNode) {
365 RS_LOGE("RSHdrUtil::NeedUseF16Capture surfaceNode is nullptr.");
366 return false;
367 }
368 auto screenNode =
369 RSBaseRenderNode::ReinterpretCast<RSScreenRenderNode>(surfaceNode->GetAncestorScreenNode().lock());
370 if (!screenNode) {
371 RS_LOGE("RSHdrUtil::NeedUseF16Capture surfaceNode get ancestor screenNode failed.");
372 return false;
373 }
374 const auto screenParams = static_cast<RSScreenRenderParams*>(screenNode->GetStagingRenderParams().get());
375 if (!screenParams) {
376 RS_LOGE("RSHdrUtil::NeedUseF16Capture get params from screenNode failed.");
377 return false;
378 }
379 bool isHDROn = screenParams->GetHDRPresent();
380 bool isScRGBEnable = RSSystemParameters::IsNeedScRGBForP3(screenParams->GetNewColorSpace()) &&
381 RSUifirstManager::Instance().GetUiFirstSwitch();
382 GraphicColorGamut colorGamut = surfaceNode->IsLeashWindow() ? surfaceNode->GetFirstLevelNodeColorGamut() :
383 surfaceNode->GetColorSpace();
384 // When the main screen uses F16 buffer and the window color space is not sRGB,
385 // the window freeze capture can use F16 format to optimize performance.
386 return (isHDROn || isScRGBEnable) && colorGamut != GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB;
387 }
388
MakeHdrHeadroomShader(float hrRatio,std::shared_ptr<Drawing::ShaderEffect> imageShader)389 std::shared_ptr<Drawing::ShaderEffect> RSHdrUtil::MakeHdrHeadroomShader(float hrRatio,
390 std::shared_ptr<Drawing::ShaderEffect> imageShader)
391 {
392 static constexpr char prog[] = R"(
393 uniform half hrRatio;
394 uniform shader imageShader;
395
396 mat3 Mat_RGB_P3toBT709 = mat3(
397 1.224939741445, -0.042056249524, -0.019637688845,
398 -0.224939599120, 1.042057784075, -0.078636557327,
399 -0.000001097215, 0.000000329788, 1.098273664879
400 );
401
402 mat3 MAT_RGB_P3tosRGB_VPE = mat3(1.22494, -0.0420569, -0.0196376,
403 -0.22494, 1.04206, -0.078636,
404 0.0, 0.0, 1.09827);
405
406 half4 main(float2 coord)
407 {
408 vec4 color = imageShader.eval(coord);
409 vec3 linearColor = sign(color.rgb) * pow(abs(color.rgb), vec3(2.2f));
410 linearColor = MAT_RGB_P3tosRGB_VPE * linearColor;
411 vec3 hdr = sign(linearColor) * pow(abs(linearColor), vec3(1.0f / 2.2f));
412 hdr = hdr * hrRatio;
413 return vec4(hdr, 1.0);
414 }
415 )";
416 if (hdrHeadroomShaderEffect_ == nullptr) {
417 hdrHeadroomShaderEffect_ = Drawing::RuntimeEffect::CreateForShader(prog);
418 if (hdrHeadroomShaderEffect_ == nullptr) {
419 ROSEN_LOGE("MakeDynamicDimShader::RuntimeShader effect error\n");
420 return nullptr;
421 }
422 }
423 std::shared_ptr<Drawing::ShaderEffect> children[] = {imageShader};
424 size_t childCount = 1;
425 auto data = std::make_shared<Drawing::Data>();
426 data->BuildWithCopy(&hrRatio, sizeof(hrRatio));
427
428 return hdrHeadroomShaderEffect_->MakeShader(data, children, childCount, nullptr, false);
429 }
430
HandleVirtualScreenHDRStatus(RSScreenRenderNode & node,const sptr<RSScreenManager> & screenManager)431 void RSHdrUtil::HandleVirtualScreenHDRStatus(RSScreenRenderNode& node, const sptr<RSScreenManager>& screenManager)
432 {
433 if (node.GetCompositeType() == CompositeType::UNI_RENDER_MIRROR_COMPOSITE) {
434 ScreenColorGamut screenColorGamut = RSHdrUtil::GetScreenColorGamut(node, screenManager);
435 std::shared_ptr<RSScreenRenderNode> mirrorNode = node.GetMirrorSource().lock();
436 if (!mirrorNode) {
437 RS_LOGE("RSHdrUtil::HandleVirtualScreenHDRStatus get mirror source failed.");
438 return;
439 }
440 bool mirrorNodeIsHDROn = RSLuminanceControl::Get().IsHdrOn(mirrorNode->GetScreenId()) &&
441 mirrorNode->GetDisplayHdrStatus() != HdrStatus::NO_HDR;
442 bool hdrCastColorGamut = static_cast<GraphicColorGamut>(screenColorGamut) == GRAPHIC_COLOR_GAMUT_BT2100_HLG;
443 bool isNeedHDRCast = mirrorNodeIsHDROn && hdrCastColorGamut;
444 RS_LOGD("RSHdrUtil::HandleVirtualScreenHDRStatus HDRCast mirrorNodeIsHDROn: %{public}d, "
445 "ColorGamut: %{public}d, GetFirstFrameVirtualScreenInit: %{public}d",
446 mirrorNodeIsHDROn, screenColorGamut, node.GetFirstFrameVirtualScreenInit());
447 UpdateHDRCastProperties(node, isNeedHDRCast, hdrCastColorGamut);
448 } else if (node.GetCompositeType() == CompositeType::UNI_RENDER_EXPAND_COMPOSITE) {
449 ScreenColorGamut screenColorGamut = RSHdrUtil::GetScreenColorGamut(node, screenManager);
450 bool expandIsHDROn = node.GetDisplayHdrStatus() != HdrStatus::NO_HDR;
451 bool hdrCastColorGamut = static_cast<GraphicColorGamut>(screenColorGamut) == GRAPHIC_COLOR_GAMUT_BT2100_HLG;
452 bool isNeedHDRCast = expandIsHDROn && hdrCastColorGamut;
453 RS_LOGD("RSHdrUtil::HandleVirtualScreenHDRStatus HDRCast expandIsHDROn: %{public}d, "
454 "ColorGamut: %{public}d, GetFirstFrameVirtualScreenInit: %{public}d",
455 expandIsHDROn, screenColorGamut, node.GetFirstFrameVirtualScreenInit());
456 UpdateHDRCastProperties(node, isNeedHDRCast, hdrCastColorGamut);
457 }
458 }
459
UpdateHDRCastProperties(RSScreenRenderNode & node,bool isNeedHDRCast,bool hdrCastColorGamut)460 void RSHdrUtil::UpdateHDRCastProperties(RSScreenRenderNode& node, bool isNeedHDRCast, bool hdrCastColorGamut)
461 {
462 if (node.GetFirstFrameVirtualScreenInit()) {
463 node.SetFirstFrameVirtualScreenInit(false);
464 if (hdrCastColorGamut) {
465 node.SetFixVirtualBuffer10Bit(true);
466 }
467 }
468 if (node.GetFixVirtualBuffer10Bit()) {
469 node.SetHDRPresent(isNeedHDRCast);
470 }
471 }
472
IsHDRCast(RSScreenRenderParams * screenParams,BufferRequestConfig & renderFrameConfig)473 bool RSHdrUtil::IsHDRCast(RSScreenRenderParams* screenParams, BufferRequestConfig& renderFrameConfig)
474 {
475 if (!screenParams) {
476 RS_LOGD("RSHdrUtil::IsHDRCast screenParams is nullptr");
477 return false;
478 }
479 // current version fix 1010102 format although is not hdr on
480 if (screenParams->GetFixVirtualBuffer10Bit()) {
481 renderFrameConfig.format = GRAPHIC_PIXEL_FMT_RGBA_1010102;
482 RS_LOGD("RSHdrUtil::IsHDRCast set 1010102 buffer");
483 if (screenParams->GetHDRPresent()) {
484 renderFrameConfig.colorGamut = GRAPHIC_COLOR_GAMUT_BT2100_HLG;
485 return true;
486 }
487 }
488 return false;
489 }
490
491 #ifdef USE_VIDEO_PROCESSING_ENGINE
HDRCastProcess(std::shared_ptr<Drawing::Image> & image,Drawing::Brush & paint,const Drawing::SamplingOptions & sampling,std::shared_ptr<Drawing::Surface> & surface,RSPaintFilterCanvas * canvas)492 bool RSHdrUtil::HDRCastProcess(std::shared_ptr<Drawing::Image>& image, Drawing::Brush& paint,
493 const Drawing::SamplingOptions& sampling, std::shared_ptr<Drawing::Surface>& surface,
494 RSPaintFilterCanvas* canvas)
495 {
496 if (!canvas) {
497 RS_LOGE("RSHdrUtil::HDRCastProcess canvas nullptr");
498 return false;
499 }
500 if (!surface) {
501 RS_LOGE("RSHdrUtil::HDRCastProcess surface nullptr");
502 return false;
503 }
504 auto gpuContext = canvas->GetGPUContext();
505 if (!gpuContext) {
506 RS_LOGE("RSHdrUtil::HDRCastProcess gpuContext nullptr");
507 return false;
508 }
509 auto canvasSurface = canvas->GetSurface();
510 if (canvasSurface == nullptr) {
511 RS_LOGE("RSHdrUtil::HDRCastProcess canvasSurface nullptr");
512 return false;
513 }
514 // Get color space from main screen canvas
515 auto colorSpace = canvasSurface->GetImageInfo().GetColorSpace();
516 image = std::make_shared<Drawing::Image>();
517 Drawing::TextureOrigin origin = Drawing::TextureOrigin::TOP_LEFT;
518 Drawing::BitmapFormat info = Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_F16, Drawing::ALPHATYPE_PREMUL };
519 image->BuildFromTexture(*gpuContext, surface->GetBackendTexture().GetTextureInfo(),
520 origin, info, colorSpace);
521 return SetHDRCastShader(image, paint, sampling);
522 }
523
SetHDRCastShader(std::shared_ptr<Drawing::Image> & image,Drawing::Brush & paint,const Drawing::SamplingOptions & sampling)524 bool RSHdrUtil::SetHDRCastShader(std::shared_ptr<Drawing::Image>& image, Drawing::Brush& paint,
525 const Drawing::SamplingOptions& sampling)
526 {
527 using namespace HDI::Display::Graphic::Common::V1_0;
528 Media::VideoProcessingEngine::ColorSpaceConverterDisplayParameter parameter;
529 if (!image) {
530 RS_LOGE("RSHdrUtil::SetHDRCastShader image is nullptr.");
531 return false;
532 }
533 auto inputShader = Drawing::ShaderEffect::CreateImageShader(*image, Drawing::TileMode::CLAMP,
534 Drawing::TileMode::CLAMP, sampling, Drawing::Matrix());
535 parameter.inputColorSpace.colorSpaceInfo = RSHDRUtilConst::HDR_CAST_IN_COLORSPACE;
536 parameter.inputColorSpace.metadataType = CM_VIDEO_HDR_VIVID;
537 parameter.outputColorSpace.colorSpaceInfo = RSHDRUtilConst::HDR_CAST_OUT_COLORSPACE;
538 parameter.outputColorSpace.metadataType = CM_VIDEO_HDR_VIVID;
539 parameter.tmoNits = RSLuminanceConst::DEFAULT_CAST_HDR_NITS;
540 parameter.currentDisplayNits = RSLuminanceConst::DEFAULT_CAST_HDR_NITS;
541 parameter.sdrNits = RSLuminanceConst::DEFAULT_CAST_SDR_NITS;
542 parameter.disableHdrFloatHeadRoom = true; // no need to apply headroom for virtual screen
543
544 std::shared_ptr<Drawing::ShaderEffect> outputShader;
545 auto colorSpaceConverterDisplay = Media::VideoProcessingEngine::ColorSpaceConverterDisplay::Create();
546 if (!colorSpaceConverterDisplay) {
547 RS_LOGE("RSHdrUtil::SetHDRCastShader VPE create failed");
548 return false;
549 }
550 auto convRet = colorSpaceConverterDisplay->Process(inputShader, outputShader, parameter);
551 if (convRet != Media::VideoProcessingEngine::VPE_ALGO_ERR_OK) {
552 RS_LOGE("RSHdrUtil::SetHDRCastShader failed with %{public}u.", convRet);
553 return false;
554 }
555 if (outputShader == nullptr) {
556 RS_LOGE("RSHdrUtil::SetHDRCastShader outputShader is null.");
557 return false;
558 }
559 paint.SetShaderEffect(outputShader);
560 RS_LOGD("RSHdrUtil::SetHDRCastShader succeed to set output shader.");
561 return true;
562 }
563
SetMetadata(const Media::VideoProcessingEngine::CM_ColorSpaceInfo & colorspaceInfo,std::unique_ptr<RSRenderFrame> & renderFrame)564 GSError RSHdrUtil::SetMetadata(const Media::VideoProcessingEngine::CM_ColorSpaceInfo& colorspaceInfo,
565 std::unique_ptr<RSRenderFrame>& renderFrame)
566 {
567 if (renderFrame == nullptr) {
568 RS_LOGD("RSHdrUtil::SetMetadata renderFrame is null.");
569 return GSERROR_INVALID_ARGUMENTS;
570 }
571 auto rsSurface = renderFrame->GetSurface();
572 if (rsSurface == nullptr) {
573 RS_LOGD("RSHdrUtil::SetMetadata surface is null.");
574 return GSERROR_INVALID_ARGUMENTS;
575 }
576 auto buffer = rsSurface->GetCurrentBuffer();
577 if (buffer == nullptr) {
578 RS_LOGD("RSHdrUtil::SetMetadata buffer is null.");
579 return GSERROR_NO_BUFFER;
580 }
581 Media::VideoProcessingEngine::HdrStaticMetadata staticMetadata;
582 staticMetadata.cta861.maxContentLightLevel = RSLuminanceConst::DEFAULT_CAST_HDR_NITS;
583 auto ret = MetadataHelper::SetHDRStaticMetadata(buffer, staticMetadata);
584 if (ret != GSERROR_OK) {
585 RS_LOGD("RSHdrUtil::SetMetadata SetHDRStaticMetadata failed %{public}d", ret);
586 return ret;
587 }
588 ret = MetadataHelper::SetHDRDynamicMetadata(buffer, HDR_VIVID_METADATA);
589 if (ret != GSERROR_OK) {
590 RS_LOGD("RSHdrUtil::SetMetadata SetHDRDynamicMetadata failed %{public}d", ret);
591 return ret;
592 }
593 std::vector<uint8_t> metadata;
594 metadata.resize(sizeof(colorspaceInfo));
595 errno_t errRet = memcpy_s(metadata.data(), metadata.size(), &colorspaceInfo, sizeof(colorspaceInfo));
596 if (errRet != EOK) {
597 RS_LOGD("RSHdrUtil::SetMetadata colorspace failed %{public}d", errRet);
598 return GSERROR_OUT_OF_RANGE;
599 }
600 RS_LOGD("RSHdrUtil::SetMetadata SetMetadata end");
601 // Metadata will overwrite the metadata in SetColorSpaceForMetadata, BT2020 is wider than P3
602 return buffer->SetMetadata(Media::VideoProcessingEngine::ATTRKEY_COLORSPACE_INFO, metadata);
603 }
604
SetMetadata(SurfaceBuffer * buffer,const HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceInfo & colorspaceInfo,const HDI::Display::Graphic::Common::V1_0::CM_HDR_Metadata_Type & value)605 GSError RSHdrUtil::SetMetadata(SurfaceBuffer* buffer,
606 const HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceInfo& colorspaceInfo,
607 const HDI::Display::Graphic::Common::V1_0::CM_HDR_Metadata_Type& value)
608 {
609 if (buffer == nullptr) {
610 RS_LOGE("RSHdrUtil::SetMetadata failed buffer nullptr");
611 return GSERROR_INVALID_ARGUMENTS;
612 }
613 std::vector<uint8_t> metadataType;
614 std::vector<uint8_t> colorSpaceMetadata;
615 metadataType.resize(sizeof(value));
616 colorSpaceMetadata.resize(sizeof(colorspaceInfo));
617 errno_t ret = memcpy_s(metadataType.data(), metadataType.size(), &value, sizeof(value));
618 if (ret != EOK) {
619 RS_LOGE("RSHdrUtil::SetMetadata metadataType memcpy_s failed error number: %{public}d", ret);
620 return GSERROR_INVALID_OPERATING;
621 }
622 ret = memcpy_s(colorSpaceMetadata.data(), colorSpaceMetadata.size(), &colorspaceInfo, sizeof(colorspaceInfo));
623 if (ret != EOK) {
624 RS_LOGE("RSHdrUtil::SetMetadata colorSpaceMetadata memcpy_s failed error number: %{public}d", ret);
625 return GSERROR_INVALID_OPERATING;
626 }
627 GSError setValueErr =
628 buffer->SetMetadata(Media::VideoProcessingEngine::ATTRKEY_HDR_METADATA_TYPE, metadataType);
629 if (setValueErr != GSERROR_OK) {
630 RS_LOGE("RSHdrUtil::SetMetadata set metadataType failed with %{public}d", setValueErr);
631 return setValueErr;
632 }
633 GSError setColorSpaceErr =
634 buffer->SetMetadata(Media::VideoProcessingEngine::ATTRKEY_COLORSPACE_INFO, colorSpaceMetadata);
635 if (setColorSpaceErr != GSERROR_OK) {
636 RS_LOGE("RSHdrUtil::SetMetadata set colorSpaceMetadata failed with %{public}d", setColorSpaceErr);
637 return setColorSpaceErr;
638 }
639 RS_LOGD("RSHdrUtil::SetMetadata set type %{public}d,"
640 " set colorSpace %{public}d-%{public}d-%{public}d-%{public}d", value,
641 static_cast<int>(colorspaceInfo.primaries), static_cast<int>(colorspaceInfo.transfunc),
642 static_cast<int>(colorspaceInfo.matrix), static_cast<int>(colorspaceInfo.range));
643 return GSERROR_OK;
644 }
645 #endif
646
647 } // namespace Rosen
648 } // namespace OHOS