1 /*
2 * libacryl_plugins/libacryl_hdr_plugin.cpp
3 *
4 * Copyright 2020 Samsung Electronics Co., Ltd.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 #include <cassert>
19 #include <array>
20
21 #include <gs101/displaycolor/displaycolor_gs101.h>
22 #include <zuma/displaycolor/displaycolor_zuma.h>
23 #include <hardware/exynos/g2d_hdr_plugin.h>
24
25 #define HDR_HDR_CON 0x3000
26 #define HDR_SFR_LEN 0x800
27
28 #define HDR_HDR_CON_NUM 1
29 #define HDR_EOTF_SCALER_NUM 1
30 #define HDR_EOTF_LUT_TS_NUM 20 // two 10-bit
31 #define HDR_EOTF_LUT_VS_NUM 20 //two 16-bit
32 #define HDR_GM_COEF_NUM 9 // one 16-bit
33 #define HDR_GM_OFF_NUM 3 // one 14-bit
34 #define HDR_TM_COEF_NUM 3 // one 12-bit
35 #define HDR_TM_YMIX_TF_NUM 1 // one 13-bit
36 #define HDR_TM_YMIX_VF_NUM 1 // one 12-bit
37 #define HDR_TM_YMIX_SLOPE_NUM 1 // one 14-bit
38 #define HDR_TM_YMIX_DV_NUM 1 // one 13 bit
39 #define HDR_TM_LUT_TS_NUM 24 //two 13-bit
40 #define HDR_TM_LUT_VS_NUM 24 //two 13-bit
41 #define HDR_OETF_LUT_TS_NUM 24 //two 14-bit
42 #define HDR_OETF_LUT_VS_NUM 24 //two 10-bit
43
44 #define HDR_MOD_CTRL_OFFSET (0x4)
45
46 // These settings are in HDR_HDR_CON
47 static const uint32_t HDR_ENABLE_HDR = 1 << 0;
48 static const uint32_t HDR_ENABLE_EOTF = 1 << 16;
49 static const uint32_t HDR_ENABLE_EOTF_LUT_SFRRAMP = 0 << 17;
50 static const uint32_t HDR_ENABLE_EOTF_LUT_PQTABLE = 1 << 17;
51 static const uint32_t HDR_ENABLE_GM = 1 << 20;
52 static const uint32_t HDR_ENABLE_TM = 1 << 24;
53 static const uint32_t HDR_ENABLE_OETF = 1 << 28 ;
54
55 // Even and odd settings for HDR coefficients.
56
57 //Defining offsets for coefficients
58 #define HDR_EOTF_SCALER_OFFSET (HDR_MOD_CTRL_OFFSET)
59 // Undefined register space of 8 bytes after eotf scaler in zuma. Adding that to the next offset
60 #define HDR_EOTF_LUT_TS_OFFSET (HDR_EOTF_SCALER_OFFSET + 8 + 4 * HDR_EOTF_SCALER_NUM)
61 #define HDR_EOTF_LUT_VS_OFFSET (HDR_EOTF_LUT_TS_OFFSET + 4 * HDR_EOTF_LUT_TS_NUM)
62 #define HDR_GM_COEF_OFFSET (HDR_EOTF_LUT_VS_OFFSET + 4 * HDR_EOTF_LUT_VS_NUM)
63 #define HDR_GM_OFF_OFFSET (HDR_GM_COEF_OFFSET + 4 * HDR_GM_COEF_NUM)
64 #define HDR_TM_COEF_OFFSET (HDR_GM_OFF_OFFSET + 4 * HDR_GM_OFF_NUM)
65 #define HDR_TM_YMIX_TF_OFFSET (HDR_TM_COEF_OFFSET + 4 * HDR_TM_COEF_NUM)
66 #define HDR_TM_YMIX_VF_OFFSET (HDR_TM_YMIX_TF_OFFSET + 4 * HDR_TM_YMIX_TF_NUM)
67 #define HDR_TM_YMIX_SLOPE_OFFSET (HDR_TM_YMIX_VF_OFFSET + 4 * HDR_TM_YMIX_VF_NUM)
68 #define HDR_TM_YMIX_DV_OFFSET (HDR_TM_YMIX_SLOPE_OFFSET + 4 * HDR_TM_YMIX_SLOPE_NUM)
69 #define HDR_TM_LUT_TS_OFFSET (HDR_TM_YMIX_DV_OFFSET + 4 * HDR_TM_YMIX_DV_NUM)
70 #define HDR_TM_LUT_VS_OFFSET (HDR_TM_LUT_TS_OFFSET + 4 * HDR_TM_LUT_TS_NUM)
71 #define HDR_OETF_LUT_TS_OFFSET (HDR_TM_LUT_VS_OFFSET + 4 * HDR_TM_LUT_VS_NUM)
72 #define HDR_OETF_LUT_VS_OFFSET (HDR_OETF_LUT_TS_OFFSET + 4 * HDR_OETF_LUT_TS_NUM)
73
74 #define HDR_LAYER_BASE(layer) (HDR_HDR_CON + HDR_SFR_LEN * (layer))
75
76 #define HDR_HDR_MOD_CON(layer) (HDR_LAYER_BASE(layer))
77 #define HDR_EOTF_SCALER(layer) (HDR_LAYER_BASE(layer) + HDR_EOTF_SCALER_OFFSET)
78 #define HDR_EOTF_LUT_TS(layer) (HDR_LAYER_BASE(layer) + HDR_EOTF_LUT_TS_OFFSET)
79 #define HDR_EOTF_LUT_VS(layer) (HDR_LAYER_BASE(layer) + HDR_EOTF_LUT_VS_OFFSET)
80 #define HDR_GM_COEF(layer) (HDR_LAYER_BASE(layer) + HDR_GM_COEF_OFFSET)
81 #define HDR_GM_OFF(layer) (HDR_LAYER_BASE(layer) + HDR_GM_OFF_OFFSET)
82 #define HDR_TM_COEF(layer) (HDR_LAYER_BASE(layer) + HDR_TM_COEF_OFFSET)
83 #define HDR_TM_YMIX_TF(layer) (HDR_LAYER_BASE(layer) + HDR_TM_YMIX_TF_OFFSET)
84 #define HDR_TM_YMIX_VF(layer) (HDR_LAYER_BASE(layer) + HDR_TM_YMIX_VF_OFFSET)
85 #define HDR_TM_YMIX_SLOPE(layer) (HDR_LAYER_BASE(layer) + HDR_TM_YMIX_SLOPE_OFFSET)
86 #define HDR_TM_YMIX_DV(layer) (HDR_LAYER_BASE(layer) + HDR_TM_YMIX_DV_OFFSET)
87 #define HDR_TM_LUT_TS(layer) (HDR_LAYER_BASE(layer) + HDR_TM_LUT_TS_OFFSET)
88 #define HDR_TM_LUT_VS(layer) (HDR_LAYER_BASE(layer) + HDR_TM_LUT_VS_OFFSET)
89 #define HDR_OETF_LUT_TS(layer) (HDR_LAYER_BASE(layer) + HDR_OETF_LUT_TS_OFFSET)
90 #define HDR_OETF_LUT_VS(layer) (HDR_LAYER_BASE(layer) + HDR_OETF_LUT_VS_OFFSET)
91
92
93 #define G2D_LAYER_HDRMODE(i) (0x390 + (i) * 0x100)
94
95 #define MAX_LAYER_COUNT 4
96
97 #define HDR_LAYER_SFR_COUNT (\
98 HDR_HDR_CON_NUM + HDR_EOTF_SCALER_NUM + \
99 HDR_EOTF_LUT_TS_NUM + HDR_EOTF_LUT_VS_NUM + HDR_GM_COEF_NUM + \
100 HDR_GM_OFF_NUM + HDR_TM_COEF_NUM + HDR_TM_YMIX_TF_NUM + \
101 HDR_TM_YMIX_TF_NUM + HDR_TM_YMIX_VF_NUM + HDR_TM_YMIX_SLOPE_NUM + \
102 HDR_TM_YMIX_DV_NUM + HDR_TM_LUT_TS_NUM + \
103 HDR_TM_LUT_VS_NUM + HDR_OETF_LUT_TS_NUM + HDR_OETF_LUT_VS_NUM \
104 )
105
106 static const size_t NUM_HDR_COEFFICIENTS = HDR_LAYER_SFR_COUNT * MAX_LAYER_COUNT + 1; // HDR SFR COUNT x LAYER COUNT + COM_CTRL
107 static const size_t NUM_HDR_MODE_REGS = MAX_LAYER_COUNT;
108
109 class G2DHdrCommandWriter: public IG2DHdr10CommandWriter {
110 std::bitset<MAX_LAYER_COUNT> mLayerAlphaMap;
111 std::array<displaycolor::IDisplayColorZuma::IDpp *, MAX_LAYER_COUNT> mLayerData{};
112
113 public:
114 struct CommandList {
115 std::array<g2d_reg, NUM_HDR_COEFFICIENTS> commands; // (294 * 4 + 1) * 8 bytes
116 std::array<g2d_reg, NUM_HDR_MODE_REGS> layer_hdr_modes; // 4 * 8 bytes
117 g2d_commandlist cmdlist{};
118
CommandListG2DHdrCommandWriter::CommandList119 CommandList() {
120 cmdlist.commands = commands.data();
121 cmdlist.layer_hdr_mode = layer_hdr_modes.data();
122 }
123
~CommandListG2DHdrCommandWriter::CommandList124 ~CommandList() { }
125
resetG2DHdrCommandWriter::CommandList126 void reset() {
127 cmdlist.command_count = 0;
128 cmdlist.layer_count = 0;
129 }
130
getG2DHdrCommandWriter::CommandList131 g2d_commandlist *get() { return &cmdlist; }
132
set_and_get_next_offsetG2DHdrCommandWriter::CommandList133 uint32_t set_and_get_next_offset(uint32_t offset, uint32_t value) {
134 commands[cmdlist.command_count].offset = offset;
135 commands[cmdlist.command_count].value = value;
136 cmdlist.command_count++;
137 return offset + sizeof(value);
138 }
139
updateLayerG2DHdrCommandWriter::CommandList140 void updateLayer(std::size_t layer, bool alpha_premultiplied, uint32_t modectl) {
141 auto &hdr_mode = layer_hdr_modes[cmdlist.layer_count++];
142
143 hdr_mode.offset = G2D_LAYER_HDRMODE(layer);
144 hdr_mode.value = layer;
145 // The premultiplied alpha should be demultiplied before HDR conversion.
146 if (alpha_premultiplied)
147 hdr_mode.value |= G2D_LAYER_HDRMODE_DEMULT_ALPHA;
148
149 set_and_get_next_offset(HDR_HDR_MOD_CON(layer), modectl);
150 }
151
152 template <typename containerT>
updateDoubleG2DHdrCommandWriter::CommandList153 void updateDouble(const containerT &container, uint32_t offset) {
154 for (std::size_t n = 0; n < container.size(); n += 2)
155 offset = set_and_get_next_offset(offset, container[n] | container[n + 1] << 16);
156 if ((container.size() % 2) == 1)
157 set_and_get_next_offset(offset, container.back());
158 }
159
160 template <typename containerT>
updateSingleG2DHdrCommandWriter::CommandList161 void updateSingle(const containerT &container, uint32_t offset) {
162 for (auto item : container)
163 offset = set_and_get_next_offset(offset, item);
164 }
165
updateTmCoefG2DHdrCommandWriter::CommandList166 void updateTmCoef(const displaycolor::IDisplayColorZuma::IDpp::DtmData::ConfigType &config, uint32_t offset) {
167 offset = set_and_get_next_offset(offset, config.coeff_r);
168 offset = set_and_get_next_offset(offset, config.coeff_g);
169 offset = set_and_get_next_offset(offset, config.coeff_b);
170 offset = set_and_get_next_offset(offset, config.ymix_tf);
171 offset = set_and_get_next_offset(offset, config.ymix_vf);
172 offset = set_and_get_next_offset(offset, config.ymix_dv);
173 set_and_get_next_offset(offset, config.ymix_slope);
174 }
175
setEotfScalarG2DHdrCommandWriter::CommandList176 void setEotfScalar(const uint16_t eotf_scalar, uint32_t offset) {
177 set_and_get_next_offset(offset, eotf_scalar);
178 }
179 } mCmdList;
180
G2DHdrCommandWriter()181 G2DHdrCommandWriter() { }
~G2DHdrCommandWriter()182 virtual ~G2DHdrCommandWriter() { }
183
setLayerStaticMetadata(int __unused index,int __unused dataspace,unsigned int __unused min_luminance,unsigned int __unused max_luminance)184 virtual bool setLayerStaticMetadata(int __unused index, int __unused dataspace,
185 unsigned int __unused min_luminance, unsigned int __unused max_luminance) override {
186 return true;
187 }
188
setLayerImageInfo(int index,unsigned int __unused pixfmt,bool alpha_premult)189 virtual bool setLayerImageInfo(int index, unsigned int __unused pixfmt, bool alpha_premult) override {
190 if (alpha_premult)
191 mLayerAlphaMap.set(index);
192 return true;
193 }
194
setTargetInfo(int __unused dataspace,void * __unused data)195 virtual bool setTargetInfo(int __unused dataspace, void * __unused data) override {
196 return true;
197 }
198
setLayerOpaqueData(int index,void * data,size_t __unused len)199 virtual bool setLayerOpaqueData(int index, void *data, size_t __unused len) override {
200 mLayerData[index] = reinterpret_cast<displaycolor::IDisplayColorZuma::IDpp *>(data);
201 return true;
202 }
203
getCommands()204 virtual struct g2d_commandlist *getCommands() override {
205 mCmdList.reset();
206
207 unsigned int i = 0;
208 for (auto layer : mLayerData) {
209 if (layer) {
210 uint32_t modectl = 0;
211
212 // EOTF settings
213 if (layer->EotfLut().enable && layer->EotfLut().config != nullptr) {
214 mCmdList.setEotfScalar(layer->EotfLut().config->eotf_scalar,
215 HDR_EOTF_SCALER(i));
216
217 if (layer->EotfLut().config->eotf_lut_en) {
218 modectl |= HDR_ENABLE_EOTF_LUT_PQTABLE;
219 } else {
220 modectl |= HDR_ENABLE_EOTF_LUT_SFRRAMP;
221 mCmdList.updateDouble(layer->EotfLut().config->tf_data.posx,
222 HDR_EOTF_LUT_TS(i));
223 mCmdList.updateDouble(layer->EotfLut().config->tf_data.posy,
224 HDR_EOTF_LUT_VS(i));
225 }
226 modectl |= HDR_ENABLE_EOTF;
227 }
228
229 // GM settings
230 if (layer->Gm().enable && layer->Gm().config != nullptr) {
231 mCmdList.updateSingle(layer->Gm().config->matrix_data.coeffs, HDR_GM_COEF(i));
232 mCmdList.updateSingle(layer->Gm().config->matrix_data.offsets, HDR_GM_OFF(i));
233 modectl |= HDR_ENABLE_GM;
234 }
235
236 // DTM settings
237 if (layer->Dtm().enable && layer->Dtm().config != nullptr) {
238 mCmdList.updateTmCoef(*layer->Dtm().config, HDR_TM_COEF(i));
239 mCmdList.updateDouble(layer->Dtm().config->tf_data.posx, HDR_TM_LUT_TS(i));
240 mCmdList.updateDouble(layer->Dtm().config->tf_data.posy, HDR_TM_LUT_VS(i));
241 modectl |= HDR_ENABLE_TM;
242 }
243
244 // OETF settings
245 if (layer->OetfLut().enable && layer->OetfLut().config != nullptr) {
246 mCmdList.updateDouble(layer->OetfLut().config->tf_data.posx,
247 HDR_OETF_LUT_TS(i));
248 mCmdList.updateDouble(layer->OetfLut().config->tf_data.posy,
249 HDR_OETF_LUT_VS(i));
250 modectl |= HDR_ENABLE_OETF;
251 }
252
253 modectl |= HDR_ENABLE_HDR;
254
255 mCmdList.updateLayer(i, mLayerAlphaMap[0], modectl);
256 }
257
258 mLayerAlphaMap >>= 1;
259 i++;
260 }
261
262 // initialize for the next layer metadata configuration
263 mLayerAlphaMap.reset();
264 mLayerData.fill(nullptr);
265
266 return mCmdList.get();
267 }
268
putCommands(struct g2d_commandlist __unused * commands)269 virtual void putCommands(struct g2d_commandlist __unused *commands) override {
270 assert(commands == &mCommandList);
271 }
272
hasColorFillLayer(void)273 virtual bool hasColorFillLayer(void) override {
274 return true;
275 };
276 };
277
createInstance()278 IG2DHdr10CommandWriter *IG2DHdr10CommandWriter::createInstance() {
279 return new G2DHdrCommandWriter();
280 }
281