drm_hwcomposer: Split gralloc out into an importer
Add the concept of an importer so we can plug in different
sources of bo.
Signed-off-by: Sean Paul <seanpaul@chromium.org>
Change-Id: I4f741ef4fa7c44e9cb31db61a146aed273854a69
diff --git a/Android.mk b/Android.mk
index 2eb3212..efc78ce 100644
--- a/Android.mk
+++ b/Android.mk
@@ -16,6 +16,9 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
+# TODO: We should specify this in device.mk
+BUFFER_IMPORTER := gralloc
+
LOCAL_SHARED_LIBRARIES := \
libdrm \
libhardware \
@@ -32,6 +35,12 @@
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := hwcomposer.cpp
+
+ifeq ($(strip $(BUFFER_IMPORTER)),gralloc)
+LOCAL_C_INCLUDES += external/drm_gralloc
+LOCAL_SRC_FILES += hwcomposer_import_drm_gralloc.cpp
+endif
+
LOCAL_MODULE := hwcomposer.drm
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_RELATIVE_PATH := hw
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
new file mode 100644
index 0000000..a83acab
--- /dev/null
+++ b/drm_hwcomposer.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+struct hwc_import_context;
+
+struct hwc_drm_bo {
+ uint32_t width;
+ uint32_t height;
+ uint32_t format; /* DRM_FORMAT_* from drm_fourcc.h */
+ uint32_t pitches[4];
+ uint32_t offsets[4];
+ uint32_t gem_handles[4];
+ uint32_t fb_id;
+ int acquire_fence_fd;
+
+ /* TODO: This is bad voodoo, remove it once drm_gralloc uses dma_buf */
+ int importer_fd;
+};
+
+int hwc_import_init(struct hwc_import_context **ctx);
+int hwc_import_destroy(struct hwc_import_context *ctx);
+
+int hwc_create_bo_from_import(int fd, struct hwc_import_context *ctx,
+ buffer_handle_t buf, struct hwc_drm_bo *bo);
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index 175e573..022fa62 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -26,16 +26,13 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
-#include <drm/drm_fourcc.h>
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
#include <sync/sync.h>
-#include <gralloc_drm.h>
-#include <gralloc_drm_priv.h>
-#include <gralloc_drm_handle.h>
+#include "drm_hwcomposer.h"
#define ARRAY_SIZE(arr) (int)(sizeof(arr) / sizeof((arr)[0]))
@@ -49,18 +46,6 @@
DRM_MODE_CONNECTOR_DSI,
};
-struct hwc_drm_bo {
- int fd; /* TODO: This is bad voodoo, remove it */
- uint32_t width;
- uint32_t height;
- uint32_t format;
- uint32_t pitches[4];
- uint32_t offsets[4];
- uint32_t gem_handles[4];
- uint32_t fb_id;
- int acquire_fence_fd;
-};
-
struct hwc_worker {
pthread_t thread;
pthread_mutex_t lock;
@@ -90,9 +75,9 @@
hwc_composer_device_1_t device;
int fd;
- struct drm_module_t *gralloc_module; /* TODO: NUKE THIS */
hwc_procs_t const *procs;
+ struct hwc_import_context *import_ctx;
struct hwc_drm_display displays[MAX_NUM_DISPLAYS];
int num_displays;
@@ -167,6 +152,20 @@
return ret;
}
+/*
+ * TODO: This hack allows us to use the importer's fd to drm to add and remove
+ * framebuffers. The reason it exists is because gralloc doesn't export its
+ * bo's, so we have to use its file descriptor to drm for some operations. Once
+ * gralloc behaves, we can remove this.
+ */
+static int hwc_get_fd_for_bo(struct hwc_context_t *ctx, struct hwc_drm_bo *bo)
+{
+ if (bo->importer_fd >= 0)
+ return bo->importer_fd;
+
+ return ctx->fd;
+}
+
static bool hwc_mode_is_equal(drmModeModeInfoPtr a, drmModeModeInfoPtr b)
{
return a->clock == b->clock &&
@@ -272,9 +271,10 @@
{
int ret;
- ret = drmModeAddFB2(hd->back.fd, hd->back.width, hd->back.height,
- hd->back.format, hd->back.gem_handles, hd->back.pitches,
- hd->back.offsets, &hd->back.fb_id, 0);
+ ret = drmModeAddFB2(hwc_get_fd_for_bo(hd->ctx, &hd->back),
+ hd->back.width, hd->back.height, hd->back.format,
+ hd->back.gem_handles, hd->back.pitches, hd->back.offsets,
+ &hd->back.fb_id, 0);
if (ret) {
ALOGE("could not create drm fb %d", ret);
return ret;
@@ -295,7 +295,8 @@
}
if (hd->front.fb_id) {
- ret = drmModeRmFB(hd->front.fd, hd->front.fb_id);
+ ret = drmModeRmFB(hwc_get_fd_for_bo(hd->ctx, &hd->front),
+ hd->front.fb_id);
if (ret) {
ALOGE("Failed to rm fb from front %d", ret);
return ret;
@@ -346,53 +347,6 @@
return NULL;
}
-static uint32_t hwc_convert_hal_format_to_drm_format(uint32_t hal_format)
-{
- switch(hal_format) {
- case HAL_PIXEL_FORMAT_RGB_888:
- return DRM_FORMAT_BGR888;
- case HAL_PIXEL_FORMAT_BGRA_8888:
- return DRM_FORMAT_ARGB8888;
- case HAL_PIXEL_FORMAT_RGBX_8888:
- return DRM_FORMAT_XBGR8888;
- case HAL_PIXEL_FORMAT_RGBA_8888:
- return DRM_FORMAT_ABGR8888;
- case HAL_PIXEL_FORMAT_RGB_565:
- return DRM_FORMAT_BGR565;
- case HAL_PIXEL_FORMAT_YV12:
- return DRM_FORMAT_YVU420;
- default:
- ALOGE("Cannot convert hal format to drm format %u", hal_format);
- return -EINVAL;
- }
-}
-
-/* TODO: NUKE THIS */
-static int hwc_convert_gralloc_handle_to_drm_bo(hwc_context_t *ctx,
- buffer_handle_t handle, struct hwc_drm_bo *bo)
-{
- gralloc_drm_t *drm = ctx->gralloc_module->drm;
- gralloc_drm_handle_t *gr_handle;
- struct gralloc_drm_bo_t *gralloc_bo;
-
- gr_handle = (gralloc_drm_handle_t *)handle;
-
- gralloc_bo = gr_handle->data;
- if (!gralloc_bo) {
- ALOGE("Could not get drm bo from handle");
- return -EINVAL;
- }
-
- bo->fd = drm->fd;
- bo->width = gr_handle->width;
- bo->height = gr_handle->height;
- bo->format = hwc_convert_hal_format_to_drm_format(gr_handle->format);
- bo->pitches[0] = gr_handle->stride;
- bo->gem_handles[0] = gralloc_bo->fb_handle;
-
- return 0;
-}
-
static int hwc_set_display(hwc_context_t *ctx, int display,
hwc_display_contents_1_t* display_contents)
{
@@ -442,10 +396,10 @@
goto out;
}
- ret = hwc_convert_gralloc_handle_to_drm_bo(ctx, layer->handle,
- &hd->back);
+ ret = hwc_create_bo_from_import(ctx->fd, ctx->import_ctx, layer->handle,
+ &hd->back);
if (ret) {
- ALOGE("Failed to convert gralloc handle to drm bo %d", ret);
+ ALOGE("Failed to import handle to drm bo %d", ret);
goto out;
}
@@ -938,12 +892,17 @@
static int hwc_device_close(struct hw_device_t *dev)
{
struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
- int i;
+ int ret, i;
for (i = 0; i < MAX_NUM_DISPLAYS; i++)
hwc_destroy_display(&ctx->displays[i]);
drmClose(ctx->fd);
+
+ ret = hwc_import_destroy(ctx->import_ctx);
+ if (ret)
+ ALOGE("Could not destroy import %d", ret);
+
free(ctx);
return 0;
@@ -1100,11 +1059,9 @@
return -ENOMEM;
}
- /* TODO: NUKE THIS */
- ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
- (const hw_module_t **)&ctx->gralloc_module);
+ ret = hwc_import_init(&ctx->import_ctx);
if (ret) {
- ALOGE("Failed to open gralloc module");
+ ALOGE("Failed to initialize import context");
goto out;
}
diff --git a/hwcomposer_import_drm_gralloc.cpp b/hwcomposer_import_drm_gralloc.cpp
new file mode 100644
index 0000000..065170c
--- /dev/null
+++ b/hwcomposer_import_drm_gralloc.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+#include <cutils/log.h>
+
+#include <drm/drm_fourcc.h>
+
+#include <gralloc_drm.h>
+#include <gralloc_drm_priv.h>
+#include <gralloc_drm_handle.h>
+
+#include "drm_hwcomposer.h"
+
+struct hwc_import_context {
+ struct drm_module_t *gralloc_module;
+};
+
+int hwc_import_init(struct hwc_import_context **ctx)
+{
+ int ret;
+ struct hwc_import_context *import_ctx;
+
+ import_ctx = (struct hwc_import_context *)calloc(1,
+ sizeof(*import_ctx));
+ if (!ctx) {
+ ALOGE("Failed to allocate gralloc import context");
+ return -ENOMEM;
+ }
+
+ ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&import_ctx->gralloc_module);
+ if (ret) {
+ ALOGE("Failed to open gralloc module");
+ goto err;
+ }
+
+ *ctx = import_ctx;
+
+ return 0;
+
+err:
+ free(import_ctx);
+ return ret;
+}
+
+int hwc_import_destroy(struct hwc_import_context *ctx)
+{
+ free(ctx);
+ return 0;
+}
+
+static uint32_t hwc_convert_hal_format_to_drm_format(uint32_t hal_format)
+{
+ switch(hal_format) {
+ case HAL_PIXEL_FORMAT_RGB_888:
+ return DRM_FORMAT_BGR888;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ return DRM_FORMAT_ARGB8888;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ return DRM_FORMAT_XBGR8888;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ return DRM_FORMAT_ABGR8888;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ return DRM_FORMAT_BGR565;
+ case HAL_PIXEL_FORMAT_YV12:
+ return DRM_FORMAT_YVU420;
+ default:
+ ALOGE("Cannot convert hal format to drm format %u", hal_format);
+ return -EINVAL;
+ }
+}
+
+int hwc_create_bo_from_import(int /* fd */, hwc_import_context *ctx,
+ buffer_handle_t handle, struct hwc_drm_bo *bo)
+{
+ gralloc_drm_t *drm = ctx->gralloc_module->drm;
+ gralloc_drm_handle_t *gr_handle;
+ struct gralloc_drm_bo_t *gralloc_bo;
+ gr_handle = (gralloc_drm_handle_t *)handle;
+
+ gralloc_bo = gr_handle->data;
+ if (!gralloc_bo) {
+ ALOGE("Could not get drm bo from handle");
+ return -EINVAL;
+ }
+
+ bo->importer_fd = drm->fd;
+ bo->width = gr_handle->width;
+ bo->height = gr_handle->height;
+ bo->format = hwc_convert_hal_format_to_drm_format(gr_handle->format);
+ bo->pitches[0] = gr_handle->stride;
+ bo->gem_handles[0] = gralloc_bo->fb_handle;
+ bo->offsets[0] = 0;
+
+ return 0;
+}