OSDN Git Service

Add support to import framebuffers from minigbm buffers
authorlambdadroid <lambdadroid@gmail.com>
Fri, 4 Jan 2019 19:36:25 +0000 (20:36 +0100)
committerlambdadroid <lambdadroid@gmail.com>
Sun, 6 Jan 2019 18:25:15 +0000 (19:25 +0100)
The buffers are checked at runtime to handle both allocator
implementations transparently without having to re-compile.

Android.mk
DrmFramebuffer.cpp
DrmFramebufferImporter.h [new file with mode: 0644]
DrmFramebufferLibDrm.cpp [new file with mode: 0644]
DrmFramebufferMinigbm.cpp [new file with mode: 0644]

index 5beaefc..179f4ff 100644 (file)
@@ -8,6 +8,7 @@ LOCAL_MODULE := android.hardware.graphics.composer@2.1-service.drmfb
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_VENDOR_MODULE := true
 LOCAL_INIT_RC := android.hardware.graphics.composer@2.1-service.drmfb.rc
+
 LOCAL_CPP_STD := c++17
 
 LOCAL_SRC_FILES := \
@@ -15,7 +16,8 @@ LOCAL_SRC_FILES := \
     DrmComposer.cpp \
     DrmDevice.cpp \
     DrmDisplay.cpp \
-    DrmFramebuffer.cpp
+    DrmFramebuffer.cpp \
+    DrmFramebufferLibDrm.cpp
 
 LOCAL_HEADER_LIBRARIES := \
     android.hardware.graphics.composer@2.1-hal
@@ -35,4 +37,11 @@ LOCAL_SHARED_LIBRARIES := \
     android.hardware.graphics.mapper@2.0 \
     android.hardware.graphics.composer@2.1
 
+ifeq ($(strip $(BOARD_USES_MINIGBM)), true)
+LOCAL_CFLAGS += -DUSE_MINIGBM
+LOCAL_SRC_FILES += DrmFramebufferMinigbm.cpp
+LOCAL_C_INCLUDES += external/minigbm/cros_gralloc
+LOCAL_SHARED_LIBRARIES += libnativewindow # TODO: Remove
+endif
+
 include $(BUILD_EXECUTABLE)
index f8242d2..2b57efc 100644 (file)
@@ -4,13 +4,9 @@
 #define LOG_TAG "drmfb-framebuffer"
 
 #include <android-base/logging.h>
-#include <drm/drm_fourcc.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
-#include <system/graphics.h>
-#include <android/gralloc_handle.h>
-#include "DrmFramebuffer.h"
 #include "DrmDevice.h"
+#include "DrmFramebuffer.h"
+#include "DrmFramebufferImporter.h"
 
 namespace android {
 namespace hardware {
@@ -20,54 +16,17 @@ namespace V2_1 {
 namespace drmfb {
 
 namespace {
-static uint32_t convertAndroidToDrmFbFormat(uint32_t format) {
-    switch (format) {
-    case HAL_PIXEL_FORMAT_RGBA_8888:
-        /* Avoid using alpha bits for the framebuffer.
-         * They are not supported on older Intel GPUs for primary planes. */
-    case HAL_PIXEL_FORMAT_RGBX_8888:
-        return DRM_FORMAT_XBGR8888;
-    case HAL_PIXEL_FORMAT_RGB_888:
-        return DRM_FORMAT_BGR888;
-    case HAL_PIXEL_FORMAT_RGB_565:
-        return DRM_FORMAT_BGR565;
-    case HAL_PIXEL_FORMAT_BGRA_8888:
-        return DRM_FORMAT_ARGB8888;
-    default:
-        LOG(ERROR) << "Unsupported framebuffer format: " << format;
-        return 0;
-    }
-}
-
+// TODO: Add a proper importer interface
 uint32_t addFramebuffer(int fd, buffer_handle_t buffer) {
-    auto handle = gralloc_handle(buffer);
-    if (!handle) {
-        LOG(ERROR) << "Failed to add framebuffer for buffer " << buffer
-            << ": Not a libdrm gralloc handle";
-        return 0;
-    }
-
-    // Lookup the handle for the prime fd
-    uint32_t id;
-    if (drmPrimeFDToHandle(fd, handle->prime_fd, &id)) {
-        PLOG(ERROR) << "Failed to add framebuffer for buffer " << buffer
-            << ": Failed to get handle for prime fd " << handle->prime_fd;
-        return 0;
-    }
-
-    // Add a new framebuffer
-    uint32_t pitches[4] = { handle->stride, 0, 0, 0 };
-    uint32_t offsets[4] = { 0, 0, 0, 0 };
-    uint32_t handles[4] = { id, 0, 0, 0 };
-
-    if (drmModeAddFB2(fd, handle->width, handle->height,
-            convertAndroidToDrmFbFormat(handle->format),
-            handles, pitches, offsets, &id, 0)) {
-        PLOG(ERROR) << "drmModeAddFB2 failed for buffer " << buffer;
-        return 0;
-    }
-
-    return id;
+    uint32_t id = 0;
+    if (libdrm::addFramebuffer(fd, buffer, &id))
+        return id;
+    if (minigbm::addFramebuffer(fd, buffer, &id))
+        return id;
+
+    LOG(ERROR) << "No importer available for buffer with "
+        << buffer->numFds << " FDs and " << buffer->numInts << " ints";
+    return 0;
 }
 }
 
diff --git a/DrmFramebufferImporter.h b/DrmFramebufferImporter.h
new file mode 100644 (file)
index 0000000..c703d38
--- /dev/null
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2019 Stephan Gerhold
+
+#pragma once
+
+#include <cstdint>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace drmfb {
+
+namespace libdrm {
+    bool addFramebuffer(int fd, buffer_handle_t buffer, uint32_t* id);
+}
+
+namespace minigbm {
+#ifdef USE_MINIGBM
+    bool addFramebuffer(int fd, buffer_handle_t buffer, uint32_t* id);
+#else
+    constexpr bool addFramebuffer(int, buffer_handle_t, uint32_t*) {
+        return false;
+    }
+#endif
+}
+
+}  // namespace drmfb
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/DrmFramebufferLibDrm.cpp b/DrmFramebufferLibDrm.cpp
new file mode 100644 (file)
index 0000000..cb2bd82
--- /dev/null
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2019 Stephan Gerhold
+
+#define LOG_TAG "drmfb-framebuffer-libdrm"
+
+#include <android-base/logging.h>
+#include <drm/drm_fourcc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <system/graphics.h>
+
+#include <android/gralloc_handle.h>
+#include "DrmFramebufferImporter.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace drmfb {
+namespace libdrm {
+
+namespace {
+static uint32_t convertAndroidToDrmFbFormat(uint32_t format) {
+    switch (format) {
+    case HAL_PIXEL_FORMAT_RGBA_8888:
+        /* Avoid using alpha bits for the framebuffer.
+         * They are not supported on older Intel GPUs for primary planes. */
+    case HAL_PIXEL_FORMAT_RGBX_8888:
+        return DRM_FORMAT_XBGR8888;
+    case HAL_PIXEL_FORMAT_RGB_888:
+        return DRM_FORMAT_BGR888;
+    case HAL_PIXEL_FORMAT_RGB_565:
+        return DRM_FORMAT_BGR565;
+    case HAL_PIXEL_FORMAT_BGRA_8888:
+        return DRM_FORMAT_ARGB8888;
+    default:
+        LOG(ERROR) << "Unsupported framebuffer format: " << format;
+        return 0;
+    }
+}
+
+void addFramebuffer(int fd, struct gralloc_handle_t* handle, uint32_t* id) {
+    uint32_t handles[4] = {};
+    uint32_t pitches[4] = {handle->stride};
+    uint32_t offsets[4] = {};
+
+    if (drmPrimeFDToHandle(fd, handle->prime_fd, &handles[0])) {
+        PLOG(ERROR) << "Failed to get handle for prime fd " << handle->prime_fd;
+        return;
+    }
+
+    if (drmModeAddFB2(fd, handle->width, handle->height,
+            convertAndroidToDrmFbFormat(handle->format),
+            handles, pitches, offsets, id, 0)) {
+        PLOG(ERROR) << "drmModeAddFB2 failed";
+    }
+}
+}
+
+bool addFramebuffer(int fd, buffer_handle_t buffer, uint32_t* id) {
+    if (buffer->numFds != GRALLOC_HANDLE_NUM_FDS
+            || buffer->numInts < static_cast<int>(GRALLOC_HANDLE_NUM_INTS))
+        return false;
+
+    auto handle = gralloc_handle(buffer);
+    if (handle->magic != GRALLOC_HANDLE_MAGIC)
+        return false;
+
+    if (handle->version != GRALLOC_HANDLE_VERSION) {
+        LOG(ERROR) << "gralloc_handle_t version mismatch: expected "
+                       << GRALLOC_HANDLE_VERSION << ", got " << handle->version;
+        return true;
+    }
+
+    addFramebuffer(fd, handle, id);
+    return true;
+}
+
+}  // namespace libdrm
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/DrmFramebufferMinigbm.cpp b/DrmFramebufferMinigbm.cpp
new file mode 100644 (file)
index 0000000..9613d44
--- /dev/null
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright (C) 2019 Stephan Gerhold
+
+#define LOG_TAG "drmfb-framebuffer-minigbm"
+
+#include <android-base/logging.h>
+#include <drm/drm_fourcc.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+
+#include <cros_gralloc_handle.h>
+#include <cros_gralloc_helpers.h>
+#include "DrmFramebufferImporter.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace drmfb {
+namespace minigbm {
+
+namespace {
+void addFramebuffer(int fd, cros_gralloc_handle_t handle, int planes, uint32_t* id) {
+    uint32_t handles[DRV_MAX_PLANES] = {};
+    for (int i = 0; i < planes; ++i) {
+        if (drmPrimeFDToHandle(fd, handle->fds[i], &handles[i])) {
+            PLOG(ERROR) << "Failed to get handle for prime fd "
+                << handle->fds[i] << " (plane " << i << ")";
+            return;
+        }
+    }
+
+    /*
+     * Avoid using alpha bits for the framebuffer.
+     * They are not supported on older Intel GPUs for primary planes.
+     */
+    auto format = handle->format;
+    if (format == DRM_FORMAT_ABGR8888)
+        format = DRM_FORMAT_XBGR8888;
+
+    // TODO: Consider using drmModeAddFB2WithModifiers
+    if (drmModeAddFB2(fd, handle->width, handle->height,
+            format, handles, handle->strides, handle->offsets, id, 0)) {
+        PLOG(ERROR) << "drmModeAddFB2 failed";
+    }
+}
+}
+
+bool addFramebuffer(int fd, buffer_handle_t buffer, uint32_t* id) {
+    auto planes = buffer->numFds;
+    if (planes < 1 && planes > DRV_MAX_PLANES)
+        return false;
+    if ((buffer->numInts + planes) < static_cast<int>(handle_data_size))
+        return false;
+
+    auto handle = reinterpret_cast<cros_gralloc_handle_t>(buffer);
+    if (handle->magic != cros_gralloc_magic)
+        return false;
+
+    addFramebuffer(fd, handle, planes, id);
+    return true;
+}
+
+}  // namespace minigbm
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android