/* * libacryl_plugins/libacryl_hdr_plugin.cpp * * Copyright 2020 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #define HDR_BASE 0x3000 #define HDR_SFR_LEN 0x800 #define HDR_COM_CTRL 0x3004 // [0] HDR enable static const uint32_t VAL_HDR_CTRL_ENABLE = 1; #define HDR_MOD_CTRL_NUM 1 // [0] oetf enable, [1] eotf enable [2] gm enable [5] tm enable #define HDR_OETF_POSX_NUM 17 // two 16-bit from LSB #define HDR_OETF_POSY_NUM 17 // two 10-bit from LSB #define HDR_EOTF_POSX_NUM 65 // two 10-bit from LSB #define HDR_EOTF_POSY_NUM 129 // one 16-bit #define HDR_GM_COEF_NUM 9 // one 19-bit #define HDR_GM_OFF_NUM 3 // one 17-bit #define HDR_TM_COEF_NUM 1 // three 10-bit from LSB (R, G, B) #define HDR_TM_RNGX_NUM 1 // two 16-bit from LSB (min:max) #define HDR_TM_RNGY_NUM 1 // two 9-bit from LSB (min:max) #define HDR_TM_POSX_NUM 17 // two 16-bit from LSB #define HDR_TM_POSY_NUM 33 // one 27-bit from LSB #define HDR_MOD_CTRL_OFFSET (0x8) static const uint32_t HDR_ENABLE_OETF = 1 << 0; static const uint32_t HDR_ENABLE_EOTF = 1 << 1; static const uint32_t HDR_ENABLE_GM = 1 << 2; static const uint32_t HDR_ENABLE_DTM = 1 << 5; #define HDR_OETF_POSX_OFFSET (HDR_MOD_CTRL_OFFSET + 4 * HDR_MOD_CTRL_NUM ) #define HDR_OETF_POSY_OFFSET (HDR_OETF_POSX_OFFSET + 4 * HDR_OETF_POSX_NUM) #define HDR_EOTF_POSX_OFFSET (HDR_OETF_POSY_OFFSET + 4 * HDR_OETF_POSY_NUM) #define HDR_EOTF_POSY_OFFSET (HDR_EOTF_POSX_OFFSET + 4 * HDR_EOTF_POSX_NUM) #define HDR_GM_COEF_OFFSET (HDR_EOTF_POSY_OFFSET + 4 * HDR_EOTF_POSY_NUM) #define HDR_GM_OFF_OFFSET (HDR_GM_COEF_OFFSET + 4 * HDR_GM_COEF_NUM ) #define HDR_TM_COEF_OFFSET (HDR_GM_OFF_OFFSET + 4 * HDR_GM_OFF_NUM ) #define HDR_TM_RNGX_OFFSET (HDR_TM_COEF_OFFSET + 4 * HDR_TM_COEF_NUM ) #define HDR_TM_RNGY_OFFSET (HDR_TM_RNGX_OFFSET + 4 * HDR_TM_RNGX_NUM ) #define HDR_TM_POSX_OFFSET (HDR_TM_RNGY_OFFSET + 4 * HDR_TM_RNGY_NUM ) #define HDR_TM_POSY_OFFSET (HDR_TM_POSX_OFFSET + 4 * HDR_TM_POSX_NUM ) #define HDR_LAYER_BASE(layer) (HDR_BASE + HDR_SFR_LEN * (layer)) #define HDR_MOD_CTRL(layer) (HDR_LAYER_BASE(layer) + HDR_MOD_CTRL_OFFSET ) #define HDR_OETF_POSX(layer) (HDR_LAYER_BASE(layer) + HDR_OETF_POSX_OFFSET) #define HDR_OETF_POSY(layer) (HDR_LAYER_BASE(layer) + HDR_OETF_POSY_OFFSET) #define HDR_EOTF_POSX(layer) (HDR_LAYER_BASE(layer) + HDR_EOTF_POSX_OFFSET) #define HDR_EOTF_POSY(layer) (HDR_LAYER_BASE(layer) + HDR_EOTF_POSY_OFFSET) #define HDR_GM_COEF(layer) (HDR_LAYER_BASE(layer) + HDR_GM_COEF_OFFSET ) #define HDR_GM_OFF(layer) (HDR_LAYER_BASE(layer) + HDR_GM_OFF_OFFSET ) #define HDR_TM_COEF(layer) (HDR_LAYER_BASE(layer) + HDR_TM_COEF_OFFSET ) #define HDR_TM_RNGX(layer) (HDR_LAYER_BASE(layer) + HDR_TM_RNGX_OFFSET ) #define HDR_TM_RNGY(layer) (HDR_LAYER_BASE(layer) + HDR_TM_RNGY_OFFSET ) #define HDR_TM_POSX(layer) (HDR_LAYER_BASE(layer) + HDR_TM_POSX_OFFSET ) #define HDR_TM_POSY(layer) (HDR_LAYER_BASE(layer) + HDR_TM_POSY_OFFSET ) #define G2D_LAYER_HDRMODE(i) (0x290 + (i) * 0x100) #define MAX_LAYER_COUNT 4 #define HDR_LAYER_SFR_COUNT (\ HDR_MOD_CTRL_NUM + HDR_OETF_POSX_NUM + HDR_OETF_POSY_NUM + \ HDR_EOTF_POSX_NUM + HDR_EOTF_POSY_NUM + HDR_GM_COEF_NUM + \ HDR_GM_OFF_NUM + HDR_TM_COEF_NUM + HDR_TM_RNGX_NUM + \ HDR_TM_RNGY_NUM + HDR_TM_POSX_NUM + HDR_TM_POSY_NUM\ ) static const size_t NUM_HDR_COEFFICIENTS = HDR_LAYER_SFR_COUNT * MAX_LAYER_COUNT + 1; // HDR SFR COUNT x LAYER COUNT + COM_CTRL static const size_t NUM_HDR_MODE_REGS = MAX_LAYER_COUNT; class G2DHdrCommandWriter: public IG2DHdr10CommandWriter { std::bitset mLayerAlphaMap; std::array mLayerData{}; public: struct CommandList { std::array commands; // (294 * 4 + 1) * 8 bytes std::array layer_hdr_modes; // 4 * 8 bytes g2d_commandlist cmdlist{}; CommandList() { cmdlist.commands = commands.data(); cmdlist.layer_hdr_mode = layer_hdr_modes.data(); } ~CommandList() { } void reset() { cmdlist.command_count = 0; cmdlist.layer_count = 0; } g2d_commandlist *get() { return &cmdlist; } uint32_t set_and_get_next_offset(uint32_t offset, uint32_t value) { commands[cmdlist.command_count].offset = offset; commands[cmdlist.command_count].value = value; cmdlist.command_count++; return offset + sizeof(value); } void updateLayer(std::size_t layer, bool alpha_premultiplied, uint32_t modectl) { auto &hdr_mode = layer_hdr_modes[cmdlist.layer_count++]; hdr_mode.offset = G2D_LAYER_HDRMODE(layer); hdr_mode.value = layer; // The premultiplied alpha should be demultiplied before HDR conversion. if (alpha_premultiplied) hdr_mode.value |= G2D_LAYER_HDRMODE_DEMULT_ALPHA; set_and_get_next_offset(HDR_MOD_CTRL(layer), modectl); } template void updateDouble(const containerT &container, uint32_t offset) { for (std::size_t n = 0; n < container.size(); n += 2) offset = set_and_get_next_offset(offset, container[n] | container[n + 1] << 16); if ((container.size() % 2) == 1) set_and_get_next_offset(offset, container.back()); } template void updateSingle(const containerT &container, uint32_t offset) { for (auto item : container) offset = set_and_get_next_offset(offset, item); } void updateTmCoef(const displaycolor::IDisplayColorGS101::IDpp::DtmData::ConfigType &config, uint32_t offset) { offset = set_and_get_next_offset(offset, config.coeff_r | (config.coeff_g << 10) | (config.coeff_b << 20)); offset = set_and_get_next_offset(offset, config.rng_x_min | (config.rng_x_max << 16)); set_and_get_next_offset(offset, config.rng_y_min | (config.rng_y_max << 16)); } void updateHdr() { if (cmdlist.command_count > 0) set_and_get_next_offset(HDR_COM_CTRL, VAL_HDR_CTRL_ENABLE); } } mCmdList; G2DHdrCommandWriter() { } virtual ~G2DHdrCommandWriter() { } virtual bool setLayerStaticMetadata(int __unused index, int __unused dataspace, unsigned int __unused min_luminance, unsigned int __unused max_luminance) override { return true; } virtual bool setLayerImageInfo(int index, unsigned int __unused pixfmt, bool alpha_premult) override { if (alpha_premult) mLayerAlphaMap.set(index); return true; } virtual bool setTargetInfo(int __unused dataspace, void * __unused data) override { return true; } virtual bool setLayerOpaqueData(int index, void *data, size_t __unused len) override { mLayerData[index] = reinterpret_cast(data); return true; } virtual struct g2d_commandlist *getCommands() override { mCmdList.reset(); unsigned int i = 0; for (auto layer : mLayerData) { if (layer) { uint32_t modectl = 0; if (layer->EotfLut().enable && layer->EotfLut().config != nullptr) { mCmdList.updateDouble(layer->EotfLut().config->tf_data.posx, HDR_EOTF_POSX(i)); mCmdList.updateSingle(layer->EotfLut().config->tf_data.posy, HDR_EOTF_POSY(i)); modectl |= HDR_ENABLE_EOTF; } if (layer->Gm().enable && layer->Gm().config != nullptr) { mCmdList.updateSingle(layer->Gm().config->matrix_data.coeffs, HDR_GM_COEF(i)); mCmdList.updateSingle(layer->Gm().config->matrix_data.offsets, HDR_GM_OFF(i)); modectl |= HDR_ENABLE_GM; } if (layer->Dtm().enable && layer->Dtm().config != nullptr) { mCmdList.updateTmCoef(*layer->Dtm().config, HDR_TM_COEF(i)); mCmdList.updateDouble(layer->Dtm().config->tf_data.posx, HDR_TM_POSX(i)); mCmdList.updateSingle(layer->Dtm().config->tf_data.posy, HDR_TM_POSY(i)); modectl |= HDR_ENABLE_DTM; } if (layer->OetfLut().enable && layer->OetfLut().config != nullptr) { mCmdList.updateDouble(layer->OetfLut().config->tf_data.posx, HDR_OETF_POSX(i)); mCmdList.updateDouble(layer->OetfLut().config->tf_data.posy, HDR_OETF_POSY(i)); modectl |= HDR_ENABLE_OETF; } mCmdList.updateLayer(i, mLayerAlphaMap[0], modectl); } mLayerAlphaMap >>= 1; i++; } mCmdList.updateHdr(); // initialize for the next layer metadata configuration mLayerAlphaMap.reset(); mLayerData.fill(nullptr); return mCmdList.get(); } virtual void putCommands(struct g2d_commandlist __unused *commands) override { assert(commands == &mCommandList); } }; IG2DHdr10CommandWriter *IG2DHdr10CommandWriter::createInstance() { return new G2DHdrCommandWriter(); }