summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Pundir <amit.pundir@linaro.org>2018-04-24 14:20:20 +0000
committerLinaro Android Code Review <android-review@review.linaro.org>2018-04-24 14:20:20 +0000
commite77be5f5c8d2b05d338417be07e8ef686d57da1e (patch)
tree93e337806ee7c0b4c03e960025c8de6ec6cbace5
parenta88454d37fd4602efe6fbf67d358c23b34dbf7ef (diff)
parent55bad2a20fb1cb10cfa35b600947e699b224a3a0 (diff)
Merge "dragonboard: temporarily copy gbm_gralloc into dragonboard" into dragonboard
-rw-r--r--gralloc/Android.mk54
-rw-r--r--gralloc/gralloc.cpp259
-rw-r--r--gralloc/gralloc_drm.h42
-rw-r--r--gralloc/gralloc_gbm.cpp473
-rw-r--r--gralloc/gralloc_gbm_priv.h55
5 files changed, 883 insertions, 0 deletions
diff --git a/gralloc/Android.mk b/gralloc/Android.mk
new file mode 100644
index 0000000..5dc89bf
--- /dev/null
+++ b/gralloc/Android.mk
@@ -0,0 +1,54 @@
+# 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 := \
+ libdrm \
+ libgbm \
+ liblog \
+ libcutils
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)
+
+LOCAL_MODULE := gralloc.gbm
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := \
+ $(LOCAL_PATH)
+
+LOCAL_MODULE := libgralloc_drm
+LOCAL_MODULE_TAGS := optional
+LOCAL_PROPRIETARY_MODULE := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/gralloc/gralloc.cpp b/gralloc/gralloc.cpp
new file mode 100644
index 0000000..2753ee9
--- /dev/null
+++ b/gralloc/gralloc.cpp
@@ -0,0 +1,259 @@
+/*
+ * 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 <string.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;
+};
+
+/*
+ * 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;
+ uint32_t uop = static_cast<uint32_t>(op);
+
+ err = gbm_init(dmod);
+ if (err)
+ return err;
+
+ va_start(args, op);
+ switch (uop) {
+ 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;
+ int err;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ err = gralloc_gbm_bo_lock(handle, usage, x, y, w, h, ptr);
+ ALOGV("buffer %p lock usage = %08x", handle, usage);
+
+ 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;
+ int err;
+
+ pthread_mutex_lock(&dmod->mutex);
+ err = gralloc_gbm_bo_unlock(handle);
+ 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;
+
+ pthread_mutex_lock(&dmod->mutex);
+ gbm_free(handle);
+ native_handle_close(handle);
+ delete handle;
+
+ pthread_mutex_unlock(&dmod->mutex);
+ return 0;
+}
+
+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;
+ int err = 0;
+
+ pthread_mutex_lock(&dmod->mutex);
+
+ *handle = gralloc_gbm_bo_create(dmod->gbm, w, h, format, usage, stride);
+ if (!*handle)
+ err = -errno;
+
+ ALOGV("buffer %p usage = %08x", *handle, usage);
+ 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/gralloc_drm.h b/gralloc/gralloc_drm.h
new file mode 100644
index 0000000..0ece652
--- /dev/null
+++ b/gralloc/gralloc_drm.h
@@ -0,0 +1,42 @@
+/*
+ * 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 {
+ /* perform(const struct gralloc_module_t *mod,
+ * int op,
+ * int *fd);
+ */
+ GRALLOC_MODULE_PERFORM_GET_DRM_FD = 0x40000002,
+};
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRALLOC_DRM_H_ */
diff --git a/gralloc/gralloc_gbm.cpp b/gralloc/gralloc_gbm.cpp
new file mode 100644
index 0000000..418b7bb
--- /dev/null
+++ b/gralloc/gralloc_gbm.cpp
@@ -0,0 +1,473 @@
+/*
+ * 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 <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include <hardware/gralloc.h>
+#include <system/graphics.h>
+
+#include <gbm.h>
+
+#include "gralloc_gbm_priv.h"
+#include <android/gralloc_handle.h>
+
+#include <unordered_map>
+
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+static std::unordered_map<buffer_handle_t, struct gbm_bo *> gbm_bo_handle_map;
+
+struct bo_data_t {
+ void *map_data;
+ int lock_count;
+ int locked_for;
+};
+
+void gralloc_gbm_destroy_user_data(struct gbm_bo *bo, void *data)
+{
+ struct bo_data_t *bo_data = (struct bo_data_t *)data;
+ delete bo_data;
+
+ (void)bo;
+}
+
+static struct bo_data_t *gbm_bo_data(struct gbm_bo *bo) {
+ return (struct bo_data_t *)gbm_bo_get_user_data(bo);
+}
+
+
+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_RGB565;
+ break;
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ fmt = GBM_FORMAT_ARGB8888;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ /* YV12 is planar, but must be a single buffer so ask for GR88 */
+ fmt = GBM_FORMAT_GR88;
+ break;
+ case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ default:
+ fmt = 0;
+ break;
+ }
+
+ return fmt;
+}
+
+static 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;
+}
+
+static unsigned int get_pipe_bind(int usage)
+{
+ unsigned int bind = 0;
+
+ if (usage & (GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN))
+ bind |= GBM_BO_USE_LINEAR;
+ if (usage & GRALLOC_USAGE_CURSOR)
+ ;//bind |= GBM_BO_USE_CURSOR;
+ if (usage & (GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE))
+ bind |= GBM_BO_USE_RENDERING;
+ if (usage & GRALLOC_USAGE_HW_FB)
+ bind |= GBM_BO_USE_SCANOUT;
+
+ return bind;
+}
+
+static struct gbm_bo *gbm_import(struct gbm_device *gbm,
+ buffer_handle_t _handle)
+{
+ struct gbm_bo *bo;
+ struct gralloc_handle_t *handle = gralloc_handle(_handle);
+ #ifdef GBM_BO_IMPORT_FD_MODIFIER
+ struct gbm_import_fd_modifier_data data;
+ #else
+ struct gbm_import_fd_data data;
+ #endif
+
+ int format = get_gbm_format(handle->format);
+ if (handle->prime_fd < 0)
+ return NULL;
+
+ memset(&data, 0, sizeof(data));
+ data.width = handle->width;
+ data.height = handle->height;
+ data.format = format;
+ /* Adjust the width and height for a GBM GR88 buffer */
+ if (handle->format == HAL_PIXEL_FORMAT_YV12) {
+ data.width /= 2;
+ data.height += handle->height / 2;
+ }
+
+ #ifdef GBM_BO_IMPORT_FD_MODIFIER
+ data.num_fds = 1;
+ data.fds[0] = handle->prime_fd;
+ data.strides[0] = handle->stride;
+ data.modifier = handle->modifier;
+ bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
+ #else
+ data.fd = handle->prime_fd;
+ data.stride = handle->stride;
+ bo = gbm_bo_import(gbm, GBM_BO_IMPORT_FD, &data, 0);
+ #endif
+
+ return bo;
+}
+
+static struct gbm_bo *gbm_alloc(struct gbm_device *gbm,
+ buffer_handle_t _handle)
+{
+ struct gbm_bo *bo;
+ struct gralloc_handle_t *handle = gralloc_handle(_handle);
+ int format = get_gbm_format(handle->format);
+ int usage = get_pipe_bind(handle->usage);
+ int width, height;
+
+ width = handle->width;
+ height = handle->height;
+ if (usage & GBM_BO_USE_CURSOR) {
+ if (handle->width < 64)
+ width = 64;
+ if (handle->height < 64)
+ height = 64;
+ }
+
+ /*
+ * For YV12, we request GR88, so halve the width since we're getting
+ * 16bpp. Then increase the height by 1.5 for the U and V planes.
+ */
+ if (handle->format == HAL_PIXEL_FORMAT_YV12) {
+ width /= 2;
+ height += handle->height / 2;
+ }
+
+ ALOGV("create BO, size=%dx%d, fmt=%d, usage=%x",
+ handle->width, handle->height, handle->format, usage);
+ bo = gbm_bo_create(gbm, width, height, format, usage);
+ if (!bo) {
+ ALOGE("failed to create BO, size=%dx%d, fmt=%d, usage=%x",
+ handle->width, handle->height, handle->format, usage);
+ return NULL;
+ }
+
+ handle->prime_fd = gbm_bo_get_fd(bo);
+ handle->stride = gbm_bo_get_stride(bo);
+ #ifdef GBM_BO_IMPORT_FD_MODIFIER
+ handle->modifier = gbm_bo_get_modifier(bo);
+ #endif
+
+ return bo;
+}
+
+void gbm_free(buffer_handle_t handle)
+{
+ struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+
+ if (!bo)
+ return;
+
+ gbm_bo_handle_map.erase(handle);
+ gbm_bo_destroy(bo);
+}
+
+/*
+ * Return the bo of a registered handle.
+ */
+struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle)
+{
+ return gbm_bo_handle_map[handle];
+}
+
+static int gbm_map(buffer_handle_t handle, int x, int y, int w, int h,
+ int enable_write, void **addr)
+{
+ int err = 0;
+ int flags = GBM_BO_TRANSFER_READ;
+ struct gralloc_gbm_handle_t *gbm_handle = gralloc_handle(handle);
+ struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+ struct bo_data_t *bo_data = gbm_bo_data(bo);
+ uint32_t stride;
+
+ if (bo_data->map_data)
+ return -EINVAL;
+
+ if (gbm_handle->format == HAL_PIXEL_FORMAT_YV12) {
+ if (x || y)
+ ALOGE("can't map with offset for planar %p", bo);
+ w /= 2;
+ h += h / 2;
+ }
+
+ if (enable_write)
+ flags |= GBM_BO_TRANSFER_WRITE;
+
+ *addr = gbm_bo_map(bo, 0, 0, x + w, y + h, flags, &stride, &bo_data->map_data);
+ ALOGV("mapped bo %p (%d, %d)-(%d, %d) at %p", bo, x, y, w, h, *addr);
+ if (*addr == NULL)
+ return -ENOMEM;
+
+ assert(stride == gbm_bo_get_stride(bo));
+
+ return err;
+}
+
+static void gbm_unmap(struct gbm_bo *bo)
+{
+ struct bo_data_t *bo_data = gbm_bo_data(bo);
+
+ gbm_bo_unmap(bo, bo_data->map_data);
+ bo_data->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 | O_CLOEXEC);
+ if (fd < 0) {
+ ALOGE("failed to open %s", path);
+ return NULL;
+ }
+
+ gbm = gbm_create_device(fd);
+ if (!gbm) {
+ ALOGE("failed to create gbm device");
+ close(fd);
+ }
+
+ return gbm;
+}
+
+/*
+ * Register a buffer handle.
+ */
+int gralloc_gbm_handle_register(buffer_handle_t _handle, struct gbm_device *gbm)
+{
+ struct gbm_bo *bo;
+
+ if (!_handle)
+ return -EINVAL;
+
+ if (gbm_bo_handle_map.count(_handle))
+ return -EINVAL;
+
+ bo = gbm_import(gbm, _handle);
+ if (!bo)
+ return -EINVAL;
+
+ gbm_bo_handle_map.emplace(_handle, bo);
+
+ return 0;
+}
+
+/*
+ * Unregister a buffer handle. It is no-op for handles created locally.
+ */
+int gralloc_gbm_handle_unregister(buffer_handle_t handle)
+{
+ gbm_free(handle);
+
+ return 0;
+}
+
+/*
+ * Create a bo.
+ */
+buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
+ int width, int height, int format, int usage, int *stride)
+{
+ struct gbm_bo *bo;
+ native_handle_t *handle;
+
+ handle = gralloc_handle_create(width, height, format, usage);
+ if (!handle)
+ return NULL;
+
+ bo = gbm_alloc(gbm, handle);
+ if (!bo) {
+ native_handle_delete(handle);
+ return NULL;
+ }
+
+ gbm_bo_handle_map.emplace(handle, bo);
+
+ /* in pixels */
+ struct gralloc_handle_t *ghandle = gralloc_handle(handle);
+ *stride = ghandle->stride / gralloc_gbm_get_bpp(format);
+
+ return handle;
+}
+
+/*
+ * Lock a bo. XXX thread-safety?
+ */
+int gralloc_gbm_bo_lock(buffer_handle_t handle,
+ int usage, int x, int y, int w, int h,
+ void **addr)
+{
+ struct gralloc_handle_t *gbm_handle = gralloc_handle(handle);
+ struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+ struct bo_data_t *bo_data;
+
+ if (!bo)
+ return -EINVAL;
+
+ if ((gbm_handle->usage & usage) != (uint32_t)usage) {
+ /* make FB special for testing software renderer with */
+
+ if (!(gbm_handle->usage & GRALLOC_USAGE_SW_READ_OFTEN) &&
+ !(gbm_handle->usage & GRALLOC_USAGE_HW_FB) &&
+ !(gbm_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",
+ gbm_handle->usage, usage);
+ return -EINVAL;
+ }
+ }
+
+ bo_data = gbm_bo_data(bo);
+ if (!bo_data) {
+ bo_data = new struct bo_data_t();
+ gbm_bo_set_user_data(bo, bo_data, gralloc_gbm_destroy_user_data);
+ }
+
+ ALOGI("lock bo %p, cnt=%d, usage=%x", bo, bo_data->lock_count, usage);
+
+ /* allow multiple locks with compatible usages */
+ if (bo_data->lock_count && (bo_data->locked_for & usage) != usage)
+ return -EINVAL;
+
+ usage |= bo_data->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(handle, x, y, w, h, write, addr);
+ if (err)
+ return err;
+ }
+ else {
+ /* kernel handles the synchronization here */
+ }
+
+ bo_data->lock_count++;
+ bo_data->locked_for |= usage;
+
+ return 0;
+}
+
+/*
+ * Unlock a bo.
+ */
+int gralloc_gbm_bo_unlock(buffer_handle_t handle)
+{
+ struct gbm_bo *bo = gralloc_gbm_bo_from_handle(handle);
+ struct bo_data_t *bo_data;
+ if (!bo)
+ return -EINVAL;
+
+ bo_data = gbm_bo_data(bo);
+
+ int mapped = bo_data->locked_for &
+ (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK);
+
+ if (!bo_data->lock_count)
+ return 0;
+
+ if (mapped)
+ gbm_unmap(bo);
+
+ bo_data->lock_count--;
+ if (!bo_data->lock_count)
+ bo_data->locked_for = 0;
+
+ return 0;
+}
diff --git a/gralloc/gralloc_gbm_priv.h b/gralloc/gralloc_gbm_priv.h
new file mode 100644
index 0000000..7174fb8
--- /dev/null
+++ b/gralloc/gralloc_gbm_priv.h
@@ -0,0 +1,55 @@
+/*
+ * 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 gbm_bo;
+
+int gralloc_gbm_handle_register(buffer_handle_t handle, struct gbm_device *gbm);
+int gralloc_gbm_handle_unregister(buffer_handle_t handle);
+
+buffer_handle_t gralloc_gbm_bo_create(struct gbm_device *gbm,
+ int width, int height, int format, int usage, int *stride);
+void gbm_free(buffer_handle_t handle);
+
+struct gbm_bo *gralloc_gbm_bo_from_handle(buffer_handle_t handle);
+buffer_handle_t gralloc_gbm_bo_get_handle(struct gbm_bo *bo);
+int gralloc_gbm_get_gem_handle(buffer_handle_t handle);
+
+int gralloc_gbm_bo_lock(buffer_handle_t handle, int x, int y, int w, int h, int enable_write, void **addr);
+int gralloc_gbm_bo_unlock(buffer_handle_t handle);
+
+struct gbm_device *gbm_dev_create(void);
+void gbm_dev_destroy(struct gbm_device *gbm);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _GRALLOC_GBM_PRIV_H_ */