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;
+}