composer: Add VRR related Composer 2.4 APIs
Define SetActiveConfigWithConstraints and GetDisplayVsyncPeriod
APIs for VRR on Composer 2.4 .
CRs-Fixed: 2632089
Change-Id: Id64e71a9756e183b1d47a285fb6be0cae9ca046e
diff --git a/composer/QtiComposerClient.cpp b/composer/QtiComposerClient.cpp
index 28692e9..e913ed6 100644
--- a/composer/QtiComposerClient.cpp
+++ b/composer/QtiComposerClient.cpp
@@ -156,9 +156,9 @@
auto client = reinterpret_cast<QtiComposerClient*>(callbackData);
android::hardware::Return<void> ret;
if (client->callback24_) {
- uint32_t vsync_period;
- client->hwc_session_->GetVsyncPeriod(display, &vsync_period);
- ret = client->callback24_->onVsync_2_4(display, timestamp, vsync_period);
+ VsyncPeriodNanos vsync_period;
+ client->hwc_session_->GetDisplayVsyncPeriod(display, &vsync_period);
+ ret = client->callback24_->onVsync_2_4(display, timestamp, static_cast<uint32_t>(vsync_period));
} else {
ret = client->callback_->onVsync(display, timestamp);
}
@@ -1026,23 +1026,23 @@
Return<void> QtiComposerClient::getDisplayVsyncPeriod(uint64_t display,
getDisplayVsyncPeriod_cb _hidl_cb) {
- uint32_t vsync_period;
- auto error = hwc_session_->GetVsyncPeriod(display, &vsync_period);
+ VsyncPeriodNanos vsync_period;
+ auto error = hwc_session_->GetDisplayVsyncPeriod(display, &vsync_period);
_hidl_cb(static_cast<composer_V2_4::Error>(error), vsync_period);
return Void();
}
Return<void> QtiComposerClient::setActiveConfigWithConstraints(
uint64_t display, uint32_t config,
- const composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints
- &vsyncPeriodChangeConstraints,
+ const VsyncPeriodChangeConstraints &vsyncPeriodChangeConstraints,
setActiveConfigWithConstraints_cb _hidl_cb) {
- auto error = hwc_session_->SetActiveConfig(display, config);
- // TODO(user): implement properly
- composer_V2_4::VsyncPeriodChangeTimeline timeline;
+ VsyncPeriodChangeTimeline timeline;
timeline.newVsyncAppliedTimeNanos = systemTime();
timeline.refreshRequired = false;
timeline.refreshTimeNanos = 0;
+
+ auto error = hwc_session_->SetActiveConfigWithConstraints(
+ display, config, &vsyncPeriodChangeConstraints, &timeline);
_hidl_cb(static_cast<composer_V2_4::Error>(error), timeline);
return Void();
}
diff --git a/composer/QtiComposerClient.h b/composer/QtiComposerClient.h
index 89180a8..847eedb 100644
--- a/composer/QtiComposerClient.h
+++ b/composer/QtiComposerClient.h
@@ -202,8 +202,7 @@
Return<void> getDisplayVsyncPeriod(uint64_t display, getDisplayVsyncPeriod_cb _hidl_cb) override;
Return<void> setActiveConfigWithConstraints(
uint64_t display, uint32_t config,
- const composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints
- &vsyncPeriodChangeConstraints,
+ const VsyncPeriodChangeConstraints &vsyncPeriodChangeConstraints,
setActiveConfigWithConstraints_cb _hidl_cb) override;
Return<composer_V2_4::Error> setAutoLowLatencyMode(uint64_t display, bool on) override;
diff --git a/composer/hwc_callbacks.cpp b/composer/hwc_callbacks.cpp
index e36a60f..29e737f 100644
--- a/composer/hwc_callbacks.cpp
+++ b/composer/hwc_callbacks.cpp
@@ -83,6 +83,27 @@
return HWC2::Error::None;
}
+HWC2::Error HWCCallbacks::Vsync_2_4(hwc2_display_t display, int64_t timestamp, uint32_t period) {
+ DTRACE_SCOPED();
+ if (!vsync_2_4_) {
+ return HWC2::Error::NoResources;
+ }
+
+ vsync_2_4_(vsync_2_4_data_, display, timestamp, period);
+ return HWC2::Error::None;
+}
+
+HWC2::Error HWCCallbacks::VsyncPeriodTimingChanged(
+ hwc2_display_t display, hwc_vsync_period_change_timeline_t *updated_timeline) {
+ DTRACE_SCOPED();
+ if (!vsync_period_timing_changed_) {
+ return HWC2::Error::NoResources;
+ }
+
+ vsync_period_timing_changed_(vsync_period_timing_changed_data_, display, updated_timeline);
+ return HWC2::Error::None;
+}
+
HWC2::Error HWCCallbacks::Register(HWC2::Callback descriptor, hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer) {
SCOPE_LOCK(callbacks_lock_);
@@ -101,6 +122,15 @@
vsync_data_ = callback_data;
vsync_ = reinterpret_cast<HWC2_PFN_VSYNC>(pointer);
break;
+ case HWC2::Callback::Vsync_2_4:
+ vsync_2_4_data_ = callback_data;
+ vsync_2_4_ = reinterpret_cast<HWC2_PFN_VSYNC_2_4>(pointer);
+ break;
+ case HWC2::Callback::VsyncPeriodTimingChanged:
+ vsync_period_timing_changed_data_ = callback_data;
+ vsync_period_timing_changed_ =
+ reinterpret_cast<HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED>(pointer);
+ break;
default:
return HWC2::Error::BadParameter;
}
diff --git a/composer/hwc_callbacks.h b/composer/hwc_callbacks.h
index 6db3139..eb92da2 100644
--- a/composer/hwc_callbacks.h
+++ b/composer/hwc_callbacks.h
@@ -54,6 +54,9 @@
HWC2::Error Hotplug(hwc2_display_t display, HWC2::Connection state);
HWC2::Error Refresh(hwc2_display_t display);
HWC2::Error Vsync(hwc2_display_t display, int64_t timestamp);
+ HWC2::Error Vsync_2_4(hwc2_display_t display, int64_t timestamp, uint32_t period);
+ HWC2::Error VsyncPeriodTimingChanged(hwc2_display_t display,
+ hwc_vsync_period_change_timeline_t *updated_timeline);
HWC2::Error Register(HWC2::Callback, hwc2_callback_data_t callback_data,
hwc2_function_pointer_t pointer);
void UpdateVsyncSource(hwc2_display_t from) {
@@ -62,6 +65,7 @@
hwc2_display_t GetVsyncSource() { return vsync_source_; }
bool VsyncCallbackRegistered() { return (vsync_ != nullptr && vsync_data_ != nullptr); }
+ bool Vsync_2_4CallbackRegistered() { return (vsync_2_4_ != nullptr); }
bool NeedsRefresh(hwc2_display_t display) { return pending_refresh_.test(UINT32(display)); }
void ResetRefresh(hwc2_display_t display) { pending_refresh_.reset(UINT32(display)); }
bool IsClientConnected() {
@@ -73,10 +77,15 @@
hwc2_callback_data_t hotplug_data_ = nullptr;
hwc2_callback_data_t refresh_data_ = nullptr;
hwc2_callback_data_t vsync_data_ = nullptr;
+ hwc2_callback_data_t vsync_2_4_data_ = nullptr;
+ hwc2_callback_data_t vsync_period_timing_changed_data_ = nullptr;
HWC2_PFN_HOTPLUG hotplug_ = nullptr;
HWC2_PFN_REFRESH refresh_ = nullptr;
HWC2_PFN_VSYNC vsync_ = nullptr;
+ HWC2_PFN_VSYNC_2_4 vsync_2_4_ = nullptr;
+ HWC2_PFN_VSYNC_PERIOD_TIMING_CHANGED vsync_period_timing_changed_ = nullptr;
+
hwc2_display_t vsync_source_ = HWC_DISPLAY_PRIMARY; // hw vsync is active on this display
std::bitset<kNumDisplays> pending_refresh_; // Displays waiting to get refreshed
diff --git a/composer/hwc_display.cpp b/composer/hwc_display.cpp
index 5e04e30..3e59bd2 100644
--- a/composer/hwc_display.cpp
+++ b/composer/hwc_display.cpp
@@ -53,6 +53,7 @@
namespace sdm {
uint32_t HWCDisplay::throttling_refresh_rate_ = 60;
+constexpr uint32_t kVsyncTimeDriftNs = 1000000;
bool NeedsToneMap(const LayerStack &layer_stack) {
for (Layer *layer : layer_stack.layers) {
@@ -63,6 +64,10 @@
return false;
}
+bool IsTimeAfterOrEqualVsyncTime(int64_t time, int64_t vsync_time) {
+ return ((vsync_time != INT64_MAX) && ((time - (vsync_time - kVsyncTimeDriftNs)) >= 0));
+}
+
HWCColorMode::HWCColorMode(DisplayInterface *display_intf) : display_intf_(display_intf) {}
HWC2::Error HWCColorMode::Init() {
@@ -875,7 +880,8 @@
ATRACE_INT("SetVsyncState ", enabled == HWC2::Vsync::Enable ? 1 : 0);
DisplayError error = kErrorNone;
- if (shutdown_pending_ || !callbacks_->VsyncCallbackRegistered()) {
+ if (shutdown_pending_ ||
+ (!callbacks_->VsyncCallbackRegistered() && !callbacks_->Vsync_2_4CallbackRegistered())) {
return HWC2::Error::None;
}
@@ -1248,7 +1254,17 @@
}
DisplayError HWCDisplay::VSync(const DisplayEventVSync &vsync) {
- callbacks_->Vsync(id_, vsync.timestamp);
+ if (callbacks_->Vsync_2_4CallbackRegistered()) {
+ VsyncPeriodNanos vsync_period;
+ if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
+ vsync_period = 0;
+ }
+ ATRACE_INT("VsyncPeriod", INT32(vsync_period));
+ callbacks_->Vsync_2_4(id_, vsync.timestamp, vsync_period);
+ } else {
+ callbacks_->Vsync(id_, vsync.timestamp);
+ }
+
return kErrorNone;
}
@@ -2486,4 +2502,176 @@
return -1;
}
+HWC2::Error HWCDisplay::GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period) {
+ if (GetTransientVsyncPeriod(vsync_period)) {
+ return HWC2::Error::None;
+ }
+
+ return GetVsyncPeriodByActiveConfig(vsync_period);
+}
+
+HWC2::Error HWCDisplay::SetActiveConfigWithConstraints(
+ hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+ VsyncPeriodChangeTimeline *out_timeline) {
+ if (variable_config_map_.find(config) == variable_config_map_.end()) {
+ DLOGE("Invalid config: %d", config);
+ return HWC2::Error::BadConfig;
+ }
+
+ if (vsync_period_change_constraints->seamlessRequired && !AllowSeamless(config)) {
+ DLOGE("Seamless switch to the config: %d, is not allowed!", config);
+ return HWC2::Error::SeamlessNotAllowed;
+ }
+
+ VsyncPeriodNanos vsync_period;
+ if (GetDisplayVsyncPeriod(&vsync_period) != HWC2::Error::None) {
+ return HWC2::Error::BadConfig;
+ }
+
+ std::tie(out_timeline->refreshTimeNanos, out_timeline->newVsyncAppliedTimeNanos) =
+ RequestActiveConfigChange(config, vsync_period,
+ vsync_period_change_constraints->desiredTimeNanos);
+
+ out_timeline->refreshRequired = true;
+ return HWC2::Error::None;
+}
+
+void HWCDisplay::ProcessActiveConfigChange() {
+ if (!IsActiveConfigReadyToSubmit(systemTime(SYSTEM_TIME_MONOTONIC))) {
+ return;
+ }
+
+ DTRACE_SCOPED();
+ VsyncPeriodNanos vsync_period;
+ if (GetVsyncPeriodByActiveConfig(&vsync_period) == HWC2::Error::None) {
+ SubmitActiveConfigChange(vsync_period);
+ }
+}
+
+HWC2::Error HWCDisplay::GetVsyncPeriodByActiveConfig(VsyncPeriodNanos *vsync_period) {
+ hwc2_config_t active_config;
+
+ auto error = GetActiveConfig(&active_config);
+ if (error != HWC2::Error::None) {
+ DLOGE("Failed to get active config!");
+ return error;
+ }
+
+ int32_t active_vsync_period;
+ error = GetDisplayAttribute(active_config, HwcAttribute::VSYNC_PERIOD, &active_vsync_period);
+ if (error != HWC2::Error::None) {
+ DLOGE("Failed to get VsyncPeriod of config: %d", active_config);
+ return error;
+ }
+
+ *vsync_period = static_cast<VsyncPeriodNanos>(active_vsync_period);
+ return HWC2::Error::None;
+}
+
+bool HWCDisplay::GetTransientVsyncPeriod(VsyncPeriodNanos *vsync_period) {
+ std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
+ auto now = systemTime(SYSTEM_TIME_MONOTONIC);
+
+ while (!transient_refresh_rate_info_.empty()) {
+ if (IsActiveConfigApplied(now, transient_refresh_rate_info_.front().vsync_applied_time)) {
+ transient_refresh_rate_info_.pop_front();
+ } else {
+ *vsync_period = transient_refresh_rate_info_.front().transient_vsync_period;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+std::tuple<int64_t, int64_t> HWCDisplay::RequestActiveConfigChange(
+ hwc2_config_t config, VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
+ int64_t refresh_time, applied_time;
+ std::tie(refresh_time, applied_time) =
+ EstimateVsyncPeriodChangeTimeline(current_vsync_period, desired_time);
+
+ pending_refresh_rate_config_ = config;
+ pending_refresh_rate_refresh_time_ = refresh_time;
+ pending_refresh_rate_applied_time_ = applied_time;
+
+ return std::make_tuple(refresh_time, applied_time);
+}
+
+std::tuple<int64_t, int64_t> HWCDisplay::EstimateVsyncPeriodChangeTimeline(
+ VsyncPeriodNanos current_vsync_period, int64_t desired_time) {
+ const auto now = systemTime(SYSTEM_TIME_MONOTONIC);
+ const auto delta = desired_time - now;
+ const auto refresh_rate_activate_period = current_vsync_period * vsyncs_to_apply_rate_change_;
+ nsecs_t refresh_time;
+
+ if (delta < 0) {
+ refresh_time = now + (delta % current_vsync_period);
+ } else if (delta < refresh_rate_activate_period) {
+ refresh_time = now + (delta % current_vsync_period) - current_vsync_period;
+ } else {
+ refresh_time = desired_time - refresh_rate_activate_period;
+ }
+
+ const auto applied_time = refresh_time + refresh_rate_activate_period;
+ return std::make_tuple(refresh_time, applied_time);
+}
+
+void HWCDisplay::SubmitActiveConfigChange(VsyncPeriodNanos current_vsync_period) {
+ HWC2::Error error = SetActiveConfig(pending_refresh_rate_config_);
+ if (error != HWC2::Error::None) {
+ return;
+ }
+
+ std::lock_guard<std::mutex> lock(transient_refresh_rate_lock_);
+ hwc_vsync_period_change_timeline_t timeline;
+ std::tie(timeline.refreshTimeNanos, timeline.newVsyncAppliedTimeNanos) =
+ EstimateVsyncPeriodChangeTimeline(current_vsync_period, pending_refresh_rate_refresh_time_);
+
+ transient_refresh_rate_info_.push_back({current_vsync_period, timeline.newVsyncAppliedTimeNanos});
+ if (timeline.newVsyncAppliedTimeNanos != pending_refresh_rate_applied_time_) {
+ timeline.refreshRequired = false;
+ callbacks_->VsyncPeriodTimingChanged(id_, &timeline);
+ }
+
+ pending_refresh_rate_config_ = UINT_MAX;
+ pending_refresh_rate_refresh_time_ = INT64_MAX;
+ pending_refresh_rate_applied_time_ = INT64_MAX;
+}
+
+bool HWCDisplay::IsActiveConfigReadyToSubmit(int64_t time) {
+ return ((pending_refresh_rate_config_ != UINT_MAX) &&
+ IsTimeAfterOrEqualVsyncTime(time, pending_refresh_rate_refresh_time_));
+}
+
+bool HWCDisplay::IsActiveConfigApplied(int64_t time, int64_t vsync_applied_time) {
+ return IsTimeAfterOrEqualVsyncTime(time, vsync_applied_time);
+}
+
+bool HWCDisplay::IsSameGroup(hwc2_config_t config_id1, hwc2_config_t config_id2) {
+ const auto &variable_config1 = variable_config_map_.find(config_id1);
+ const auto &variable_config2 = variable_config_map_.find(config_id2);
+
+ if ((variable_config1 == variable_config_map_.end()) ||
+ (variable_config2 == variable_config_map_.end())) {
+ DLOGE("Invalid config: %u, %u", config_id1, config_id2);
+ return false;
+ }
+
+ const DisplayConfigGroupInfo &config_group1 = variable_config1->second;
+ const DisplayConfigGroupInfo &config_group2 = variable_config2->second;
+
+ return (config_group1 == config_group2);
+}
+
+bool HWCDisplay::AllowSeamless(hwc2_config_t config) {
+ hwc2_config_t active_config;
+ auto error = GetActiveConfig(&active_config);
+ if (error != HWC2::Error::None) {
+ DLOGE("Failed to get active config!");
+ return false;
+ }
+
+ return IsSameGroup(active_config, config);
+}
+
} // namespace sdm
diff --git a/composer/hwc_display.h b/composer/hwc_display.h
index 491d85a..ebbfb74 100644
--- a/composer/hwc_display.h
+++ b/composer/hwc_display.h
@@ -49,6 +49,9 @@
using android::hardware::graphics::common::V1_2::Hdr;
namespace composer_V2_4 = ::android::hardware::graphics::composer::V2_4;
using HwcAttribute = composer_V2_4::IComposerClient::Attribute;
+using VsyncPeriodChangeConstraints = composer_V2_4::IComposerClient::VsyncPeriodChangeConstraints;
+using VsyncPeriodChangeTimeline = composer_V2_4::VsyncPeriodChangeTimeline;
+using VsyncPeriodNanos = composer_V2_4::VsyncPeriodNanos;
namespace sdm {
@@ -86,6 +89,11 @@
kCWBClientComposer, // Client to HWC i.e. SurfaceFlinger
};
+struct TransientRefreshRateInfo {
+ uint32_t transient_vsync_period;
+ int64_t vsync_applied_time;
+};
+
class HWCColorMode {
public:
explicit HWCColorMode(DisplayInterface *display_intf);
@@ -267,6 +275,7 @@
return HWC2::Error::Unsupported;
}
bool IsFirstCommitDone() { return !first_cycle_; }
+ virtual void ProcessActiveConfigChange();
// HWC2 APIs
virtual HWC2::Error AcceptDisplayChanges(void);
@@ -396,6 +405,12 @@
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]);
+
+ virtual HWC2::Error GetDisplayVsyncPeriod(VsyncPeriodNanos *vsync_period);
+ virtual HWC2::Error SetActiveConfigWithConstraints(
+ hwc2_config_t config, const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+ VsyncPeriodChangeTimeline *out_timeline);
+
HWC2::Error SetDisplayElapseTime(uint64_t time);
protected:
@@ -432,6 +447,19 @@
int32_t SetClientTargetDataSpace(int32_t dataspace);
int SetFrameBufferConfig(uint32_t x_pixels, uint32_t y_pixels);
int32_t GetDisplayConfigGroup(DisplayConfigGroupInfo variable_config);
+ HWC2::Error GetVsyncPeriodByActiveConfig(VsyncPeriodNanos *vsync_period);
+ bool GetTransientVsyncPeriod(VsyncPeriodNanos *vsync_period);
+ std::tuple<int64_t, int64_t> RequestActiveConfigChange(hwc2_config_t config,
+ VsyncPeriodNanos current_vsync_period,
+ int64_t desired_time);
+ std::tuple<int64_t, int64_t> EstimateVsyncPeriodChangeTimeline(
+ VsyncPeriodNanos current_vsync_period, int64_t desired_time);
+ void SubmitActiveConfigChange(VsyncPeriodNanos current_vsync_period);
+ bool IsActiveConfigReadyToSubmit(int64_t time);
+ bool IsActiveConfigApplied(int64_t time, int64_t vsync_applied_time);
+ bool IsSameGroup(hwc2_config_t config_id1, hwc2_config_t config_id2);
+ bool AllowSeamless(hwc2_config_t request_config);
+ void SetVsyncsApplyRateChange(uint32_t vsyncs) { vsyncs_to_apply_rate_change_ = vsyncs; }
bool validated_ = false;
bool layer_stack_invalid_ = true;
@@ -487,6 +515,12 @@
bool client_connected_ = true;
bool pending_config_ = false;
bool has_client_composition_ = false;
+ uint32_t vsyncs_to_apply_rate_change_ = 1;
+ hwc2_config_t pending_refresh_rate_config_ = UINT_MAX;
+ int64_t pending_refresh_rate_refresh_time_ = INT64_MAX;
+ int64_t pending_refresh_rate_applied_time_ = INT64_MAX;
+ std::deque<TransientRefreshRateInfo> transient_refresh_rate_info_;
+ std::mutex transient_refresh_rate_lock_;
private:
void DumpInputBuffers(void);
diff --git a/composer/hwc_display_builtin.cpp b/composer/hwc_display_builtin.cpp
index 343dc33..bdeb4de 100644
--- a/composer/hwc_display_builtin.cpp
+++ b/composer/hwc_display_builtin.cpp
@@ -134,6 +134,12 @@
DLOGI("Drop redundant drawcycles %d", id_);
}
+ int vsyncs = 0;
+ HWCDebugHandler::Get()->GetProperty(DEFER_FPS_FRAME_COUNT, &vsyncs);
+ if (vsyncs > 0) {
+ SetVsyncsApplyRateChange(UINT32(vsyncs));
+ }
+
is_primary_ = display_intf_->IsPrimaryDisplay();
return status;
diff --git a/composer/hwc_session.cpp b/composer/hwc_session.cpp
index f6dc8c2..1d221e1 100644
--- a/composer/hwc_session.cpp
+++ b/composer/hwc_session.cpp
@@ -769,6 +769,7 @@
if (pending_power_mode_[display]) {
status = HWC2::Error::None;
} else {
+ hwc_display_[target_display]->ProcessActiveConfigChange();
status = PresentDisplayInternal(target_display);
if (status == HWC2::Error::None) {
// Check if hwc's refresh trigger is getting exercised.
@@ -3396,4 +3397,24 @@
}
}
+int32_t HWCSession::GetDisplayVsyncPeriod(hwc2_display_t disp, VsyncPeriodNanos *vsync_period) {
+ if (vsync_period == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return CallDisplayFunction(disp, &HWCDisplay::GetDisplayVsyncPeriod, vsync_period);
+}
+
+int32_t HWCSession::SetActiveConfigWithConstraints(
+ hwc2_display_t display, hwc2_config_t config,
+ const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+ VsyncPeriodChangeTimeline *out_timeline) {
+ if ((vsync_period_change_constraints == nullptr) || (out_timeline == nullptr)) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ return CallDisplayFunction(display, &HWCDisplay::SetActiveConfigWithConstraints, config,
+ vsync_period_change_constraints, out_timeline);
+}
+
} // namespace sdm
diff --git a/composer/hwc_session.h b/composer/hwc_session.h
index 2808f00..9079a91 100644
--- a/composer/hwc_session.h
+++ b/composer/hwc_session.h
@@ -283,6 +283,12 @@
int32_t GetVsyncPeriod(hwc2_display_t disp, uint32_t *vsync_period);
void Refresh(hwc2_display_t display);
+ int32_t GetDisplayVsyncPeriod(hwc2_display_t display, VsyncPeriodNanos *out_vsync_period);
+ int32_t SetActiveConfigWithConstraints(
+ hwc2_display_t display, hwc2_config_t config,
+ const VsyncPeriodChangeConstraints *vsync_period_change_constraints,
+ VsyncPeriodChangeTimeline *out_timeline);
+
static Locker locker_[HWCCallbacks::kNumDisplays];
static Locker power_state_[HWCCallbacks::kNumDisplays];
static Locker hdr_locker_[HWCCallbacks::kNumDisplays];