1/* 2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com> 3 * Copyright (C) 2010-2011 LunarG Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#define LOG_TAG "GRALLOC-MOD" 25 26#include <cutils/log.h> 27#include <stdlib.h> 28#include <stdarg.h> 29#include <pthread.h> 30#include <errno.h> 31 32#include "gralloc_drm.h" 33#include "gralloc_drm_priv.h" 34 35/* 36 * Initialize the DRM device object 37 */ 38static int drm_init(struct drm_module_t *dmod) 39{ 40 int err = 0; 41 42 pthread_mutex_lock(&dmod->mutex); 43 if (!dmod->drm) { 44 dmod->drm = gralloc_drm_create(); 45 if (!dmod->drm) 46 err = -EINVAL; 47 } 48 pthread_mutex_unlock(&dmod->mutex); 49 50 return err; 51} 52 53static int drm_mod_perform(const struct gralloc_module_t *mod, int op, ...) 54{ 55 struct drm_module_t *dmod = (struct drm_module_t *) mod; 56 va_list args; 57 int err; 58 59 err = drm_init(dmod); 60 if (err) 61 return err; 62 63 va_start(args, op); 64 switch (op) { 65 case static_cast<int>(GRALLOC_MODULE_PERFORM_GET_DRM_FD): 66 { 67 int *fd = va_arg(args, int *); 68 *fd = gralloc_drm_get_fd(dmod->drm); 69 err = 0; 70 } 71 break; 72 default: 73 err = -EINVAL; 74 break; 75 } 76 va_end(args); 77 78 return err; 79} 80 81static int drm_mod_register_buffer(const gralloc_module_t *mod, 82 buffer_handle_t handle) 83{ 84 struct drm_module_t *dmod = (struct drm_module_t *) mod; 85 int err; 86 87 err = drm_init(dmod); 88 if (err) 89 return err; 90 91 return gralloc_drm_handle_register(handle, dmod->drm); 92} 93 94static int drm_mod_unregister_buffer(const gralloc_module_t *mod, 95 buffer_handle_t handle) 96{ 97 return gralloc_drm_handle_unregister(handle); 98} 99 100static int drm_mod_lock(const gralloc_module_t *mod, buffer_handle_t handle, 101 int usage, int x, int y, int w, int h, void **ptr) 102{ 103 struct gralloc_drm_bo_t *bo; 104 int err; 105 106 bo = gralloc_drm_bo_from_handle(handle); 107 if (!bo) 108 return -EINVAL; 109 110 return gralloc_drm_bo_lock(bo, usage, x, y, w, h, ptr); 111} 112 113static int drm_mod_lock_ycbcr(const gralloc_module_t *mod, buffer_handle_t bhandle, 114 int usage, int x, int y, int w, int h, struct android_ycbcr *ycbcr) 115{ 116 struct gralloc_drm_handle_t *handle; 117 struct gralloc_drm_bo_t *bo; 118 void *ptr; 119 int err; 120 121 bo = gralloc_drm_bo_from_handle(bhandle); 122 if (!bo) 123 return -EINVAL; 124 handle = bo->handle; 125 126 switch(handle->format) { 127 case HAL_PIXEL_FORMAT_YCbCr_420_888: 128 break; 129 default: 130 return -EINVAL; 131 } 132 133 err = gralloc_drm_bo_lock(bo, usage, x, y, w, h, &ptr); 134 if (err) 135 return err; 136 137 switch(handle->format) { 138 case HAL_PIXEL_FORMAT_YCbCr_420_888: 139 ycbcr->y = ptr; 140 ycbcr->cb = (uint8_t *)ptr + handle->stride * handle->height; 141 ycbcr->cr = (uint8_t *)ycbcr->cb + 1; 142 ycbcr->ystride = handle->stride; 143 ycbcr->cstride = handle->stride; 144 ycbcr->chroma_step = 2; 145 break; 146 default: 147 break; 148 } 149 150 return 0; 151} 152 153static int drm_mod_unlock(const gralloc_module_t *mod, buffer_handle_t handle) 154{ 155 struct drm_module_t *dmod = (struct drm_module_t *) mod; 156 struct gralloc_drm_bo_t *bo; 157 158 bo = gralloc_drm_bo_from_handle(handle); 159 if (!bo) 160 return -EINVAL; 161 162 gralloc_drm_bo_unlock(bo); 163 164 return 0; 165} 166 167static int drm_mod_close_gpu0(struct hw_device_t *dev) 168{ 169 struct drm_module_t *dmod = (struct drm_module_t *)dev->module; 170 struct alloc_device_t *alloc = (struct alloc_device_t *) dev; 171 172 gralloc_drm_destroy(dmod->drm); 173 delete alloc; 174 175 return 0; 176} 177 178static int drm_mod_free_gpu0(alloc_device_t *dev, buffer_handle_t handle) 179{ 180 struct drm_module_t *dmod = (struct drm_module_t *) dev->common.module; 181 struct gralloc_drm_bo_t *bo; 182 183 bo = gralloc_drm_bo_from_handle(handle); 184 if (!bo) 185 return -EINVAL; 186 187 gralloc_drm_bo_decref(bo); 188 189 return 0; 190} 191 192static int drm_mod_alloc_gpu0(alloc_device_t *dev, 193 int w, int h, int format, int usage, 194 buffer_handle_t *handle, int *stride) 195{ 196 struct drm_module_t *dmod = (struct drm_module_t *) dev->common.module; 197 struct gralloc_drm_bo_t *bo; 198 int size, bpp, err; 199 200 bpp = gralloc_drm_get_bpp(format); 201 if (!bpp) 202 return -EINVAL; 203 204 bo = gralloc_drm_bo_create(dmod->drm, w, h, format, usage); 205 if (!bo) 206 return -ENOMEM; 207 208 *handle = gralloc_drm_bo_get_handle(bo, stride); 209 /* in pixels */ 210 *stride /= bpp; 211 212 return 0; 213} 214 215static int drm_mod_open_gpu0(struct drm_module_t *dmod, hw_device_t **dev) 216{ 217 struct alloc_device_t *alloc; 218 int err; 219 220 err = drm_init(dmod); 221 if (err) 222 return err; 223 224 alloc = new alloc_device_t; 225 if (!alloc) 226 return -EINVAL; 227 228 alloc->common.tag = HARDWARE_DEVICE_TAG; 229 alloc->common.version = 0; 230 alloc->common.module = &dmod->base.common; 231 alloc->common.close = drm_mod_close_gpu0; 232 233 alloc->alloc = drm_mod_alloc_gpu0; 234 alloc->free = drm_mod_free_gpu0; 235 236 *dev = &alloc->common; 237 238 return 0; 239} 240 241static int drm_mod_open(const struct hw_module_t *mod, 242 const char *name, struct hw_device_t **dev) 243{ 244 struct drm_module_t *dmod = (struct drm_module_t *) mod; 245 int err; 246 247 if (strcmp(name, GRALLOC_HARDWARE_GPU0) == 0) 248 err = drm_mod_open_gpu0(dmod, dev); 249 else 250 err = -EINVAL; 251 252 return err; 253} 254 255static struct hw_module_methods_t drm_mod_methods = { 256 .open = drm_mod_open 257}; 258 259struct drm_module_t HAL_MODULE_INFO_SYM = { 260 .base = { 261 .common = { 262 .tag = HARDWARE_MODULE_TAG, 263 .version_major = 1, 264 .version_minor = 0, 265 .id = GRALLOC_HARDWARE_MODULE_ID, 266 .name = "DRM Memory Allocator", 267 .author = "Chia-I Wu", 268 .methods = &drm_mod_methods 269 }, 270 .registerBuffer = drm_mod_register_buffer, 271 .unregisterBuffer = drm_mod_unregister_buffer, 272 .lock = drm_mod_lock, 273 .unlock = drm_mod_unlock, 274 .perform = drm_mod_perform, 275 .lock_ycbcr = drm_mod_lock_ycbcr, 276 }, 277 278 .mutex = PTHREAD_MUTEX_INITIALIZER, 279 .drm = NULL 280}; 281