drm_hwcomposer: Put hwc2 PresentDisplay and GetReleaseFences to frontend Another step towards full frontend/backend split. Change-Id: I0b70a3c6ff6f3ee8bd65735f0a65fbb042c32fbd Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp index c94f875..de11c1f 100644 --- a/hwc2_device/HwcDisplay.cpp +++ b/hwc2_device/HwcDisplay.cpp
@@ -379,12 +379,32 @@ auto HwcDisplay::PresentStagedComposition( SharedFd &out_present_fence, std::vector<ReleaseFence> &out_release_fences) -> bool { - int out_fd = -1; - auto error = PresentDisplay(&out_fd); - out_present_fence = MakeSharedFd(out_fd); - if (error != HWC2::Error::None) { - return false; + if (IsInHeadlessMode()) { + return true; } + HWC2::Error ret{}; + + ++total_stats_.total_frames_; + + AtomicCommitArgs a_args{}; + ret = CreateComposition(a_args); + + if (ret != HWC2::Error::None) + ++total_stats_.failed_kms_present_; + + if (ret == HWC2::Error::BadLayer) { + // Can we really have no client or device layers? + return true; + } + if (ret != HWC2::Error::None) + return false; + + out_present_fence = a_args.out_fence; + + // Reset the color matrix so we don't apply it over and over again. + color_matrix_ = {}; + + ++frame_no_; if (!out_present_fence) { return true; @@ -712,45 +732,6 @@ return HWC2::Error::None; } -/* Find API details at: - * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1767 - * - * Called after PresentDisplay(), CLIENT is expecting release fence for the - * prior buffer (not the one assigned to the layer at the moment). - */ -HWC2::Error HwcDisplay::GetReleaseFences(uint32_t *num_elements, - hwc2_layer_t *layers, - int32_t *fences) { - if (IsInHeadlessMode()) { - *num_elements = 0; - return HWC2::Error::None; - } - - uint32_t num_layers = 0; - - for (auto &l : layers_) { - if (!l.second.GetPriorBufferScanOutFlag() || !present_fence_) { - continue; - } - - ++num_layers; - - if (layers == nullptr || fences == nullptr) - continue; - - if (num_layers > *num_elements) { - ALOGW("Overflow num_elements %d/%d", num_layers, *num_elements); - return HWC2::Error::None; - } - - layers[num_layers - 1] = l.first; - fences[num_layers - 1] = DupFd(present_fence_); - } - *num_elements = num_layers; - - return HWC2::Error::None; -} - AtomicCommitArgs HwcDisplay::CreateModesetCommit( const HwcDisplayConfig *config, const std::optional<LayerData> &modeset_layer) { @@ -912,43 +893,6 @@ return HWC2::Error::None; } -/* Find API details at: - * https://cs.android.com/android/platform/superproject/+/android-11.0.0_r3:hardware/libhardware/include/hardware/hwcomposer2.h;l=1805 - */ -HWC2::Error HwcDisplay::PresentDisplay(int32_t *out_present_fence) { - if (IsInHeadlessMode()) { - *out_present_fence = -1; - return HWC2::Error::None; - } - HWC2::Error ret{}; - - ++total_stats_.total_frames_; - - AtomicCommitArgs a_args{}; - ret = CreateComposition(a_args); - - if (ret != HWC2::Error::None) - ++total_stats_.failed_kms_present_; - - if (ret == HWC2::Error::BadLayer) { - // Can we really have no client or device layers? - *out_present_fence = -1; - return HWC2::Error::None; - } - if (ret != HWC2::Error::None) - return ret; - - this->present_fence_ = a_args.out_fence; - *out_present_fence = DupFd(a_args.out_fence); - - // Reset the color matrix so we don't apply it over and over again. - color_matrix_ = {}; - - ++frame_no_; - - return HWC2::Error::None; -} - HWC2::Error HwcDisplay::SetActiveConfigInternal(uint32_t config, int64_t change_time) { if (configs_.hwc_configs.count(config) == 0) {
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h index a1c78c3..1d90de0 100644 --- a/hwc2_device/HwcDisplay.h +++ b/hwc2_device/HwcDisplay.h
@@ -162,9 +162,6 @@ float *max_luminance, float *max_average_luminance, float *min_luminance); - HWC2::Error GetReleaseFences(uint32_t *num_elements, hwc2_layer_t *layers, - int32_t *fences); - HWC2::Error PresentDisplay(int32_t *out_present_fence); HWC2::Error SetActiveConfig(hwc2_config_t config); HWC2::Error ChosePreferredConfig(); HWC2::Error SetColorMode(int32_t mode); @@ -259,8 +256,6 @@ DrmHwc *const hwc_; - SharedFd present_fence_; - int64_t staged_mode_change_time_{}; std::optional<uint32_t> staged_mode_config_id_{};
diff --git a/hwc2_device/hwc2_device.cpp b/hwc2_device/hwc2_device.cpp index 29831ff..27ff611 100644 --- a/hwc2_device/hwc2_device.cpp +++ b/hwc2_device/hwc2_device.cpp
@@ -49,6 +49,21 @@ return str.substr(p1, p2 - p1); } +class Hwc2DeviceDisplay : public FrontendDisplayBase { + public: + std::vector<HwcDisplay::ReleaseFence> release_fences; +}; + +static auto GetHwc2DeviceDisplay(HwcDisplay &display) + -> std::shared_ptr<Hwc2DeviceDisplay> { + auto frontend_private_data = display.GetFrontendPrivateData(); + if (!frontend_private_data) { + frontend_private_data = std::make_shared<Hwc2DeviceDisplay>(); + display.SetFrontendPrivateData(frontend_private_data); + } + return std::static_pointer_cast<Hwc2DeviceDisplay>(frontend_private_data); +} + class Hwc2DeviceLayer : public FrontendLayerBase { public: auto HandleNextBuffer(buffer_handle_t buffer_handle, int32_t fence_fd) @@ -365,6 +380,57 @@ return 0; } +static int32_t GetReleaseFences(hwc2_device_t *device, hwc2_display_t display, + uint32_t *out_num_elements, + hwc2_layer_t *out_layers, int32_t *out_fences) { + ALOGV("GetReleaseFences"); + LOCK_COMPOSER(device); + GET_DISPLAY(display); + + auto hwc2display = GetHwc2DeviceDisplay(*idisplay); + + if (*out_num_elements < hwc2display->release_fences.size()) { + ALOGW("Overflow num_elements %d/%zu", *out_num_elements, + hwc2display->release_fences.size()); + return static_cast<int32_t>(HWC2::Error::NoResources); + } + + for (size_t i = 0; i < hwc2display->release_fences.size(); ++i) { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): + out_layers[i] = hwc2display->release_fences[i].first; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic): + out_fences[i] = DupFd(hwc2display->release_fences[i].second); + } + + *out_num_elements = hwc2display->release_fences.size(); + hwc2display->release_fences.clear(); + + return static_cast<int32_t>(HWC2::Error::None); +} + +static int32_t PresentDisplay(hwc2_device_t *device, hwc2_display_t display, + int32_t *out_release_fence) { + ALOGV("PresentDisplay"); + LOCK_COMPOSER(device); + GET_DISPLAY(display); + + auto hwc2display = GetHwc2DeviceDisplay(*idisplay); + + SharedFd out_fence; + + hwc2display->release_fences.clear(); + + if (!idisplay->PresentStagedComposition(out_fence, + hwc2display->release_fences)) { + ALOGE("Failed to present display"); + return static_cast<int32_t>(HWC2::Error::BadDisplay); + } + + *out_release_fence = DupFd(out_fence); + + return 0; +} + #if __ANDROID_API__ >= 28 static int32_t GetDisplayBrightnessSupport(hwc2_device_t * /*device*/, @@ -699,14 +765,9 @@ &HwcDisplay::GetHdrCapabilities, uint32_t *, int32_t *, float *, float *, float *>); case HWC2::FunctionDescriptor::GetReleaseFences: - return ToHook<HWC2_PFN_GET_RELEASE_FENCES>( - DisplayHook<decltype(&HwcDisplay::GetReleaseFences), - &HwcDisplay::GetReleaseFences, uint32_t *, hwc2_layer_t *, - int32_t *>); + return (hwc2_function_pointer_t)GetReleaseFences; case HWC2::FunctionDescriptor::PresentDisplay: - return ToHook<HWC2_PFN_PRESENT_DISPLAY>( - DisplayHook<decltype(&HwcDisplay::PresentDisplay), - &HwcDisplay::PresentDisplay, int32_t *>); + return (hwc2_function_pointer_t)PresentDisplay; case HWC2::FunctionDescriptor::SetActiveConfig: return ToHook<HWC2_PFN_SET_ACTIVE_CONFIG>( DisplayHook<decltype(&HwcDisplay::SetActiveConfig),