diff options
Diffstat (limited to 'sdm/libs/hwc2/hwc_display.cpp')
-rw-r--r-- | sdm/libs/hwc2/hwc_display.cpp | 278 |
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 |