OSDN Git Service

drm_hwcomposer: Tracking of the DRM FB objects using RAII
authorRoman Stratiienko <r.stratiienko@gmail.com>
Tue, 9 Feb 2021 15:49:55 +0000 (17:49 +0200)
committerRoman Stratiienko <r.stratiienko@gmail.com>
Wed, 19 May 2021 16:31:29 +0000 (19:31 +0300)
DRM framebuffer objects must be kept registered in DRM/KMS
while used for scanning-out (After atomic commit applied
for processing by display controller and until next atomic
commit is applied for processing).

Existing logic for tracking current state is overcomplicated and
needs to be redesigned. Also further developing of drm_hwc will
require migration to asynchronous atomic commit, so additional
asynchronous FB cleanup logic must be created.
Buffer caching logic will also benefit from this.

With the RAII all further changes will be less painful and more robust.

By this commit I also renamed DrmGenericImporter to DrmFbImporter:
'Fb' word is present in most of existing composers (android and linux)
so it will be easier to compare different implementations.

Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
16 files changed:
.ci/.common.sh
Android.bp
DrmHwcTwo.cpp
DrmHwcTwo.h
compositor/DrmDisplayCompositor.cpp
drm/DrmDevice.cpp
drm/DrmDevice.h
drm/DrmFbImporter.cpp [new file with mode: 0644]
drm/DrmFbImporter.h [new file with mode: 0644]
drm/DrmGenericImporter.cpp [deleted file]
drm/DrmGenericImporter.h [deleted file]
drm/ResourceManager.cpp
drm/ResourceManager.h
include/drmhwcgralloc.h
include/drmhwcomposer.h
utils/hwcutils.cpp

index 93f7f95..0183aba 100644 (file)
@@ -5,7 +5,7 @@ CLANG_TIDY="clang-tidy-11"
 
 CXXARGS="-fPIC -Wall -Werror -DPLATFORM_SDK_VERSION=30 -D__ANDROID_API__=30 -Wsign-promo -Wimplicit-fallthrough"
 CXXARGS+=" -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -Wno-gnu-include-next "
-CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fexceptions -fno-rtti"
+CXXARGS+=" -fvisibility-inlines-hidden -std=gnu++17 -DHWC2_USE_CPP11 -DHWC2_INCLUDE_STRINGIFICATION -fno-rtti"
 
 BUILD_FILES=(
 backend/BackendClient.cpp
@@ -28,7 +28,7 @@ drm/DrmCrtc.cpp
 drm/DrmDevice.cpp
 drm/DrmEncoder.cpp
 drm/DrmEventListener.cpp
-drm/DrmGenericImporter.cpp
+drm/DrmFbImporter.cpp
 drm/DrmMode.cpp
 drm/DrmPlane.cpp
 drm/DrmProperty.cpp
index 9bed9e4..ddf66fb 100644 (file)
@@ -96,7 +96,7 @@ cc_library_static {
         "drm/DrmDevice.cpp",
         "drm/DrmEncoder.cpp",
         "drm/DrmEventListener.cpp",
-        "drm/DrmGenericImporter.cpp",
+        "drm/DrmFbImporter.cpp",
         "drm/DrmMode.cpp",
         "drm/DrmPlane.cpp",
         "drm/DrmProperty.cpp",
index 8b2abfd..4a7a416 100644 (file)
@@ -47,14 +47,13 @@ DrmHwcTwo::DrmHwcTwo() : hwc2_device() {
 HWC2::Error DrmHwcTwo::CreateDisplay(hwc2_display_t displ,
                                      HWC2::DisplayType type) {
   DrmDevice *drm = resource_manager_.GetDrmDevice(displ);
-  std::shared_ptr<Importer> importer = resource_manager_.GetImporter(displ);
-  if (!drm || !importer) {
-    ALOGE("Failed to get a valid drmresource and importer");
+  if (!drm) {
+    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, importer,
-                                          displ, type));
+                    std::forward_as_tuple(&resource_manager_, drm, displ,
+                                          type));
 
   DrmCrtc *crtc = drm->GetCrtcForDisplay(static_cast<int>(displ));
   if (!crtc) {
@@ -209,12 +208,10 @@ HWC2::Error DrmHwcTwo::RegisterCallback(int32_t descriptor,
 }
 
 DrmHwcTwo::HwcDisplay::HwcDisplay(ResourceManager *resource_manager,
-                                  DrmDevice *drm,
-                                  std::shared_ptr<Importer> importer,
-                                  hwc2_display_t handle, HWC2::DisplayType type)
+                                  DrmDevice *drm, hwc2_display_t handle,
+                                  HWC2::DisplayType type)
     : resource_manager_(resource_manager),
       drm_(drm),
-      importer_(std::move(importer)),
       handle_(handle),
       type_(type),
       color_transform_hint_(HAL_COLOR_TRANSFORM_IDENTITY) {
@@ -650,7 +647,7 @@ HWC2::Error DrmHwcTwo::HwcDisplay::CreateComposition(bool test) {
   for (std::pair<const uint32_t, DrmHwcTwo::HwcLayer *> &l : z_map) {
     DrmHwcLayer layer;
     l.second->PopulateDrmLayer(&layer);
-    int ret = layer.ImportBuffer(importer_.get());
+    int ret = layer.ImportBuffer(drm_);
     if (ret) {
       ALOGE("Failed to import layer, ret=%d", ret);
       return HWC2::Error::NoResources;
index a0d8cdd..b4e1ce8 100644 (file)
@@ -25,7 +25,6 @@
 
 #include "compositor/DrmDisplayCompositor.h"
 #include "compositor/Planner.h"
-#include "drm/DrmGenericImporter.h"
 #include "drm/ResourceManager.h"
 #include "drm/VSyncWorker.h"
 #include "drmhwcomposer.h"
@@ -164,8 +163,7 @@ class DrmHwcTwo : public hwc2_device_t {
   class HwcDisplay {
    public:
     HwcDisplay(ResourceManager *resource_manager, DrmDevice *drm,
-               std::shared_ptr<Importer> importer, hwc2_display_t handle,
-               HWC2::DisplayType type);
+               hwc2_display_t handle, HWC2::DisplayType type);
     HwcDisplay(const HwcDisplay &) = delete;
     HWC2::Error Init(std::vector<DrmPlane *> *planes);
 
@@ -305,10 +303,6 @@ class DrmHwcTwo : public hwc2_device_t {
       return connector_;
     }
 
-    const std::shared_ptr<Importer> &importer() const {
-      return importer_;
-    }
-
     ResourceManager *resource_manager() const {
       return resource_manager_;
     }
@@ -329,7 +323,6 @@ class DrmHwcTwo : public hwc2_device_t {
     ResourceManager *resource_manager_;
     DrmDevice *drm_;
     DrmDisplayCompositor compositor_;
-    std::shared_ptr<Importer> importer_;
     std::unique_ptr<Planner> planner_;
 
     std::vector<DrmPlane *> primary_planes_;
index 665446e..586ebe0 100644 (file)
@@ -290,7 +290,7 @@ int DrmDisplayCompositor::CommitFrame(DrmDisplayComposition *display_comp,
         ALOGE("Expected a valid framebuffer for pset");
         break;
       }
-      fb_id = layer.buffer->fb_id;
+      fb_id = layer.buffer.FbIdHandle->GetFbId();
       fence_fd = layer.acquire_fence.get();
       display_frame = layer.display_frame;
       source_crop = layer.source_crop;
index 150aa01..d9198d4 100644 (file)
@@ -112,6 +112,8 @@ static std::vector<DrmConnector *> make_primary_display_candidates(
 }
 
 DrmDevice::DrmDevice() : event_listener_(this) {
+  self.reset(this);
+  mDrmFbImporter = std::make_unique<DrmFbImporter>(self);
 }
 
 DrmDevice::~DrmDevice() {
@@ -146,6 +148,13 @@ std::tuple<int, int> DrmDevice::Init(const char *path, int num_displays) {
   }
 #endif
 
+  uint64_t cap_value = 0;
+  if (drmGetCap(fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) {
+    ALOGW("drmGetCap failed. Fallback to no modifier support.");
+    cap_value = 0;
+  }
+  HasAddFb2ModifiersSupport_ = cap_value != 0;
+
   drmSetMaster(fd());
   if (!drmIsMaster(fd())) {
     ALOGE("DRM/KMS master access required");
index d8f347f..c92004b 100644 (file)
 #include "DrmCrtc.h"
 #include "DrmEncoder.h"
 #include "DrmEventListener.h"
+#include "DrmFbImporter.h"
 #include "DrmPlane.h"
 
 namespace android {
 
+class DrmFbImporter;
+class DrmPlane;
+
 class DrmDevice {
  public:
   DrmDevice();
@@ -83,6 +87,14 @@ class DrmDevice {
     event_listener_.RegisterHotplugHandler(handler);
   }
 
+  bool HasAddFb2ModifiersSupport() const {
+    return HasAddFb2ModifiersSupport_;
+  }
+
+  DrmFbImporter &GetDrmFbImporter() {
+    return *mDrmFbImporter.get();
+  }
+
  private:
   int TryEncoderForDisplay(int display, DrmEncoder *enc);
   int GetProperty(uint32_t obj_id, uint32_t obj_type, const char *prop_name,
@@ -104,6 +116,12 @@ class DrmDevice {
   std::pair<uint32_t, uint32_t> min_resolution_;
   std::pair<uint32_t, uint32_t> max_resolution_;
   std::map<int, int> displays_;
+
+  bool HasAddFb2ModifiersSupport_{};
+
+  std::shared_ptr<DrmDevice> self;
+
+  std::unique_ptr<DrmFbImporter> mDrmFbImporter;
 };
 }  // namespace android
 
diff --git a/drm/DrmFbImporter.cpp b/drm/DrmFbImporter.cpp
new file mode 100644 (file)
index 0000000..2b5ddd4
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
+#define LOG_TAG "hwc-platform-drm-generic"
+
+#include "DrmFbImporter.h"
+
+#include <gralloc_handle.h>
+#include <hardware/gralloc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cinttypes>
+#include <system_error>
+
+#include "utils/log.h"
+#include "utils/properties.h"
+
+namespace android {
+
+auto DrmFbIdHandle::CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle,
+                                   const std::shared_ptr<DrmDevice> &drm)
+    -> std::shared_ptr<DrmFbIdHandle> {
+  // NOLINTNEXTLINE(cppcoreguidelines-owning-memory): priv. constructor usage
+  std::shared_ptr<DrmFbIdHandle> local(new DrmFbIdHandle(drm));
+
+  local->gem_handles_[0] = first_gem_handle;
+  int32_t err = 0;
+
+  /* Framebuffer object creation require gem handle for every used plane */
+  for (int i = 1; i < local->gem_handles_.size(); i++) {
+    if (bo->prime_fds[i] > 0) {
+      if (bo->prime_fds[i] != bo->prime_fds[0]) {
+        err = drmPrimeFDToHandle(drm->fd(), bo->prime_fds[i],
+                                 &local->gem_handles_.at(i));
+        if (err != 0) {
+          ALOGE("failed to import prime fd %d errno=%d", bo->prime_fds[i],
+                errno);
+        }
+      } else {
+        local->gem_handles_.at(i) = local->gem_handles_[0];
+      }
+    }
+  }
+
+  bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE &&
+                       bo->modifiers[0] != DRM_FORMAT_MOD_INVALID;
+
+  if (!drm->HasAddFb2ModifiersSupport() && has_modifiers) {
+    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
+          bo->modifiers[0]);
+    local.reset();
+    return local;
+  }
+
+  /* Create framebuffer object */
+  if (!has_modifiers) {
+    err = drmModeAddFB2(drm->fd(), bo->width, bo->height, bo->format,
+                        &local->gem_handles_[0], &bo->pitches[0],
+                        &bo->offsets[0], &local->fb_id_, 0);
+  } else {
+    err = drmModeAddFB2WithModifiers(drm->fd(), bo->width, bo->height,
+                                     bo->format, &local->gem_handles_[0],
+                                     &bo->pitches[0], &bo->offsets[0],
+                                     &bo->modifiers[0], &local->fb_id_,
+                                     DRM_MODE_FB_MODIFIERS);
+  }
+  if (err != 0) {
+    ALOGE("could not create drm fb %d", err);
+    local.reset();
+  }
+
+  return local;
+}
+
+DrmFbIdHandle::~DrmFbIdHandle() {
+  /* Destroy framebuffer object */
+  if (drmModeRmFB(drm_->fd(), fb_id_) != 0) {
+    ALOGE("Failed to rm fb");
+  }
+
+  /* Close GEM handles.
+   *
+   * WARNING: TODO(nobody):
+   * From Linux side libweston relies on libgbm to get KMS handle and never
+   * closes it (handle is closed by libgbm on buffer destruction)
+   * Probably we should offer similar approach to users (at least on user
+   * request via system properties)
+   */
+  struct drm_gem_close gem_close {};
+  for (unsigned int gem_handle : gem_handles_) {
+    if (gem_handle == 0) {
+      continue;
+    }
+    gem_close.handle = gem_handle;
+    int32_t err = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+    if (err != 0) {
+      ALOGE("Failed to close gem handle %d, errno: %d", gem_handle, errno);
+    }
+  }
+}
+
+auto DrmFbImporter::GetOrCreateFbId(hwc_drm_bo_t *bo)
+    -> std::shared_ptr<DrmFbIdHandle> {
+  /* Lookup DrmFbIdHandle in cache first. First handle serves as a cache key. */
+  GemHandle first_handle = 0;
+  int32_t err = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0], &first_handle);
+
+  if (err != 0) {
+    ALOGE("Failed to import prime fd %d ret=%d", bo->prime_fds[0], err);
+    return std::shared_ptr<DrmFbIdHandle>();
+  }
+
+  auto drm_fb_id_cached = drm_fb_id_handle_cache_.find(first_handle);
+
+  if (drm_fb_id_cached != drm_fb_id_handle_cache_.end()) {
+    if (auto drm_fb_id_handle_shared = drm_fb_id_cached->second.lock()) {
+      return drm_fb_id_handle_shared;
+    }
+    drm_fb_id_handle_cache_.erase(drm_fb_id_cached);
+  }
+
+  /* Cleanup cached empty weak pointers */
+  const int minimal_cleanup_size = 128;
+  if (drm_fb_id_handle_cache_.size() > minimal_cleanup_size) {
+    CleanupEmptyCacheElements();
+  }
+
+  /* No DrmFbIdHandle found in cache, create framebuffer object */
+  auto fb_id_handle = DrmFbIdHandle::CreateInstance(bo, first_handle, drm_);
+  if (fb_id_handle) {
+    drm_fb_id_handle_cache_[first_handle] = fb_id_handle;
+  }
+
+  return fb_id_handle;
+}
+
+}  // namespace android
diff --git a/drm/DrmFbImporter.h b/drm/DrmFbImporter.h
new file mode 100644 (file)
index 0000000..167aa60
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DRM_DRMFBIMPORTER_H_
+#define DRM_DRMFBIMPORTER_H_
+
+#include <drm/drm_fourcc.h>
+#include <hardware/gralloc.h>
+
+#include <array>
+#include <map>
+
+#include "drm/DrmDevice.h"
+#include "drmhwcgralloc.h"
+
+#ifndef DRM_FORMAT_INVALID
+#define DRM_FORMAT_INVALID 0
+#endif
+
+using GemHandle = uint32_t;
+
+namespace android {
+
+class DrmFbIdHandle {
+ public:
+  static auto CreateInstance(hwc_drm_bo_t *bo, GemHandle first_gem_handle,
+                             const std::shared_ptr<DrmDevice> &drm)
+      -> std::shared_ptr<DrmFbIdHandle>;
+
+  ~DrmFbIdHandle();
+  DrmFbIdHandle(DrmFbIdHandle &&) = delete;
+  DrmFbIdHandle(const DrmFbIdHandle &) = delete;
+  auto operator=(const DrmFbIdHandle &) = delete;
+  auto operator=(DrmFbIdHandle &&) = delete;
+
+  auto GetFbId [[nodiscard]] () const -> uint32_t {
+    return fb_id_;
+  }
+
+ private:
+  explicit DrmFbIdHandle(std::shared_ptr<DrmDevice> drm)
+      : drm_(std::move(drm)){};
+
+  const std::shared_ptr<DrmDevice> drm_;
+
+  uint32_t fb_id_{};
+  std::array<GemHandle, HWC_DRM_BO_MAX_PLANES> gem_handles_{};
+};
+
+class DrmFbImporter {
+ public:
+  explicit DrmFbImporter(std::shared_ptr<DrmDevice> drm)
+      : drm_(std::move(drm)){};
+  ~DrmFbImporter() = default;
+  DrmFbImporter(const DrmFbImporter &) = delete;
+  DrmFbImporter(DrmFbImporter &&) = delete;
+  auto operator=(const DrmFbImporter &) = delete;
+  auto operator=(DrmFbImporter &&) = delete;
+
+  auto GetOrCreateFbId(hwc_drm_bo_t *bo) -> std::shared_ptr<DrmFbIdHandle>;
+
+ private:
+  void CleanupEmptyCacheElements() {
+    for (auto it = drm_fb_id_handle_cache_.begin();
+         it != drm_fb_id_handle_cache_.end();) {
+      if (it->second.expired()) {
+        it = drm_fb_id_handle_cache_.erase(it);
+      } else {
+        ++it;
+      }
+    }
+  }
+
+  const std::shared_ptr<DrmDevice> drm_;
+
+  std::map<GemHandle, std::weak_ptr<DrmFbIdHandle>> drm_fb_id_handle_cache_;
+};
+
+}  // namespace android
+
+#endif
diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp
deleted file mode 100644 (file)
index 0cbe601..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "hwc-platform-drm-generic"
-
-#include "DrmGenericImporter.h"
-
-#include <gralloc_handle.h>
-#include <hardware/gralloc.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-
-#include <cinttypes>
-
-#include "utils/log.h"
-#include "utils/properties.h"
-
-namespace android {
-
-DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) {
-  uint64_t cap_value = 0;
-  if (drmGetCap(drm_->fd(), DRM_CAP_ADDFB2_MODIFIERS, &cap_value)) {
-    ALOGE("drmGetCap failed. Fallback to no modifier support.");
-    cap_value = 0;
-  }
-  has_modifier_support_ = cap_value != 0;
-}
-
-int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) {
-  int ret = 0;
-
-  for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
-    if (bo->prime_fds[i] > 0) {
-      if (i == 0 || bo->prime_fds[i] != bo->prime_fds[0]) {
-        ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[i],
-                                 &bo->gem_handles[i]);
-        if (ret) {
-          ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[i], ret);
-          return ret;
-        }
-      } else {
-        bo->gem_handles[i] = bo->gem_handles[0];
-      }
-    }
-  }
-
-  bool has_modifiers = bo->modifiers[0] != DRM_FORMAT_MOD_NONE &&
-                       bo->modifiers[0] != DRM_FORMAT_MOD_INVALID;
-
-  if (!has_modifier_support_ && has_modifiers) {
-    ALOGE("No ADDFB2 with modifier support. Can't import modifier %" PRIu64,
-          bo->modifiers[0]);
-    return -EINVAL;
-  }
-
-  if (!has_modifiers)
-    ret = drmModeAddFB2(drm_->fd(), bo->width, bo->height, bo->format,
-                        bo->gem_handles, bo->pitches, bo->offsets, &bo->fb_id,
-                        0);
-  else
-    ret = drmModeAddFB2WithModifiers(drm_->fd(), bo->width, bo->height,
-                                     bo->format, bo->gem_handles, bo->pitches,
-                                     bo->offsets, bo->modifiers, &bo->fb_id,
-                                     DRM_MODE_FB_MODIFIERS);
-
-  if (ret) {
-    ALOGE("could not create drm fb %d", ret);
-    return ret;
-  }
-
-  for (unsigned int gem_handle : bo->gem_handles) {
-    if (!gem_handle)
-      continue;
-
-    ImportHandle(gem_handle);
-  }
-
-  return ret;
-}
-
-int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
-  if (bo->fb_id)
-    if (drmModeRmFB(drm_->fd(), bo->fb_id))
-      ALOGE("Failed to rm fb");
-
-  for (unsigned int &gem_handle : bo->gem_handles) {
-    if (!gem_handle)
-      continue;
-
-    if (ReleaseHandle(gem_handle))
-      ALOGE("Failed to release gem handle %d", gem_handle);
-    else
-      gem_handle = 0;
-  }
-  return 0;
-}
-
-int DrmGenericImporter::ImportHandle(uint32_t gem_handle) {
-  gem_refcount_[gem_handle]++;
-
-  return 0;
-}
-
-int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) {
-  if (--gem_refcount_[gem_handle])
-    return 0;
-
-  gem_refcount_.erase(gem_handle);
-
-  return CloseHandle(gem_handle);
-}
-
-int DrmGenericImporter::CloseHandle(uint32_t gem_handle) {
-  struct drm_gem_close gem_close {};
-  gem_close.handle = gem_handle;
-  int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
-  if (ret)
-    ALOGE("Failed to close gem handle %d %d", gem_handle, ret);
-
-  return ret;
-}
-}  // namespace android
diff --git a/drm/DrmGenericImporter.h b/drm/DrmGenericImporter.h
deleted file mode 100644 (file)
index 27cfc3b..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_PLATFORM_DRM_GENERIC_H_
-#define ANDROID_PLATFORM_DRM_GENERIC_H_
-
-#include <drm/drm_fourcc.h>
-#include <hardware/gralloc.h>
-
-#include <map>
-
-#include "drm/DrmDevice.h"
-#include "drmhwcgralloc.h"
-
-#ifndef DRM_FORMAT_INVALID
-#define DRM_FORMAT_INVALID 0
-#endif
-
-namespace android {
-
-class Importer {
- public:
-  virtual ~Importer() = default;
-
-  // Imports the buffer referred to by handle into bo.
-  //
-  // Note: This can be called from a different thread than ReleaseBuffer. The
-  //       implementation is responsible for ensuring thread safety.
-  virtual int ImportBuffer(hwc_drm_bo_t *bo) = 0;
-
-  // Releases the buffer object (ie: does the inverse of ImportBuffer)
-  //
-  // Note: This can be called from a different thread than ImportBuffer. The
-  //       implementation is responsible for ensuring thread safety.
-  virtual int ReleaseBuffer(hwc_drm_bo_t *bo) = 0;
-};
-
-class DrmGenericImporter : public Importer {
- public:
-  DrmGenericImporter(DrmDevice *drm);
-  ~DrmGenericImporter() override = default;
-
-  int ImportBuffer(hwc_drm_bo_t *bo) override;
-  int ReleaseBuffer(hwc_drm_bo_t *bo) override;
-  int ImportHandle(uint32_t gem_handle);
-  int ReleaseHandle(uint32_t gem_handle);
-
- protected:
-  DrmDevice *drm_;
-
- private:
-  int CloseHandle(uint32_t gem_handle);
-  std::map<uint32_t, int> gem_refcount_;
-  bool has_modifier_support_;
-};
-
-}  // namespace android
-
-#endif
index f8e9cab..ef44180 100644 (file)
@@ -74,20 +74,11 @@ int ResourceManager::Init() {
                        (const hw_module_t **)&gralloc_);
 }
 
-int ResourceManager::AddDrmDevice(std::string const &path) {
-  std::unique_ptr<DrmDevice> drm = std::make_unique<DrmDevice>();
+int ResourceManager::AddDrmDevice(const std::string &path) {
+  auto drm = std::make_unique<DrmDevice>();
   int displays_added = 0;
   int ret = 0;
   std::tie(ret, displays_added) = drm->Init(path.c_str(), num_displays_);
-  if (ret)
-    return ret;
-  std::shared_ptr<Importer> importer;
-  importer = std::make_shared<DrmGenericImporter>(drm.get());
-  if (!importer) {
-    ALOGE("Failed to create importer instance");
-    return -ENODEV;
-  }
-  importers_.push_back(importer);
   drms_.push_back(std::move(drm));
   num_displays_ += displays_added;
   return ret;
@@ -139,14 +130,6 @@ DrmDevice *ResourceManager::GetDrmDevice(int display) {
   return nullptr;
 }
 
-std::shared_ptr<Importer> ResourceManager::GetImporter(int display) {
-  for (unsigned int i = 0; i < drms_.size(); i++) {
-    if (drms_[i]->HandlesDisplay(display))
-      return importers_[i];
-  }
-  return nullptr;
-}
-
 const gralloc_module_t *ResourceManager::gralloc() {
   return gralloc_;
 }
index fca6e1f..9b4155b 100644 (file)
@@ -20,7 +20,7 @@
 #include <string.h>
 
 #include "DrmDevice.h"
-#include "DrmGenericImporter.h"
+#include "DrmFbImporter.h"
 
 namespace android {
 
@@ -31,7 +31,6 @@ class ResourceManager {
   ResourceManager &operator=(const ResourceManager &) = delete;
   int Init();
   DrmDevice *GetDrmDevice(int display);
-  std::shared_ptr<Importer> GetImporter(int display);
   const gralloc_module_t *gralloc();
   DrmConnector *AvailableWritebackConnector(int display);
   const std::vector<std::unique_ptr<DrmDevice>> &getDrmDevices() const {
@@ -50,7 +49,6 @@ class ResourceManager {
 
   int num_displays_;
   std::vector<std::unique_ptr<DrmDevice>> drms_;
-  std::vector<std::shared_ptr<Importer>> importers_;
   const gralloc_module_t *gralloc_;
 
   bool scale_with_gpu_{};
index 05b2cf0..db54802 100644 (file)
@@ -29,11 +29,8 @@ typedef struct hwc_drm_bo {
   uint32_t pitches[HWC_DRM_BO_MAX_PLANES];
   uint32_t offsets[HWC_DRM_BO_MAX_PLANES];
   uint32_t prime_fds[HWC_DRM_BO_MAX_PLANES];
-  uint32_t gem_handles[HWC_DRM_BO_MAX_PLANES];
   uint64_t modifiers[HWC_DRM_BO_MAX_PLANES];
-  uint32_t fb_id;
   int acquire_fence_fd;
-  void *priv;
 } hwc_drm_bo_t;
 
 #endif  // ANDROID_DRMHWCGRALLOC_H_
index a04cc29..e090dc6 100644 (file)
 #ifndef ANDROID_DRM_HWCOMPOSER_H_
 #define ANDROID_DRM_HWCOMPOSER_H_
 
+#include <hardware/hardware.h>
+#include <hardware/hwcomposer.h>
 #include <stdbool.h>
 #include <stdint.h>
 
 #include <vector>
 
-#include <hardware/hardware.h>
-#include <hardware/hwcomposer.h>
 #include "autofd.h"
+#include "drm/DrmFbImporter.h"
 #include "drmhwcgralloc.h"
 
+class DrmFbIdHandle;
 struct hwc_import_context;
 
 int hwc_import_init(struct hwc_import_context **ctx);
@@ -39,43 +41,43 @@ bool hwc_import_bo_release(int fd, struct hwc_import_context *ctx,
 
 namespace android {
 
-class Importer;
-
 class DrmHwcBuffer {
  public:
   DrmHwcBuffer() = default;
-  DrmHwcBuffer(const hwc_drm_bo &bo, Importer *importer)
-      : bo_(bo), importer_(importer) {
+  DrmHwcBuffer(const hwc_drm_bo &bo, DrmDevice *drmDevice)
+      : bo_(bo), mDrmDevice(drmDevice) {
   }
-  DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), importer_(rhs.importer_) {
-    rhs.importer_ = NULL;
+  DrmHwcBuffer(DrmHwcBuffer &&rhs) : bo_(rhs.bo_), mDrmDevice(rhs.mDrmDevice) {
+    rhs.mDrmDevice = nullptr;
+    FbIdHandle.swap(rhs.FbIdHandle);
   }
 
   ~DrmHwcBuffer() {
-    Clear();
   }
 
   DrmHwcBuffer &operator=(DrmHwcBuffer &&rhs) {
-    Clear();
-    importer_ = rhs.importer_;
-    rhs.importer_ = NULL;
+    FbIdHandle.swap(rhs.FbIdHandle);
+    mDrmDevice = rhs.mDrmDevice;
+    rhs.mDrmDevice = nullptr;
     bo_ = rhs.bo_;
     return *this;
   }
 
   operator bool() const {
-    return importer_ != NULL;
+    return mDrmDevice != NULL;
   }
 
   const hwc_drm_bo *operator->() const;
 
   void Clear();
 
-  int ImportBuffer(buffer_handle_t handle, Importer *importer);
+  std::shared_ptr<DrmFbIdHandle> FbIdHandle;
+
+  int ImportBuffer(buffer_handle_t handle, DrmDevice *drmDevice);
 
  private:
   hwc_drm_bo bo_;
-  Importer *importer_ = NULL;
+  DrmDevice *mDrmDevice;
 };
 
 class DrmHwcNativeHandle {
@@ -141,8 +143,8 @@ struct DrmHwcLayer {
   UniqueFd acquire_fence;
   OutputFd release_fence;
 
-  int ImportBuffer(Importer *importer);
-  int InitFromDrmHwcLayer(DrmHwcLayer *layer, Importer *importer);
+  int ImportBuffer(DrmDevice *drmDevice);
+  int InitFromDrmHwcLayer(DrmHwcLayer *layer, DrmDevice *drmDevice);
 
   void SetTransform(int32_t sf_transform);
 
index 81097ce..d9b8a87 100644 (file)
@@ -22,7 +22,7 @@
 #include <ui/GraphicBufferMapper.h>
 
 #include "bufferinfo/BufferInfoGetter.h"
-#include "drm/DrmGenericImporter.h"
+#include "drm/DrmFbImporter.h"
 #include "drmhwcomposer.h"
 
 #define UNUSED(x) (void)(x)
@@ -30,7 +30,7 @@
 namespace android {
 
 const hwc_drm_bo *DrmHwcBuffer::operator->() const {
-  if (importer_ == nullptr) {
+  if (mDrmDevice == nullptr) {
     ALOGE("Access of non-existent BO");
     exit(1);
     return nullptr;
@@ -39,13 +39,11 @@ const hwc_drm_bo *DrmHwcBuffer::operator->() const {
 }
 
 void DrmHwcBuffer::Clear() {
-  if (importer_ != nullptr) {
-    importer_->ReleaseBuffer(&bo_);
-    importer_ = nullptr;
-  }
+  FbIdHandle.reset();
+  mDrmDevice = nullptr;
 }
 
-int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
+int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, DrmDevice *drmDevice) {
   hwc_drm_bo tmp_bo{};
 
   int ret = BufferInfoGetter::GetInstance()->ConvertBoInfo(handle, &tmp_bo);
@@ -54,18 +52,13 @@ int DrmHwcBuffer::ImportBuffer(buffer_handle_t handle, Importer *importer) {
     return ret;
   }
 
-  ret = importer->ImportBuffer(&tmp_bo);
-  if (ret) {
-    ALOGE("Failed to import buffer %d", ret);
-    return ret;
-  }
-
-  if (importer_ != nullptr) {
-    importer_->ReleaseBuffer(&bo_);
+  FbIdHandle = drmDevice->GetDrmFbImporter().GetOrCreateFbId(&tmp_bo);
+  if (!FbIdHandle) {
+    ALOGE("Failed to import buffer");
+    return -EINVAL;
   }
 
-  importer_ = importer;
-
+  mDrmDevice = drmDevice;
   bo_ = tmp_bo;
 
   return 0;
@@ -106,8 +99,8 @@ void DrmHwcNativeHandle::Clear() {
   }
 }
 
-int DrmHwcLayer::ImportBuffer(Importer *importer) {
-  int ret = buffer.ImportBuffer(sf_handle, importer);
+int DrmHwcLayer::ImportBuffer(DrmDevice *drmDevice) {
+  int ret = buffer.ImportBuffer(sf_handle, drmDevice);
   if (ret)
     return ret;
 
@@ -123,7 +116,7 @@ int DrmHwcLayer::ImportBuffer(Importer *importer) {
 }
 
 int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer,
-                                     Importer *importer) {
+                                     DrmDevice *drmDevice) {
   blending = src_layer->blending;
   sf_handle = src_layer->sf_handle;
   acquire_fence = -1;
@@ -131,7 +124,7 @@ int DrmHwcLayer::InitFromDrmHwcLayer(DrmHwcLayer *src_layer,
   alpha = src_layer->alpha;
   source_crop = src_layer->source_crop;
   transform = src_layer->transform;
-  return ImportBuffer(importer);
+  return ImportBuffer(drmDevice);
 }
 
 void DrmHwcLayer::SetTransform(int32_t sf_transform) {