summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2011-06-12 16:21:30 +0800
committerRob Herring <robh@kernel.org>2016-04-01 15:32:25 -0500
commitf6a33583e7ac19ef5a3f1d104b768ecd471fa851 (patch)
tree2372158843f33af9b4d0a3a5da6653033abfd1b7
downloadgbm_gralloc-f6a33583e7ac19ef5a3f1d104b768ecd471fa851.tar.gz
gbm_gralloc-f6a33583e7ac19ef5a3f1d104b768ecd471fa851.tar.xz
Initial GBM based gralloc
Based on drm_gralloc. Some remants of drm_gralloc remain to be compatible with mesa and drm_hwcomposer. Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r--Android.mk40
-rw-r--r--gralloc.cpp322
-rw-r--r--gralloc_drm.h38
-rw-r--r--gralloc_drm_handle.h92
-rw-r--r--gralloc_gbm.cpp486
-rw-r--r--gralloc_gbm_priv.h62
6 files changed, 1040 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..0c1695b
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,40 @@
+# Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+# DEALINGS IN THE SOFTWARE.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ gralloc_gbm.cpp \
+ gralloc.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libgbm \
+ liblog \
+ libcutils
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)
+
+LOCAL_MODULE := gralloc.drm
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_RELATIVE_PATH := hw
+include $(BUILD_SHARED_LIBRARY)
diff --git a/gralloc.cpp b/gralloc.cpp
new file mode 100644
index 0000000..809862d
--- /dev/null
+++ b/gralloc.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define LOG_TAG "GRALLOC-GBM"
+
+#include <cutils/log.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+#include <gbm.h>
+
+#include "gralloc_drm.h"
+#include "gralloc_gbm_priv.h"
+
+struct gbm_module_t {
+ gralloc_module_t base;
+
+ pthread_mutex_t mutex;
+ struct gbm_device *gbm;
+};
+
+static inline int gralloc_gbm_get_bpp(int format)
+{
+ int bpp;
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ bpp = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ bpp = 3;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ case HAL_PIXEL_FORMAT_YCbCr_422_I:
+ bpp = 2;
+ break;
+ /* planar; only Y is considered */
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ bpp = 1;
+ break;
+ default:
+ bpp = 0;
+ break;
+ }
+
+ return bpp;
+}
+
+/*
+ * Initialize the DRM device object
+ */
+static int gbm_init(struct gbm_module_t *dmod)
+{
+ int err = 0;
+
+ pthread_mutex_lock(&dmod->mutex);
+ if (!dmod->gbm) {
+ dmod->gbm = gbm_dev_create();
+ if (!dmod->gbm)
+ err = -EINVAL;
+ }
+ pthread_mutex_unlock(&dmod->mutex);
+
+ return err;
+}
+
+static int gbm_mod_perform(const struct gralloc_module_t *mod, int op, ...)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ va_list args;
+ int err;
+
+ err = gbm_init(dmod);
+ if (err)
+ return err;
+
+ va_start(args, op);
+ switch (op) {
+ case GRALLOC_MODULE_PERFORM_GET_DRM_FD:
+ {
+ int *fd = va_arg(args, int *);
+ *fd = gbm_device_get_fd(dmod->gbm);
+ err = 0;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ va_end(args);
+
+ return err;
+}
+
+static int gbm_mod_register_buffer(const gralloc_module_t *mod,
+ buffer_handle_t handle)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ int err;
+
+ err = gbm_init(dmod);
+ if (err)
+ return err;
+
+ pthread_mutex_lock(&dmod->mutex);
+ err = gralloc_gbm_handle_register(handle, dmod->gbm);
+ pthread_mutex_unlock(&dmod->mutex);
+
+ return err;
+}
+
+static int gbm_mod_unregister_buffer(const gralloc_module_t *mod,
+ buffer_handle_t handle)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ int err;
+
+ pthread_mutex_lock(&dmod->mutex);
+ err = gralloc_gbm_handle_unregister(handle);
+ pthread_mutex_unlock(&dmod->mutex);
+
+ return err;
+}
+
+static int gbm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle,
+ int usage, int x, int y, int w, int h, void **ptr)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ struct gralloc_gbm_bo_t *bo;
+ int err;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ bo = gralloc_gbm_bo_from_handle(handle);
+ if (!bo) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ err = gralloc_gbm_bo_lock(bo, usage, x, y, w, h, ptr);
+ ALOGE("buffer %p lock usage = %08x", handle, usage);
+
+unlock:
+ pthread_mutex_unlock(&dmod->mutex);
+ return err;
+}
+
+static int gbm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ struct gralloc_gbm_bo_t *bo;
+ int err = 0;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ bo = gralloc_gbm_bo_from_handle(handle);
+ if (!bo) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ gralloc_gbm_bo_unlock(bo);
+
+unlock:
+ pthread_mutex_unlock(&dmod->mutex);
+ return err;
+}
+
+static int gbm_mod_close_gpu0(struct hw_device_t *dev)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *)dev->module;
+ struct alloc_device_t *alloc = (struct alloc_device_t *) dev;
+
+ gbm_dev_destroy(dmod->gbm);
+ delete alloc;
+
+ return 0;
+}
+
+static int gbm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module;
+ struct gralloc_gbm_bo_t *bo;
+ int err = 0;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ bo = gralloc_gbm_bo_from_handle(handle);
+ if (!bo) {
+ err = -EINVAL;
+ goto unlock;
+ }
+
+ gralloc_gbm_bo_decref(bo);
+
+unlock:
+ pthread_mutex_unlock(&dmod->mutex);
+ return err;
+}
+
+static int gbm_mod_alloc_gpu0(alloc_device_t *dev,
+ int w, int h, int format, int usage,
+ buffer_handle_t *handle, int *stride)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) dev->common.module;
+ struct gralloc_gbm_bo_t *bo;
+ int size, err = 0;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ bo = gralloc_gbm_bo_create(dmod->gbm, w, h, format, usage);
+ if (!bo) {
+ err = -errno;
+ goto unlock;
+ }
+
+ *handle = gralloc_gbm_bo_get_handle(bo);
+ /* in pixels */
+ *stride = gbm_bo_get_stride(gralloc_gbm_bo_to_gbm_bo(bo)) /
+ gralloc_gbm_get_bpp(format);
+
+ ALOGE("buffer %p usage = %08x", *handle, usage);
+unlock:
+ pthread_mutex_unlock(&dmod->mutex);
+ return err;
+}
+
+static int gbm_mod_open_gpu0(struct gbm_module_t *dmod, hw_device_t **dev)
+{
+ struct alloc_device_t *alloc;
+ int err;
+
+ err = gbm_init(dmod);
+ if (err)
+ return err;
+
+ alloc = new alloc_device_t;
+ if (!alloc)
+ return -EINVAL;
+
+ alloc->common.tag = HARDWARE_DEVICE_TAG;
+ alloc->common.version = 0;
+ alloc->common.module = &dmod->base.common;
+ alloc->common.close = gbm_mod_close_gpu0;
+
+ alloc->alloc = gbm_mod_alloc_gpu0;
+ alloc->free = gbm_mod_free_gpu0;
+
+ *dev = &alloc->common;
+
+ return 0;
+}
+
+static int gbm_mod_open(const struct hw_module_t *mod,
+ const char *name, struct hw_device_t **dev)
+{
+ struct gbm_module_t *dmod = (struct gbm_module_t *) mod;
+ int err;
+
+ if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0)
+ err = gbm_mod_open_gpu0(dmod, dev);
+ else
+ err = -EINVAL;
+
+ return err;
+}
+
+static struct hw_module_methods_t gbm_mod_methods = {
+ .open = gbm_mod_open
+};
+
+struct gbm_module_t HAL_MODULE_INFO_SYM = {
+ .base = {
+ .common = {
+ .tag = HARDWARE_MODULE_TAG,
+ .version_major = 1,
+ .version_minor = 0,
+ .id = GRALLOC_HARDWARE_MODULE_ID,
+ .name = "GBM Memory Allocator",
+ .author = "Rob Herring - Linaro",
+ .methods = &gbm_mod_methods
+ },
+ .registerBuffer = gbm_mod_register_buffer,
+ .unregisterBuffer = gbm_mod_unregister_buffer,
+ .lock = gbm_mod_lock,
+ .unlock = gbm_mod_unlock,
+ .perform = gbm_mod_perform
+ },
+
+ .mutex = PTHREAD_MUTEX_INITIALIZER,
+ .gbm = NULL,
+};
diff --git a/gralloc_drm.h b/gralloc_drm.h
new file mode 100644
index 0000000..e4b528f
--- /dev/null
+++ b/gralloc_drm.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _GRALLOC_DRM_H_
+#define _GRALLOC_DRM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRALLOC_DRM_H_ */
diff --git a/gralloc_drm_handle.h b/gralloc_drm_handle.h
new file mode 100644
index 0000000..be2984a
--- /dev/null
+++ b/gralloc_drm_handle.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _GRALLOC_GBM_HANDLE_H_
+#define _GRALLOC_GBM_HANDLE_H_
+
+#include <cutils/log.h>
+#include <cutils/native_handle.h>
+#include <system/graphics.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct gralloc_drm_handle_t {
+ native_handle_t base;
+
+ /* file descriptors */
+ int prime_fd;
+
+ /* integers */
+ int magic;
+
+ int width;
+ int height;
+ int format;
+ int usage;
+
+ int name; /* the name of the bo */
+ int stride; /* the stride in bytes */
+
+ int data_owner; /* owner of data (for validation) */
+ union {
+ void *data; /* pointer to struct gralloc_gbm_bo_t */
+ uint64_t reserved;
+ } __attribute__((aligned(8)));
+};
+#define GRALLOC_GBM_HANDLE_MAGIC 0x12345678
+#define GRALLOC_GBM_HANDLE_NUM_FDS 1
+#define GRALLOC_GBM_HANDLE_NUM_INTS ( \
+ ((sizeof(struct gralloc_drm_handle_t) - sizeof(native_handle_t))/sizeof(int)) \
+ - GRALLOC_GBM_HANDLE_NUM_FDS)
+
+static inline struct gralloc_drm_handle_t *gralloc_drm_handle(buffer_handle_t _handle)
+{
+ struct gralloc_drm_handle_t *handle =
+ (struct gralloc_drm_handle_t *) _handle;
+
+ if (handle && (handle->base.version != sizeof(handle->base) ||
+ handle->base.numInts != GRALLOC_GBM_HANDLE_NUM_INTS ||
+ handle->base.numFds != GRALLOC_GBM_HANDLE_NUM_FDS ||
+ handle->magic != GRALLOC_GBM_HANDLE_MAGIC)) {
+ ALOGE("invalid handle: version=%d, numInts=%d, numFds=%d, magic=%x",
+ handle->base.version, handle->base.numInts,
+ handle->base.numFds, handle->magic);
+ handle = NULL;
+ }
+
+ return handle;
+}
+
+static inline int gralloc_drm_get_prime_fd(buffer_handle_t _handle)
+{
+ struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle);
+ return (handle) ? handle->prime_fd : -1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRALLOC_GBM_HANDLE_H_ */
diff --git a/gralloc_gbm.cpp b/gralloc_gbm.cpp
new file mode 100644
index 0000000..115aa8c
--- /dev/null
+++ b/gralloc_gbm.cpp
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define LOG_TAG "GRALLOC-GBM"
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+#include <cutils/properties.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+#include <gbm.h>
+
+#include "gralloc_gbm_priv.h"
+#include "gralloc_drm_handle.h"
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+struct gralloc_gbm_bo_t {
+ struct gbm_bo *bo;
+ void *map_data;
+
+ struct gralloc_gbm_handle_t *handle;
+
+ int imported; /* the handle is from a remote proces when true */
+
+ int lock_count;
+ int locked_for;
+
+ unsigned int refcount;
+};
+
+static int32_t gralloc_gbm_pid = 0;
+
+static uint32_t get_gbm_format(int format)
+{
+ uint32_t fmt;
+
+ switch (format) {
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ fmt = GBM_FORMAT_ABGR8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ fmt = GBM_FORMAT_XBGR8888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ fmt = GBM_FORMAT_RGB888;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ fmt = GBM_FORMAT_BGR565;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ fmt = GBM_FORMAT_ARGB8888;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ default:
+ fmt = 0;
+ break;
+ }
+
+ return fmt;
+}
+
+static unsigned get_pipe_bind(int usage)
+{
+ unsigned bind = 0;
+#if 0
+ if (usage & GRALLOC_USAGE_SW_READ_MASK)
+ bind |= PIPE_BIND_TRANSFER_READ;
+ if (usage & GRALLOC_USAGE_SW_WRITE_MASK)
+ bind |= PIPE_BIND_TRANSFER_WRITE;
+ if (usage & GRALLOC_USAGE_HW_TEXTURE)
+ bind |= PIPE_BIND_SAMPLER_VIEW;
+#endif
+ if (usage & GRALLOC_USAGE_HW_RENDER)
+ bind |= GBM_BO_USE_RENDERING;
+ if (usage & GRALLOC_USAGE_HW_FB) {
+ bind |= GBM_BO_USE_SCANOUT;
+ }
+
+ return bind;
+}
+
+static struct gralloc_gbm_bo_t *gbm_import(struct gbm_device *gbm,
+ struct gralloc_gbm_handle_t *handle)
+{
+ struct gralloc_gbm_bo_t *buf;
+ struct gbm_import_fd_data data;
+ int format = get_gbm_format(handle->format);
+ int usage = get_pipe_bind(handle->usage);
+
+ if (handle->prime_fd < 0)
+ return NULL;
+
+ buf = new struct gralloc_gbm_bo_t();
+ if (!buf) {
+ ALOGE("failed to allocate pipe buffer");
+ return NULL;
+ }
+
+ data.fd = handle->prime_fd;
+ data.width = handle->width;
+ data.height = handle->height;
+ data.stride = handle->stride;
+ data.format = format;
+
+ buf->bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
+ if (!buf->bo) {
+ delete buf;
+ return NULL;
+ }
+ return buf;
+}
+
+static struct gralloc_gbm_bo_t *gbm_alloc(struct gbm_device *gbm,
+ struct gralloc_gbm_handle_t *handle)
+{
+ struct gralloc_gbm_bo_t *buf;
+ int format = get_gbm_format(handle->format);
+ int usage = get_pipe_bind(handle->usage);
+
+ buf = new struct gralloc_gbm_bo_t();
+ if (!buf) {
+ ALOGE("failed to allocate pipe buffer");
+ return NULL;
+ }
+
+ buf->bo = gbm_bo_create(gbm, handle->width, handle->height, format, usage);
+ if (!buf->bo) {
+ delete buf;
+ return NULL;
+ }
+
+ handle->prime_fd = gbm_bo_get_fd(buf->bo);
+ handle->stride = gbm_bo_get_stride(buf->bo);
+
+ return buf;
+}
+
+static void gbm_free(struct gralloc_gbm_bo_t *bo)
+{
+ struct gralloc_gbm_handle_t *handle = bo->handle;
+
+ close(handle->prime_fd);
+ handle->prime_fd = -1;
+
+ gbm_bo_destroy(bo->bo);
+ delete bo;
+}
+
+static int gbm_map(struct gralloc_gbm_bo_t *bo, int x, int y, int w, int h,
+ int enable_write, void **addr)
+{
+ int err = 0;
+
+ if (bo->map_data)
+ return -EINVAL;
+
+ *addr = gbm_bo_map(bo->bo, x, y, w, h, 0, &bo->map_data);
+ ALOGE("mapped bo %p at %p", bo, *addr);
+ if (*addr == NULL)
+ err = -ENOMEM;
+
+ return err;
+}
+
+static void gbm_unmap(struct gralloc_gbm_bo_t *bo)
+{
+ gbm_bo_unmap(bo->bo, bo->map_data);
+ bo->map_data = NULL;
+}
+
+void gbm_dev_destroy(struct gbm_device *gbm)
+{
+ int fd = gbm_device_get_fd(gbm);
+
+ gbm_device_destroy(gbm);
+ close(fd);
+}
+
+struct gbm_device *gbm_dev_create(void)
+{
+ struct gbm_device *gbm;
+ char path[PROPERTY_VALUE_MAX];
+ int fd;
+
+ property_get("gralloc.gbm.device", path, "/dev/dri/renderD128");
+ fd = open(path, O_RDWR);
+ if (fd < 0) {
+ ALOGE("failed to open %s", path);
+ return NULL;
+ }
+
+ gbm = gbm_create_device(fd);
+ if (!gbm) {
+ ALOGE("failed to create gbm device");
+ }
+
+ return gbm;
+}
+
+/*
+ * Return the pid of the process.
+ */
+static int gralloc_gbm_get_pid(void)
+{
+ if (unlikely(!gralloc_gbm_pid))
+ android_atomic_write((int32_t) getpid(), &gralloc_gbm_pid);
+
+ return gralloc_gbm_pid;
+}
+
+/*
+ * Validate a buffer handle and return the associated bo.
+ */
+static struct gralloc_gbm_bo_t *validate_handle(buffer_handle_t _handle,
+ struct gbm_device *gbm)
+{
+ struct gralloc_gbm_bo_t *bo;
+ struct gralloc_gbm_handle_t *handle = gralloc_gbm_handle(_handle);
+
+ if (!handle)
+ return NULL;
+
+ /* the buffer handle is passed to a new process */
+ //ALOGE("data_owner=%d gralloc_pid=%d data=%p\n", handle->data_owner, gralloc_gbm_get_pid(), handle->data);
+ if (handle->data_owner == gralloc_gbm_get_pid())
+ return (struct gralloc_gbm_bo_t *)handle->data;
+
+ /* check only */
+ if (!gbm)
+ return NULL;
+
+ ALOGE("handle: name=%d pfd=%d\n", handle->name,
+ handle->prime_fd);
+ /* create the struct gralloc_gbm_bo_t locally */
+ if (handle->name || handle->prime_fd >= 0)
+ bo = gbm_import(gbm, handle);
+ else /* an invalid handle */
+ bo = NULL;
+ if (bo) {
+ bo->imported = 1;
+ bo->handle = handle;
+ bo->refcount = 1;
+ }
+
+ handle->data_owner = gralloc_gbm_get_pid();
+ handle->data = bo;
+
+ return bo;
+}
+
+/*
+ * Register a buffer handle.
+ */
+int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm)
+{
+ return (validate_handle(handle, gbm)) ? 0 : -EINVAL;
+}
+
+/*
+ * Unregister a buffer handle. It is no-op for handles created locally.
+ */
+int gralloc_gbm_handle_unregister(buffer_handle_t handle)
+{
+ struct gralloc_gbm_bo_t *bo;
+
+ bo = validate_handle(handle, NULL);
+ if (!bo)
+ return -EINVAL;
+
+ if (bo->imported)
+ gralloc_gbm_bo_decref(bo);
+
+ return 0;
+}
+
+/*
+ * Create a buffer handle.
+ */
+static struct gralloc_gbm_handle_t *create_bo_handle(int width,
+ int height, int format, int usage)
+{
+ struct gralloc_gbm_handle_t *handle;
+
+ handle = new gralloc_gbm_handle_t();
+ if (!handle)
+ return NULL;
+
+ handle->base.version = sizeof(handle->base);
+ handle->base.numInts = GRALLOC_GBM_HANDLE_NUM_INTS;
+ handle->base.numFds = GRALLOC_GBM_HANDLE_NUM_FDS;
+
+ handle->magic = GRALLOC_GBM_HANDLE_MAGIC;
+ handle->width = width;
+ handle->height = height;
+ handle->format = format;
+ handle->usage = usage;
+ handle->prime_fd = -1;
+
+ return handle;
+}
+
+/*
+ * Create a bo.
+ */
+struct gralloc_gbm_bo_t *gralloc_gbm_bo_create(struct gbm_device *gbm,
+ int width, int height, int format, int usage)
+{
+ struct gralloc_gbm_bo_t *bo;
+ struct gralloc_gbm_handle_t *handle;
+
+ handle = create_bo_handle(width, height, format, usage);
+ if (!handle)
+ return NULL;
+
+ bo = gbm_alloc(gbm, handle);
+ if (!bo) {
+ delete handle;
+ return NULL;
+ }
+
+ bo->imported = 0;
+ bo->handle = handle;
+ bo->refcount = 1;
+
+ handle->data_owner = gralloc_gbm_get_pid();
+ handle->data = bo;
+
+ return bo;
+}
+
+/*
+ * Destroy a bo.
+ */
+static void gralloc_gbm_bo_destroy(struct gralloc_gbm_bo_t *bo)
+{
+ struct gralloc_gbm_handle_t *handle = bo->handle;
+ int imported = bo->imported;
+
+ /* gralloc still has a reference */
+ if (bo->refcount)
+ return;
+
+ gbm_free(bo);
+ if (imported) {
+ handle->data_owner = 0;
+ handle->data = 0;
+ }
+ else {
+ delete handle;
+ }
+}
+
+/*
+ * Decrease refcount, if no refs anymore then destroy.
+ */
+void gralloc_gbm_bo_decref(struct gralloc_gbm_bo_t *bo)
+{
+ if (!--bo->refcount)
+ gralloc_gbm_bo_destroy(bo);
+}
+
+/*
+ * Return the bo of a registered handle.
+ */
+struct gralloc_gbm_bo_t *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
+{
+ return validate_handle(handle, NULL);
+}
+
+/*
+ * Get the buffer handle and stride of a bo.
+ */
+buffer_handle_t gralloc_gbm_bo_get_handle(struct gralloc_gbm_bo_t *bo)
+{
+ return &bo->handle->base;
+}
+
+/*
+ * Get the buffer handle and stride of a bo.
+ */
+struct gbm_bo *gralloc_gbm_bo_to_gbm_bo(struct gralloc_gbm_bo_t *_bo)
+{
+ return _bo->bo;
+}
+
+/*
+ * Query YUV component offsets for a buffer handle
+ */
+void gralloc_gbm_resolve_format(buffer_handle_t _handle,
+ uint32_t *pitches, uint32_t *offsets, uint32_t *handles)
+{}
+
+/*
+ * Lock a bo. XXX thread-safety?
+ */
+int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo,
+ int usage, int x, int y, int w, int h,
+ void **addr)
+{
+ if ((bo->handle->usage & usage) != usage) {
+ /* make FB special for testing software renderer with */
+
+ if (!(bo->handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
+ !(bo->handle->usage & GRALLOC_USAGE_HW_FB) &&
+ !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) {
+ ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE",
+ bo->handle->usage, usage);
+ return -EINVAL;
+ }
+ }
+
+ /* allow multiple locks with compatible usages */
+ if (bo->lock_count && (bo->locked_for & usage) != usage)
+ return -EINVAL;
+
+ usage |= bo->locked_for;
+
+ if (usage & (GRALLOC_USAGE_SW_WRITE_MASK |
+ GRALLOC_USAGE_SW_READ_MASK)) {
+ /* the driver is supposed to wait for the bo */
+ int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK);
+ int err = gbm_map(bo, x, y, w, h, write, addr);
+ if (err)
+ return err;
+ }
+ else {
+ /* kernel handles the synchronization here */
+ }
+
+ bo->lock_count++;
+ bo->locked_for |= usage;
+
+ return 0;
+}
+
+/*
+ * Unlock a bo.
+ */
+void gralloc_gbm_bo_unlock(struct gralloc_gbm_bo_t *bo)
+{
+ int mapped = bo->locked_for &
+ (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
+
+ if (!bo->lock_count)
+ return;
+
+ if (mapped)
+ gbm_unmap(bo);
+
+ bo->lock_count--;
+ if (!bo->lock_count)
+ bo->locked_for = 0;
+}
diff --git a/gralloc_gbm_priv.h b/gralloc_gbm_priv.h
new file mode 100644
index 0000000..8f52ce3
--- /dev/null
+++ b/gralloc_gbm_priv.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
+ * Copyright (C) 2010-2011 LunarG Inc.
+ * Copyright (C) 2016 Linaro, Ltd., Rob Herring <robh@kernel.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _GRALLOC_GBM_PRIV_H_
+#define _GRALLOC_GBM_PRIV_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct gbm_device;
+struct gralloc_gbm_bo_t;
+
+#define gralloc_gbm_handle_t gralloc_drm_handle_t
+#define gralloc_gbm_handle gralloc_drm_handle
+
+int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm);
+int gralloc_gbm_handle_unregister(buffer_handle_t handle);
+
+struct gralloc_gbm_bo_t *gralloc_gbm_bo_create(struct gbm_device *gbm,
+ int width, int height, int format, int usage);
+void gralloc_gbm_bo_decref(struct gralloc_gbm_bo_t *bo);
+
+struct gralloc_gbm_bo_t *gralloc_gbm_bo_from_handle(buffer_handle_t handle);
+buffer_handle_t gralloc_gbm_bo_get_handle(struct gralloc_gbm_bo_t *bo);
+int gralloc_gbm_get_gem_handle(buffer_handle_t handle);
+void gralloc_gbm_resolve_format(buffer_handle_t _handle, uint32_t *pitches, uint32_t *offsets, uint32_t *handles);
+//unsigned int planes_for_format(struct gralloc_gbm_t *gbm, int hal_format);
+
+struct gbm_bo *gralloc_gbm_bo_to_gbm_bo(struct gralloc_gbm_bo_t *_bo);
+
+int gralloc_gbm_bo_lock(struct gralloc_gbm_bo_t *bo, int x, int y, int w, int h, int enable_write, void **addr);
+void gralloc_gbm_bo_unlock(struct gralloc_gbm_bo_t *bo);
+
+struct gbm_device *gbm_dev_create(void);
+void gbm_dev_destroy(struct gbm_device *gbm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRALLOC_GBM_PRIV_H_ */