From 63762a9d5d131bb20b29d9ab92c2ddbd7dc1889e Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Mon, 18 Sep 2023 22:33:45 +0300 Subject: drm_hwcomposer: Use shared pointer type for the pipeline_ variable The change will help with resource management in further patches. Signed-off-by: Roman Stratiienko --- hwc2_device/DrmHwcTwo.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'hwc2_device/DrmHwcTwo.cpp') diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp index 64755c3..99756eb 100644 --- a/hwc2_device/DrmHwcTwo.cpp +++ b/hwc2_device/DrmHwcTwo.cpp @@ -35,13 +35,13 @@ void DrmHwcTwo::FinalizeDisplayBinding() { displays_[kPrimaryDisplay] = std::make_unique< HwcDisplay>(kPrimaryDisplay, HWC2::DisplayType::Physical, this); /* Initializes null-display */ - displays_[kPrimaryDisplay]->SetPipeline(nullptr); + displays_[kPrimaryDisplay]->SetPipeline({}); } if (displays_[kPrimaryDisplay]->IsInHeadlessMode() && !display_handles_.empty()) { /* Reattach first secondary display to take place of the primary */ - auto *pipe = display_handles_.begin()->first; + auto pipe = display_handles_.begin()->first; ALOGI("Primary display was disconnected, reattaching '%s' as new primary", pipe->connector->Get()->GetName().c_str()); UnbindDisplay(pipe); @@ -66,10 +66,10 @@ void DrmHwcTwo::FinalizeDisplayBinding() { } } -bool DrmHwcTwo::BindDisplay(DrmDisplayPipeline *pipeline) { +bool DrmHwcTwo::BindDisplay(std::shared_ptr pipeline) { if (display_handles_.count(pipeline) != 0) { ALOGE("%s, pipeline is already used by another display, FIXME!!!: %p", - __func__, pipeline); + __func__, pipeline.get()); return false; } @@ -96,9 +96,9 @@ bool DrmHwcTwo::BindDisplay(DrmDisplayPipeline *pipeline) { return true; } -bool DrmHwcTwo::UnbindDisplay(DrmDisplayPipeline *pipeline) { +bool DrmHwcTwo::UnbindDisplay(std::shared_ptr pipeline) { if (display_handles_.count(pipeline) == 0) { - ALOGE("%s, can't find the display, pipeline: %p", __func__, pipeline); + ALOGE("%s, can't find the display, pipeline: %p", __func__, pipeline.get()); return false; } auto handle = display_handles_[pipeline]; @@ -112,7 +112,7 @@ bool DrmHwcTwo::UnbindDisplay(DrmDisplayPipeline *pipeline) { ALOGE("%s, can't find the display, handle: %" PRIu64, __func__, handle); return false; } - displays_[handle]->SetPipeline(nullptr); + displays_[handle]->SetPipeline({}); /* We must defer display disposal and removal, since it may still have pending * HWC_API calls scheduled and waiting until ueventlistener thread releases -- cgit v1.2.3 From f2c060f8be1ed1270728b43a2588d3b9eb00c292 Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Mon, 18 Sep 2023 22:46:08 +0300 Subject: drm_hwcomposer: Virtual display acceleration support Some platforms like RaspberryPI-4 can benefit from Display Blender IP Core's ability to write back the composition into RAM, offloading the GPU in cases where the display content needs to be used (screen record, remote display, etc.). To enable this feature the following system property must be enabled: PRODUCT_VENDOR_PROPERTIES += debug.sf.enable_hwc_vds=1 The feature was requested by the Tesla Android project to improve UI performance. Closes: https://gitlab.freedesktop.org/drm-hwcomposer/drm-hwcomposer/-/issues/4 Change-Id: I643f94551408bf218a0b889f1a031598646242f1 Signed-off-by: Roman Stratiienko --- hwc2_device/DrmHwcTwo.cpp | 55 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 11 deletions(-) (limited to 'hwc2_device/DrmHwcTwo.cpp') diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp index 99756eb..b151155 100644 --- a/hwc2_device/DrmHwcTwo.cpp +++ b/hwc2_device/DrmHwcTwo.cpp @@ -124,17 +124,47 @@ bool DrmHwcTwo::UnbindDisplay(std::shared_ptr pipeline) { return true; } -HWC2::Error DrmHwcTwo::CreateVirtualDisplay(uint32_t /*width*/, - uint32_t /*height*/, - int32_t * /*format*/, - hwc2_display_t * /*display*/) { - // TODO(nobody): Implement virtual display - return HWC2::Error::Unsupported; +HWC2::Error DrmHwcTwo::CreateVirtualDisplay( + uint32_t width, uint32_t height, + int32_t *format, // NOLINT(readability-non-const-parameter) + hwc2_display_t *display) { + ALOGI("Creating virtual display %dx%d format %d", width, height, *format); + + auto virtual_pipeline = resource_manager_.GetVirtualDisplayPipeline(); + if (!virtual_pipeline) + return HWC2::Error::Unsupported; + + *display = ++last_display_handle_; + auto disp = std::make_unique(*display, HWC2::DisplayType::Virtual, + this); + + disp->SetVirtualDisplayResolution(width, height); + disp->SetPipeline(virtual_pipeline); + displays_[*display] = std::move(disp); + return HWC2::Error::None; } -HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t /*display*/) { - // TODO(nobody): Implement virtual display - return HWC2::Error::Unsupported; +HWC2::Error DrmHwcTwo::DestroyVirtualDisplay(hwc2_display_t display) { + ALOGI("Destroying virtual display %" PRIu64, display); + + if (displays_.count(display) == 0) { + ALOGE("Trying to destroy non-existent display %" PRIu64, display); + return HWC2::Error::BadDisplay; + } + + displays_[display]->SetPipeline({}); + + /* Wait 0.2s before removing the displays to flush pending HWC2 transactions + */ + auto &mutex = GetResMan().GetMainLock(); + mutex.unlock(); + const int kTimeForSFToDisposeDisplayUs = 200000; + usleep(kTimeForSFToDisposeDisplayUs); + mutex.lock(); + + displays_.erase(display); + + return HWC2::Error::None; } void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) { @@ -156,8 +186,11 @@ void DrmHwcTwo::Dump(uint32_t *outSize, char *outBuffer) { } uint32_t DrmHwcTwo::GetMaxVirtualDisplayCount() { - // TODO(nobody): Implement virtual display - return 0; + auto writeback_count = resource_manager_.GetWritebackConnectorsCount(); + writeback_count = std::min(writeback_count, 1U); + /* Currently, only 1 virtual display is supported. Other cases need testing */ + ALOGI("Max virtual display count: %d", writeback_count); + return writeback_count; } HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor, -- cgit v1.2.3