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