From 2b1f1af17f8e8f199cb0dd4f7f1a225529b357c5 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 11 Oct 2010 16:06:47 +0800 Subject: android: Add DRM-based gralloc. --- src/gralloc/gralloc_mod.c | 328 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 328 insertions(+) create mode 100644 src/gralloc/gralloc_mod.c (limited to 'src/gralloc/gralloc_mod.c') diff --git a/src/gralloc/gralloc_mod.c b/src/gralloc/gralloc_mod.c new file mode 100644 index 0000000000..1296d2af04 --- /dev/null +++ b/src/gralloc/gralloc_mod.c @@ -0,0 +1,328 @@ +#define LOG_TAG "GRALLOC-MOD" + +#include +#include +#include +#include + +#include "gralloc_mod.h" +#include "gralloc_gem.h" +#include "gralloc_kms.h" + +static int +drm_mod_perform(const struct gralloc_module_t *mod, int op, ...) +{ + struct drm_module_t *drm = (struct drm_module_t *) mod; + va_list args; + int ret; + + va_start(args, op); + switch (op) { + case GRALLOC_MODULE_PERFORM_GET_DRM_FD: + { + int *fd = va_arg(args, int *); + + ret = drm_gem_init(drm); + if (!ret) + *fd = drm->fd; + } + break; + case GRALLOC_MODULE_PERFORM_GET_DRM_MAGIC: + { + int32_t *magic = va_arg(args, int32_t *); + + ret = drm_gem_init(drm); + if (!ret) + ret = drm_gem_get_magic(drm, magic); + } + break; + case GRALLOC_MODULE_PERFORM_AUTH_DRM_MAGIC: + { + int32_t magic = va_arg(args, int32_t); + + ret = drm_gem_init(drm); + if (!ret) + ret = drm_gem_auth_magic(drm, magic); + } + break; + default: + ret = -EINVAL; + break; + } + va_end(args); + + return ret; +} + +static int +drm_mod_register_buffer(const gralloc_module_t *mod, buffer_handle_t handle) +{ + return (drm_gem_get(handle)) ? 0 : -EINVAL; +} + +static int +drm_mod_unregister_buffer(const gralloc_module_t *mod, buffer_handle_t handle) +{ + return (drm_gem_get(handle)) ? 0 : -EINVAL; +} + +static int +drm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle, + int usage, int x, int y, int w, int h, void **ptr) +{ + struct drm_module_t *drm = (struct drm_module_t *) mod; + struct drm_bo_t *bo; + int ret; + + ret = drm_gem_init(drm); + if (!ret) + ret = drm_gem_drv_init(drm); + if (ret) + return ret; + + bo = drm_gem_validate(handle); + if (!bo) + return -EINVAL; + + return drm_gem_drv_map(drm, bo, x, y, w, h, 1, ptr); +} + +static int +drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle) +{ + struct drm_module_t *drm = (struct drm_module_t *) mod; + struct drm_bo_t *bo; + + bo = drm_gem_validate(handle); + if (!bo) + return -EINVAL; + + drm_gem_drv_unmap(drm, bo); + + return 0; +} + +static int +drm_mod_close_gpu0(struct hw_device_t *dev) +{ + struct alloc_device_t *alloc = (struct alloc_device_t *) dev; + + free(alloc); + + return 0; +} + +static int +drm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle) +{ + struct drm_module_t *drm = (struct drm_module_t *) dev->common.module; + struct drm_bo_t *bo; + + bo = drm_gem_validate(handle); + if (!bo) + return -EINVAL; + + if (bo->usage & GRALLOC_USAGE_HW_FB) + drm_kms_rm_fb(drm, bo); + + drm_gem_drv_free(drm, bo); + + return 0; +} + +static int +drm_mod_alloc_gpu0(alloc_device_t *dev, int w, int h, int format, int usage, + buffer_handle_t *handle, int *stride) +{ + struct drm_module_t *drm = (struct drm_module_t *) dev->common.module; + struct drm_bo_t *bo; + int size, bpp, ret; + + ret = drm_gem_drv_init(drm); + if (ret) + return ret; + + bpp = drm_mod_get_bpp(format); + if (!bpp) + return -EINVAL; + + bo = drm_gem_drv_alloc(drm, w, h, format, usage, stride); + if (!bo) + return -EINVAL; + if (bo->usage & GRALLOC_USAGE_HW_FB) { + ret = drm_kms_add_fb(drm, bo); + if (ret) { + LOGE("failed to add fb"); + drm_gem_drv_free(drm, bo); + return ret; + } + } + + *stride /= bpp; + *handle = &bo->base; + + return 0; +} + +static int +drm_mod_open_gpu0(struct drm_module_t *drm, hw_device_t **dev) +{ + struct alloc_device_t *alloc; + int ret; + + ret = drm_gem_init(drm); + if (ret) + return ret; + + alloc = calloc(1, sizeof(*alloc)); + if (!alloc) + return -EINVAL; + + alloc->common.tag = HARDWARE_DEVICE_TAG; + alloc->common.version = 0; + alloc->common.module = (hw_module_t *) drm; + alloc->common.close = drm_mod_close_gpu0; + + alloc->alloc = drm_mod_alloc_gpu0; + alloc->free = drm_mod_free_gpu0; + + *dev = &alloc->common; + + return 0; +} + +static int +drm_mod_close_fb0(struct hw_device_t *dev) +{ + struct framebuffer_device_t *fb = (struct framebuffer_device_t *) dev; + + free(fb); + + return 0; +} + +static int +drm_mod_set_swap_interval_fb0(struct framebuffer_device_t *fb, int interval) +{ + if (interval < fb->minSwapInterval || interval > fb->maxSwapInterval) + return -EINVAL; + return 0; +} + +static int +drm_mod_post_fb0(struct framebuffer_device_t *fb, buffer_handle_t handle) +{ + struct drm_module_t *drm = (struct drm_module_t *) fb->common.module; + struct drm_bo_t *bo; + + bo = drm_gem_validate(handle); + if (!bo) + return -EINVAL; + + return drm_kms_post(drm, bo); +} + +#include +static int +drm_mod_composition_complete_fb0(struct framebuffer_device_t *fb) +{ + eglWaitClient(); + return 0; +} + +static int +drm_mod_open_fb0(struct drm_module_t *drm, struct hw_device_t **dev) +{ + struct framebuffer_device_t *fb; + int ret; + + fb = calloc(1, sizeof(*fb)); + if (!fb) + return -ENOMEM; + + ret = drm_gem_init(drm); + if (!ret) + ret = drm_kms_init(drm); + if (ret) { + free(fb); + return ret; + } + + fb->common.tag = HARDWARE_DEVICE_TAG; + fb->common.version = 0; + fb->common.module = (hw_module_t *) drm; + fb->common.close = drm_mod_close_fb0; + + fb->setSwapInterval = drm_mod_set_swap_interval_fb0; + fb->post = drm_mod_post_fb0; + fb->compositionComplete = drm_mod_composition_complete_fb0; + + *((uint32_t *) &fb->flags) = 0x0; + *((uint32_t *) &fb->width) = drm->mode.hdisplay; + *((uint32_t *) &fb->height) = drm->mode.vdisplay; + *((int *) &fb->stride) = drm->mode.hdisplay; + *((float *) &fb->fps) = drm->mode.vrefresh; + + *((int *) &fb->format) = drm->format; + *((float *) &fb->xdpi) = drm->xdpi; + *((float *) &fb->ydpi) = drm->ydpi; + *((int *) &fb->minSwapInterval) = drm->swap_interval; + *((int *) &fb->maxSwapInterval) = drm->swap_interval; + + *dev = &fb->common; + + LOGI("mode.hdisplay %d\n" + "mode.vdisplay %d\n" + "mode.vrefresh %d\n" + "format 0x%x\n" + "xdpi %d\n" + "ydpi %d\n", + drm->mode.hdisplay, + drm->mode.vdisplay, + drm->mode.vrefresh, + drm->format, + drm->xdpi, drm->ydpi); + + return 0; +} + +static int +drm_mod_open(const struct hw_module_t *mod, const char *name, struct hw_device_t **dev) +{ + struct drm_module_t *drm = (struct drm_module_t *) mod; + int ret; + + if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0) + ret = drm_mod_open_gpu0(drm, dev); + else if (strcmp(name, GRALLOC_HARDWARE_FB0) == 0) + ret = drm_mod_open_fb0(drm, dev); + else + ret = -EINVAL; + + return ret; +} + +static struct hw_module_methods_t drm_mod_methods = { + .open = drm_mod_open +}; + +struct drm_module_t HAL_MODULE_INFO_SYM = { + .base = { + .common = { + .tag = HARDWARE_MODULE_TAG, + .version_major = 1, + .version_minor = 0, + .id = GRALLOC_HARDWARE_MODULE_ID, + .name = "DRM Memory Allocator", + .author = "Chia-I Wu", + .methods = &drm_mod_methods + }, + .registerBuffer = drm_mod_register_buffer, + .unregisterBuffer = drm_mod_unregister_buffer, + .lock = drm_mod_lock, + .unlock = drm_mod_unlock, + .perform = drm_mod_perform + }, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .fd = -1 +}; -- cgit v1.2.3