• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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