OSDN Git Service

Initial GBM based gralloc
authorRob Herring <robh@kernel.org>
Sun, 12 Jun 2011 08:21:30 +0000 (16:21 +0800)
committerRob Herring <robh@kernel.org>
Fri, 1 Apr 2016 20:32:25 +0000 (15:32 -0500)
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>
Android.mk [new file with mode: 0644]
gralloc.cpp [new file with mode: 0644]
gralloc_drm.h [new file with mode: 0644]
gralloc_drm_handle.h [new file with mode: 0644]
gralloc_gbm.cpp [new file with mode: 0644]
gralloc_gbm_priv.h [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..0c1695b
--- /dev/null
@@ -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 (file)
index 0000000..809862d
--- /dev/null
@@ -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 (file)
index 0000000..e4b528f
--- /dev/null
@@ -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 (file)
index 0000000..be2984a
--- /dev/null
@@ -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 (file)
index 0000000..115aa8c
--- /dev/null
@@ -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 (file)
index 0000000..8f52ce3
--- /dev/null
@@ -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_ */