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),