Skip to content

Commit

Permalink
sdm: Add support for qsync based idle fallback.
Browse files Browse the repository at this point in the history
-- Switch to continuous mode on idle event.
-- Notify idle event to client.
-- Drop h/w vsyncs as long as display is in idle.

CRs-Fixed: 2788694
Change-Id: If3a414d6c383b5267b09837698d79d14218b0807
  • Loading branch information
Pullakavi Srinivas committed Oct 16, 2020
1 parent 0732652 commit 8580e6e
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 14 deletions.
4 changes: 4 additions & 0 deletions composer/hwc_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1348,6 +1348,9 @@ DisplayError HWCDisplay::HandleEvent(DisplayEvent event) {
case kInvalidateDisplay:
validated_ = false;
break;
case kPostIdleTimeout:
display_idle_ = true;
break;
default:
DLOGW("Unknown event: %d", event);
break;
Expand All @@ -1364,6 +1367,7 @@ HWC2::Error HWCDisplay::PrepareLayerStack(uint32_t *out_num_types, uint32_t *out
layer_changes_.clear();
layer_requests_.clear();
has_client_composition_ = false;
display_idle_ = false;

DTRACE_SCOPED();
if (shutdown_pending_) {
Expand Down
2 changes: 2 additions & 0 deletions composer/hwc_display.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ class HWCDisplay : public DisplayEventHandler {
VsyncPeriodChangeTimeline *out_timeline);

HWC2::Error SetDisplayElapseTime(uint64_t time);
virtual bool IsDisplayIdle() { return false; };

protected:
static uint32_t throttling_refresh_rate_;
Expand Down Expand Up @@ -546,6 +547,7 @@ class HWCDisplay : public DisplayEventHandler {
uint32_t active_refresh_rate_ = 0;
SecureEvent secure_event_ = kSecureEventMax;
bool display_pause_pending_ = false;
bool display_idle_ = false;

private:
void DumpInputBuffers(void);
Expand Down
6 changes: 6 additions & 0 deletions composer/hwc_display_builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1578,4 +1578,10 @@ void HWCDisplayBuiltIn::SetCpuPerfHintLargeCompCycle() {
}
}

bool HWCDisplayBuiltIn::IsDisplayIdle() {
// Notify only if this display is source of vsync.
bool vsync_source = (callbacks_->GetVsyncSource() == id_);
return vsync_source && display_idle_;
}

} // namespace sdm
1 change: 1 addition & 0 deletions composer/hwc_display_builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class HWCDisplayBuiltIn : public HWCDisplay, public SyncTask<LayerStitchTaskCode
uint64_t *samples[NUM_HISTOGRAM_COLOR_COMPONENTS]);
void Dump(std::ostringstream *os) override;
virtual HWC2::Error SetPowerMode(HWC2::PowerMode mode, bool teardown);
virtual bool IsDisplayIdle();

private:
HWCDisplayBuiltIn(CoreInterface *core_intf, BufferAllocator *buffer_allocator,
Expand Down
13 changes: 13 additions & 0 deletions composer/hwc_session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,18 @@ void HWCSession::PerformQsyncCallback(hwc2_display_t display) {
}
}

void HWCSession::PerformIdleStatusCallback(hwc2_display_t display) {
std::shared_ptr<DisplayConfig::ConfigCallback> callback = idle_callback_.lock();
if (!callback) {
return;
}

if (hwc_display_[display]->IsDisplayIdle()) {
DTRACE_SCOPED();
callback->NotifyIdleStatus(true);
}
}

int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *out_retire_fence) {
auto status = HWC2::Error::BadDisplay;
DTRACE_SCOPED();
Expand Down Expand Up @@ -808,6 +820,7 @@ int32_t HWCSession::PresentDisplay(hwc2_display_t display, shared_ptr<Fence> *ou
status = hwc_display_[target_display]->Present(out_retire_fence);
if (status == HWC2::Error::None) {
PerformQsyncCallback(target_display);
PerformIdleStatusCallback(target_display);
Locker::ScopeLock tui_lock(tui_locker_[target_display]);
if (tui_transition_pending_[target_display]) {
tui_transition_pending_[target_display] = false;
Expand Down
3 changes: 3 additions & 0 deletions composer/hwc_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, public qClient::BnQClient,
std::vector<uint32_t> *supported_refresh_rates);
virtual int IsRCSupported(uint32_t disp_id, bool *supported);
virtual int IsSupportedConfigSwitch(uint32_t disp_id, uint32_t config, bool *supported);
virtual int ControlIdleStatusCallback(bool enable);

std::weak_ptr<DisplayConfig::ConfigCallback> callback_;
HWCSession *hwc_session_ = nullptr;
Expand Down Expand Up @@ -515,6 +516,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, public qClient::BnQClient,
android::status_t TUITransitionStart(int disp_id);
android::status_t TUITransitionEnd(int disp_id);
android::status_t TUITransitionUnPrepare(int disp_id);
void PerformIdleStatusCallback(hwc2_display_t display);

CoreInterface *core_intf_ = nullptr;
HWCDisplay *hwc_display_[HWCCallbacks::kNumDisplays] = {nullptr};
Expand Down Expand Up @@ -556,6 +558,7 @@ class HWCSession : hwc2_device_t, HWCUEventListener, public qClient::BnQClient,
std::bitset<HWCCallbacks::kNumDisplays> pending_refresh_;
CWB cwb_;
std::weak_ptr<DisplayConfig::ConfigCallback> qsync_callback_;
std::weak_ptr<DisplayConfig::ConfigCallback> idle_callback_;
bool async_powermode_ = false;
bool async_vds_creation_ = false;
bool power_state_transition_[HWCCallbacks::kNumDisplays] = {};
Expand Down
11 changes: 11 additions & 0 deletions composer/hwc_session_services.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,17 @@ int HWCSession::DisplayConfigImpl::IsSupportedConfigSwitch(uint32_t disp_id, uin
}

*supported = hwc_session_->hwc_display_[disp_idx]->IsModeSwitchAllowed(config);

return 0;
}

int HWCSession::DisplayConfigImpl::ControlIdleStatusCallback(bool enable) {
if (enable) {
hwc_session_->idle_callback_ = callback_;
} else {
hwc_session_->idle_callback_.reset();
}

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/display_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
// PERF hint properties
#define ENABLE_PERF_HINT_LARGE_COMP_CYCLE DISPLAY_PROP("enable_perf_hint_large_comp_cycle")
#define DISABLE_DYNAMIC_FPS DISPLAY_PROP("disable_dynamic_fps")
#define ENABLE_QSYNC_IDLE DISPLAY_PROP("enable_qsync_idle")

// Add all vendor.display properties above

Expand Down
1 change: 1 addition & 0 deletions sdm/include/core/display_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ enum DisplayEvent {
kDisplayPowerResetEvent, // Event triggered by Hardware Recovery.
kInvalidateDisplay, // Event triggered by DrawCycle thread to Invalidate display.
kSyncInvalidateDisplay, // Event triggered by Non-DrawCycle threads to Invalidate display.
kPostIdleTimeout, // Event triggered after entering idle.
};

/*! @brief This enum represents the secure events received by Display HAL. */
Expand Down
94 changes: 80 additions & 14 deletions sdm/libs/core/display_builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ DisplayError DisplayBuiltIn::Init() {
DebugHandler::Get()->GetProperty(DISABLE_DYNAMIC_FPS, &value);
disable_dyn_fps_ = (value == 1);

value = 0;
DebugHandler::Get()->GetProperty(ENABLE_QSYNC_IDLE, &value);
enable_qsync_idle_ = hw_panel_info_.qsync_support && (value == 1);
if (enable_qsync_idle_) {
DLOGI("Enabling qsync on idling");
}

return error;
}

Expand Down Expand Up @@ -208,17 +215,15 @@ DisplayError DisplayBuiltIn::Prepare(LayerStack *layer_stack) {
}
} else {
if (CanSkipDisplayPrepare(layer_stack)) {
hw_layers_.hw_avr_info.update = needs_avr_update_;
hw_layers_.hw_avr_info.mode = GetAvrMode(qsync_mode_);
UpdateQsyncMode();
return kErrorNone;
}
}

// Clean hw layers for reuse.
hw_layers_ = HWLayers();

hw_layers_.hw_avr_info.update = needs_avr_update_;
hw_layers_.hw_avr_info.mode = GetAvrMode(qsync_mode_);
UpdateQsyncMode();

left_frame_roi_ = {};
right_frame_roi_ = {};
Expand Down Expand Up @@ -252,6 +257,31 @@ DisplayError DisplayBuiltIn::Prepare(LayerStack *layer_stack) {
return error;
}

void DisplayBuiltIn::UpdateQsyncMode() {
if (!hw_panel_info_.qsync_support || (hw_panel_info_.mode == kModeCommand)) {
return;
}

QSyncMode mode = kQSyncModeNone;
if (handle_idle_timeout_ && enable_qsync_idle_) {
// Override to continuous mode upon idling.
mode = kQSyncModeContinuous;
DLOGV_IF(kTagDisplay, "Qsync entering continuous mode");
} else {
// Set Qsync mode requested by client.
mode = qsync_mode_;
DLOGV_IF(kTagDisplay, "Restoring client's qsync mode: %d", mode);
}

hw_layers_.hw_avr_info.update = (mode != active_qsync_mode_) || needs_avr_update_;
hw_layers_.hw_avr_info.mode = GetAvrMode(mode);

DLOGV_IF(kTagDisplay, "update: %d mode: %d", hw_layers_.hw_avr_info.update, mode);

// Store active mde.
active_qsync_mode_ = mode;
}

HWAVRModes DisplayBuiltIn::GetAvrMode(QSyncMode mode) {
switch (mode) {
case kQSyncModeNone:
Expand Down Expand Up @@ -428,6 +458,18 @@ DisplayError DisplayBuiltIn::Commit(LayerStack *layer_stack) {
}
dpps_info_.Init(this, hw_panel_info_.panel_name);

HandleQsyncPostCommit(layer_stack);

first_cycle_ = false;

previous_retire_fence_ = layer_stack->retire_fence;

handle_idle_timeout_ = false;

return error;
}

void DisplayBuiltIn::HandleQsyncPostCommit(LayerStack *layer_stack) {
if (qsync_mode_ == kQsyncModeOneShot) {
// Reset qsync mode.
SetQSyncMode(kQSyncModeNone);
Expand All @@ -439,11 +481,13 @@ DisplayError DisplayBuiltIn::Commit(LayerStack *layer_stack) {
needs_avr_update_ = false;
}

first_cycle_ = false;

previous_retire_fence_ = layer_stack->retire_fence;
SetVsyncStatus(true /*Re-enable vsync.*/);

return error;
bool notify_idle = enable_qsync_idle_ && (active_qsync_mode_ != kQSyncModeNone) &&
handle_idle_timeout_;
if (notify_idle) {
event_handler_->HandleEvent(kPostIdleTimeout);
}
}

void DisplayBuiltIn::UpdateDisplayModeParams() {
Expand Down Expand Up @@ -653,22 +697,43 @@ DisplayError DisplayBuiltIn::SetRefreshRate(uint32_t refresh_rate, bool final_ra

// On success, set current refresh rate to new refresh rate
current_refresh_rate_ = refresh_rate;
handle_idle_timeout_ = false;
deferred_config_.MarkDirty();

return ReconfigureDisplay();
}

DisplayError DisplayBuiltIn::VSync(int64_t timestamp) {
if (vsync_enable_ && !drop_hw_vsync_) {
DisplayEventVSync vsync;
vsync.timestamp = timestamp;
event_handler_->VSync(vsync);
DTRACE_SCOPED();
bool qsync_enabled = enable_qsync_idle_ && (active_qsync_mode_ != kQSyncModeNone);
// Client isn't aware of underlying qsync mode.
// Disable vsync propagation as long as qsync is enabled.
bool propagate_vsync = vsync_enable_ && !drop_hw_vsync_ && !qsync_enabled;
if (!propagate_vsync) {
// Re enable when display updates.
SetVsyncStatus(false /*Disable vsync events.*/);
return kErrorNone;
}

DisplayEventVSync vsync;
vsync.timestamp = timestamp;
event_handler_->VSync(vsync);

return kErrorNone;
}

void DisplayBuiltIn::SetVsyncStatus(bool enable) {
string trace_name = enable ? "enable" : "disable";
DTRACE_BEGIN(trace_name.c_str());
if (enable) {
// Enable if vsync is still enabled.
hw_events_intf_->SetEventState(HWEvent::VSYNC, vsync_enable_);
pending_vsync_enable_ = false;
} else {
hw_events_intf_->SetEventState(HWEvent::VSYNC, false);
pending_vsync_enable_ = true;
}
}

void DisplayBuiltIn::IdleTimeout() {
if (hw_panel_info_.mode == kModeVideo) {
if (event_handler_->HandleEvent(kIdleTimeout) != kErrorNone) {
Expand Down Expand Up @@ -1013,6 +1078,7 @@ std::string DisplayBuiltIn::Dump() {
os << " h_total: " << display_attributes_.h_total;
os << " clk: " << display_attributes_.clock_khz;
os << " Topology: " << display_attributes_.topology;
os << " Qsync mode: " << active_qsync_mode_;
os << std::noboolalpha;

DynamicRangeType curr_dynamic_range = kSdrType;
Expand Down Expand Up @@ -1254,7 +1320,7 @@ void DppsInfo::DppsNotifyOps(enum DppsNotifyOps op, void *payload, size_t size)
}

DisplayError DisplayBuiltIn::GetQSyncMode(QSyncMode *qsync_mode) {
*qsync_mode = qsync_mode_;
*qsync_mode = active_qsync_mode_;
return kErrorNone;
}

Expand Down
6 changes: 6 additions & 0 deletions sdm/libs/core/display_builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,9 @@ class DisplayBuiltIn : public DisplayBase, HWEventHandler, DppsPropIntf {
DisplayError SetupSPR();
DisplayError SetupDemura();
void UpdateDisplayModeParams();
void HandleQsyncPostCommit(LayerStack *layer_stack);
void UpdateQsyncMode();
void SetVsyncStatus(bool enable);

const uint32_t kPuTimeOutMs = 1000;
std::vector<HWEvent> event_list_;
Expand Down Expand Up @@ -208,6 +211,9 @@ class DisplayBuiltIn : public DisplayBase, HWEventHandler, DppsPropIntf {
GetPanelFeatureFactoryIntfType GetPanelFeatureFactoryIntfFunc_ = nullptr;
int spr_prop_value_ = 0;
bool needs_validate_on_pu_enable_ = false;
bool enable_qsync_idle_ = false;
bool pending_vsync_enable_ = false;
QSyncMode active_qsync_mode_ = kQSyncModeNone;
};

} // namespace sdm
Expand Down

0 comments on commit 8580e6e

Please sign in to comment.