drm_hwcomposer: refactor platform directory
Motivation:
Platform term meaning used in drm_hwcomposer does not correspond to the
content of the platform directory. Platform directory consists of:
1. Buffer information getters for different gralloc (currently called platform).
2. Composition planner logic (which has flaws and should be reworked into
layer->plane mapping during validation stage logic).
3. DrmGenericImpoter with reference counting logic.
Android-11 IMapper@4 metadata API offers a generic way to access buffer
information which makes other gralloc buffer information getters obsolete.
Legacy getters should be maintained for some time until all known users
will migrate to Mapper@4 API.
Implementation:
1. Split 'PlatformImporter' logic to 'Importer' only and 'Buffer Getter' logic.
a. Remove buffer_handle_t parameter from ImportBuffer(). Instead user should
get BufferInfo using ConvertBoInfo to struct hwc_drm_bo_t, then use it for
ImportBuffer().
b. Move DrmGenericImporter.{cpp/h} into the drm directory.
2. Isolate planner code in single file and move it to compositor directory as
compositor/Planner.{cpp/h}
3. Rename platform definition
a. Rename platform directory to bufferinfo.
b. Rename/move bufferinfo/platorm*.{cpp,h} getters to
bufferinfo/legacy/BufferInfo*.{cpp,h}. Align class names/includes.
4. Split legacy/metadata getters logic.
a. Apply existing bufferinfogetter base class only for legacy getters.
b. Combine legacy/generic gettera under new base class.
c. Create a placeholder for generic(metadata) getter.
Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
diff --git a/drm/DrmDevice.cpp b/drm/DrmDevice.cpp
index 28ecfda..bf1a5e2 100644
--- a/drm/DrmDevice.cpp
+++ b/drm/DrmDevice.cpp
@@ -29,6 +29,7 @@
#include <algorithm>
#include <array>
#include <cinttypes>
+#include <sstream>
#include <string>
static void trim_left(std::string &str) {
diff --git a/drm/DrmDevice.h b/drm/DrmDevice.h
index d7ea359..be68aa6 100644
--- a/drm/DrmDevice.h
+++ b/drm/DrmDevice.h
@@ -19,6 +19,7 @@
#include <stdint.h>
+#include <map>
#include <tuple>
#include "DrmConnector.h"
@@ -26,7 +27,6 @@
#include "DrmEncoder.h"
#include "DrmEventListener.h"
#include "DrmPlane.h"
-#include "platform/platform.h"
namespace android {
diff --git a/drm/DrmGenericImporter.cpp b/drm/DrmGenericImporter.cpp
new file mode 100644
index 0000000..b4dc063
--- /dev/null
+++ b/drm/DrmGenericImporter.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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 <cutils/properties.h>
+#include <gralloc_handle.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+namespace android {
+
+DrmGenericImporter::DrmGenericImporter(DrmDevice *drm) : drm_(drm) {
+}
+
+DrmGenericImporter::~DrmGenericImporter() {
+}
+
+int DrmGenericImporter::ImportBuffer(hwc_drm_bo_t *bo) {
+ int ret = drmPrimeFDToHandle(drm_->fd(), bo->prime_fds[0],
+ &bo->gem_handles[0]);
+ if (ret) {
+ ALOGE("failed to import prime fd %d ret=%d", bo->prime_fds[0], ret);
+ return ret;
+ }
+
+ for (int i = 1; i < HWC_DRM_BO_MAX_PLANES; i++) {
+ int fd = bo->prime_fds[i];
+ if (fd != 0) {
+ if (fd != bo->prime_fds[0]) {
+ ALOGE("Multiplanar FBs are not supported by this version of composer");
+ return -ENOTSUP;
+ }
+ bo->gem_handles[i] = bo->gem_handles[0];
+ }
+ }
+
+ if (!bo->with_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,
+ bo->modifiers[0] ? DRM_MODE_FB_MODIFIERS
+ : 0);
+
+ if (ret) {
+ ALOGE("could not create drm fb %d", ret);
+ return ret;
+ }
+
+ ImportHandle(bo->gem_handles[0]);
+
+ 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 (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
+ if (!bo->gem_handles[i])
+ continue;
+
+ if (ReleaseHandle(bo->gem_handles[i])) {
+ ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
+ } else {
+ for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
+ if (bo->gem_handles[j] == bo->gem_handles[i])
+ bo->gem_handles[j] = 0;
+ bo->gem_handles[i] = 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;
+
+ memset(&gem_close, 0, sizeof(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
new file mode 100644
index 0000000..efda6be
--- /dev/null
+++ b/drm/DrmGenericImporter.h
@@ -0,0 +1,72 @@
+/*
+ * 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() {
+ }
+
+ // 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;
+
+ 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_;
+};
+
+} // namespace android
+
+#endif
diff --git a/drm/ResourceManager.cpp b/drm/ResourceManager.cpp
index 67ef7f8..fc24aea 100644
--- a/drm/ResourceManager.cpp
+++ b/drm/ResourceManager.cpp
@@ -24,6 +24,8 @@
#include <sstream>
+#include "bufferinfo/BufferInfoGetter.h"
+
namespace android {
ResourceManager::ResourceManager() : num_displays_(0), gralloc_(NULL) {
@@ -62,6 +64,11 @@
property_get("vendor.hwc.drm.scale_with_gpu", scale_with_gpu, "0");
scale_with_gpu_ = bool(strncmp(scale_with_gpu, "0", 1));
+ if (!BufferInfoGetter::GetInstance()) {
+ ALOGE("Failed to initialize BufferInfoGetter");
+ return -EINVAL;
+ }
+
return hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gralloc_);
}
@@ -73,7 +80,7 @@
if (ret)
return ret;
std::shared_ptr<Importer> importer;
- importer.reset(Importer::CreateInstance(drm.get()));
+ importer.reset(new DrmGenericImporter(drm.get()));
if (!importer) {
ALOGE("Failed to create importer instance");
return -ENODEV;
diff --git a/drm/ResourceManager.h b/drm/ResourceManager.h
index 94ba43e..7102cea 100644
--- a/drm/ResourceManager.h
+++ b/drm/ResourceManager.h
@@ -20,7 +20,7 @@
#include <string.h>
#include "DrmDevice.h"
-#include "platform/platform.h"
+#include "DrmGenericImporter.h"
namespace android {