diff options
author | HyunKyung Kim <hk310.kim@samsung.com> | 2020-04-14 16:45:35 +0900 |
---|---|---|
committer | HyunKyung Kim <hk310.kim@samsung.com> | 2020-04-29 19:47:00 +0900 |
commit | b4b563005de82b3ed42363fd2f68df6e33612c40 (patch) | |
tree | ce282835dad4646c86233557f0c3dccee3e41fa4 /libhwc2.1/libdisplayinterface | |
parent | 3798c44929fa4d0cd191d23e01f4ba1bf829841b (diff) | |
download | gs101-b4b563005de82b3ed42363fd2f68df6e33612c40.tar.gz |
libhwc2.1: Support color management
Bug: 143335640
Bug: 154275156
Change-Id: Ib89afaa475ab795a40d0da24dde67ec7522529e2
Signed-off-by: HyunKyung Kim <hk310.kim@samsung.com>
Diffstat (limited to 'libhwc2.1/libdisplayinterface')
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp | 452 | ||||
-rw-r--r-- | libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h | 39 |
2 files changed, 490 insertions, 1 deletions
diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp index 192a5c6..c9b2b98 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.cpp @@ -15,7 +15,34 @@ */ #include "ExynosDisplayDrmInterfaceModule.h" -//////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule ////////////////////////////////////////////////////////////////// +#include "ExynosPrimaryDisplayModule.h" + +template <typename T, typename M> +int32_t convertDqeMatrixDataToMatrix( + const IDisplayColorGS101::MatrixData<T> &colorMatrix, + M &mat, uint32_t dimension) +{ + if (colorMatrix.coeffs.size() != (dimension * dimension)) { + HWC_LOGE(nullptr, "Invalid coeff size(%zu)", + colorMatrix.coeffs.size()); + return -EINVAL; + } + for (uint32_t i = 0; i < (dimension * dimension); i++) { + mat.coeffs[i] = colorMatrix.coeffs[i]; + } + + if (colorMatrix.offsets.size() != dimension) { + HWC_LOGE(nullptr, "Invalid offset size(%zu)", + colorMatrix.offsets.size()); + return -EINVAL; + } + for (uint32_t i = 0; i < dimension; i++) { + mat.offsets[i] = colorMatrix.offsets[i]; + } + return NO_ERROR; +} + +/////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule ////////////////////////////////////////////////////////////////// ExynosDisplayDrmInterfaceModule::ExynosDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay) : ExynosDisplayDrmInterface(exynosDisplay) { @@ -23,6 +50,429 @@ ExynosDisplayDrmInterfaceModule::ExynosDisplayDrmInterfaceModule(ExynosDisplay * ExynosDisplayDrmInterfaceModule::~ExynosDisplayDrmInterfaceModule() { + destroyOldBlobs(mOldBlobsForDisplayColor); + destroyOldBlobs(mOldBlobsForPlaneColor); +} + +void ExynosDisplayDrmInterfaceModule::destroyOldBlobs( + std::vector<uint32_t> &oldBlobs) +{ + for (auto &blob : oldBlobs) { + mDrmDevice->DestroyPropertyBlob(blob); + } + oldBlobs.clear(); +} + +int32_t ExynosDisplayDrmInterfaceModule::createCgcBlobFromIDqe( + const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId) +{ + struct cgc_lut cgc; + const IDisplayColorGS101::IDqe::CgcData &cgcData = dqe.Cgc(); + if ((cgcData.r_values.size() != CGC_LUT_REG_CNT) || + (cgcData.g_values.size() != CGC_LUT_REG_CNT) || + (cgcData.b_values.size() != CGC_LUT_REG_CNT)) { + ALOGE("CGC data size is not same (r: %zu, g: %zu: b: %zu)", + cgcData.r_values.size(), cgcData.g_values.size(), + cgcData.b_values.size()); + return -EINVAL; + } + + for (uint32_t i = 0; i < CGC_LUT_REG_CNT; i++) { + cgc.r_values[i] = cgcData.r_values[i]; + cgc.g_values[i] = cgcData.g_values[i]; + cgc.b_values[i] = cgcData.b_values[i]; + } + int ret = mDrmDevice->CreatePropertyBlob(&cgc, sizeof(cgc_lut), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create cgc blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createDegammaLutBlobFromIDqe( + const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId) +{ + int ret = 0; + uint64_t lut_size = 0; + std::tie(ret, lut_size) = mDrmCrtc->degamma_lut_size_property().value(); + if (ret < 0) { + HWC_LOGE(mExynosDisplay, "%s: there is no degamma_lut_size (ret = %d)", + __func__, ret); + return ret; + } + if (lut_size != IDisplayColorGS101::IDqe::DegammaLutData::kLutLen) { + HWC_LOGE(mExynosDisplay, "%s: invalid lut size (%" PRId64 ")", + __func__, lut_size); + return -EINVAL; + } + + struct drm_color_lut color_lut[IDisplayColorGS101::IDqe::DegammaLutData::kLutLen]; + for (uint32_t i = 0; i < lut_size; i++) { + color_lut[i].red = dqe.DegammaLut().values[i]; + } + ret = mDrmDevice->CreatePropertyBlob(color_lut, sizeof(color_lut), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create degamma lut blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createRegammaLutBlobFromIDqe( + const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId) +{ + int ret = 0; + uint64_t lut_size = 0; + std::tie(ret, lut_size) = mDrmCrtc->gamma_lut_size_property().value(); + if (ret < 0) { + HWC_LOGE(mExynosDisplay, "%s: there is no gamma_lut_size (ret = %d)", + __func__, ret); + return ret; + } + if (lut_size != IDisplayColorGS101::IDqe::DegammaLutData::kLutLen) { + HWC_LOGE(mExynosDisplay, "%s: invalid lut size (%" PRId64 ")", + __func__, lut_size); + return -EINVAL; + } + + struct drm_color_lut color_lut[IDisplayColorGS101::IDqe::DegammaLutData::kLutLen]; + for (uint32_t i = 0; i < lut_size; i++) { + color_lut[i].red = dqe.RegammaLut().r_values[i]; + color_lut[i].green = dqe.RegammaLut().g_values[i]; + color_lut[i].blue = dqe.RegammaLut().b_values[i]; + } + ret = mDrmDevice->CreatePropertyBlob(color_lut, sizeof(color_lut), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create gamma lut blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createGammaMatBlobFromIDqe( + const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId) +{ + /* TODO: This function should be implemented */ + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createLinearMatBlobFromIDqe( + const IDisplayColorGS101::IDqe &dqe, uint32_t &blobId) +{ + /* TODO: This function should be implemented */ + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createEotfBlobFromIDpp( + const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId) +{ + struct hdr_eotf_lut eotf_lut; + if ((dpp.EotfLut().posx.size() != HDR_EOTF_LUT_LEN) || + (dpp.EotfLut().posy.size() != HDR_EOTF_LUT_LEN)) { + HWC_LOGE(mExynosDisplay, "%s: eotf pos size (%zu, %zu)", + __func__, dpp.EotfLut().posx.size(), dpp.EotfLut().posy.size()); + return -EINVAL; + } + for (uint32_t i = 0; i < HDR_EOTF_LUT_LEN; i++) { + eotf_lut.posx[i] = dpp.EotfLut().posx[i]; + eotf_lut.posy[i] = dpp.EotfLut().posy[i]; + } + int ret = mDrmDevice->CreatePropertyBlob(&eotf_lut, sizeof(eotf_lut), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create eotf lut blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createGmBlobFromIDpp( + const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId) +{ + int ret = 0; + struct hdr_gm_data gm_matrix; + if ((ret = convertDqeMatrixDataToMatrix( + dpp.Gm(), gm_matrix, HDR_GM_DIMENSIONS)) != NO_ERROR) + { + HWC_LOGE(mExynosDisplay, "Failed to convert gm matrix"); + return ret; + } + ret = mDrmDevice->CreatePropertyBlob(&gm_matrix, sizeof(gm_matrix), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create gm matrix blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::createDtmBlobFromIDpp( + const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId) +{ + struct hdr_tm_data tm_data; + if ((dpp.Dtm().posx.size() != HDR_TM_LUT_LEN) || + (dpp.Dtm().posy.size() != HDR_TM_LUT_LEN)) { + HWC_LOGE(mExynosDisplay, "%s: dtm pos size (%zu, %zu)", + __func__, dpp.Dtm().posx.size(), dpp.Dtm().posy.size()); + return -EINVAL; + } + + for (uint32_t i = 0; i < HDR_TM_LUT_LEN; i++) { + tm_data.posx[i] = dpp.Dtm().posx[i]; + tm_data.posy[i] = dpp.Dtm().posy[i]; + } + + tm_data.coeff_r = dpp.Dtm().coeff_r; + tm_data.coeff_g = dpp.Dtm().coeff_g; + tm_data.coeff_b = dpp.Dtm().coeff_b; + tm_data.rng_x_min = dpp.Dtm().rng_x_min; + tm_data.rng_x_max = dpp.Dtm().rng_x_max; + tm_data.rng_y_min = dpp.Dtm().rng_y_min; + tm_data.rng_y_max = dpp.Dtm().rng_y_max; + + int ret = mDrmDevice->CreatePropertyBlob(&tm_data, sizeof(tm_data), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create tm_data blob %d", ret); + return ret; + } + + return NO_ERROR; +} +int32_t ExynosDisplayDrmInterfaceModule::createOetfBlobFromIDpp( + const IDisplayColorGS101::IDpp &dpp, uint32_t &blobId) +{ + struct hdr_oetf_lut oetf_lut; + if ((dpp.OetfLut().posx.size() != HDR_OETF_LUT_LEN) || + (dpp.OetfLut().posy.size() != HDR_OETF_LUT_LEN)) { + HWC_LOGE(mExynosDisplay, "%s: oetf pos size (%zu, %zu)", + __func__, dpp.OetfLut().posx.size(), dpp.OetfLut().posy.size()); + return -EINVAL; + } + for (uint32_t i = 0; i < HDR_OETF_LUT_LEN; i++) { + oetf_lut.posx[i] = dpp.OetfLut().posx[i]; + oetf_lut.posy[i] = dpp.OetfLut().posy[i]; + } + int ret = mDrmDevice->CreatePropertyBlob(&oetf_lut, sizeof(oetf_lut), &blobId); + if (ret) { + HWC_LOGE(mExynosDisplay, "Failed to create oetf lut blob %d", ret); + return ret; + } + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::setDisplayColorSetting( + ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq) +{ + destroyOldBlobs(mOldBlobsForDisplayColor); + + if ((mColorSettingChanged == false) || + (isPrimary() == false)) + return NO_ERROR; + + ExynosPrimaryDisplayModule* display = + (ExynosPrimaryDisplayModule*)mExynosDisplay; + + int ret = NO_ERROR; + uint32_t blobId = 0; + const IDisplayColorGS101::IDqe &dqe = display->getDqe(); + + if (dqe.Cgc().enable && mDrmCrtc->cgc_lut_property().id()) { + if ((ret = createCgcBlobFromIDqe(dqe, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createCgcBlobFromIDqe fail", __func__); + return ret; + } + mOldBlobsForDisplayColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), + mDrmCrtc->cgc_lut_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set cgc_lut_property", + __func__); + return ret; + } + } + if (dqe.DegammaLut().enable && mDrmCrtc->degamma_lut_property().id()) { + if ((ret = createDegammaLutBlobFromIDqe(dqe, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createDegammaLutBlobFromIDqe fail", + __func__); + return ret; + } + mOldBlobsForDisplayColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), + mDrmCrtc->degamma_lut_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set degamma_lut_property", + __func__); + return ret; + } + } + if (dqe.RegammaLut().enable && mDrmCrtc->gamma_lut_property().id()) { + if ((ret = createRegammaLutBlobFromIDqe(dqe, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createRegammaLutBlobFromIDqe fail", + __func__); + return ret; + } + mOldBlobsForDisplayColor.push_back(blobId); + ALOGD("set regamma lut %d", blobId); + if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), + mDrmCrtc->gamma_lut_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set gamma_lut_property", + __func__); + return ret; + } + } + if (dqe.GammaMatrix().enable && mDrmCrtc->gamma_matrix_property().id()) { + if ((ret = createGammaMatBlobFromIDqe(dqe, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createGammaMatBlobFromIDqe fail", + __func__); + return ret; + } + mOldBlobsForDisplayColor.push_back(blobId); + ALOGD("set gamma matrix %d", blobId); + if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), + mDrmCrtc->gamma_matrix_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set gamma_matrix_property", + __func__); + return ret; + } + } + if (dqe.LinearMatrix().enable && mDrmCrtc->linear_matrix_property().id()) { + if ((ret = createLinearMatBlobFromIDqe(dqe, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createLinearMatBlobFromIDqe fail", + __func__); + return ret; + } + mOldBlobsForDisplayColor.push_back(blobId); + ALOGD("set linear matrix %d", blobId); + if ((ret = drmReq.atomicAddProperty(mDrmCrtc->id(), + mDrmCrtc->linear_matrix_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set linear_matrix_property", + __func__); + return ret; + } + } + + return NO_ERROR; +} + +int32_t ExynosDisplayDrmInterfaceModule::setPlaneColorSetting( + ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq, + const std::unique_ptr<DrmPlane> &plane, + const exynos_win_config_data &config) +{ + destroyOldBlobs(mOldBlobsForPlaneColor); + + if ((mColorSettingChanged == false) || + (isPrimary() == false)) + return NO_ERROR; + + if ((config.assignedMPP == nullptr) || + (config.assignedMPP->mAssignedSources.size() == 0)) { + HWC_LOGE(mExynosDisplay, "%s:: config's mpp source size is invalid", + __func__); + return -EINVAL; + } + ExynosMPPSource* mppSource = config.assignedMPP->mAssignedSources[0]; + + /* + * Color conversion of Client and Exynos composition buffer + * is already addressed by GLES or G2D + */ + if (mppSource->mSourceType == MPP_SOURCE_COMPOSITION_TARGET) + return NO_ERROR; + + if (mppSource->mSourceType != MPP_SOURCE_LAYER) { + HWC_LOGE(mExynosDisplay, "%s:: invalid mpp source type (%d)", + __func__, mppSource->mSourceType); + return -EINVAL; + } + + ExynosLayer* layer = (ExynosLayer*)mppSource; + + /* color conversion was already handled by m2mMPP */ + if ((layer->mM2mMPP != nullptr) && + (layer->mSrcImg.dataSpace != layer->mMidImg.dataSpace)) { + return NO_ERROR; + } + + ExynosPrimaryDisplayModule* display = + (ExynosPrimaryDisplayModule*)mExynosDisplay; + + if (display->hasDppForLayer(layer) == false) { + HWC_LOGE(mExynosDisplay, + "%s: layer need color conversion but there is no IDpp", + __func__); + return -EINVAL; + } + + const IDisplayColorGS101::IDpp &dpp = display->getDppForLayer(layer); + uint32_t blobId = 0; + int ret = 0; + + if (dpp.EotfLut().enable && plane->eotf_lut_property().id()) + { + if ((ret = createEotfBlobFromIDpp(dpp, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createEotfBlobFromIDpp fail", + __func__); + return ret; + } + mOldBlobsForPlaneColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(plane->id(), + plane->eotf_lut_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set eotf_lut_property", + __func__); + return ret; + } + } + + if (dpp.Gm().enable && plane->gammut_matrix_property().id()) + { + if ((ret = createGmBlobFromIDpp(dpp, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createGmBlobFromIDpp fail", + __func__); + return ret; + } + mOldBlobsForPlaneColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(plane->id(), + plane->gammut_matrix_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set gammut_matrix_property", + __func__); + return ret; + } + } + + /* TODO: For now, Dtm setting is not verified. This should be set */ +#if 0 + if (dpp.Dtm().enable && plane->tone_mapping_property().id()) + { + if ((ret = createDtmBlobFromIDpp(dpp, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createDtmBlobFromIDpp fail", + __func__); + return ret; + } + mOldBlobsForPlaneColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(plane->id(), + plane->tone_mapping_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set tone_mapping_property", + __func__); + return ret; + } + } +#endif + + if (dpp.OetfLut().enable && plane->oetf_lut_property().id()) + { + if ((ret = createOetfBlobFromIDpp(dpp, blobId)) != NO_ERROR) { + HWC_LOGE(mExynosDisplay, "%s: createOetfBlobFromIDpp fail", + __func__); + return ret; + } + mOldBlobsForPlaneColor.push_back(blobId); + if ((ret = drmReq.atomicAddProperty(plane->id(), + plane->oetf_lut_property(), blobId)) < 0) { + HWC_LOGE(mExynosDisplay, "%s: Fail to set oetf_lut_property", + __func__); + return ret; + } + } + + return 0; } //////////////////////////////////////////////////// ExynosPrimaryDisplayDrmInterfaceModule ////////////////////////////////////////////////////////////////// diff --git a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h index 163655c..4739e53 100644 --- a/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h +++ b/libhwc2.1/libdisplayinterface/ExynosDisplayDrmInterfaceModule.h @@ -18,11 +18,50 @@ #define EXYNOS_DISPLAY_DRM_INTERFACE_MODULE_H #include "ExynosDisplayDrmInterface.h" +#include "DeconDrmHeader.h" +#include <displaycolor/displaycolor_gs101.h> + +using namespace displaycolor; class ExynosDisplayDrmInterfaceModule : public ExynosDisplayDrmInterface { public: ExynosDisplayDrmInterfaceModule(ExynosDisplay *exynosDisplay); virtual ~ExynosDisplayDrmInterfaceModule(); + + virtual int32_t setDisplayColorSetting( + ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq); + virtual int32_t setPlaneColorSetting( + ExynosDisplayDrmInterface::DrmModeAtomicReq &drmReq, + const std::unique_ptr<DrmPlane> &plane, + const exynos_win_config_data &config); + void setColorSettingChanged(bool changed) { + mColorSettingChanged = changed; }; + void destroyOldBlobs(std::vector<uint32_t> &oldBlobs); + + int32_t createCgcBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe, + uint32_t &blobId); + int32_t createDegammaLutBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe, + uint32_t &blobId); + int32_t createRegammaLutBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe, + uint32_t &blobId); + int32_t createGammaMatBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe, + uint32_t &blobId); + int32_t createLinearMatBlobFromIDqe(const IDisplayColorGS101::IDqe &dqe, + uint32_t &blobId); + + int32_t createEotfBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp, + uint32_t &blobId); + int32_t createGmBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp, + uint32_t &blobId); + int32_t createDtmBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp, + uint32_t &blobId); + int32_t createOetfBlobFromIDpp(const IDisplayColorGS101::IDpp &dpp, + uint32_t &blobId); + + std::vector<uint32_t> mOldBlobsForDisplayColor; + std::vector<uint32_t> mOldBlobsForPlaneColor; + private: + bool mColorSettingChanged = false; }; class ExynosPrimaryDisplayDrmInterfaceModule : public ExynosDisplayDrmInterfaceModule { |