summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2019-04-09 03:55:44 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2019-04-09 03:55:44 +0000
commit1c3903b59f159857f017866c0173e04dc238b149 (patch)
tree894dd46e5329cae760e71afb7162d41c993f0ea1
parent5e157cfbb71dad4fb8eafc68312fbe1b61059339 (diff)
parent729e1071df20e964d3bf310134e887ecddf084d2 (diff)
downloadandroid_hardware_qcom_sdm845_display-1c3903b59f159857f017866c0173e04dc238b149.tar.gz
android_hardware_qcom_sdm845_display-1c3903b59f159857f017866c0173e04dc238b149.tar.bz2
android_hardware_qcom_sdm845_display-1c3903b59f159857f017866c0173e04dc238b149.zip
Merge "hwc2: Add color compensation feature for adaptive color mode" into qt-dev
-rw-r--r--include/display_properties.h2
-rw-r--r--libqservice/IQService.h1
-rw-r--r--sdm/libs/hwc2/hwc_display.cpp242
-rw-r--r--sdm/libs/hwc2/hwc_display.h114
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.cpp12
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.h1
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp19
-rw-r--r--sdm/libs/hwc2/hwc_session.h1
8 files changed, 381 insertions, 11 deletions
diff --git a/include/display_properties.h b/include/display_properties.h
index 3944dc65..e59e800e 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -94,6 +94,8 @@
#define ENABLE_DEFAULT_COLOR_MODE DISPLAY_PROP("enable_default_color_mode")
#define DISABLE_HDR DISPLAY_PROP("disable_hdr")
#define DATASPACE_SATURATION_MATRIX_PROP DISPLAY_PROP("dataspace_saturation_matrix")
+#define ADAPTIVE_WHITE_COEFFICIENT_PROP DISPLAY_PROP("adaptive_white_coefficient")
+#define ADAPTIVE_SATURATION_PARAMETER_PROP DISPLAY_PROP("adaptive_saturation_parameter")
#define HDR_CONFIG_PROP RO_DISPLAY_PROP("hdr.config")
#define QDCM_PCC_TRANS_PROP DISPLAY_PROP("qdcm.pcc_for_trans")
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 52d72e96..686b2441 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -82,6 +82,7 @@ public:
// Start custom transactions from 200
SET_COLOR_SAMPLING_ENABLED = 200, // Toggle the collection of display color stats
+ SET_WHITE_COMPENSATION = 201, // Enable/disable white point compensation
COMMAND_LIST_END = 400,
};
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index b5e2a5a5..45effc06 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -54,6 +54,7 @@ HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(displ
HWC2::Error HWCColorMode::Init() {
PopulateColorModes();
+ InitColorCompensation();
return ApplyDefaultColorMode();
}
@@ -119,11 +120,13 @@ HWC2::Error HWCColorMode::SetColorModeWithRenderIntent(ColorMode mode, RenderInt
DLOGE("failed for mode = %d intent = %d name = %s", mode, intent, mode_string.c_str());
return HWC2::Error::Unsupported;
}
- // The mode does not have the PCC configured, restore the transform
- RestoreColorTransform();
current_color_mode_ = mode;
current_render_intent_ = intent;
+
+ // The mode does not have the PCC configured, restore the transform
+ RestoreColorTransform();
+
DLOGV_IF(kTagClient, "Successfully applied mode = %d intent = %d name = %s", mode, intent,
mode_string.c_str());
return HWC2::Error::None;
@@ -140,7 +143,8 @@ HWC2::Error HWCColorMode::SetColorModeById(int32_t color_mode_id) {
}
HWC2::Error HWCColorMode::RestoreColorTransform() {
- DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix_);
+ DisplayError error =
+ display_intf_->SetColorTransform(kColorTransformMatrixCount, PickTransferMatrix());
if (error != kErrorNone) {
DLOGE("Failed to set Color Transform");
return HWC2::Error::BadParameter;
@@ -149,19 +153,227 @@ HWC2::Error HWCColorMode::RestoreColorTransform() {
return HWC2::Error::None;
}
+void HWCColorMode::InitColorCompensation() {
+ char value[kPropertyMax] = {0};
+ if (Debug::Get()->GetProperty(ADAPTIVE_WHITE_COEFFICIENT_PROP, value) == kErrorNone) {
+ adaptive_white_ = std::make_unique<WhiteCompensation>(string(value));
+ adaptive_white_->SetEnabled(true);
+ }
+ std::memset(value, 0, sizeof(value));
+ if (Debug::Get()->GetProperty(ADAPTIVE_SATURATION_PARAMETER_PROP, value) == kErrorNone) {
+ adaptive_saturation_ = std::make_unique<SaturationCompensation>(string(value));
+ adaptive_saturation_->SetEnabled(true);
+ }
+}
+
+const double *HWCColorMode::PickTransferMatrix() {
+ double matrix[kColorTransformMatrixCount] = {0};
+ if (current_render_intent_ == RenderIntent::ENHANCE) {
+ CopyColorTransformMatrix(color_matrix_, matrix);
+ if (HasSaturationCompensation())
+ adaptive_saturation_->ApplyToMatrix(matrix);
+
+ if (HasWhiteCompensation())
+ adaptive_white_->ApplyToMatrix(matrix);
+
+ CopyColorTransformMatrix(matrix, compensated_color_matrix_);
+ return compensated_color_matrix_;
+ } else {
+ return color_matrix_;
+ }
+}
+
+HWC2::Error HWCColorMode::SetWhiteCompensation(bool enabled) {
+ if (adaptive_white_ == NULL)
+ return HWC2::Error::Unsupported;
+
+ if (adaptive_white_->SetEnabled(enabled) != HWC2::Error::None) {
+ return HWC2::Error::NotValidated;
+ }
+
+ RestoreColorTransform();
+
+ DLOGI("Set White Compensation: %d", enabled);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCColorMatrix::SetEnabled(bool enabled) {
+ enabled_ = enabled;
+ return HWC2::Error::None;
+}
+
+bool HWCColorMatrix::ParseFloatValueByCommas(const string &values, uint32_t length,
+ std::vector<float> &elements) const {
+ std::istringstream data_stream(values);
+ string data;
+ uint32_t index = 0;
+ std::vector<float> temp_elements;
+ while (std::getline(data_stream, data, ',')) {
+ temp_elements.push_back(std::move(std::stof(data.c_str())));
+ index++;
+ }
+
+ if (index != length) {
+ DLOGW("Insufficient elements defined");
+ return false;
+ }
+ std::move(temp_elements.begin(), temp_elements.end(), elements.begin());
+ return true;
+}
+
+HWC2::Error WhiteCompensation::SetEnabled(bool enabled) {
+ // re-parse data when set enabled for retry calibration
+ if (enabled) {
+ if (!ConfigCoefficients() || !ParseWhitePointCalibrationData()) {
+ enabled_ = false;
+ DLOGE("Failed to WhiteCompensation Set");
+ return HWC2::Error::NotValidated;
+ }
+ CalculateRGBRatio();
+ }
+ enabled_ = enabled;
+ return HWC2::Error::None;
+}
+
+bool WhiteCompensation::ParseWhitePointCalibrationData() {
+ static constexpr char kWhitePointCalibrationDataPath[] = "/persist/display/calibrated_rgb";
+ FILE *fp = fopen(kWhitePointCalibrationDataPath, "r");
+ int ret;
+
+ if (!fp) {
+ DLOGW("Failed to open white point calibration data file");
+ return false;
+ }
+
+ ret = fscanf(fp, "%d %d %d", &compensated_red_, &compensated_green_, &compensated_blue_);
+ fclose(fp);
+
+ if ((ret == kNumOfCompensationData) && CheckCompensatedRGB(compensated_red_) &&
+ CheckCompensatedRGB(compensated_green_) && CheckCompensatedRGB(compensated_blue_)) {
+ DLOGD("Compensated RGB: %d %d %d", compensated_red_, compensated_green_, compensated_blue_);
+ return true;
+ } else {
+ compensated_red_ = kCompensatedMaxRGB;
+ compensated_green_ = kCompensatedMaxRGB;
+ compensated_blue_ = kCompensatedMaxRGB;
+ DLOGE("Wrong white compensated value");
+ return false;
+ }
+}
+
+bool WhiteCompensation::ConfigCoefficients() {
+ std::vector<float> CompensatedCoefficients(kCoefficientElements);
+ if (!ParseFloatValueByCommas(key_values_, kCoefficientElements, CompensatedCoefficients))
+ return false;
+ std::move(CompensatedCoefficients.begin(), CompensatedCoefficients.end(),
+ white_compensated_Coefficients_);
+ for (const auto &c : white_compensated_Coefficients_) {
+ DLOGD("white_compensated_Coefficients_=%f", c);
+ }
+ return true;
+}
+
+void WhiteCompensation::CalculateRGBRatio() {
+ // r = r_coeffient2 * R^2 + r_coeffient1 * R + r_coeffient0
+ // g = g_coeffient2 * G^2 + g_coeffient1 * G + g_coeffient0
+ // b = b_coeffient2 * B^2 + b_coeffient1 * B + b_coeffient0
+ // r_ratio = r/kCompensatedMaxRGB
+ // g_ratio = g/kCompensatedMaxRGB
+ // b_ratio = b/kCompensatedMaxRGB
+ auto rgb_ratio = [=](int rgb, float c2, float c1, float c0) {
+ return ((c2 * rgb * rgb + c1 * rgb + c0) / kCompensatedMaxRGB);
+ };
+
+ compensated_red_ratio_ =
+ rgb_ratio(compensated_red_, white_compensated_Coefficients_[0],
+ white_compensated_Coefficients_[1], white_compensated_Coefficients_[2]);
+ compensated_green_ratio_ =
+ rgb_ratio(compensated_green_, white_compensated_Coefficients_[3],
+ white_compensated_Coefficients_[4], white_compensated_Coefficients_[5]);
+ compensated_blue_ratio_ =
+ rgb_ratio(compensated_blue_, white_compensated_Coefficients_[6],
+ white_compensated_Coefficients_[7], white_compensated_Coefficients_[8]);
+ DLOGI("Compensated ratio %f %f %f", compensated_red_ratio_, compensated_green_ratio_,
+ compensated_blue_ratio_);
+}
+
+void WhiteCompensation::ApplyToMatrix(double *in) {
+ double matrix[kColorTransformMatrixCount] = {0};
+ for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
+ if ((i % 4) == 0)
+ matrix[i] = compensated_red_ratio_ * in[i];
+ else if ((i % 4) == 1)
+ matrix[i] = compensated_green_ratio_ * in[i];
+ else if ((i % 4) == 2)
+ matrix[i] = compensated_blue_ratio_ * in[i];
+ else if ((i % 4) == 3)
+ matrix[i] = in[i];
+ }
+ std::move(&matrix[0], &matrix[kColorTransformMatrixCount - 1], in);
+}
+
+HWC2::Error SaturationCompensation::SetEnabled(bool enabled) {
+ if (enabled == enabled_)
+ return HWC2::Error::None;
+
+ if (enabled) {
+ if (!ConfigSaturationParameter()) {
+ enabled_ = false;
+ return HWC2::Error::NotValidated;
+ }
+ }
+ enabled_ = enabled;
+ return HWC2::Error::None;
+}
+
+bool SaturationCompensation::ConfigSaturationParameter() {
+ std::vector<float> SaturationParameter(kSaturationParameters);
+ if (!ParseFloatValueByCommas(key_values_, kSaturationParameters, SaturationParameter))
+ return false;
+
+ int32_t matrix_index = 0;
+ for (uint32_t i = 0; i < SaturationParameter.size(); i++) {
+ saturated_matrix_[matrix_index] = SaturationParameter.at(i);
+ // Put parameters to matrix and keep the last row/column identity
+ if ((i + 1) % 3 == 0) {
+ matrix_index += 2;
+ } else {
+ matrix_index++;
+ }
+ DLOGD("SaturationParameter[%d]=%f", i, SaturationParameter.at(i));
+ }
+ return true;
+}
+
+void SaturationCompensation::ApplyToMatrix(double *in) {
+ double matrix[kColorTransformMatrixCount] = {0};
+ // 4 x 4 matrix multiplication
+ for (uint32_t i = 0; i < kNumOfRows; i++) {
+ for (uint32_t j = 0; j < kColumnsPerRow; j++) {
+ for (uint32_t k = 0; k < kColumnsPerRow; k++) {
+ matrix[j + (i * kColumnsPerRow)] +=
+ saturated_matrix_[k + (i * kColumnsPerRow)] * in[j + (k * kColumnsPerRow)];
+ }
+ }
+ }
+ std::move(&matrix[0], &matrix[kColorTransformMatrixCount - 1], in);
+}
+
HWC2::Error HWCColorMode::SetColorTransform(const float *matrix,
android_color_transform_t /*hint*/) {
DTRACE_SCOPED();
auto status = HWC2::Error::None;
- double color_matrix[kColorTransformMatrixCount] = {0};
- CopyColorTransformMatrix(matrix, color_matrix);
-
- DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix);
+ double color_matrix_restore[kColorTransformMatrixCount] = {0};
+ CopyColorTransformMatrix(color_matrix_, color_matrix_restore);
+ CopyColorTransformMatrix(matrix, color_matrix_);
+ DisplayError error =
+ display_intf_->SetColorTransform(kColorTransformMatrixCount, PickTransferMatrix());
if (error != kErrorNone) {
+ CopyColorTransformMatrix(color_matrix_restore, color_matrix_);
DLOGE("Failed to set Color Transform Matrix");
status = HWC2::Error::Unsupported;
}
- CopyColorTransformMatrix(matrix, color_matrix_);
+
return status;
}
@@ -310,13 +522,23 @@ void HWCColorMode::Dump(std::ostringstream* os) {
}
*os << "current mode: " << static_cast<uint32_t>(current_color_mode_) << std::endl;
*os << "current render_intent: " << static_cast<uint32_t>(current_render_intent_) << std::endl;
+ *os << "Need WhiteCompensation: "
+ << (current_render_intent_ == RenderIntent::ENHANCE && HasWhiteCompensation()) << std::endl;
+ *os << "Need SaturationCompensation: "
+ << (current_render_intent_ == RenderIntent::ENHANCE && HasSaturationCompensation())
+ << std::endl;
+
*os << "current transform: ";
+ double color_matrix[kColorTransformMatrixCount] = {0};
+
+ CopyColorTransformMatrix(PickTransferMatrix(), color_matrix);
+
for (uint32_t i = 0; i < kColorTransformMatrixCount; i++) {
if (i % 4 == 0) {
*os << std::endl;
}
- *os << std::fixed << std::setprecision(2) << std::setw(6) << std::setfill(' ')
- << color_matrix_[i] << " ";
+ *os << std::fixed << std::setprecision(4) << std::setw(8) << std::setfill(' ')
+ << color_matrix[i] << " ";
}
*os << std::endl;
}
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 3b46f5ac..0d3520a8 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -47,6 +47,7 @@ namespace sdm {
class BlitEngine;
class HWCToneMapper;
+constexpr uint32_t kColorTransformMatrixCount = 16;
// Subclasses set this to their type. This has to be different from DisplayType.
// This is to avoid RTTI and dynamic_cast
@@ -57,6 +58,103 @@ enum DisplayClass {
DISPLAY_CLASS_NULL
};
+class HWCColorMatrix {
+ public:
+ HWCColorMatrix(const string &values) : key_values_(values){};
+ virtual ~HWCColorMatrix() = default;
+ virtual HWC2::Error SetEnabled(bool enabled);
+ bool GetEnabled() const { return enabled_; }
+ // Apply effect to input matrix
+ virtual void ApplyToMatrix(double *in) = 0;
+ bool ParseFloatValueByCommas(const string &values, uint32_t length,
+ std::vector<float> &elements) const;
+
+ protected:
+ bool enabled_ = false;
+ const string key_values_;
+};
+
+class WhiteCompensation : public HWCColorMatrix {
+ public:
+ WhiteCompensation(const string &values) : HWCColorMatrix(values){};
+ int GetCompensatedRed() const { return compensated_red_; }
+ int GetCompensatedGreen() const { return compensated_green_; }
+ int GetCompensatedBlue() const { return compensated_blue_; }
+ HWC2::Error SetEnabled(bool enabled) override;
+ /*
+ * Transform matrix is 4 x 4
+ * |r.r r.g r.b 0|
+ * |g.r g.g g.b 0|
+ * |b.r b.g b.b 0|
+ * |T.r T.g T.b 1|
+ * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
+ * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
+ * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
+ *
+ * Cr, Cg, Cb for white point compensation
+ * |r.r*Cr r.g*Cg r.b*Cb 0|
+ * |g.r*Cr g.g*Cg g.b*Cb 0|
+ * |b.r*Cr b.g*Cg b.b*Cb 0|
+ * |T.r*Cr T.g*Cg T.b*Cb 1|
+ * R_out = R_in * r.r * Cr + G_in * g.r * Cr + B_in * b.r * Cr + Tr * Cr
+ * G_out = R_in * r.g * Cg + G_in * g.g * Cg + B_in * b.g * Cg + Tg * Cg
+ * B_out = R_in * r.b * Cb + G_in * g.b * Cb + B_in * b.b * Cb + Tb * Cb
+ */
+ void ApplyToMatrix(double *in) override;
+
+ private:
+ static constexpr int kCompensatedMaxRGB = 255;
+ static constexpr int kCompensatedMinRGB = 230;
+ static constexpr int kNumOfCompensationData = 3;
+ int compensated_red_ = kCompensatedMaxRGB;
+ int compensated_green_ = kCompensatedMaxRGB;
+ int compensated_blue_ = kCompensatedMaxRGB;
+
+ double compensated_red_ratio_ = 1.0;
+ double compensated_green_ratio_ = 1.0;
+ double compensated_blue_ratio_ = 1.0;
+
+ static constexpr int kCoefficientElements = 9;
+ float white_compensated_Coefficients_[kCoefficientElements] = {0.0, 1.0, 0.0, 0.0, 1.0,
+ 0.0, 0.0, 1.0, 0.0};
+ bool ConfigCoefficients();
+ bool ParseWhitePointCalibrationData();
+ inline static constexpr bool CheckCompensatedRGB(int value) {
+ return ((value >= kCompensatedMinRGB) && (value <= kCompensatedMaxRGB));
+ }
+ void CalculateRGBRatio();
+};
+
+class SaturationCompensation : public HWCColorMatrix {
+ public:
+ SaturationCompensation(const string &values) : HWCColorMatrix(values){};
+ HWC2::Error SetEnabled(bool enabled) override;
+ /* Saturated matrix is 4 x 4
+ * | s0 s1 s2 s3|
+ * | s4 s5 s6 s7|
+ * | s8 s9 s10 s11|
+ * | s12 s13 s14 s15|
+ * Transform matrix is 4 x 4
+ * |a0 a1 a2 a3|
+ * |a4 a5 a6 a7|
+ * |a8 a9 a10 a11|
+ * |a12 a13 a14 a15|
+ *
+ * Saturated matrix[] X Transform matrix[]
+ */
+ void ApplyToMatrix(double *in) override;
+
+ private:
+ static constexpr int kSaturationParameters = 9;
+ static constexpr int kNumOfRows = 4;
+ static constexpr int kColumnsPerRow = 4;
+ static_assert(kNumOfRows * kColumnsPerRow == kColorTransformMatrixCount,
+ "Rows x Columns should be equal to matrix count");
+ float saturated_matrix_[kColorTransformMatrixCount] = {1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0};
+ bool ConfigSaturationParameter();
+};
+
class HWCColorMode {
public:
explicit HWCColorMode(DisplayInterface *display_intf);
@@ -74,9 +172,9 @@ class HWCColorMode {
HWC2::Error RestoreColorTransform();
PrimariesTransfer GetWorkingColorSpace();
ColorMode GetCurrentColorMode() { return current_color_mode_; }
+ HWC2::Error SetWhiteCompensation(bool enabled);
private:
- static const uint32_t kColorTransformMatrixCount = 16;
void PopulateColorModes();
void FindRenderIntent(const ColorMode &mode, const std::string &mode_string);
template <class T>
@@ -98,6 +196,19 @@ class HWCColorMode {
0.0, 1.0, 0.0, 0.0, \
0.0, 0.0, 1.0, 0.0, \
0.0, 0.0, 0.0, 1.0 };
+ void InitColorCompensation();
+ std::unique_ptr<WhiteCompensation> adaptive_white_;
+ std::unique_ptr<SaturationCompensation> adaptive_saturation_;
+ double compensated_color_matrix_[kColorTransformMatrixCount] = { 1.0, 0.0, 0.0, 0.0, \
+ 0.0, 1.0, 0.0, 0.0, \
+ 0.0, 0.0, 1.0, 0.0, \
+ 0.0, 0.0, 0.0, 1.0 };
+ bool HasWhiteCompensation() { return (adaptive_white_ && adaptive_white_->GetEnabled()); }
+ bool HasSaturationCompensation() {
+ return (adaptive_saturation_ && adaptive_saturation_->GetEnabled());
+ }
+
+ const double *PickTransferMatrix();
};
class HWCDisplay : public DisplayEventHandler {
@@ -203,6 +314,7 @@ class HWCDisplay : public DisplayEventHandler {
virtual HWC2::Error SetClientTarget(buffer_handle_t target, int32_t acquire_fence,
int32_t dataspace, hwc_region_t damage);
virtual HWC2::Error SetColorMode(ColorMode mode) { return HWC2::Error::Unsupported; }
+ virtual HWC2::Error SetWhiteCompensation(bool enabled) { return HWC2::Error::Unsupported; }
virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
return HWC2::Error::Unsupported;
}
diff --git a/sdm/libs/hwc2/hwc_display_primary.cpp b/sdm/libs/hwc2/hwc_display_primary.cpp
index 6b7b7dd2..ac8d12a4 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -372,6 +372,18 @@ HWC2::Error HWCDisplayPrimary::SetColorMode(ColorMode mode) {
return SetColorModeWithRenderIntent(mode, RenderIntent::COLORIMETRIC);
}
+HWC2::Error HWCDisplayPrimary::SetWhiteCompensation(bool enabled) {
+ auto status = color_mode_->SetWhiteCompensation(enabled);
+ if (status != HWC2::Error::None) {
+ DLOGE("failed for SetWhiteCompensation to %d", enabled);
+ return status;
+ }
+
+ callbacks_->Refresh(HWC_DISPLAY_PRIMARY);
+
+ return status;
+}
+
HWC2::Error HWCDisplayPrimary::SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent) {
auto status = color_mode_->SetColorModeWithRenderIntent(mode, intent);
if (status != HWC2::Error::None) {
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index 332a2a3d..69a8522c 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -61,6 +61,7 @@ class HWCDisplayPrimary : public HWCDisplay {
virtual HWC2::Error Present(int32_t *out_retire_fence);
virtual HWC2::Error GetColorModes(uint32_t *out_num_modes, ColorMode *out_modes);
virtual HWC2::Error SetColorMode(ColorMode mode);
+ virtual HWC2::Error SetWhiteCompensation(bool enabled);
virtual HWC2::Error GetRenderIntents(ColorMode mode, uint32_t *out_num_intents,
RenderIntent *out_intents);
virtual HWC2::Error SetColorModeWithRenderIntent(ColorMode mode, RenderIntent intent);
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 3b13681b..911df97d 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1491,6 +1491,13 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa
status = setColorSamplingEnabled(input_parcel);
break;
+ case qService::IQService::SET_WHITE_COMPENSATION:
+ if (!input_parcel) {
+ DLOGE("QService command = %d: input_parcel needed.", command);
+ break;
+ }
+ status = SetWhiteCompensation(input_parcel);
+ break;
default:
DLOGW("QService command = %d is not supported.", command);
break;
@@ -1706,6 +1713,18 @@ android::status_t HWCSession::SetColorModeOverride(const android::Parcel *input_
return 0;
}
+android::status_t HWCSession::SetWhiteCompensation(const android::Parcel *input_parcel) {
+ auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
+ auto enabled = static_cast<bool>(input_parcel->readInt32());
+ auto device = static_cast<hwc2_device_t *>(this);
+
+ auto err = CallDisplayFunction(device, display, &HWCDisplay::SetWhiteCompensation, enabled);
+ if (err != HWC2_ERROR_NONE)
+ return -EINVAL;
+
+ return 0;
+}
+
android::status_t HWCSession::SetColorModeWithRenderIntentOverride(
const android::Parcel *input_parcel) {
auto display = static_cast<hwc2_display_t>(input_parcel->readInt32());
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 52ae7e83..ea187bcf 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -277,6 +277,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
android::status_t SetMixerResolution(const android::Parcel *input_parcel);
android::status_t SetColorModeOverride(const android::Parcel *input_parcel);
android::status_t SetColorModeWithRenderIntentOverride(const android::Parcel *input_parcel);
+ android::status_t SetWhiteCompensation(const android::Parcel *input_parcel);
android::status_t SetColorModeById(const android::Parcel *input_parcel);
android::status_t getComposerStatus();