drm_hwcomposer: Fixes for display hotplug / headless mode
Further testing showed that several issues is still present:
1. Boot without display doesn't work.
2. Unplug/plug primary display has some flaws due to incomplete
HwcDisplay disposal.
3. In case creation of the pipeline fails, hwcomposer crashes.
This commit aims to address them.
Fixes: bb594baa1c68 ("drm_hwcomposer: Rework HwcDisplay disposal to avoid races")
Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index cedac19..0f957a7 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -102,24 +102,36 @@
HwcDisplay::~HwcDisplay() = default;
void HwcDisplay::SetPipeline(DrmDisplayPipeline *pipeline) {
+ Deinit();
+
pipeline_ = pipeline;
- if (pipeline != nullptr) {
- ChosePreferredConfig();
+ if (pipeline != nullptr || handle_ == kPrimaryDisplay) {
Init();
-
hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ true);
} else {
- backend_.reset();
- vsync_worker_.Init(nullptr, [](int64_t) {});
- SetClientTarget(nullptr, -1, 0, {});
- if (handle_ != kPrimaryDisplay) {
- hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false);
- }
+ hwc2_->ScheduleHotplugEvent(handle_, /*connected = */ false);
}
}
+void HwcDisplay::Deinit() {
+ if (pipeline_ != nullptr) {
+ AtomicCommitArgs a_args{};
+ a_args.active = false;
+ a_args.composition = std::make_shared<DrmKmsPlan>();
+ GetPipe().atomic_state_manager->ExecuteAtomicCommit(a_args);
+
+ vsync_worker_.Init(nullptr, [](int64_t) {});
+ current_plan_.reset();
+ backend_.reset();
+ }
+
+ SetClientTarget(nullptr, -1, 0, {});
+}
+
HWC2::Error HwcDisplay::Init() {
+ ChosePreferredConfig();
+
int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) {
const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock());
if (vsync_event_en_) {