diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-05-07 21:44:22 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-05-07 21:44:22 +0000 |
commit | bd4db00c91a14ea924ba017c176af4b7e86c430c (patch) | |
tree | 510a7cd442886bab031399a963112a3ba72a5649 | |
parent | f232a1224e1a8404e294acfcc2f0551e81852bce (diff) | |
parent | 71b5571bcbd349571e7bfb18e68d702f055c8f61 (diff) | |
download | display-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.cpp | 1 | ||||
-rw-r--r-- | include/display_properties.h | 2 | ||||
-rw-r--r-- | libqservice/IQService.h | 1 | ||||
-rw-r--r-- | sdm/libs/core/display_base.cpp | 1 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_device_drm.cpp | 6 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_device_drm.h | 1 | ||||
-rw-r--r-- | sdm/libs/core/drm/hw_peripheral_drm.cpp | 13 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display.cpp | 247 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display.h | 113 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_primary.cpp | 18 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_display_primary.h | 1 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.cpp | 20 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session.h | 1 | ||||
-rw-r--r-- | sdm/libs/hwc2/hwc_session_services.cpp | 8 |
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!!"); } |