diff options
author | Amit Pundir <amit.pundir@linaro.org> | 2018-04-24 14:20:20 +0000 |
---|---|---|
committer | Linaro Android Code Review <android-review@review.linaro.org> | 2018-04-24 14:20:20 +0000 |
commit | e77be5f5c8d2b05d338417be07e8ef686d57da1e (patch) | |
tree | 93e337806ee7c0b4c03e960025c8de6ec6cbace5 | |
parent | a88454d37fd4602efe6fbf67d358c23b34dbf7ef (diff) | |
parent | 55bad2a20fb1cb10cfa35b600947e699b224a3a0 (diff) |
Merge "dragonboard: temporarily copy gbm_gralloc into dragonboard" into dragonboard
-rw-r--r-- | gralloc/Android.mk | 54 | ||||
-rw-r--r-- | gralloc/gralloc.cpp | 259 | ||||
-rw-r--r-- | gralloc/gralloc_drm.h | 42 | ||||
-rw-r--r-- | gralloc/gralloc_gbm.cpp | 473 | ||||
-rw-r--r-- | gralloc/gralloc_gbm_priv.h | 55 |
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_ */ |