summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-05-07 21:44:22 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-05-07 21:44:22 +0000
commitbd4db00c91a14ea924ba017c176af4b7e86c430c (patch)
tree510a7cd442886bab031399a963112a3ba72a5649
parentf232a1224e1a8404e294acfcc2f0551e81852bce (diff)
parent71b5571bcbd349571e7bfb18e68d702f055c8f61 (diff)
downloaddisplay-pie-platform-release.tar.gz
Snap for 5450365 from 71b5571bcbd349571e7bfb18e68d702f055c8f61 to pi-platform-releasepie-platform-release
Change-Id: I51993d92b44a8c195616eec1affa7b0dbaee3dde
-rw-r--r--gralloc/gr_buf_mgr.cpp1
-rw-r--r--include/display_properties.h2
-rw-r--r--libqservice/IQService.h1
-rw-r--r--sdm/libs/core/display_base.cpp1
-rw-r--r--sdm/libs/core/drm/hw_device_drm.cpp6
-rw-r--r--sdm/libs/core/drm/hw_device_drm.h1
-rw-r--r--sdm/libs/core/drm/hw_peripheral_drm.cpp13
-rw-r--r--sdm/libs/hwc2/hwc_display.cpp247
-rw-r--r--sdm/libs/hwc2/hwc_display.h113
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.cpp18
-rw-r--r--sdm/libs/hwc2/hwc_display_primary.h1
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp20
-rw-r--r--sdm/libs/hwc2/hwc_session.h1
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp8
14 files changed, 412 insertions, 21 deletions
diff --git a/gralloc/gr_buf_mgr.cpp b/gralloc/gr_buf_mgr.cpp
index c8309525..985dd3ef 100644
--- a/gralloc/gr_buf_mgr.cpp
+++ b/gralloc/gr_buf_mgr.cpp
@@ -376,6 +376,7 @@ Error BufferManager::AllocateBuffer(const BufferDescriptor &descriptor, buffer_h
}
Error BufferManager::Dump(std::ostringstream *os) {
+ std::lock_guard<std::mutex> buffer_lock(buffer_lock_);
for (auto it : handles_map_) {
auto buf = it.second;
auto hnd = buf->handle;
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 b2012560..e9af5a17 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -79,6 +79,7 @@ public:
GET_COMPOSER_STATUS = 37, // Get composer init status-true if primary display init is done
SET_COLOR_MODE_WITH_RENDER_INTENT = 38,
SET_IDLE_PC = 39, // Enable/disable Idle power collapse
+ SET_WHITE_POINT_COMPENSATION = 399, // Enable/disable white point compensation
COMMAND_LIST_END = 400,
};
diff --git a/sdm/libs/core/display_base.cpp b/sdm/libs/core/display_base.cpp
index 67f7ac83..e5f61c15 100644
--- a/sdm/libs/core/display_base.cpp
+++ b/sdm/libs/core/display_base.cpp
@@ -1299,6 +1299,7 @@ void DisplayBase::CommitLayerParams(LayerStack *layer_stack) {
hw_layer.input_buffer.size = sdm_layer->input_buffer.size;
hw_layer.input_buffer.acquire_fence_fd = sdm_layer->input_buffer.acquire_fence_fd;
hw_layer.input_buffer.handle_id = sdm_layer->input_buffer.handle_id;
+ hw_layer.input_buffer.buffer_id = sdm_layer->input_buffer.buffer_id;
}
return;
diff --git a/sdm/libs/core/drm/hw_device_drm.cpp b/sdm/libs/core/drm/hw_device_drm.cpp
index 627e0080..40e0b220 100644
--- a/sdm/libs/core/drm/hw_device_drm.cpp
+++ b/sdm/libs/core/drm/hw_device_drm.cpp
@@ -1047,6 +1047,11 @@ void HWDeviceDRM::SetSolidfillStages() {
}
}
+void HWDeviceDRM::ClearSolidfillStages() {
+ solid_fills_.clear();
+ SetSolidfillStages();
+}
+
DisplayError HWDeviceDRM::Validate(HWLayers *hw_layers) {
DTRACE_SCOPED();
@@ -1184,6 +1189,7 @@ DisplayError HWDeviceDRM::AtomicCommit(HWLayers *hw_layers) {
DisplayError HWDeviceDRM::Flush() {
DTRACE_SCOPED();
+ ClearSolidfillStages();
int ret = drm_atomic_intf_->Commit(false /* synchronous */, false /* retain_planes*/);
if (ret) {
DLOGE("failed with error %d", ret);
diff --git a/sdm/libs/core/drm/hw_device_drm.h b/sdm/libs/core/drm/hw_device_drm.h
index 63853c4a..c4f06c35 100644
--- a/sdm/libs/core/drm/hw_device_drm.h
+++ b/sdm/libs/core/drm/hw_device_drm.h
@@ -126,6 +126,7 @@ class HWDeviceDRM : public HWInterface {
void UpdateMixerAttributes();
void SetSolidfillStages();
void AddSolidfillStage(const HWSolidfillStage &sf, uint32_t plane_alpha);
+ void ClearSolidfillStages();
void SetBlending(const LayerBlending &source, sde_drm::DRMBlendType *target);
void SetSrcConfig(const LayerBuffer &input_buffer, const HWRotatorMode &mode, uint32_t *config);
void SelectCscType(const LayerBuffer &input_buffer, sde_drm::DRMCscType *type);
diff --git a/sdm/libs/core/drm/hw_peripheral_drm.cpp b/sdm/libs/core/drm/hw_peripheral_drm.cpp
index 03403e5a..e4da1081 100644
--- a/sdm/libs/core/drm/hw_peripheral_drm.cpp
+++ b/sdm/libs/core/drm/hw_peripheral_drm.cpp
@@ -165,6 +165,13 @@ void HWPeripheralDRM::SetupConcurrentWriteback(const HWLayersInfo &hw_layer_info
if (enable) {
// Set DRM properties for Concurrent Writeback.
ConfigureConcurrentWriteback(hw_layer_info.stack);
+
+ if (!validate) {
+ // Set GET_RETIRE_FENCE property to get Concurrent Writeback fence.
+ int *fence = &hw_layer_info.stack->output_buffer->release_fence_fd;
+ drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE,
+ cwb_config_.token.conn_id, fence);
+ }
} else {
// Tear down the Concurrent Writeback topology.
drm_atomic_intf_->Perform(DRMOps::CONNECTOR_SET_CRTC, cwb_config_.token.conn_id, 0);
@@ -239,11 +246,7 @@ void HWPeripheralDRM::ConfigureConcurrentWriteback(LayerStack *layer_stack) {
void HWPeripheralDRM::PostCommitConcurrentWriteback(LayerBuffer *output_buffer) {
bool enabled = hw_resource_.has_concurrent_writeback && output_buffer;
- if (enabled) {
- // Get Concurrent Writeback fence
- int *fence = &output_buffer->release_fence_fd;
- drm_atomic_intf_->Perform(DRMOps::CONNECTOR_GET_RETIRE_FENCE, cwb_config_.token.conn_id, fence);
- } else {
+ if (!enabled) {
drm_mgr_intf_->UnregisterDisplay(cwb_config_.token);
cwb_config_.enabled = false;
}
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index f06de99f..5940dc2c 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();
}
@@ -121,11 +122,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;
@@ -142,7 +145,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;
@@ -151,19 +155,228 @@ 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 Point 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() || !ParseWhiteCompensatedData()) {
+ enabled_ = false;
+ DLOGE("Failed to WhiteCompensation Set");
+ return HWC2::Error::NotValidated;
+ }
+ CalculateRGBRatio();
+ }
+ enabled_ = enabled;
+ return HWC2::Error::None;
+}
+
+bool WhiteCompensation::ParseWhiteCompensatedData() {
+ static constexpr char kWhitePointCalibrationDataPath[] = "/persist/display/calibrated_rgb";
+ FILE *fp = fopen(kWhitePointCalibrationDataPath, "r");
+ int ret;
+
+ if (!fp) {
+ DLOGW("Failed to open white compensated 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("Failed to get white compensated data");
+ 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);
+ double color_matrix_restore[kColorTransformMatrixCount] = {0};
+ CopyColorTransformMatrix(color_matrix_, color_matrix_restore);
- DisplayError error = display_intf_->SetColorTransform(kColorTransformMatrixCount, color_matrix);
+ 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;
}
@@ -312,13 +525,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;
}
@@ -377,7 +600,7 @@ int HWCDisplay::Init() {
DisplayConfigFixedInfo fixed_info = {};
display_intf_->GetConfig(&fixed_info);
- partial_update_enabled_ = fixed_info.partial_update;
+ partial_update_enabled_ = fixed_info.partial_update || (!fixed_info.is_cmdmode);
client_target_->SetPartialUpdate(partial_update_enabled_);
DLOGI("Display created with id: %d", id_);
@@ -1784,11 +2007,15 @@ int HWCDisplay::SetDisplayStatus(DisplayStatus display_status) {
switch (display_status) {
case kDisplayStatusResume:
display_paused_ = false;
+ status = INT32(SetPowerMode(HWC2::PowerMode::On));
+ break;
case kDisplayStatusOnline:
status = INT32(SetPowerMode(HWC2::PowerMode::On));
break;
case kDisplayStatusPause:
display_paused_ = true;
+ status = INT32(SetPowerMode(HWC2::PowerMode::Off));
+ break;
case kDisplayStatusOffline:
status = INT32(SetPowerMode(HWC2::PowerMode::Off));
break;
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index 49406785..4523cb58 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -46,6 +46,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
@@ -56,6 +57,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 ParseWhiteCompensatedData();
+ 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);
@@ -73,9 +171,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>
@@ -97,6 +195,18 @@ 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 {
@@ -202,6 +312,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 1a6944b2..4d70d7fa 100644
--- a/sdm/libs/hwc2/hwc_display_primary.cpp
+++ b/sdm/libs/hwc2/hwc_display_primary.cpp
@@ -73,6 +73,10 @@ void HWCDisplayPrimary::PMICInterface::Deinit() {
DisplayError HWCDisplayPrimary::PMICInterface::Notify(bool secure_display_start) {
std::string str_sd_start = secure_display_start ? std::to_string(1) : std::to_string(0);
+ if (fd_lcd_bias_ < 0 || fd_wled_ < 0) {
+ DLOGI("Ignore notify because fd_lcd_bias_ or fd_wled_ open failed");
+ return kErrorNotSupported;
+ }
ssize_t err = ::pwrite(fd_lcd_bias_, str_sd_start.c_str(), str_sd_start.length(), 0);
if (err <= 0) {
DLOGE("Write failed for lcd_bias, Error = %s", strerror(errno));
@@ -256,6 +260,7 @@ HWC2::Error HWCDisplayPrimary::Validate(uint32_t *out_num_types, uint32_t *out_n
// here in a subsequent draw round. Readback is not allowed for any secure use case.
readback_configured_ = !layer_stack_.flags.secure_present;
if (readback_configured_) {
+ DisablePartialUpdateOneFrame();
layer_stack_.output_buffer = &output_buffer_;
layer_stack_.flags.post_processed_output = post_processed_output_;
}
@@ -338,6 +343,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) {
@@ -422,7 +439,6 @@ HWC2::Error HWCDisplayPrimary::SetReadbackBuffer(const native_handle_t *buffer,
readback_configured_ = false;
validated_ = false;
- DisablePartialUpdateOneFrame();
return HWC2::Error::None;
}
diff --git a/sdm/libs/hwc2/hwc_display_primary.h b/sdm/libs/hwc2/hwc_display_primary.h
index 40f0f489..0794b94a 100644
--- a/sdm/libs/hwc2/hwc_display_primary.h
+++ b/sdm/libs/hwc2/hwc_display_primary.h
@@ -58,6 +58,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 e4404648..570e0fe3 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -1355,6 +1355,14 @@ android::status_t HWCSession::notifyCallback(uint32_t command, const android::Pa
status = SetIdlePC(input_parcel);
break;
+ case qService::IQService::SET_WHITE_POINT_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;
@@ -1551,6 +1559,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 5b94b572..6271e61d 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -271,6 +271,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();
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index 519346f0..90ed00b4 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -524,8 +524,8 @@ Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchrono
if (!idle_pc_ref_cnt_) {
HWC2::Error err =
hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
- if (err != HWC2::Error::None) {
- return -EINVAL;
+ if (err == HWC2::Error::Unsupported) {
+ return 0;
}
Refresh(HWC_DISPLAY_PRIMARY);
int32_t error = locker_[HWC_DISPLAY_PRIMARY].WaitFinite(kCommitDoneTimeoutMs);
@@ -540,8 +540,8 @@ Return<int32_t> HWCSession::controlIdlePowerCollapse(bool enable, bool synchrono
if (!(idle_pc_ref_cnt_ - 1)) {
HWC2::Error err =
hwc_display_[HWC_DISPLAY_PRIMARY]->ControlIdlePowerCollapse(enable, synchronous);
- if (err != HWC2::Error::None) {
- return -EINVAL;
+ if (err == HWC2::Error::Unsupported) {
+ return 0;
}
DLOGI("Idle PC enabled!!");
}