ui/display: Modeset only once during retry
This CL modifies the behavior of display configuration retry logic to
use test-modeset during search, and only modeset once.
This is necessary in order to avoid excessive display flickers.
Bug: b:236674622
Test: display_unittests && ozone_unittests
Change-Id: I2a1b8247a10cacccd011609574b408ef1b017db9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3763071
Reviewed-by: Daniel Nicoara <[email protected]>
Commit-Queue: Gil Dekel <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1027315}
diff --git a/ui/display/manager/configure_displays_task.cc b/ui/display/manager/configure_displays_task.cc
index 98653ce..e7b15db 100644
--- a/ui/display/manager/configure_displays_task.cc
+++ b/ui/display/manager/configure_displays_task.cc
@@ -272,7 +272,7 @@
is_first_attempt ? &ConfigureDisplaysTask::OnFirstAttemptConfigured
: &ConfigureDisplaysTask::OnRetryConfigured;
- uint32_t modeset_flags = display::kTestModeset | display::kCommitModeset;
+ uint32_t modeset_flags = display::kTestModeset;
if (configuration_type_ == kConfigurationTypeSeamless)
modeset_flags |= display::kSeamlessModeset;
delegate_->Configure(
@@ -309,15 +309,22 @@
}
// This code execute only when the first modeset attempt fully succeeds.
- // Update the displays' status and report success.
- for (const DisplayConfigureRequest& request : requests_) {
- request.display->set_current_mode(request.mode);
- request.display->set_origin(request.origin);
- final_requests_status_.emplace_back(std::make_pair(&request, true));
+ // Submit the current |requests_| for modeset.
+ std::vector<display::DisplayConfigurationParams> config_requests;
+ for (const auto& request : requests_) {
+ final_requests_status_.emplace_back(&request, true);
+
+ config_requests.emplace_back(request.display->display_id(), request.origin,
+ request.mode);
}
- UpdateFinalStatusUma(final_requests_status_);
- std::move(callback_).Run(task_status_);
+ uint32_t modeset_flags = display::kCommitModeset;
+ if (configuration_type_ == kConfigurationTypeSeamless)
+ modeset_flags |= display::kSeamlessModeset;
+ delegate_->Configure(config_requests,
+ base::BindOnce(&ConfigureDisplaysTask::OnConfigured,
+ weak_ptr_factory_.GetWeakPtr()),
+ modeset_flags);
}
void ConfigureDisplaysTask::OnRetryConfigured(bool config_success) {
@@ -339,19 +346,21 @@
pair.request->mode = nullptr;
task_status_ = ERROR;
}
+ } else {
+ // This configuration attempt passed test-modeset. Cache it so we can use it
+ // to modeset the displays once we are done testing, or if no other future
+ // attempts succeed.
+ last_successful_config_parameters_.clear();
+ for (const auto& request : requests_) {
+ last_successful_config_parameters_.emplace_back(
+ request.display->display_id(), request.origin, request.mode);
+ }
}
// This code executes only when this display group request fully succeeds or
// fails to modeset. Update the final status of this group.
- for (const auto& pair : pending_display_group_requests_.front()) {
- const DisplayConfigureRequest* request = pair.request;
- final_requests_status_.emplace_back(
- std::make_pair(request, config_success));
- if (config_success) {
- request->display->set_current_mode(request->mode);
- request->display->set_origin(request->origin);
- }
- }
+ for (const auto& pair : pending_display_group_requests_.front())
+ final_requests_status_.emplace_back(pair.request, config_success);
// Subsequent modeset attempts will be done on the next pending display group,
// if one exists.
@@ -364,7 +373,38 @@
return;
}
- // No more display groups to retry.
+ if (task_status_ == ERROR) {
+ LOG(WARNING) << "One or more of the connected display groups failed to "
+ "pass test-modeset entirely and will be disabled.";
+
+ if (last_successful_config_parameters_.empty()) {
+ LOG(ERROR) << "Display configuration failed. No modeset was attempted.";
+
+ UpdateFinalStatusUma(final_requests_status_);
+ std::move(callback_).Run(task_status_);
+ return;
+ }
+ }
+
+ // Configure the displays using the last successful configuration parameter
+ // list.
+ uint32_t modeset_flags = display::kCommitModeset;
+ if (configuration_type_ == kConfigurationTypeSeamless)
+ modeset_flags |= display::kSeamlessModeset;
+ delegate_->Configure(last_successful_config_parameters_,
+ base::BindOnce(&ConfigureDisplaysTask::OnConfigured,
+ weak_ptr_factory_.GetWeakPtr()),
+ modeset_flags);
+}
+
+void ConfigureDisplaysTask::OnConfigured(bool config_success) {
+ if (config_success) {
+ for (const DisplayConfigureRequest& request : requests_) {
+ request.display->set_current_mode(request.mode);
+ request.display->set_origin(request.origin);
+ }
+ }
+
UpdateFinalStatusUma(final_requests_status_);
std::move(callback_).Run(task_status_);
}