From ee6d843ef8960d656d48f379f66b07cc2b27801c Mon Sep 17 00:00:00 2001 From: Roman Stratiienko Date: Fri, 14 Feb 2025 06:25:30 +0200 Subject: [PATCH] drm_hwcomposer: Rework CreateLayer/DestroyLayer - Make HwcDisplay CreateLayer/DestroyLayer frontend-agnostic. - Provide LayerId as an input for CreateLayer. It is necessary to add the HWC3 LayerLifecycleBatchCommand feature, where layer ID is generated by the client. Change-Id: I317dcf22461fe4390ced9f0c0c780cffaa3b8f5d Signed-off-by: Roman Stratiienko --- compositor/LayerData.h | 2 ++ hwc2_device/HwcDisplay.cpp | 34 +++++++++++++++--------------- hwc2_device/HwcDisplay.h | 17 ++++++++------- hwc2_device/hwc2_device.cpp | 41 +++++++++++++++++++++++++++++++------ hwc3/ComposerClient.cpp | 26 +++++++++++------------ hwc3/DrmHwcThree.h | 2 ++ hwc3/Utils.h | 10 --------- 7 files changed, 76 insertions(+), 56 deletions(-) diff --git a/compositor/LayerData.h b/compositor/LayerData.h index 962141f..90ae7be 100644 --- a/compositor/LayerData.h +++ b/compositor/LayerData.h @@ -30,6 +30,8 @@ namespace android { class DrmFbIdHandle; +using ILayerId = int64_t; + /* Rotation is defined in the clockwise direction */ /* The flip is done before rotation */ struct LayerTransform { diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index 9db384b..26a60be 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp @@ -330,8 +330,8 @@ auto HwcDisplay::GetDisplayBoundsMm() -> std::pair { } auto HwcDisplay::AcceptValidatedComposition() -> void { - for (std::pair &l : layers_) { - l.second.AcceptTypeChange(); + for (auto &[_, layer] : layers_) { + layer.AcceptTypeChange(); } } @@ -480,20 +480,18 @@ HWC2::Error HwcDisplay::ChosePreferredConfig() { return SetActiveConfig(configs_.preferred_config_id); } -HWC2::Error HwcDisplay::CreateLayer(hwc2_layer_t *layer) { - layers_.emplace(static_cast(layer_idx_), HwcLayer(this)); - *layer = static_cast(layer_idx_); - ++layer_idx_; - return HWC2::Error::None; +auto HwcDisplay::CreateLayer(ILayerId new_layer_id) -> bool { + if (layers_.count(new_layer_id) > 0) + return false; + + layers_.emplace(new_layer_id, HwcLayer(this)); + + return true; } -HWC2::Error HwcDisplay::DestroyLayer(hwc2_layer_t layer) { - if (!get_layer(layer)) { - return HWC2::Error::BadLayer; - } - - layers_.erase(layer); - return HWC2::Error::None; +auto HwcDisplay::DestroyLayer(ILayerId layer_id) -> bool { + auto count = layers_.erase(layer_id); + return count != 0; } HWC2::Error HwcDisplay::GetActiveConfig(hwc2_config_t *config) const { @@ -742,15 +740,15 @@ HWC2::Error HwcDisplay::CreateComposition(AtomicCommitArgs &a_args) { bool use_client_layer = false; uint32_t client_z_order = UINT32_MAX; std::map z_map; - for (std::pair &l : layers_) { - switch (l.second.GetValidatedType()) { + for (auto &[_, layer] : layers_) { + switch (layer.GetValidatedType()) { case HWC2::Composition::Device: - z_map.emplace(l.second.GetZOrder(), &l.second); + z_map.emplace(layer.GetZOrder(), &layer); break; case HWC2::Composition::Client: // Place it at the z_order of the lowest client layer use_client_layer = true; - client_z_order = std::min(client_z_order, l.second.GetZOrder()); + client_z_order = std::min(client_z_order, layer.GetZOrder()); break; default: continue; diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index c3a5f1a..7c24dea 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h @@ -101,7 +101,7 @@ class HwcDisplay { // To be called after SetDisplayProperties. Returns an empty vector if the // requested layers have been validated, otherwise the vector describes // the requested composition type changes. - using ChangedLayer = std::pair; + using ChangedLayer = std::pair; auto ValidateStagedComposition() -> std::vector; // Mark previously validated properties as ready to present. @@ -110,7 +110,7 @@ class HwcDisplay { // Present previously staged properties, and return fences to indicate when // the new content has been presented, and when the previous buffers have // been released. - using ReleaseFence = std::pair; + using ReleaseFence = std::pair; auto PresentStagedComposition(SharedFd &out_present_fence, std::vector &out_release_fences) -> bool; @@ -123,9 +123,10 @@ class HwcDisplay { frontend_private_data_ = std::move(data); } + auto CreateLayer(ILayerId new_layer_id) -> bool; + auto DestroyLayer(ILayerId layer_id) -> bool; + // HWC2 Hooks - these should not be used outside of the hwc2 device. - HWC2::Error CreateLayer(hwc2_layer_t *layer); - HWC2::Error DestroyLayer(hwc2_layer_t layer); HWC2::Error GetActiveConfig(hwc2_config_t *config) const; HWC2::Error GetColorModes(uint32_t *num_modes, int32_t *modes); HWC2::Error GetDisplayAttribute(hwc2_config_t config, int32_t attribute, @@ -168,7 +169,7 @@ class HwcDisplay { HWC2::Error SetColorTransform(const float *matrix, int32_t hint); HWC2::Error SetPowerMode(int32_t mode); HWC2::Error SetVsyncEnabled(int32_t enabled); - HwcLayer *get_layer(hwc2_layer_t layer) { + HwcLayer *get_layer(ILayerId layer) { auto it = layers_.find(layer); if (it == layers_.end()) return nullptr; @@ -201,7 +202,7 @@ class HwcDisplay { return hwc_; } - std::map &layers() { + auto layers() -> std::map & { return layers_; } @@ -269,9 +270,7 @@ class HwcDisplay { const hwc2_display_t handle_; HWC2::DisplayType type_; - uint32_t layer_idx_{}; - - std::map layers_; + std::map layers_; HwcLayer client_layer_; std::unique_ptr writeback_layer_; uint16_t virtual_disp_width_{}; diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp index 72d0aa9..c1c5157 100644 --- a/hwc2_device/hwc2_device.cpp +++ b/hwc2_device/hwc2_device.cpp @@ -53,6 +53,8 @@ class Hwc2DeviceDisplay : public FrontendDisplayBase { public: std::vector release_fences; std::vector changed_layers; + + int64_t next_layer_id = 1; }; static auto GetHwc2DeviceDisplay(HwcDisplay &display) @@ -267,6 +269,37 @@ static BufferSampleRange Hwc2ToSampleRange(int32_t dataspace) { } /* Display functions */ +static int32_t CreateLayer(hwc2_device_t *device, hwc2_display_t display, + hwc2_layer_t *out_layer) { + ALOGV("CreateLayer"); + LOCK_COMPOSER(device); + GET_DISPLAY(display); + + auto hwc2display = GetHwc2DeviceDisplay(*idisplay); + + if (!idisplay->CreateLayer(hwc2display->next_layer_id)) { + return static_cast(HWC2::Error::BadDisplay); + } + + *out_layer = (hwc2_layer_t)hwc2display->next_layer_id; + hwc2display->next_layer_id++; + + return 0; +} + +static int32_t DestroyLayer(hwc2_device_t *device, hwc2_display_t display, + hwc2_layer_t layer) { + ALOGV("DestroyLayer"); + LOCK_COMPOSER(device); + GET_DISPLAY(display); + + if (!idisplay->DestroyLayer((ILayerId)layer)) { + return static_cast(HWC2::Error::BadLayer); + } + + return 0; +} + static int32_t GetDisplayRequests(hwc2_device_t * /*device*/, hwc2_display_t /*display*/, int32_t * /* out_display_requests */, @@ -763,13 +796,9 @@ static hwc2_function_pointer_t HookDevGetFunction(struct hwc2_device * /*dev*/, case HWC2::FunctionDescriptor::AcceptDisplayChanges: return (hwc2_function_pointer_t)AcceptDisplayChanges; case HWC2::FunctionDescriptor::CreateLayer: - return ToHook( - DisplayHook); + return (hwc2_function_pointer_t)CreateLayer; case HWC2::FunctionDescriptor::DestroyLayer: - return ToHook( - DisplayHook); + return (hwc2_function_pointer_t)DestroyLayer; case HWC2::FunctionDescriptor::GetActiveConfig: return ToHook( DisplayHookCreateLayer(&hwc2_layer_id)); - if (err != hwc3::Error::kNone) { - return ToBinderStatus(err); + auto hwc3display = DrmHwcThree::GetHwc3Display(*display); + + if (!display->CreateLayer(hwc3display->next_layer_id)) { + return ToBinderStatus(hwc3::Error::kBadDisplay); } - *layer_id = Hwc2LayerToHwc3(hwc2_layer_id); + *layer_id = hwc3display->next_layer_id; + + hwc3display->next_layer_id++; + return ndk::ScopedAStatus::ok(); } @@ -534,12 +537,11 @@ ndk::ScopedAStatus ComposerClient::destroyLayer(int64_t display_id, return ToBinderStatus(hwc3::Error::kBadDisplay); } - auto err = Hwc2toHwc3Error(display->DestroyLayer(Hwc3LayerToHwc2(layer_id))); - if (err != hwc3::Error::kNone) { - return ToBinderStatus(err); + if (!display->DestroyLayer(layer_id)) { + return ToBinderStatus(hwc3::Error::kBadLayer); } - return ToBinderStatus(err); + return ToBinderStatus(hwc3::Error::kNone); } ndk::ScopedAStatus ComposerClient::destroyVirtualDisplay(int64_t display_id) { @@ -698,8 +700,7 @@ void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) { changed_layers = display->ValidateStagedComposition(); DisplayChanges changes{}; for (auto [layer_id, composition_type] : changed_layers) { - changes.AddLayerCompositionChange(command.display, - Hwc2LayerToHwc3(layer_id), + changes.AddLayerCompositionChange(command.display, layer_id, static_cast( composition_type)); } @@ -743,8 +744,7 @@ void ComposerClient::ExecuteDisplayCommand(const DisplayCommand& command) { std::unordered_map hal_release_fences; for (const auto& [layer_id, release_fence] : release_fences) { - hal_release_fences[Hwc2LayerToHwc3(layer_id)] = // - unique_fd(::android::DupFd(release_fence)); + hal_release_fences[layer_id] = unique_fd(::android::DupFd(release_fence)); } cmd_result_writer_->AddReleaseFence(display_id, hal_release_fences); } diff --git a/hwc3/DrmHwcThree.h b/hwc3/DrmHwcThree.h index 44168aa..10470ea 100644 --- a/hwc3/DrmHwcThree.h +++ b/hwc3/DrmHwcThree.h @@ -26,6 +26,8 @@ namespace aidl::android::hardware::graphics::composer3::impl { class Hwc3Display : public ::android::FrontendDisplayBase { public: bool must_validate = false; + + int64_t next_layer_id = 1; }; class DrmHwcThree : public ::android::DrmHwc { diff --git a/hwc3/Utils.h b/hwc3/Utils.h index 642c777..e892832 100644 --- a/hwc3/Utils.h +++ b/hwc3/Utils.h @@ -57,12 +57,6 @@ inline ndk::ScopedAStatus ToBinderStatus(HWC2::Error error) { return ToBinderStatus(Hwc2toHwc3Error(error)); } -// ID conversion. HWC2 uses typedef'd unsigned integer types while HWC3 uses -// signed integer types. static_cast in between these. -inline int64_t Hwc2LayerToHwc3(hwc2_layer_t layer) { - return static_cast(layer); -} - inline int64_t Hwc2DisplayToHwc3(hwc2_display_t display) { return static_cast(display); } @@ -71,10 +65,6 @@ inline int32_t Hwc2ConfigIdToHwc3(hwc2_config_t config_id) { return static_cast(config_id); } -inline hwc2_layer_t Hwc3LayerToHwc2(int64_t layer) { - return static_cast(layer); -} - inline hwc2_display_t Hwc3DisplayToHwc2(int64_t display) { return static_cast(display); }