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 struct gralloc_drm_bo_t *bo; 198 199 bo = validate_handle(handle, drm); 200 if (!bo) 201 return -EINVAL; 202 203 bo->refcount++; 204 205 return 0; 206 } 207 208 /* 209 * Unregister a buffer handle. It is no-op for handles created locally. 210 */ 211 int gralloc_drm_handle_unregister(buffer_handle_t handle) 212 { 213 struct gralloc_drm_bo_t *bo; 214 215 bo = validate_handle(handle, NULL); 216 if (!bo) 217 return -EINVAL; 218 219 gralloc_drm_bo_decref(bo); 220 if (bo->imported) 221 gralloc_drm_bo_decref(bo); 222 223 return 0; 224 } 225 226 /* 227 * Create a buffer handle. 228 */ 229 static struct gralloc_drm_handle_t *create_bo_handle(int width, 230 int height, int format, int usage) 231 { 232 struct gralloc_drm_handle_t *handle; 233 234 handle = new gralloc_drm_handle_t; 235 if (!handle) 236 return NULL; 237 238 handle->base.version = sizeof(handle->base); 239 handle->base.numInts = GRALLOC_DRM_HANDLE_NUM_INTS; 240 handle->base.numFds = GRALLOC_DRM_HANDLE_NUM_FDS; 241 242 handle->magic = GRALLOC_DRM_HANDLE_MAGIC; 243 handle->width = width; 244 handle->height = height; 245 handle->format = format; 246 handle->usage = usage; 247 handle->prime_fd = -1; 248 249 return handle; 250 } 251 252 /* 253 * Create a bo. 254 */ 255 struct gralloc_drm_bo_t *gralloc_drm_bo_create(struct gralloc_drm_t *drm, 256 int width, int height, int format, int usage) 257 { 258 struct gralloc_drm_bo_t *bo; 259 struct gralloc_drm_handle_t *handle; 260 261 handle = create_bo_handle(width, height, format, usage); 262 if (!handle) 263 return NULL; 264 265 bo = drm->drv->alloc(drm->drv, handle); 266 if (!bo) { 267 delete handle; 268 return NULL; 269 } 270 271 bo->drm = drm; 272 bo->imported = 0; 273 bo->handle = handle; 274 bo->fb_id = 0; 275 bo->refcount = 1; 276 277 handle->data_owner = gralloc_drm_get_pid(); 278 handle->data = bo; 279 280 return bo; 281 } 282 283 /* 284 * Destroy a bo. 285 */ 286 static void gralloc_drm_bo_destroy(struct gralloc_drm_bo_t *bo) 287 { 288 struct gralloc_drm_handle_t *handle = bo->handle; 289 int imported = bo->imported; 290 291 /* gralloc still has a reference */ 292 if (bo->refcount) 293 return; 294 295 bo->drm->drv->free(bo->drm->drv, bo); 296 if (imported) { 297 handle->data_owner = 0; 298 handle->data = 0; 299 } 300 else { 301 delete handle; 302 } 303 } 304 305 /* 306 * Decrease refcount, if no refs anymore then destroy. 307 */ 308 void gralloc_drm_bo_decref(struct gralloc_drm_bo_t *bo) 309 { 310 if (!--bo->refcount) 311 gralloc_drm_bo_destroy(bo); 312 } 313 314 /* 315 * Return the bo of a registered handle. 316 */ 317 struct gralloc_drm_bo_t *gralloc_drm_bo_from_handle(buffer_handle_t handle) 318 { 319 return validate_handle(handle, NULL); 320 } 321 322 /* 323 * Get the buffer handle and stride of a bo. 324 */ 325 buffer_handle_t gralloc_drm_bo_get_handle(struct gralloc_drm_bo_t *bo, int *stride) 326 { 327 if (stride) 328 *stride = bo->handle->stride; 329 return &bo->handle->base; 330 } 331 332 /* 333 * Query YUV component offsets for a buffer handle 334 */ 335 void gralloc_drm_resolve_format(buffer_handle_t _handle, 336 uint32_t *pitches, uint32_t *offsets, uint32_t *handles) 337 { 338 struct gralloc_drm_handle_t *handle = gralloc_drm_handle(_handle); 339 struct gralloc_drm_bo_t *bo = handle->data; 340 struct gralloc_drm_t *drm = bo->drm; 341 342 /* if handle exists and driver implements resolve_format */ 343 if (handle && drm->drv->resolve_format) 344 drm->drv->resolve_format(drm->drv, bo, 345 pitches, offsets, handles); 346 } 347 348 /* 349 * Lock a bo. XXX thread-safety? 350 */ 351 int gralloc_drm_bo_lock(struct gralloc_drm_bo_t *bo, 352 int usage, int x, int y, int w, int h, 353 void **addr) 354 { 355 if ((bo->handle->usage & usage) != usage) { 356 /* make FB special for testing software renderer with */ 357 358 if (!(bo->handle->usage & GRALLOC_USAGE_HW_FB) 359 && !(bo->handle->usage & GRALLOC_USAGE_HW_TEXTURE)) { 360 ALOGE("bo.usage:x%X/usage:x%X is not GRALLOC_USAGE_HW_FB or GRALLOC_USAGE_HW_TEXTURE" 361 ,bo->handle->usage,usage); 362 return -EINVAL; 363 } 364 } 365 366 /* allow multiple locks with compatible usages */ 367 if (bo->lock_count && (bo->locked_for & usage) != usage) 368 return -EINVAL; 369 370 usage |= bo->locked_for; 371 372 if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | 373 GRALLOC_USAGE_SW_READ_MASK)) { 374 /* the driver is supposed to wait for the bo */ 375 int write = !!(usage & GRALLOC_USAGE_SW_WRITE_MASK); 376 int err = bo->drm->drv->map(bo->drm->drv, bo, 377 x, y, w, h, write, addr); 378 if (err) 379 return err; 380 } 381 else { 382 /* kernel handles the synchronization here */ 383 } 384 385 bo->lock_count++; 386 bo->locked_for |= usage; 387 388 return 0; 389 } 390 391 /* 392 * Unlock a bo. 393 */ 394 void gralloc_drm_bo_unlock(struct gralloc_drm_bo_t *bo) 395 { 396 int mapped = bo->locked_for & 397 (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_SW_READ_MASK); 398 399 if (!bo->lock_count) 400 return; 401 402 if (mapped) 403 bo->drm->drv->unmap(bo->drm->drv, bo); 404 405 bo->lock_count--; 406 if (!bo->lock_count) 407 bo->locked_for = 0; 408 } 409