1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "ColorManager.h"
17 
18 #include "BrightnessController.h"
19 #include "ExynosDisplay.h"
20 #include "ExynosHWCDebug.h"
21 #include "ExynosLayer.h"
22 
23 namespace gs101 {
24 
25 #define CLR_LOGD(msg, ...) \
26     ALOGD("[%s] %s: " msg, mExynosDisplay->mDisplayName.c_str(), __func__, ##__VA_ARGS__);
27 
getColorModes(uint32_t * outNumModes,int32_t * outModes)28 int32_t ColorManager::getColorModes(uint32_t* outNumModes, int32_t* outModes) {
29     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
30     const DisplayType display = mExynosDisplay->getDcDisplayType();
31     const ColorModesMap colorModeMap = displayColorInterface == nullptr
32             ? ColorModesMap()
33             : displayColorInterface->ColorModesAndRenderIntents(display);
34     CLR_LOGD("size(%zu)", colorModeMap.size());
35     if (outNumModes == nullptr) {
36         DISPLAY_DRM_LOGE("%s: outNumModes is null", __func__);
37         return HWC2_ERROR_BAD_PARAMETER;
38     }
39     if (outModes == nullptr) {
40         *outNumModes = colorModeMap.size();
41         return HWC2_ERROR_NONE;
42     }
43     if (*outNumModes != colorModeMap.size()) {
44         DISPLAY_DRM_LOGE("%s: Invalid color mode size(%d), It should be(%zu)", __func__,
45                          *outNumModes, colorModeMap.size());
46         return HWC2_ERROR_BAD_PARAMETER;
47     }
48 
49     uint32_t index = 0;
50     for (const auto& it : colorModeMap) {
51         outModes[index] = static_cast<int32_t>(it.first);
52         CLR_LOGD("\tmode[%d] %d", index, outModes[index]);
53         index++;
54     }
55 
56     return HWC2_ERROR_NONE;
57 }
58 
setColorMode(int32_t mode)59 int32_t ColorManager::setColorMode(int32_t mode) {
60     CLR_LOGD("mode(%d)", mode);
61     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
62     const DisplayType display = mExynosDisplay->getDcDisplayType();
63     const ColorModesMap colorModeMap = displayColorInterface == nullptr
64             ? ColorModesMap()
65             : displayColorInterface->ColorModesAndRenderIntents(display);
66     hwc::ColorMode colorMode = static_cast<hwc::ColorMode>(mode);
67     const auto it = colorModeMap.find(colorMode);
68     if (it == colorModeMap.end()) {
69         DISPLAY_DRM_LOGE("%s: Invalid color mode(%d)", __func__, mode);
70         return HWC2_ERROR_BAD_PARAMETER;
71     }
72     mDisplaySceneInfo.setColorMode(colorMode);
73 
74     if (mExynosDisplay->mColorMode != mode)
75         mExynosDisplay->setGeometryChanged(GEOMETRY_DISPLAY_COLOR_MODE_CHANGED);
76     mExynosDisplay->mColorMode = (android_color_mode_t)mode;
77 
78     return HWC2_ERROR_NONE;
79 }
80 
getRenderIntents(int32_t mode,uint32_t * outNumIntents,int32_t * outIntents)81 int32_t ColorManager::getRenderIntents(int32_t mode, uint32_t* outNumIntents, int32_t* outIntents) {
82     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
83     const DisplayType display = mExynosDisplay->getDcDisplayType();
84     const ColorModesMap colorModeMap = displayColorInterface == nullptr
85             ? ColorModesMap()
86             : displayColorInterface->ColorModesAndRenderIntents(display);
87     CLR_LOGD("size(%zu)", colorModeMap.size());
88     hwc::ColorMode colorMode = static_cast<hwc::ColorMode>(mode);
89     const auto it = colorModeMap.find(colorMode);
90     if (it == colorModeMap.end()) {
91         DISPLAY_DRM_LOGE("%s: Invalid color mode(%d)", __func__, mode);
92         return HWC2_ERROR_BAD_PARAMETER;
93     }
94     auto& renderIntents = it->second;
95     if (outIntents == NULL) {
96         *outNumIntents = renderIntents.size();
97         CLR_LOGD("\tintent num(%zu)", renderIntents.size());
98         return HWC2_ERROR_NONE;
99     }
100     if (*outNumIntents != renderIntents.size()) {
101         DISPLAY_DRM_LOGE("%s: Invalid intent size(%d), It should be(%zu)", __func__, *outNumIntents,
102                          renderIntents.size());
103         return HWC2_ERROR_BAD_PARAMETER;
104     }
105 
106     for (uint32_t i = 0; i < renderIntents.size(); i++) {
107         outIntents[i] = static_cast<uint32_t>(renderIntents[i]);
108         CLR_LOGD("\tintent[%d] %d", i, outIntents[i]);
109     }
110 
111     return HWC2_ERROR_NONE;
112 }
113 
setColorModeWithRenderIntent(int32_t mode,int32_t intent)114 int32_t ColorManager::setColorModeWithRenderIntent(int32_t mode, int32_t intent) {
115     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
116     const DisplayType display = mExynosDisplay->getDcDisplayType();
117     const ColorModesMap colorModeMap = displayColorInterface == nullptr
118             ? ColorModesMap()
119             : displayColorInterface->ColorModesAndRenderIntents(display);
120     hwc::ColorMode colorMode = static_cast<hwc::ColorMode>(mode);
121     hwc::RenderIntent renderIntent = static_cast<hwc::RenderIntent>(intent);
122 
123     const auto mode_it = colorModeMap.find(colorMode);
124     if (mode_it == colorModeMap.end()) {
125         DISPLAY_DRM_LOGE("%s: Invalid color mode(%d)", __func__, mode);
126         return HWC2_ERROR_BAD_PARAMETER;
127     }
128 
129     auto& renderIntents = mode_it->second;
130     auto intent_it = std::find(renderIntents.begin(), renderIntents.end(), renderIntent);
131     if (intent_it == renderIntents.end()) {
132         DISPLAY_DRM_LOGE("%s: Invalid render intent(%d)", __func__, intent);
133         return HWC2_ERROR_BAD_PARAMETER;
134     }
135 
136     mDisplaySceneInfo.setColorMode(colorMode);
137     mDisplaySceneInfo.setRenderIntent(renderIntent);
138 
139     if (mExynosDisplay->mColorMode != mode) {
140         CLR_LOGD("mode(%d), intent(%d)", mode, intent);
141         mExynosDisplay->setGeometryChanged(GEOMETRY_DISPLAY_COLOR_MODE_CHANGED);
142     }
143     mExynosDisplay->mColorMode = (android_color_mode_t)mode;
144 
145     if (mExynosDisplay->mBrightnessController)
146         mExynosDisplay->mBrightnessController->updateColorRenderIntent(intent);
147 
148     return HWC2_ERROR_NONE;
149 }
150 
setColorTransform(const float * matrix,int32_t hint)151 int32_t ColorManager::setColorTransform(const float* matrix, int32_t hint) {
152     if ((hint < HAL_COLOR_TRANSFORM_IDENTITY) || (hint > HAL_COLOR_TRANSFORM_CORRECT_TRITANOPIA))
153         return HWC2_ERROR_BAD_PARAMETER;
154     if (mExynosDisplay->mColorTransformHint != hint) {
155         ALOGI("[%s] %s:: %d -> %d", mExynosDisplay->mDisplayName.c_str(), __func__,
156               mExynosDisplay->mColorTransformHint, hint);
157         mExynosDisplay->setGeometryChanged(GEOMETRY_DISPLAY_COLOR_TRANSFORM_CHANGED);
158     }
159     mExynosDisplay->mColorTransformHint = hint;
160 #ifdef HWC_SUPPORT_COLOR_TRANSFORM
161     mDisplaySceneInfo.setColorTransform(matrix);
162 #endif
163     return HWC2_ERROR_NONE;
164 }
165 
hasDppForLayer(ExynosMPPSource * layer)166 bool ColorManager::hasDppForLayer(ExynosMPPSource* layer) {
167     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
168     if (displayColorInterface == nullptr) {
169         return false;
170     }
171 
172     if (getDisplaySceneInfo().layerDataMappingInfo.count(layer) == 0) return false;
173 
174     uint32_t index = getDisplaySceneInfo().layerDataMappingInfo[layer].dppIdx;
175     const DisplayType display = mExynosDisplay->getDcDisplayType();
176     auto size = displayColorInterface->GetPipelineData(display)->Dpp().size();
177     if (index >= size) {
178         DISPLAY_DRM_LOGE("%s: invalid dpp index(%d) dpp size(%zu)", __func__, index, size);
179         return false;
180     }
181 
182     return true;
183 }
184 
getDppForLayer(ExynosMPPSource * layer)185 const ColorManager::GsInterfaceType::IDpp& ColorManager::getDppForLayer(ExynosMPPSource* layer) {
186     uint32_t index = getDisplaySceneInfo().layerDataMappingInfo[layer].dppIdx;
187     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
188     const DisplayType display = mExynosDisplay->getDcDisplayType();
189     return displayColorInterface->GetPipelineData(display)->Dpp()[index].get();
190 }
191 
getDppIndexForLayer(ExynosMPPSource * layer)192 int32_t ColorManager::getDppIndexForLayer(ExynosMPPSource* layer) {
193     if (getDisplaySceneInfo().layerDataMappingInfo.count(layer) == 0) return -1;
194     uint32_t index = getDisplaySceneInfo().layerDataMappingInfo[layer].dppIdx;
195 
196     return static_cast<int32_t>(index);
197 }
198 
getDqe()199 const ColorManager::GsInterfaceType::IDqe& ColorManager::getDqe() {
200     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
201     return displayColorInterface->GetPipelineData(mExynosDisplay->getDcDisplayType())->Dqe();
202 }
203 
setLayersColorData()204 int32_t ColorManager::setLayersColorData() {
205     int32_t ret = 0;
206     uint32_t layerNum = 0;
207 
208     // TODO: b/212616164 remove dimSdrRatio
209     float dimSdrRatio = 1;
210     if (mExynosDisplay->mBrightnessController)
211         dimSdrRatio = mExynosDisplay->mBrightnessController->getSdrDimRatioForInstantHbm();
212 
213     // for client target
214     {
215         LayerColorData& layerColorData = getDisplaySceneInfo().getLayerColorDataInstance(layerNum);
216 
217         /* set layer data mapping info */
218         if ((ret = getDisplaySceneInfo()
219                            .setLayerDataMappingInfo(&mExynosDisplay->mClientCompositionInfo,
220                                                     layerNum)) != NO_ERROR) {
221             DISPLAY_DRM_LOGE("%s: setLayerDataMappingInfo fail for client composition", __func__);
222             return ret;
223         }
224 
225         if ((ret = getDisplaySceneInfo()
226                            .setClientCompositionColorData(mExynosDisplay->mClientCompositionInfo,
227                                                           layerColorData, dimSdrRatio)) !=
228             NO_ERROR) {
229             DISPLAY_DRM_LOGE("%s: setClientCompositionColorData fail", __func__);
230             return ret;
231         }
232 
233         layerColorData.is_client_target = true;
234         layerNum++;
235     }
236 
237     for (uint32_t i = 0; i < mExynosDisplay->mLayers.size(); i++) {
238         ExynosLayer* layer = mExynosDisplay->mLayers[i];
239 
240         if (layer->mCompositionType == HWC2_COMPOSITION_CLIENT) continue;
241 
242         LayerColorData& layerColorData = getDisplaySceneInfo().getLayerColorDataInstance(layerNum);
243 
244         /* set layer data mapping info */
245         if ((ret = getDisplaySceneInfo().setLayerDataMappingInfo(layer, layerNum)) != NO_ERROR) {
246             DISPLAY_DRM_LOGE("%s: layer[%d] setLayerDataMappingInfo fail, layerNum(%d)", __func__,
247                              i, layerNum);
248             return ret;
249         }
250 
251         if ((ret = getDisplaySceneInfo().setLayerColorData(layerColorData, layer, dimSdrRatio)) !=
252             NO_ERROR) {
253             DISPLAY_DRM_LOGE("%s: layer[%d] setLayerColorData fail, layerNum(%d)", __func__, i,
254                              layerNum);
255             return ret;
256         }
257 
258         layerColorData.is_client_target = false;
259         layerNum++;
260     }
261 
262     /* Resize layer_data when layers were destroyed */
263     if (layerNum < getDisplaySceneInfo().displayScene.layer_data.size())
264         getDisplaySceneInfo().displayScene.layer_data.resize(layerNum);
265 
266     return NO_ERROR;
267 }
268 
updateColorConversionInfo()269 int32_t ColorManager::updateColorConversionInfo() {
270     int ret = 0;
271     GsInterfaceType* displayColorInterface = getDisplayColorInterface();
272     if (displayColorInterface == nullptr) {
273         return ret;
274     }
275 
276     mExynosDisplay->updateBrightnessState();
277     /* clear flag and layer mapping info before setting */
278     getDisplaySceneInfo().reset();
279 
280     if ((ret = setLayersColorData()) != NO_ERROR) return ret;
281 
282     DisplayScene& displayScene = getDisplaySceneInfo().displayScene;
283     auto& brightnessController = mExynosDisplay->mBrightnessController;
284 
285     displayScene.bm = displaycolor::BrightnessMode::BM_NOMINAL;
286     if (brightnessController && brightnessController->isGhbmOn())
287         displayScene.bm = displaycolor::BrightnessMode::BM_HBM;
288 
289     displayScene.force_hdr = false;
290     displayScene.lhbm_on = false;
291     displayScene.hdr_layer_state = displaycolor::HdrLayerState::kHdrNone;
292     displayScene.dbv = 1000;
293 
294     if (brightnessController) {
295         displayScene.force_hdr = brightnessController->isDimSdr();
296         displayScene.lhbm_on = brightnessController->isLhbmOn();
297         displayScene.hdr_layer_state = brightnessController->getHdrLayerState();
298         displayScene.dbv = brightnessController->getBrightnessLevel();
299     }
300 
301     if (hwcCheckDebugMessages(eDebugColorManagement)) getDisplaySceneInfo().printDisplayScene();
302 
303     const DisplayType display = mExynosDisplay->getDcDisplayType();
304     if ((ret = displayColorInterface->Update(display, getDisplaySceneInfo().displayScene)) != 0) {
305         DISPLAY_DRM_LOGE("Display Scene update error (%d)", ret);
306         return ret;
307     }
308 
309     return ret;
310 }
311 
resetColorMappingInfo(ExynosMPPSource * mppSrc)312 int32_t ColorManager::resetColorMappingInfo(ExynosMPPSource* mppSrc) {
313     if (getDisplaySceneInfo().layerDataMappingInfo.count(mppSrc) == 0) {
314         return -EINVAL;
315     }
316 
317     getDisplaySceneInfo().layerDataMappingInfo[mppSrc].planeId =
318             DisplaySceneInfo::LayerMappingInfo::kPlaneIdNone;
319 
320     return NO_ERROR;
321 }
322 
323 } // namespace gs101
324