summaryrefslogtreecommitdiff
path: root/sdm/libs/hwc2/hwc_display.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sdm/libs/hwc2/hwc_display.cpp')
-rw-r--r--sdm/libs/hwc2/hwc_display.cpp278
1 files changed, 265 insertions, 13 deletions
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index b8cb6e71..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();
}
@@ -79,7 +80,6 @@ HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes, ColorMode *out_
*out_num_modes = std::min(*out_num_modes, UINT32(color_mode_map_.size()));
for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
out_modes[i] = it->first;
- DLOGI("Color mode = %d is supported", out_modes[i]);
}
return HWC2::Error::None;
}
@@ -93,7 +93,6 @@ HWC2::Error HWCColorMode::GetRenderIntents(ColorMode mode, uint32_t *out_num_int
*out_num_intents = std::min(*out_num_intents, UINT32(color_mode_map_[mode].size()));
for (uint32_t i = 0; i < *out_num_intents; it++, i++) {
out_intents[i] = it->first;
- DLOGI("Color mode = %d is supported with render intent = %d", mode, out_intents[i]);
}
return HWC2::Error::None;
}
@@ -121,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;
@@ -142,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;
@@ -151,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;
}
@@ -312,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;
}
@@ -377,7 +597,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_);
@@ -1792,11 +2012,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;
@@ -2172,6 +2396,31 @@ HWC2::Error HWCDisplay::GetValidateDisplayOutput(uint32_t *out_num_types,
return ((*out_num_types > 0) ? HWC2::Error::HasChanges : HWC2::Error::None);
}
+HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabledVndService(bool enabled) {
+ return HWC2::Error::Unsupported;
+}
+
+HWC2::Error HWCDisplay::SetDisplayedContentSamplingEnabled(int32_t enabled,
+ uint8_t component_mask, uint64_t max_frames) {
+
+ DLOGV("Request to start/stop histogram thread not supported on this display");
+ return HWC2::Error::Unsupported;
+}
+
+HWC2::Error HWCDisplay::GetDisplayedContentSamplingAttributes(int32_t* format,
+ int32_t* dataspace,
+ uint8_t* supported_components) {
+ return HWC2::Error::Unsupported;
+}
+
+HWC2::Error HWCDisplay::GetDisplayedContentSample(uint64_t max_frames,
+ uint64_t timestamp,
+ uint64_t* numFrames,
+ int32_t samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
+ uint64_t* samples[NUM_HISTOGRAM_COLOR_COMPONENTS]) {
+ return HWC2::Error::Unsupported;
+}
+
void HWCDisplay::UpdateRefreshRate() {
for (auto hwc_layer : layer_set_) {
if (hwc_layer->HasMetaDataRefreshRate()) {
@@ -2180,6 +2429,9 @@ void HWCDisplay::UpdateRefreshRate() {
auto layer = hwc_layer->GetSDMLayer();
layer->frame_rate = current_refresh_rate_;
}
+
+ Layer *sdm_client_target = client_target_->GetSDMLayer();
+ sdm_client_target->frame_rate = current_refresh_rate_;
}
// Skip SDM prepare if all the layers in the current draw cycle are marked as Skip and