drm_hwcomposer: Initialize HwcDisplay using DrmDisplayPIpeline

HwcDisplay can now take all necessary objects from DrmDisplayPipeline.

Signed-off-by: Roman Stratiienko <roman.o.stratiienko@globallogic.com>
diff --git a/backend/Backend.cpp b/backend/Backend.cpp
index 98862ba..7d82eef 100644
--- a/backend/Backend.cpp
+++ b/backend/Backend.cpp
@@ -119,8 +119,8 @@
 std::tuple<int, int> Backend::GetExtraClientRange(
     HwcDisplay *display, const std::vector<HwcLayer *> &layers,
     int client_start, size_t client_size) {
-  size_t avail_planes = display->primary_planes().size() +
-                        display->overlay_planes().size();
+  size_t avail_planes = 1 /* primary planes count*/ +
+                        display->GetPipe().overlay_planes.size();
 
   /*
    * If more layers then planes, save one plane
diff --git a/backend/BackendManager.cpp b/backend/BackendManager.cpp
index 4a735eb..9bf6324 100644
--- a/backend/BackendManager.cpp
+++ b/backend/BackendManager.cpp
@@ -42,7 +42,7 @@
 }
 
 int BackendManager::SetBackendForDisplay(HwcDisplay *display) {
-  std::string driver_name(display->drm()->GetName());
+  std::string driver_name(display->GetPipe().device->GetName());
   char backend_override[PROPERTY_VALUE_MAX];
   property_get("vendor.hwc.backend_override", backend_override,
                driver_name.c_str());
@@ -51,13 +51,15 @@
   display->set_backend(GetBackendByName(backend_name));
   if (display->backend() == nullptr) {
     ALOGE("Failed to set backend '%s' for '%s' and driver '%s'",
-          backend_name.c_str(), display->connector()->GetName().c_str(),
+          backend_name.c_str(),
+          display->GetPipe().connector->Get()->GetName().c_str(),
           driver_name.c_str());
     return -EINVAL;
   }
 
   ALOGI("Backend '%s' for '%s' and driver '%s' was successfully set",
-        backend_name.c_str(), display->connector()->GetName().c_str(),
+        backend_name.c_str(),
+        display->GetPipe().connector->Get()->GetName().c_str(),
         driver_name.c_str());
 
   return 0;
diff --git a/compositor/DrmDisplayCompositor.cpp b/compositor/DrmDisplayCompositor.cpp
index d25fb98..bd0247d 100644
--- a/compositor/DrmDisplayCompositor.cpp
+++ b/compositor/DrmDisplayCompositor.cpp
@@ -39,20 +39,6 @@
 
 namespace android {
 
-auto DrmDisplayCompositor::Init(ResourceManager *resource_manager, int display)
-    -> int {
-  resource_manager_ = resource_manager;
-  display_ = display;
-  DrmDevice *drm = resource_manager_->GetDrmDevice(display);
-  if (!drm) {
-    ALOGE("Could not find drmdevice for display");
-    return -EINVAL;
-  }
-
-  initialized_ = true;
-  return 0;
-}
-
 // NOLINTNEXTLINE (readability-function-cognitive-complexity): Fixme
 auto DrmDisplayCompositor::CommitFrame(AtomicCommitArgs &args) -> int {
   ATRACE_CALL();
@@ -79,18 +65,9 @@
 
   auto new_frame_state = NewFrameState();
 
-  DrmDevice *drm = resource_manager_->GetDrmDevice(display_);
-
-  DrmConnector *connector = drm->GetConnectorForDisplay(display_);
-  if (!connector) {
-    ALOGE("Could not locate connector for display %d", display_);
-    return -ENODEV;
-  }
-  DrmCrtc *crtc = drm->GetCrtcForDisplay(display_);
-  if (!crtc) {
-    ALOGE("Could not locate crtc for display %d", display_);
-    return -ENODEV;
-  }
+  auto *drm = pipe_->device;
+  auto *connector = pipe_->connector->Get();
+  auto *crtc = pipe_->crtc->Get();
 
   auto pset = MakeDrmModeAtomicReqUnique();
   if (!pset) {
@@ -113,8 +90,7 @@
   }
 
   if (args.display_mode) {
-    new_frame_state.mode_blob = args.display_mode.value().CreateModeBlob(
-        *resource_manager_->GetDrmDevice(display_));
+    new_frame_state.mode_blob = args.display_mode.value().CreateModeBlob(*drm);
 
     if (!new_frame_state.mode_blob) {
       ALOGE("Failed to create mode_blob");
@@ -207,12 +183,14 @@
 
   if (!args.test_only) {
     if (err) {
-      ALOGE("Composite failed for display %d", display_);
+      ALOGE("Composite failed for pipeline %s",
+            pipe_->connector->Get()->GetName().c_str());
       // Disable the hw used by the last active composition. This allows us to
       // signal the release fences from that composition to avoid hanging.
       AtomicCommitArgs cl_args = {.clear_active_composition = true};
       if (CommitFrame(cl_args)) {
-        ALOGE("Failed to clean-up active composition for display %d", display_);
+        ALOGE("Failed to clean-up active composition for pipeline %s",
+              pipe_->connector->Get()->GetName().c_str());
       }
       return err;
     }
@@ -222,19 +200,12 @@
 }  // namespace android
 
 auto DrmDisplayCompositor::ActivateDisplayUsingDPMS() -> int {
-  auto *drm = resource_manager_->GetDrmDevice(display_);
-  auto *connector = drm->GetConnectorForDisplay(display_);
-  if (connector == nullptr) {
-    ALOGE("Could not locate connector for display %d", display_);
-    return -ENODEV;
-  }
-
-  if (connector->GetDpmsProperty()) {
-    drmModeConnectorSetProperty(drm->GetFd(), connector->GetId(),
-                                connector->GetDpmsProperty().id(),
-                                DRM_MODE_DPMS_ON);
-  }
-  return 0;
+  return drmModeConnectorSetProperty(pipe_->device->GetFd(),
+                                     pipe_->connector->Get()->GetId(),
+                                     pipe_->connector->Get()
+                                         ->GetDpmsProperty()
+                                         .id(),
+                                     DRM_MODE_DPMS_ON);
 }
 
 }  // namespace android
diff --git a/compositor/DrmDisplayCompositor.h b/compositor/DrmDisplayCompositor.h
index 9679520..bff3de7 100644
--- a/compositor/DrmDisplayCompositor.h
+++ b/compositor/DrmDisplayCompositor.h
@@ -54,9 +54,8 @@
 
 class DrmDisplayCompositor {
  public:
-  DrmDisplayCompositor() = default;
+  explicit DrmDisplayCompositor(DrmDisplayPipeline *pipe) : pipe_(pipe){};
   ~DrmDisplayCompositor() = default;
-  auto Init(ResourceManager *resource_manager, int display) -> int;
 
   auto ExecuteAtomicCommit(AtomicCommitArgs &args) -> int;
 
@@ -88,9 +87,7 @@
     };
   }
 
-  ResourceManager *resource_manager_ = nullptr;
-  bool initialized_{};
-  int display_ = -1;
+  DrmDisplayPipeline *const pipe_;
 };
 }  // namespace android
 
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index ece9437..d1ae7c9 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -30,6 +30,7 @@
 #include <sstream>
 #include <string>
 
+#include "compositor/DrmDisplayCompositor.h"
 #include "drm/DrmPlane.h"
 #include "utils/log.h"
 #include "utils/properties.h"
@@ -168,14 +169,6 @@
   return pipelines_.count(display) != 0;
 }
 
-DrmConnector *DrmDevice::GetConnectorForDisplay(int display) const {
-  return pipelines_.at(display)->connector->Get();
-}
-
-DrmCrtc *DrmDevice::GetCrtcForDisplay(int display) const {
-  return pipelines_.at(display)->crtc->Get();
-}
-
 auto DrmDevice::GetDisplayId(DrmConnector *conn) -> int {
   for (auto &dpipe : pipelines_) {
     if (dpipe.second->connector->Get() == conn) {
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index 8d9a34c..5220760 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -56,8 +56,10 @@
     return max_resolution_;
   }
 
-  DrmConnector *GetConnectorForDisplay(int display) const;
-  DrmCrtc *GetCrtcForDisplay(int display) const;
+  auto *GetPipelineForDisplay(int display) {
+    return pipelines_.count(display) != 0 ? pipelines_.at(display).get()
+                                          : nullptr;
+  }
 
   std::string GetName() const;
 
@@ -102,10 +104,6 @@
                   DrmProperty *property) const;
 
  private:
-  int TryEncoderForDisplay(int display, DrmEncoder *enc);
-
-  int CreateDisplayPipe(DrmConnector *connector);
-
   UniqueFd fd_;
 
   std::vector<std::unique_ptr<DrmConnector>> connectors_;
diff --git a/drm/DrmDisplayPipeline.cpp b/drm/DrmDisplayPipeline.cpp
index 69d28b3..0ce1afc 100644
--- a/drm/DrmDisplayPipeline.cpp
+++ b/drm/DrmDisplayPipeline.cpp
@@ -25,6 +25,7 @@
 #include "DrmPlane.h"
 #include "compositor/DrmDisplayCompositor.h"
 #include "utils/log.h"
+#include "utils/properties.h"
 
 namespace android {
 
@@ -97,9 +98,13 @@
     return {};
   }
 
-  bool use_overlay_planes = true;  // TODO(rsglobal): restore
-                                   // strtol(use_overlay_planes_prop, nullptr,
-                                   // 10);
+  char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
+  property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
+               "1");
+  constexpr int kStrtolBase = 10;
+  bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr,
+                                   kStrtolBase) != 0;
+
   if (use_overlay_planes) {
     for (auto *plane : overlay_planes) {
       auto op = plane->BindPipeline(pipe.get());
@@ -109,6 +114,8 @@
     }
   }
 
+  pipe->compositor = std::make_unique<DrmDisplayCompositor>(pipe.get());
+
   return pipe;
 }
 
diff --git a/drm/DrmDisplayPipeline.h b/drm/DrmDisplayPipeline.h
index cb5b9e2..a3e2dd9 100644
--- a/drm/DrmDisplayPipeline.h
+++ b/drm/DrmDisplayPipeline.h
@@ -79,6 +79,8 @@
   std::shared_ptr<BindingOwner<DrmCrtc>> crtc;
   std::shared_ptr<BindingOwner<DrmPlane>> primary_plane;
   std::vector<std::shared_ptr<BindingOwner<DrmPlane>>> overlay_planes;
+
+  std::unique_ptr<DrmDisplayCompositor> compositor;
 };
 
 }  // namespace android
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index 46f77e4..a7d99ee 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -24,7 +24,9 @@
 #include <sstream>
 
 #include "bufferinfo/BufferInfoGetter.h"
+#include "compositor/DrmDisplayCompositor.h"
 #include "drm/DrmDevice.h"
+#include "drm/DrmDisplayPipeline.h"
 #include "drm/DrmPlane.h"
 #include "utils/log.h"
 #include "utils/properties.h"
@@ -95,10 +97,12 @@
   return ret;
 }
 
-DrmDevice *ResourceManager::GetDrmDevice(int display) {
+DrmDisplayPipeline *ResourceManager::GetPipeline(int display) {
   for (auto &drm : drms_) {
-    if (drm->HandlesDisplay(display))
-      return drm.get();
+    auto *pipe = drm->GetPipelineForDisplay(display);
+    if (pipe != nullptr) {
+      return pipe;
+    }
   }
   return nullptr;
 }
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index f54d682..caeb098 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -33,8 +33,8 @@
   ~ResourceManager();
 
   int Init();
-  DrmDevice *GetDrmDevice(int display);
-  const std::vector<std::unique_ptr<DrmDevice>> &GetDrmDevices() const {
+  auto GetPipeline(int display) -> DrmDisplayPipeline *;
+  auto &GetDrmDevices() const {
     return drms_;
   }
   int GetDisplayCount() const {
diff --git a/drm/VSyncWorker.cpp b/drm/VSyncWorker.cpp
index 64af85b..8cb4d08 100644
--- a/drm/VSyncWorker.cpp
+++ b/drm/VSyncWorker.cpp
@@ -29,19 +29,12 @@
 
 namespace android {
 
-VSyncWorker::VSyncWorker()
-    : Worker("vsync", HAL_PRIORITY_URGENT_DISPLAY),
-      drm_(nullptr),
-      display_(-1),
-      enabled_(false),
-      last_timestamp_(-1) {
-}
+VSyncWorker::VSyncWorker() : Worker("vsync", HAL_PRIORITY_URGENT_DISPLAY){};
 
-auto VSyncWorker::Init(DrmDevice *drm, int display,
+auto VSyncWorker::Init(DrmDisplayPipeline *pipe,
                        std::function<void(uint64_t /*timestamp*/)> callback)
     -> int {
-  drm_ = drm;
-  display_ = display;
+  pipe_ = pipe;
   callback_ = std::move(callback);
 
   return InitWorker();
@@ -86,12 +79,10 @@
     return ret;
 
   float refresh = 60.0F;  // Default to 60Hz refresh rate
-  DrmConnector *conn = drm_->GetConnectorForDisplay(display_);
-  if (conn && conn->GetActiveMode().v_refresh() != 0.0F)
-    refresh = conn->GetActiveMode().v_refresh();
-  else
-    ALOGW("Vsync worker active with conn=%p refresh=%f\n", conn,
-          conn ? conn->GetActiveMode().v_refresh() : 0.0F);
+  if (pipe_ != nullptr &&
+      pipe_->connector->Get()->GetActiveMode().v_refresh() != 0.0F) {
+    refresh = pipe_->connector->Get()->GetActiveMode().v_refresh();
+  }
 
   int64_t phased_timestamp = GetPhasedVSync(kOneSecondNs /
                                                 static_cast<int>(refresh),
@@ -121,28 +112,26 @@
     }
   }
 
-  int display = display_;
+  auto *pipe = pipe_;
   Unlock();
 
-  DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
-  if (!crtc) {
-    ALOGE("Failed to get crtc for display");
-    return;
-  }
-  uint32_t high_crtc = (crtc->GetIndexInResArray()
-                        << DRM_VBLANK_HIGH_CRTC_SHIFT);
-
-  drmVBlank vblank;
-  memset(&vblank, 0, sizeof(vblank));
-  vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE |
-                                           (high_crtc &
-                                            DRM_VBLANK_HIGH_CRTC_MASK));
-  vblank.request.sequence = 1;
-
+  ret = -EAGAIN;
   int64_t timestamp = 0;
-  ret = drmWaitVBlank(drm_->GetFd(), &vblank);
-  if (ret == -EINTR)
-    return;
+  drmVBlank vblank{};
+
+  if (pipe != nullptr) {
+    uint32_t high_crtc = (pipe->crtc->Get()->GetIndexInResArray()
+                          << DRM_VBLANK_HIGH_CRTC_SHIFT);
+
+    vblank.request.type = (drmVBlankSeqType)(DRM_VBLANK_RELATIVE |
+                                             (high_crtc &
+                                              DRM_VBLANK_HIGH_CRTC_MASK));
+    vblank.request.sequence = 1;
+
+    ret = drmWaitVBlank(pipe->device->GetFd(), &vblank);
+    if (ret == -EINTR)
+      return;
+  }
 
   if (ret) {
     ret = SyntheticWaitVBlank(&timestamp);
diff --git a/drm/VSyncWorker.h b/drm/VSyncWorker.h
index 67aaa16..1e6d39f 100644
--- a/drm/VSyncWorker.h
+++ b/drm/VSyncWorker.h
@@ -36,7 +36,7 @@
   VSyncWorker();
   ~VSyncWorker() override = default;
 
-  auto Init(DrmDevice *drm, int display,
+  auto Init(DrmDisplayPipeline *pipe,
             std::function<void(uint64_t /*timestamp*/)> callback) -> int;
 
   void VSyncControl(bool enabled);
@@ -48,13 +48,11 @@
   int64_t GetPhasedVSync(int64_t frame_ns, int64_t current) const;
   int SyntheticWaitVBlank(int64_t *timestamp);
 
-  DrmDevice *drm_;
-
   std::function<void(uint64_t /*timestamp*/)> callback_;
 
-  int display_;
-  std::atomic_bool enabled_;
-  int64_t last_timestamp_;
+  DrmDisplayPipeline *pipe_ = nullptr;
+  std::atomic_bool enabled_ = false;
+  int64_t last_timestamp_ = -1;
 };
 }  // namespace android
 
diff --git a/hwc2_device/DrmHwcTwo.cpp b/hwc2_device/DrmHwcTwo.cpp
index 31c1440..4cb0fc3 100644
--- a/hwc2_device/DrmHwcTwo.cpp
+++ b/hwc2_device/DrmHwcTwo.cpp
@@ -27,26 +27,16 @@
 
 HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
                                      HWC2::DisplayType type) {
-  DrmDevice *drm = resource_manager_.GetDrmDevice(static_cast<int>(displ));
-  if (!drm) {
+  auto *pipe = resource_manager_.GetPipeline(static_cast<int>(displ));
+  if (!pipe) {
     ALOGE("Failed to get a valid drmresource");
     return HWC2::Error::NoResources;
   }
   displays_.emplace(std::piecewise_construct, std::forward_as_tuple(displ),
-                    std::forward_as_tuple(&resource_manager_, drm, displ, type,
+                    std::forward_as_tuple(&resource_manager_, pipe, displ, type,
                                           this));
 
-  DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
-  if (!crtc) {
-    ALOGE("Failed to get crtc for display %d", static_cast<int>(displ));
-    return HWC2::Error::BadDisplay;
-  }
-  auto display_planes = std::vector<DrmPlane *>();
-  for (const auto &plane : drm->GetPlanes()) {
-    if (plane->IsCrtcSupported(*crtc))
-      display_planes.push_back(plane.get());
-  }
-  displays_.at(displ).Init(&display_planes);
+  displays_.at(displ).Init();
   return HWC2::Error::None;
 }
 
diff --git a/hwc2_device/HwcDisplay.cpp b/hwc2_device/HwcDisplay.cpp
index ea3957c..ac5d196 100644
--- a/hwc2_device/HwcDisplay.cpp
+++ b/hwc2_device/HwcDisplay.cpp
@@ -68,8 +68,12 @@
                              " VSync remains";
   }
 
+  std::string connector_name = IsInHeadlessMode()
+                                   ? "NULL-DISPLAY"
+                                   : GetPipe().connector->Get()->GetName();
+
   std::stringstream ss;
-  ss << "- Display on: " << connector_->GetName() << "\n"
+  ss << "- Display on: " << connector_name << "\n"
      << "  Flattening state: " << flattening_state_str << "\n"
      << "Statistics since system boot:\n"
      << DumpDelta(total_stats_) << "\n\n"
@@ -80,12 +84,12 @@
   return ss.str();
 }
 
-HwcDisplay::HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
-                       hwc2_display_t handle, HWC2::DisplayType type,
-                       DrmHwcTwo *hwc2)
+HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
+                       DrmDisplayPipeline *pipeline, hwc2_display_t handle,
+                       HWC2::DisplayType type, DrmHwcTwo *hwc2)
     : hwc2_(hwc2),
       resource_manager_(resource_manager),
-      drm_(drm),
+      pipeline_(pipeline),
       handle_(handle),
       type_(type),
       color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
@@ -104,43 +108,11 @@
   }
 
   AtomicCommitArgs a_args = {.clear_active_composition = true};
-  compositor_.ExecuteAtomicCommit(a_args);
+  GetPipe().compositor->ExecuteAtomicCommit(a_args);
 }
 
-HWC2::Error HwcDisplay::Init(std::vector<DrmPlane *> *planes) {
-  int display = static_cast<int>(handle_);
-  int ret = compositor_.Init(resource_manager_, display);
-  if (ret) {
-    ALOGE("Failed display compositor init for display %d (%d)", display, ret);
-    return HWC2::Error::NoResources;
-  }
-
-  // Split up the given display planes into primary and overlay to properly
-  // interface with the composition
-  char use_overlay_planes_prop[PROPERTY_VALUE_MAX];
-  property_get("vendor.hwc.drm.use_overlay_planes", use_overlay_planes_prop,
-               "1");
-  bool use_overlay_planes = strtol(use_overlay_planes_prop, nullptr, 10);
-  for (auto &plane : *planes) {
-    if (plane->GetType() == DRM_PLANE_TYPE_PRIMARY)
-      primary_planes_.push_back(plane);
-    else if (use_overlay_planes && (plane)->GetType() == DRM_PLANE_TYPE_OVERLAY)
-      overlay_planes_.push_back(plane);
-  }
-
-  crtc_ = drm_->GetCrtcForDisplay(display);
-  if (!crtc_) {
-    ALOGE("Failed to get crtc for display %d", display);
-    return HWC2::Error::BadDisplay;
-  }
-
-  connector_ = drm_->GetConnectorForDisplay(display);
-  if (!connector_) {
-    ALOGE("Failed to get connector for display %d", display);
-    return HWC2::Error::BadDisplay;
-  }
-
-  ret = vsync_worker_.Init(drm_, display, [this](int64_t timestamp) {
+HWC2::Error HwcDisplay::Init() {
+  int ret = vsync_worker_.Init(pipeline_, [this](int64_t timestamp) {
     const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock());
     /* vsync callback */
 #if PLATFORM_SDK_VERSION > 29
@@ -159,34 +131,30 @@
     }
   });
   if (ret) {
-    ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+    ALOGE("Failed to create event worker for d=%d %d\n", int(handle_), ret);
     return HWC2::Error::BadDisplay;
   }
 
-  ret = flattening_vsync_worker_
-            .Init(drm_, display, [this](int64_t /*timestamp*/) {
-              const std::lock_guard<std::mutex> lock(
-                  hwc2_->GetResMan().GetMainLock());
-              /* Frontend flattening */
-              if (flattenning_state_ >
-                      ClientFlattenningState::ClientRefreshRequested &&
-                  --flattenning_state_ ==
-                      ClientFlattenningState::ClientRefreshRequested &&
-                  hwc2_->refresh_callback_.first != nullptr &&
-                  hwc2_->refresh_callback_.second != nullptr) {
-                hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second,
-                                               handle_);
-                flattening_vsync_worker_.VSyncControl(false);
-              }
-            });
+  ret = flattening_vsync_worker_.Init(pipeline_, [this](int64_t /*timestamp*/) {
+    const std::lock_guard<std::mutex> lock(hwc2_->GetResMan().GetMainLock());
+    /* Frontend flattening */
+    if (flattenning_state_ > ClientFlattenningState::ClientRefreshRequested &&
+        --flattenning_state_ ==
+            ClientFlattenningState::ClientRefreshRequested &&
+        hwc2_->refresh_callback_.first != nullptr &&
+        hwc2_->refresh_callback_.second != nullptr) {
+      hwc2_->refresh_callback_.first(hwc2_->refresh_callback_.second, handle_);
+      flattening_vsync_worker_.VSyncControl(false);
+    }
+  });
   if (ret) {
-    ALOGE("Failed to create event worker for d=%d %d\n", display, ret);
+    ALOGE("Failed to create event worker for d=%d %d\n", int(handle_), ret);
     return HWC2::Error::BadDisplay;
   }
 
   ret = BackendManager::GetInstance().SetBackendForDisplay(this);
   if (ret) {
-    ALOGE("Failed to set backend for d=%d %d\n", display, ret);
+    ALOGE("Failed to set backend for d=%d %d\n", int(handle_), ret);
     return HWC2::Error::BadDisplay;
   }
 
@@ -196,7 +164,7 @@
 }
 
 HWC2::Error HwcDisplay::ChosePreferredConfig() {
-  HWC2::Error err = configs_.Update(*connector_);
+  HWC2::Error err = configs_.Update(*GetPipe().connector->Get());
   if (!IsInHeadlessMode() && err != HWC2::Error::None)
     return HWC2::Error::BadDisplay;
 
@@ -258,8 +226,8 @@
 HWC2::Error HwcDisplay::GetClientTargetSupport(uint32_t width, uint32_t height,
                                                int32_t /*format*/,
                                                int32_t dataspace) {
-  std::pair<uint32_t, uint32_t> min = drm_->GetMinResolution();
-  std::pair<uint32_t, uint32_t> max = drm_->GetMaxResolution();
+  std::pair<uint32_t, uint32_t> min = GetPipe().device->GetMinResolution();
+  std::pair<uint32_t, uint32_t> max = GetPipe().device->GetMaxResolution();
   if (IsInHeadlessMode()) {
     return HWC2::Error::None;
   }
@@ -363,7 +331,7 @@
 
 HWC2::Error HwcDisplay::GetDisplayName(uint32_t *size, char *name) {
   std::ostringstream stream;
-  stream << "display-" << connector_->GetId();
+  stream << "display-" << GetPipe().connector->Get()->GetId();
   std::string string = stream.str();
   size_t length = string.length();
   if (!name) {
@@ -471,7 +439,7 @@
   for (std::pair<const uint32_t, HwcLayer *> &l : z_map) {
     DrmHwcLayer layer;
     l.second->PopulateDrmLayer(&layer);
-    int ret = layer.ImportBuffer(drm_);
+    int ret = layer.ImportBuffer(GetPipe().device);
     if (ret) {
       ALOGE("Failed to import layer, ret=%d", ret);
       return HWC2::Error::NoResources;
@@ -479,7 +447,8 @@
     composition_layers.emplace_back(std::move(layer));
   }
 
-  auto composition = std::make_shared<DrmDisplayComposition>(crtc_);
+  auto composition = std::make_shared<DrmDisplayComposition>(
+      GetPipe().crtc->Get());
 
   // TODO(nobody): Don't always assume geometry changed
   int ret = composition->SetLayers(composition_layers.data(),
@@ -489,8 +458,12 @@
     return HWC2::Error::BadLayer;
   }
 
-  std::vector<DrmPlane *> primary_planes(primary_planes_);
-  std::vector<DrmPlane *> overlay_planes(overlay_planes_);
+  std::vector<DrmPlane *> primary_planes;
+  primary_planes.emplace_back(pipeline_->primary_plane->Get());
+  std::vector<DrmPlane *> overlay_planes;
+  for (const auto &owned_plane : pipeline_->overlay_planes) {
+    overlay_planes.emplace_back(owned_plane->Get());
+  }
   ret = composition->Plan(&primary_planes, &overlay_planes);
   if (ret) {
     ALOGV("Failed to plan the composition ret=%d", ret);
@@ -501,7 +474,7 @@
   if (staged_mode) {
     a_args.display_mode = *staged_mode;
   }
-  ret = compositor_.ExecuteAtomicCommit(a_args);
+  ret = GetPipe().compositor->ExecuteAtomicCommit(a_args);
 
   if (ret) {
     if (!a_args.test_only)
@@ -656,7 +629,7 @@
        * true, as the next composition frame will implicitly activate
        * the display
        */
-      return compositor_.ActivateDisplayUsingDPMS() == 0
+      return GetPipe().compositor->ActivateDisplayUsingDPMS() == 0
                  ? HWC2::Error::None
                  : HWC2::Error::BadParameter;
       break;
@@ -668,7 +641,7 @@
       return HWC2::Error::BadParameter;
   };
 
-  int err = compositor_.ExecuteAtomicCommit(a_args);
+  int err = GetPipe().compositor->ExecuteAtomicCommit(a_args);
   if (err) {
     ALOGE("Failed to apply the dpms composition err=%d", err);
     return HWC2::Error::BadParameter;
@@ -715,9 +688,9 @@
   /* Primary display should be always internal,
    * otherwise SF will be unhappy and will crash
    */
-  if (connector_->IsInternal() || handle_ == kPrimaryDisplay)
+  if (GetPipe().connector->Get()->IsInternal() || handle_ == kPrimaryDisplay)
     *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::Internal);
-  else if (connector_->IsExternal())
+  else if (GetPipe().connector->Get()->IsExternal())
     *outType = static_cast<uint32_t>(HWC2::DisplayConnectionType::External);
   else
     return HWC2::Error::BadConfig;
@@ -772,7 +745,7 @@
 HWC2::Error HwcDisplay::GetDisplayIdentificationData(uint8_t *outPort,
                                                      uint32_t *outDataSize,
                                                      uint8_t *outData) {
-  auto blob = connector_->GetEdidBlob();
+  auto blob = GetPipe().connector->Get()->GetEdidBlob();
 
   if (!blob) {
     ALOGE("Failed to get edid property value.");
@@ -785,7 +758,7 @@
   } else {
     *outDataSize = blob->length;
   }
-  *outPort = connector_->GetId();
+  *outPort = GetPipe().connector->Get()->GetId();
 
   return HWC2::Error::None;
 }
diff --git a/hwc2_device/HwcDisplay.h b/hwc2_device/HwcDisplay.h
index 3e8a548..b73404a 100644
--- a/hwc2_device/HwcDisplay.h
+++ b/hwc2_device/HwcDisplay.h
@@ -37,10 +37,10 @@
 
 class HwcDisplay {
  public:
-  HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
+  HwcDisplay(ResourceManager *resource_manager, DrmDisplayPipeline *pipeline,
              hwc2_display_t handle, HWC2::DisplayType type, DrmHwcTwo *hwc2);
   HwcDisplay(const HwcDisplay &) = delete;
-  HWC2::Error Init(std::vector<DrmPlane *> *planes);
+  HWC2::Error Init();
 
   HWC2::Error CreateComposition(AtomicCommitArgs &a_args);
   std::vector<HwcLayer *> GetOrderLayersByZPos();
@@ -144,28 +144,12 @@
   const Backend *backend() const;
   void set_backend(std::unique_ptr<Backend> backend);
 
-  const std::vector<DrmPlane *> &primary_planes() const {
-    return primary_planes_;
-  }
-
-  const std::vector<DrmPlane *> &overlay_planes() const {
-    return overlay_planes_;
-  }
-
   std::map<hwc2_layer_t, HwcLayer> &layers() {
     return layers_;
   }
 
-  const DrmDisplayCompositor &compositor() const {
-    return compositor_;
-  }
-
-  const DrmDevice *drm() const {
-    return drm_;
-  }
-
-  const DrmConnector *connector() const {
-    return connector_;
+  auto &GetPipe() {
+    return *pipeline_;
   }
 
   ResourceManager *resource_manager() const {
@@ -209,7 +193,8 @@
    * https://source.android.com/devices/graphics/hotplug#handling-common-scenarios
    */
   bool IsInHeadlessMode() {
-    return handle_ == kPrimaryDisplay && !connector_->IsConnected();
+    return handle_ == kPrimaryDisplay &&
+           !GetPipe().connector->Get()->IsConnected();
   }
 
  private:
@@ -233,17 +218,12 @@
   std::optional<DrmMode> staged_mode;
 
   ResourceManager *resource_manager_;
-  DrmDevice *drm_;
-  DrmDisplayCompositor compositor_;
 
-  std::vector<DrmPlane *> primary_planes_;
-  std::vector<DrmPlane *> overlay_planes_;
+  DrmDisplayPipeline *const pipeline_;
 
   std::unique_ptr<Backend> backend_;
 
   VSyncWorker vsync_worker_;
-  DrmConnector *connector_ = nullptr;
-  DrmCrtc *crtc_ = nullptr;
   hwc2_display_t handle_;
   HWC2::DisplayType type_;
   uint32_t layer_idx_ = 0;