1 /* 2 * Copyright (C) 2010-2011 Chia-I Wu <olvaffe (at) 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-DRM" 25 26 #include <cutils/log.h> 27 #include <cutils/atomic.h> 28 #include <cutils/properties.h> 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <sys/types.h> 32 #include <sys/stat.h> 33 #include <fcntl.h> 34 35 #include "gralloc_drm.h" 36 #include "gralloc_drm_priv.h" 37 38 #define unlikely(x) __builtin_expect(!!(x), 0) 39 40 static int32_t gralloc_drm_pid = 0; 41 42 /* 43 * Return the pid of the process. 44 */ 45 static int gralloc_drm_get_pid(void) 46 { 47 if (unlikely(!gralloc_drm_pid)) 48 android_atomic_write((int32_t) getpid(), &gralloc_drm_pid); 49 50 return gralloc_drm_pid; 51 } 52 53 /* 54 * Create the driver for a DRM fd. 55 */ 56 static struct gralloc_drm_drv_t * 57 init_drv_from_fd(int fd) 58 { 59 struct gralloc_drm_drv_t *drv = NULL; 60 drmVersionPtr version; 61 62 /* get the kernel module name */ 63 version = drmGetVersion(fd); 64 if (!version) { 65 ALOGE("invalid DRM fd"); 66 return NULL; 67 } 68 69 if (version->name) { 70 #ifdef ENABLE_PIPE 71 drv = gralloc_drm_drv_create_for_pipe(fd, version->name); 72 #endif 73 74 #ifdef ENABLE_INTEL 75 if (!drv && !strcmp(version->name, "i915")) 76 drv = gralloc_drm_drv_create_for_intel(fd); 77 #endif 78 #ifdef ENABLE_RADEON 79 if (!drv && !strcmp(version->name, "radeon")) 80 drv = gralloc_drm_drv_create_for_radeon(fd); 81 #endif 82 #ifdef ENABLE_ROCKCHIP 83 if (!drv && !strcmp(version->name, "rockchip")) 84 drv = gralloc_drm_drv_create_for_rockchip(fd); 85 #endif 86 #ifdef ENABLE_NOUVEAU 87 if (!drv && !strcmp(version->name, "nouveau")) 88 drv = gralloc_drm_drv_create_for_nouveau(fd); 89 #endif 90 } 91 92 if (!drv) { 93 ALOGE("unsupported driver: %s", (version->name) ? 94 version->name : "NULL"); 95 } 96 97 drmFreeVersion(version); 98 99 return drv; 100 } 101 102 /* 103 * Create a DRM device object. 104 */ 105 struct gralloc_drm_t *gralloc_drm_create(void) 106 { 107 char path[PROPERTY_VALUE_MAX]; 108 struct gralloc_drm_t *drm; 109 int err; 110 111 drm = new gralloc_drm_t; 112 if (!drm) 113 return NULL; 114 115 property_get("gralloc.drm.device", path, "/dev/dri/renderD128"); 116 drm->fd = open(path, O_RDWR); 117 if (drm->fd < 0) { 118 ALOGE("failed to open %s", path); 119 return NULL; 120 } 121 122 drm->drv = init_drv_from_fd(drm->fd); 123 if (!drm->drv) { 124 close(drm->fd); 125 delete drm; 126 return NULL; 127 } 128 129 return drm; 130 } 131 132 /* 133 * Destroy a DRM device object. 134 */ 135 void gralloc_drm_destroy(struct gralloc_drm_t *drm) 136 { 137 if (drm->drv) 138 drm->drv->destroy(drm->drv); 139 close(drm->fd); 140 delete drm; 141 } 142 143 /* 144 * Get the file descriptor of a DRM device object. 145 */ 146 int gralloc_drm_get_fd(struct gralloc_drm_t *drm) 147 { 148 return drm->fd; 149 } 150 151 /* 152 * Validate a buffer handle and return the associated bo. 153 */ 154 static struct gralloc_drm_bo_t *validate_handle(buffer_handle_t _handle, 155 struct gralloc_drm_t *drm) 156 { 157 struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle); 158 159 if (!handle) 160 return NULL; 161 162 /* the buffer handle is passed to a new process */ 163 ALOGE("data_owner=%d gralloc_pid=%d data=%p\n", handle->data_owner, gralloc_drm_get_pid(), handle->data); 164 if (unlikely(handle->data_owner != gralloc_drm_pid)) { 165 struct gralloc_drm_bo_t *bo; 166 167 /* check only */ 168 if (!drm) 169 return NULL; 170 171 ALOGE("handle: name=%d pfd=%d\n", handle->name, 172 handle->prime_fd); 173 /* create the struct gralloc_drm_bo_t locally */ 174 if (handle->name || handle->prime_fd >= 0) 175 bo = drm->drv->alloc(drm->drv, handle); 176 else /* an invalid handle */ 177 bo = NULL; 178 if (bo) { 179 bo->drm = drm; 180 bo->imported = 1; 181 bo->handle = handle; 182 bo->refcount = 1; 183 } 184 185 handle->data_owner = gralloc_drm_get_pid(); 186 handle->data = bo; 187 } 188 189 return handle->data; 190 } 191 192 /* 193 * Register a buffer handle. 194 */ 195 int gralloc_drm_handle_register(buffer_handle_t handle, struct gralloc_drm_t *drm) 196 { 197 return (validate_handle(handle, drm)) ? 0 : -EINVAL; 198 } 199 200 /* 201 * Unregister a buffer handle. It is no-op for handles created locally. 202 */ 203 int gralloc_drm_handle_unregister(buffer_handle_t handle) 204 { 205 struct gralloc_drm_bo_t *bo; 206 207 bo = validate_handle(handle, NULL); 208 if (!bo) 209 return -EINVAL; 210 211 if (bo->imported) 212 gralloc_drm_bo_decref(bo); 213 214 return 0; 215 } 216 217 /* 218 * Create a buffer handle. 219 */ 220 static struct gralloc_drm_handle_t *create_bo_handle(int width, 221 int height, int format, int usage) 222 { 223 struct gralloc_drm_handle_t *handle; 224 225 handle = new gralloc_drm_handle_t; 226 if (!handle) 227 return NULL; 228 229 handle->base.version = sizeof(handle->base); 230 handle->base.numInts = GRALLOC_DRM_HANDLE_NUM_INTS; 231 handle->base.numFds = GRALLOC_DRM_HANDLE_NUM_FDS; 232 233 handle->magic = GRALLOC_DRM_HANDLE_MAGIC; 234 handle->width = width; 235 handle->height = height; 236 handle->format = format; 237 handle->usage = usage; 238 handle->prime_fd = -1; 239 240 return handle; 241 } 242 243 /* 244 * Create a bo. 245 */ 246 struct gralloc_drm_bo_t *gralloc_drm_bo_create(struct gralloc_drm_t *drm, 247 int width, int height, int format, int usage) 248 { 249 struct gralloc_drm_bo_t *bo; 250 struct gralloc_drm_handle_t *handle; 251 252 handle = create_bo_handle(width, height, format, usage); 253 if (!handle) 254 return NULL; 255 256 bo = drm->drv->alloc(drm->drv, handle); 257 if (!bo) { 258 delete handle; 259 return NULL; 260 } 261 262 bo->drm = drm; 263 bo->imported = 0; 264 bo->handle = handle; 265 bo->fb_id = 0; 266 bo->refcount = 1; 267 268 handle->data_owner = gralloc_drm_get_pid(); 269 handle->data = bo; 270 271 return bo; 272 } 273 274 /* 275 * Destroy a bo. 276 */ 277 static void gralloc_drm_bo_destroy(struct gralloc_drm_bo_t *bo) 278 { 279 struct gralloc_drm_handle_t *handle = bo->handle; 280 int imported = bo->imported; 281 282 /* gralloc still has a reference */ 283 if (bo->refcount) 284 return; 285 286 bo->drm->drv->free(bo->drm->drv, bo); 287 if (imported) { 288 handle->data_owner = 0; 289 handle->data = 0; 290 } 291 else { 292 delete handle; 293 } 294 } 295 296 /* 297 * Decrease refcount, if no refs anymore then destroy. 298 */ 299 void gralloc_drm_bo_decref(struct gralloc_drm_bo_t *bo) 300 { 301 if (!--bo->refcount) 302 gralloc_drm_bo_destroy(bo); 303 } 304 305 /* 306 * Return the bo of a registered handle. 307 */ 308 struct gralloc_drm_bo_t *gralloc_drm_bo_from_handle(buffer_handle_t handle) 309 { 310 return validate_handle(handle, NULL); 311 } 312 313 /* 314 * Get the buffer handle and stride of a bo. 315 */ 316 buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride) 317 { 318 if (stride) 319 *stride = bo->handle->stride; 320 return &bo->handle->base; 321 } 322 323 /* 324 * Query YUV component offsets for a buffer handle 325 */ 326 void gralloc_drm_resolve_format(buffer_handle_t _handle, 327 uint32_t *pitches, uint32_t *offsets, uint32_t *handles) 328 { 329 struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle); 330 struct gralloc_drm_bo_t *bo = handle->data; 331 struct gralloc_drm_t *drm = bo->drm; 332 333 /* if handle exists and driver implements resolve_format */ 334 if (handle && drm->drv->resolve_format) 335 drm->drv->resolve_format(drm->drv, bo, 336 pitches, offsets, handles); 337 } 338 339 /* 340 * Lock a bo. XXX thread-safety? 341 */ 342 int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo, 343 int usage, int x, int y, int w, int h, 344 void **addr) 345 { 346 if ((bo->handle->usage & usage) != usage) { 347 /* make FB special for testing software renderer with */ 348 349 if (!(bo->handle->usage & GRALLOC_USAGE_HW_FB) 350 && !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) { 351 ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE" 352 ,bo->handle->usage,usage); 353 return -EINVAL; 354 } 355 } 356 357 /* allow multiple locks with compatible usages */ 358 if (bo->lock_count && (bo->locked_for & usage) != usage) 359 return -EINVAL; 360 361 usage |= bo->locked_for; 362 363 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | 364 GRALLOC_USAGE_SW_READ_MASK)) { 365 /* the driver is supposed to wait for the bo */ 366 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK); 367 int err = bo->drm->drv->map(bo->drm->drv, bo, 368 x, y, w, h, write, addr); 369 if (err) 370 return err; 371 } 372 else { 373 /* kernel handles the synchronization here */ 374 } 375 376 bo->lock_count++; 377 bo->locked_for |= usage; 378 379 return 0; 380 } 381 382 /* 383 * Unlock a bo. 384 */ 385 void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo) 386 { 387 int mapped = bo->locked_for & 388 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK); 389 390 if (!bo->lock_count) 391 return; 392 393 if (mapped) 394 bo->drm->drv->unmap(bo->drm->drv, bo); 395 396 bo->lock_count--; 397 if (!bo->lock_count) 398 bo->locked_for = 0; 399 } 400