summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlinpeter <linpeter@google.com>2019-03-14 15:26:08 +0800
committerPeter Lin <linpeter@google.com>2019-04-08 04:06:01 +0000
commit729e1071df20e964d3bf310134e887ecddf084d2 (patch)
tree1cae3bb6b014a3f6da8e2a29b1a66bfb38df027d
parent57ae6067fa315aa05fb3abf019a9e6ca8d509d19 (diff)
downloadandroid_hardware_qcom_sdm845_display-729e1071df20e964d3bf310134e887ecddf084d2.tar.gz
android_hardware_qcom_sdm845_display-729e1071df20e964d3bf310134e887ecddf084d2.tar.bz2
android_hardware_qcom_sdm845_display-729e1071df20e964d3bf310134e887ecddf084d2.zip
hwc2: Add color compensation feature for adaptive color mode
Using transfer matrix to do color compensation for adaptive color mode. Feature provides white compensation and saturation compensation. It configured by property vendor.display.adaptive_white_coefficient and vendor.display.adaptive_saturation_parameter. In addition, white compentation needs device calibraiton data (persist/display/calibrated_rgb) to calulate compensated value. And it has interface command to enable/disable. adb shell vndservice call display.qservice 201 i32 0 i32 1 Bug: 121231574 Bug: 116282483 Bug: 123483411 Test: Switch mode test and check dumpsys information (Need WhiteCompensation, Need SaturationCompensation, current transform) Change-Id: I5e1aabc31ffdd25172049f745ea4c74b7db02454
-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();