sdm: Add support to defer Fps config
On Builtin display, add support to defer Fps (Transfer time) config
to Comp Manager until number of frames, configured with Vendor properties.
CRs-Fixed: 2472355
Change-Id: Ie314136878b5ec15bfafa629b9a89643cf094d49
diff --git a/include/display_properties.h b/include/display_properties.h
index 5096591..06ab31d 100644
--- a/include/display_properties.h
+++ b/include/display_properties.h
@@ -129,5 +129,6 @@
#define DISABLE_UI_3D_TONEMAP DISPLAY_PROP("disable_ui_3d_tonemap")
#define DISABLE_PARALLEL_CACHE DISPLAY_PROP("disable_parallel_cache")
#define ENABLE_FORCE_SPLIT DISPLAY_PROP("enable_force_split")
+#define DEFER_FPS_FRAME_COUNT DISPLAY_PROP("defer_fps_frame_count")
#endif // __DISPLAY_PROPERTIES_H__
diff --git a/sdm/include/core/display_interface.h b/sdm/include/core/display_interface.h
index d7dabf6..43aa2d8 100644
--- a/sdm/include/core/display_interface.h
+++ b/sdm/include/core/display_interface.h
@@ -147,6 +147,7 @@
kIdlePowerCollapse, // Event triggered by Idle Power Collapse.
kPanelDeadEvent, // Event triggered by ESD.
kDisplayPowerResetEvent, // Event triggered by Hardware Recovery.
+ kInvalidateDisplay, // Event triggered to Invalidate display.
};
/*! @brief This enum represents the secure events received by Display HAL. */
diff --git a/sdm/libs/core/display_base.h b/sdm/libs/core/display_base.h
index 8c77e43..9981e77 100644
--- a/sdm/libs/core/display_base.h
+++ b/sdm/libs/core/display_base.h
@@ -151,6 +151,7 @@
uint8_t *out_data);
virtual bool CanSkipValidate();
virtual DisplayError GetRefreshRate(uint32_t *refresh_rate) { return kErrorNotSupported; }
+ virtual DisplayError ReconfigureDisplay();
protected:
const char *kBt2020Pq = "bt2020_pq";
@@ -164,7 +165,6 @@
void HwRecovery(const HWRecoveryEvent sdm_event_code);
const char *GetName(const LayerComposition &composition);
- DisplayError ReconfigureDisplay();
bool NeedsMixerReconfiguration(LayerStack *layer_stack, uint32_t *new_mixer_width,
uint32_t *new_mixer_height);
DisplayError ReconfigureMixer(uint32_t width, uint32_t height);
diff --git a/sdm/libs/core/display_builtin.cpp b/sdm/libs/core/display_builtin.cpp
index 57cf70b..eaed45b 100644
--- a/sdm/libs/core/display_builtin.cpp
+++ b/sdm/libs/core/display_builtin.cpp
@@ -117,9 +117,12 @@
Debug::GetProperty(DISABLE_DEFER_POWER_STATE, &disable_defer_power_state);
defer_power_state_ = !disable_defer_power_state;
-
DLOGI("defer_power_state %d", defer_power_state_);
+ int value = 0;
+ Debug::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &value);
+ deferred_config_.frame_count = (value > 0) ? UINT32(value) : 0;
+
return error;
}
@@ -227,7 +230,14 @@
dpps_info_.DppsNotifyOps(kDppsCommitEvent, &display_type_, sizeof(display_type_));
}
- DisplayBase::ReconfigureDisplay();
+ deferred_config_.UpdateDeferCount();
+
+ ReconfigureDisplay();
+
+ if (deferred_config_.CanApplyDeferredState()) {
+ event_handler_->HandleEvent(kInvalidateDisplay);
+ deferred_config_.Clear();
+ }
int idle_time_ms = hw_layers_.info.set_idle_time_ms;
if (idle_time_ms >= 0) {
@@ -265,6 +275,11 @@
int *release_fence) {
lock_guard<recursive_mutex> obj(recursive_mutex_);
DisplayError error = kErrorNone;
+
+ if ((state == kStateOn) && deferred_config_.IsDeferredState()) {
+ SetDeferredFpsConfig();
+ }
+
error = DisplayBase::SetDisplayState(state, teardown, release_fence);
if (error != kErrorNone) {
return error;
@@ -391,8 +406,9 @@
// On success, set current refresh rate to new refresh rate
current_refresh_rate_ = refresh_rate;
handle_idle_timeout_ = false;
+ deferred_config_.MarkDirty();
- return DisplayBase::ReconfigureDisplay();
+ return ReconfigureDisplay();
}
DisplayError DisplayBuiltIn::VSync(int64_t timestamp) {
@@ -778,4 +794,119 @@
return kErrorNone;
}
+DisplayError DisplayBuiltIn::SetActiveConfig(uint32_t index) {
+ deferred_config_.MarkDirty();
+ return DisplayBase::SetActiveConfig(index);
+}
+
+DisplayError DisplayBuiltIn::ReconfigureDisplay() {
+ lock_guard<recursive_mutex> obj(recursive_mutex_);
+ DisplayError error = kErrorNone;
+ HWDisplayAttributes display_attributes;
+ HWMixerAttributes mixer_attributes;
+ HWPanelInfo hw_panel_info;
+ uint32_t active_index = 0;
+
+ DTRACE_SCOPED();
+
+ error = hw_intf_->GetActiveConfig(&active_index);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetDisplayAttributes(active_index, &display_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetMixerAttributes(&mixer_attributes);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ error = hw_intf_->GetHWPanelInfo(&hw_panel_info);
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ const bool dirty = deferred_config_.IsDirty();
+ if (deferred_config_.IsDeferredState()) {
+ if (dirty) {
+ SetDeferredFpsConfig();
+ } else {
+ // In Deferred state, use current config for comparison.
+ GetFpsConfig(&display_attributes, &hw_panel_info);
+ }
+ }
+
+ const bool display_unchanged = (display_attributes == display_attributes_);
+ const bool mixer_unchanged = (mixer_attributes == mixer_attributes_);
+ const bool panel_unchanged = (hw_panel_info == hw_panel_info_);
+ if (!dirty && display_unchanged && mixer_unchanged && panel_unchanged) {
+ return kErrorNone;
+ }
+
+ if (CanDeferFpsConfig(display_attributes.fps)) {
+ deferred_config_.Init(display_attributes.fps, display_attributes.vsync_period_ns,
+ hw_panel_info.transfer_time_us);
+
+ // Apply current config until new Fps is deferred.
+ GetFpsConfig(&display_attributes, &hw_panel_info);
+ }
+
+ error = comp_manager_->ReconfigureDisplay(display_comp_ctx_, display_attributes, hw_panel_info,
+ mixer_attributes, fb_config_,
+ &(default_qos_data_.clock_hz));
+ if (error != kErrorNone) {
+ return error;
+ }
+
+ bool disble_pu = true;
+ if (mixer_unchanged && panel_unchanged) {
+ // Do not disable Partial Update for one frame, if only FPS has changed.
+ // Because if first frame after transition, has a partial Frame-ROI and
+ // is followed by Skip Validate frames, then it can benefit those frames.
+ disble_pu = !display_attributes_.OnlyFpsChanged(display_attributes);
+ }
+
+ if (disble_pu) {
+ DisablePartialUpdateOneFrame();
+ }
+
+ display_attributes_ = display_attributes;
+ mixer_attributes_ = mixer_attributes;
+ hw_panel_info_ = hw_panel_info;
+
+ // TODO(user): Temporary changes, to be removed when DRM driver supports
+ // Partial update with Destination scaler enabled.
+ SetPUonDestScaler();
+
+ return kErrorNone;
+}
+
+bool DisplayBuiltIn::CanDeferFpsConfig(uint32_t fps) {
+ if (deferred_config_.CanApplyDeferredState()) {
+ // Deferred Fps Config needs to be applied.
+ return false;
+ }
+
+ // In case of higher to lower Fps transition on a Builtin display, defer the Fps
+ // (Transfer time) configuration, for the number of frames based on frame_count.
+ return ((deferred_config_.frame_count != 0) && (display_attributes_.fps > fps));
+}
+
+void DisplayBuiltIn::SetDeferredFpsConfig() {
+ // Update with the deferred Fps Config.
+ display_attributes_.fps = deferred_config_.fps;
+ display_attributes_.vsync_period_ns = deferred_config_.vsync_period_ns;
+ hw_panel_info_.transfer_time_us = deferred_config_.transfer_time_us;
+ deferred_config_.Clear();
+}
+
+void DisplayBuiltIn::GetFpsConfig(HWDisplayAttributes *display_attr, HWPanelInfo *panel_info) {
+ display_attr->fps = display_attributes_.fps;
+ display_attr->vsync_period_ns = display_attributes_.vsync_period_ns;
+ panel_info->transfer_time_us = hw_panel_info_.transfer_time_us;
+}
+
} // namespace sdm
diff --git a/sdm/libs/core/display_builtin.h b/sdm/libs/core/display_builtin.h
index 1de4b23..6dd8305 100644
--- a/sdm/libs/core/display_builtin.h
+++ b/sdm/libs/core/display_builtin.h
@@ -34,6 +34,46 @@
namespace sdm {
+struct DeferFpsConfig {
+ uint32_t frame_count = 0;
+ uint32_t frames_to_defer = 0;
+ uint32_t fps = 0;
+ uint32_t vsync_period_ns = 0;
+ uint32_t transfer_time_us = 0;
+ bool dirty = false;
+ bool apply = false;
+
+ void Init(uint32_t refresh_rate, uint32_t vsync_period, uint32_t transfer_time) {
+ fps = refresh_rate;
+ vsync_period_ns = vsync_period;
+ transfer_time_us = transfer_time;
+ frames_to_defer = frame_count;
+ dirty = false;
+ apply = false;
+ }
+
+ bool IsDeferredState() { return (frames_to_defer != 0); }
+
+ bool CanApplyDeferredState() { return apply; }
+
+ bool IsDirty() { return dirty; }
+
+ void MarkDirty() { dirty = IsDeferredState(); }
+
+ void UpdateDeferCount() {
+ if (frames_to_defer > 0) {
+ frames_to_defer--;
+ apply = (frames_to_defer == 0);
+ }
+ }
+
+ void Clear() {
+ frames_to_defer = 0;
+ dirty = false;
+ apply = false;
+ }
+};
+
class DppsInfo {
public:
void Init(DppsPropIntf *intf, const std::string &panel_name);
@@ -95,11 +135,16 @@
// Implement the DppsPropIntf
virtual DisplayError DppsProcessOps(enum DppsOps op, void *payload, size_t size);
+ virtual DisplayError SetActiveConfig(uint32_t index);
+ virtual DisplayError ReconfigureDisplay();
private:
bool CanCompareFrameROI(LayerStack *layer_stack);
bool CanSkipDisplayPrepare(LayerStack *layer_stack);
HWAVRModes GetAvrMode(QSyncMode mode);
+ bool CanDeferFpsConfig(uint32_t fps);
+ void SetDeferredFpsConfig();
+ void GetFpsConfig(HWDisplayAttributes *display_attributes, HWPanelInfo *panel_info);
std::vector<HWEvent> event_list_;
bool avr_prop_disabled_ = false;
@@ -111,6 +156,7 @@
LayerRect right_frame_roi_ = {};
bool first_cycle_ = true;
int previous_retire_fence_ = -1;
+ DeferFpsConfig deferred_config_ = {};
};
} // namespace sdm
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 22b9f89..b98bcaf 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -1266,6 +1266,9 @@
id_);
}
} break;
+ case kInvalidateDisplay:
+ validated_ = false;
+ break;
default:
DLOGW("Unknown event: %d", event);
break;