• 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 "display_engine/rs_color_temperature.h"
19 #include "hdi_layer_info.h"
20 #include "metadata_helper.h"
21 #include "pipeline/main_thread/rs_main_thread.h"
22 #include "platform/common/rs_log.h"
23 #ifdef USE_VIDEO_PROCESSING_ENGINE
24 #include "render/rs_colorspace_convert.h"
25 #endif
26 #include "v2_1/cm_color_space.h"
27 
28 namespace OHOS {
29 namespace Rosen {
30 
31 constexpr float DEFAULT_HDR_RATIO = 1.0f;
32 constexpr float DEFAULT_SCALER = 1000.0f / 203.0f;
33 constexpr float GAMMA2_2 = 2.2f;
34 constexpr uint32_t DEFAULT_DYNAMIC_METADATA_SIZE = 50;
35 constexpr size_t MATRIX_SIZE = 9;
36 
CheckIsHdrSurface(const RSSurfaceRenderNode & surfaceNode)37 HdrStatus RSHdrUtil::CheckIsHdrSurface(const RSSurfaceRenderNode& surfaceNode)
38 {
39     if (!surfaceNode.IsOnTheTree()) {
40         return HdrStatus::NO_HDR;
41     }
42     if (!surfaceNode.GetRSSurfaceHandler()) {
43         return HdrStatus::NO_HDR;
44     }
45     return CheckIsHdrSurfaceBuffer(surfaceNode.GetRSSurfaceHandler()->GetBuffer());
46 }
47 
CheckIsHdrSurfaceBuffer(const sptr<SurfaceBuffer> surfaceBuffer)48 HdrStatus RSHdrUtil::CheckIsHdrSurfaceBuffer(const sptr<SurfaceBuffer> surfaceBuffer)
49 {
50     if (surfaceBuffer == nullptr) {
51         return HdrStatus::NO_HDR;
52     }
53     if (!RSSystemProperties::GetHdrVideoEnabled()) {
54         RS_LOGD("RSHdrUtil::CheckIsHdrSurfaceBuffer HDRVideoEnabled false");
55         return HdrStatus::NO_HDR;
56     }
57 #ifdef USE_VIDEO_PROCESSING_ENGINE
58     std::vector<uint8_t> metadataType{};
59     if (surfaceBuffer->GetMetadata(Media::VideoProcessingEngine::ATTRKEY_HDR_METADATA_TYPE, metadataType) ==
60         GSERROR_OK && metadataType.size() > 0 &&
61         metadataType[0] == HDI::Display::Graphic::Common::V2_1::CM_VIDEO_AI_HDR) {
62         return HdrStatus::AI_HDR_VIDEO;
63     }
64 #endif
65     if (surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_RGBA_1010102 &&
66         surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_YCBCR_P010 &&
67         surfaceBuffer->GetFormat() != GRAPHIC_PIXEL_FMT_YCRCB_P010) {
68         return HdrStatus::NO_HDR;
69     }
70     using namespace HDI::Display::Graphic::Common::V1_0;
71     CM_ColorSpaceInfo colorSpaceInfo;
72     if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, colorSpaceInfo) == GSERROR_OK) {
73         if (colorSpaceInfo.transfunc == TRANSFUNC_PQ || colorSpaceInfo.transfunc == TRANSFUNC_HLG) {
74             return HdrStatus::HDR_VIDEO;
75         }
76     }
77     return HdrStatus::NO_HDR;
78 }
79 
CheckIsSurfaceWithMetadata(const RSSurfaceRenderNode & surfaceNode)80 bool RSHdrUtil::CheckIsSurfaceWithMetadata(const RSSurfaceRenderNode& surfaceNode)
81 {
82     if (!surfaceNode.IsOnTheTree()) {
83         return false;
84     }
85     if (!surfaceNode.GetRSSurfaceHandler()) {
86         return false;
87     }
88     return CheckIsSurfaceBufferWithMetadata(surfaceNode.GetRSSurfaceHandler()->GetBuffer());
89 }
90 
CheckIsSurfaceBufferWithMetadata(const sptr<SurfaceBuffer> surfaceBuffer)91 bool RSHdrUtil::CheckIsSurfaceBufferWithMetadata(const sptr<SurfaceBuffer> surfaceBuffer)
92 {
93     if (surfaceBuffer == nullptr) {
94         return false;
95     }
96     using namespace HDI::Display::Graphic::Common::V1_0;
97     CM_ColorSpaceInfo colorSpaceInfo;
98     if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, colorSpaceInfo) != GSERROR_OK) {
99         RS_LOGD("RSHdrUtil::CheckIsSurfaceBufferWithMetadata failed to get ColorSpaceInfo");
100         return false;
101     }
102     // only primaries P3_D65 and BT2020 has metadata
103     if (colorSpaceInfo.primaries != CM_ColorPrimaries::COLORPRIMARIES_P3_D65 &&
104         colorSpaceInfo.primaries != CM_ColorPrimaries::COLORPRIMARIES_BT2020) {
105         RS_LOGD("RSHdrUtil::CheckIsSurfaceBufferWithMetadata colorSpaceInfo.primaries not satisfied");
106         return false;
107     }
108 #ifdef USE_VIDEO_PROCESSING_ENGINE
109     std::vector<uint8_t> dynamicMetadata{};
110     if (MetadataHelper::GetHDRDynamicMetadata(surfaceBuffer, dynamicMetadata) ==
111         GSERROR_OK && dynamicMetadata.size() > 0) {
112         return true;
113     }
114 #endif
115     return false;
116 }
117 
UpdateSurfaceNodeNit(RSSurfaceRenderNode & surfaceNode,ScreenId screenId)118 void RSHdrUtil::UpdateSurfaceNodeNit(RSSurfaceRenderNode& surfaceNode, ScreenId screenId)
119 {
120     if (!surfaceNode.GetRSSurfaceHandler()) {
121         RS_LOGE("RSHdrUtil::UpdateSurfaceNodeNit surfaceHandler is NULL");
122         return;
123     }
124     const sptr<SurfaceBuffer>& surfaceBuffer = surfaceNode.GetRSSurfaceHandler()->GetBuffer();
125     if (surfaceBuffer == nullptr) {
126         RS_LOGE("surfaceNode.GetRSSurfaceHandler is NULL");
127         return;
128     }
129     auto& rsLuminance = RSLuminanceControl::Get();
130     if (surfaceNode.GetVideoHdrStatus() == HdrStatus::NO_HDR) {
131         surfaceNode.SetDisplayNit(rsLuminance.GetSdrDisplayNits(screenId));
132         surfaceNode.SetSdrNit(rsLuminance.GetSdrDisplayNits(screenId));
133         surfaceNode.SetBrightnessRatio(rsLuminance.GetHdrBrightnessRatio(screenId, 0));
134         // color temperature
135         if (surfaceNode.GetSdrHasMetadata()) {
136             UpdateSurfaceNodeLayerLinearMatrix(surfaceNode, screenId);
137         }
138         return;
139     }
140 
141     using namespace HDI::Display::Graphic::Common::V1_0;
142     std::vector<uint8_t> hdrStaticMetadataVec;
143     std::vector<uint8_t> hdrDynamicMetadataVec;
144     GSError ret = GSERROR_OK;
145 #ifdef USE_VIDEO_PROCESSING_ENGINE
146     RSColorSpaceConvert::Instance().GetHDRStaticMetadata(surfaceBuffer, hdrStaticMetadataVec, ret);
147     RSColorSpaceConvert::Instance().GetHDRDynamicMetadata(surfaceBuffer, hdrDynamicMetadataVec, ret);
148 #endif
149     float scaler = DEFAULT_SCALER;
150     if (hdrStaticMetadataVec.size() != sizeof(HdrStaticMetadata) || hdrStaticMetadataVec.data() == nullptr) {
151         RS_LOGD("hdrStaticMetadataVec is invalid");
152         scaler = surfaceNode.GetHDRBrightness() * (scaler - 1.0f) + 1.0f;
153     } else {
154         const auto& data = *reinterpret_cast<HdrStaticMetadata*>(hdrStaticMetadataVec.data());
155         scaler = rsLuminance.CalScaler(data.cta861.maxContentLightLevel, ret == GSERROR_OK ?
156             hdrDynamicMetadataVec.size() : DEFAULT_DYNAMIC_METADATA_SIZE, surfaceNode.GetHDRBrightness());
157     }
158 
159     float sdrNits = rsLuminance.GetSdrDisplayNits(screenId);
160     float displayNits = rsLuminance.GetDisplayNits(screenId);
161 
162     float layerNits = std::clamp(sdrNits * scaler, sdrNits, displayNits);
163     surfaceNode.SetDisplayNit(layerNits);
164     surfaceNode.SetSdrNit(sdrNits);
165     if (ROSEN_LE(displayNits, 0.0f)) {
166         surfaceNode.SetBrightnessRatio(DEFAULT_HDR_RATIO);
167     } else {
168         surfaceNode.SetBrightnessRatio(std::pow(layerNits / displayNits, 1.0f / GAMMA2_2)); // gamma 2.2
169     }
170     // color temperature
171     UpdateSurfaceNodeLayerLinearMatrix(surfaceNode, screenId);
172     RS_LOGD("RSHdrUtil::UpdateSurfaceNodeNit layerNits: %{public}.2f, displayNits: %{public}.2f,"
173         " sdrNits: %{public}.2f, scaler: %{public}.2f, HDRBrightness: %{public}f", layerNits, displayNits, sdrNits,
174         scaler, surfaceNode.GetHDRBrightness());
175 }
176 
UpdateSurfaceNodeLayerLinearMatrix(RSSurfaceRenderNode & surfaceNode,ScreenId screenId)177 void RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix(RSSurfaceRenderNode& surfaceNode, ScreenId screenId)
178 {
179     if (!surfaceNode.GetRSSurfaceHandler()) {
180         RS_LOGE("RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix surfaceHandler is NULL");
181         return;
182     }
183     const sptr<SurfaceBuffer>& surfaceBuffer = surfaceNode.GetRSSurfaceHandler()->GetBuffer();
184     if (surfaceBuffer == nullptr) {
185         RS_LOGE("surfaceNode.GetRSSurfaceHandler is NULL");
186         return;
187     }
188     using namespace HDI::Display::Graphic::Common::V1_0;
189     CM_ColorSpaceInfo srcColorSpaceInfo;
190     CM_Matrix srcColorMatrix = CM_Matrix::MATRIX_P3;
191     if (MetadataHelper::GetColorSpaceInfo(surfaceBuffer, srcColorSpaceInfo) == GSERROR_OK) {
192         srcColorMatrix = srcColorSpaceInfo.matrix;
193     }
194     std::vector<uint8_t> hdrDynamicMetadataVec;
195     GSError ret = GSERROR_OK;
196 #ifdef USE_VIDEO_PROCESSING_ENGINE
197     RSColorSpaceConvert::Instance().GetHDRDynamicMetadata(surfaceBuffer, hdrDynamicMetadataVec, ret);
198 #endif
199     std::vector<float> layerLinearMatrix = RSColorTemperature::Get().GetLayerLinearCct(screenId,
200         ret == GSERROR_OK ? hdrDynamicMetadataVec : std::vector<uint8_t>(), srcColorMatrix);
201     surfaceNode.SetLayerLinearMatrix(layerLinearMatrix);
202     if (layerLinearMatrix.size() >= MATRIX_SIZE) {
203         // main diagonal indices of a 3x3 matrix are 0, 4 and 8
204         RS_LOGD("RSHdrUtil::UpdateSurfaceNodeLayerLinearMatrix "
205             "matrix[0]: %{public}.2f, matrix[4]: %{public}.2f, matrix[8]: %{public}.2f",
206             layerLinearMatrix[0], layerLinearMatrix[4], layerLinearMatrix[8]);
207     }
208 }
209 
UpdatePixelFormatAfterHwcCalc(RSDisplayRenderNode & node)210 void RSHdrUtil::UpdatePixelFormatAfterHwcCalc(RSDisplayRenderNode& node)
211 {
212     const auto& selfDrawingNodes = RSMainThread::Instance()->GetSelfDrawingNodes();
213     for (const auto& selfDrawingNode : selfDrawingNodes) {
214         if (!selfDrawingNode || !selfDrawingNode->GetAncestorDisplayNode().lock()) {
215             RS_LOGD("RSHdrUtil::UpdatePixelFormatAfterHwcCalc selfDrawingNode or ancestoreNode is nullptr");
216             continue;
217         }
218         auto ancestor = selfDrawingNode->GetAncestorDisplayNode().lock()->ReinterpretCastTo<RSDisplayRenderNode>();
219         if (ancestor != nullptr && node.GetId() == ancestor->GetId()) {
220             CheckPixelFormatWithSelfDrawingNode(*selfDrawingNode, node);
221         }
222     }
223 }
224 
CheckPixelFormatWithSelfDrawingNode(RSSurfaceRenderNode & surfaceNode,RSDisplayRenderNode & displayNode)225 void RSHdrUtil::CheckPixelFormatWithSelfDrawingNode(RSSurfaceRenderNode& surfaceNode,
226     RSDisplayRenderNode& displayNode)
227 {
228     if (!surfaceNode.IsOnTheTree()) {
229         RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) is not on the tree",
230             surfaceNode.GetName().c_str());
231         return;
232     }
233     if (!surfaceNode.GetRSSurfaceHandler()) {
234         RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode surfaceHandler is null");
235         return;
236     }
237     auto screenId = displayNode.GetScreenId();
238     UpdateSurfaceNodeNit(surfaceNode, screenId);
239     displayNode.CollectHdrStatus(surfaceNode.GetVideoHdrStatus());
240     if (RSLuminanceControl::Get().IsForceCloseHdr()) {
241         RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) forceCloseHdr.",
242             surfaceNode.GetName().c_str());
243         return;
244     }
245     if (!surfaceNode.IsHardwareForcedDisabled()) {
246         RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode node(%{public}s) is hardware-enabled",
247             surfaceNode.GetName().c_str());
248         return;
249     }
250     if (surfaceNode.GetVideoHdrStatus() != HdrStatus::NO_HDR) {
251         SetHDRParam(surfaceNode, true);
252         if (displayNode.GetIsLuminanceStatusChange()) {
253             surfaceNode.SetContentDirty();
254         }
255         displayNode.SetPixelFormat(GRAPHIC_PIXEL_FMT_RGBA_1010102);
256         RS_LOGD("RSHdrUtil::CheckPixelFormatWithSelfDrawingNode HDRService pixelformat is set to 1010102");
257     }
258 }
259 
SetHDRParam(RSSurfaceRenderNode & node,bool flag)260 void RSHdrUtil::SetHDRParam(RSSurfaceRenderNode& node, bool flag)
261 {
262     auto firstLevelNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetFirstLevelNode());
263     if (firstLevelNode != nullptr && node.GetFirstLevelNodeId() != node.GetId()) {
264         firstLevelNode->SetHDRPresent(flag);
265     }
266     node.SetHDRPresent(flag);
267 }
268 
269 } // namespace Rosen
270 } // namespace OHOS