1 /* 2 * Copyright 2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Benjamin Franzke <benjaminfranzke (at) googlemail.com> 26 */ 27 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <stddef.h> 31 #include <stdint.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <limits.h> 35 #include <assert.h> 36 37 #include <sys/types.h> 38 #include <unistd.h> 39 #include <dlfcn.h> 40 #include <xf86drm.h> 41 42 #include <GL/gl.h> /* dri_interface needs GL types */ 43 #include <GL/internal/dri_interface.h> 44 45 #include "gbm_driint.h" 46 47 #include "gbmint.h" 48 #include "loader.h" 49 50 /* For importing wl_buffer */ 51 #if HAVE_WAYLAND_PLATFORM 52 #include "../../../egl/wayland/wayland-drm/wayland-drm.h" 53 #endif 54 55 static __DRIimage * 56 dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 57 { 58 struct gbm_dri_device *dri = data; 59 60 if (dri->lookup_image == NULL) 61 return NULL; 62 63 return dri->lookup_image(screen, image, dri->lookup_user_data); 64 } 65 66 static __DRIbuffer * 67 dri_get_buffers(__DRIdrawable * driDrawable, 68 int *width, int *height, 69 unsigned int *attachments, int count, 70 int *out_count, void *data) 71 { 72 struct gbm_dri_surface *surf = data; 73 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 74 75 if (dri->get_buffers == NULL) 76 return NULL; 77 78 return dri->get_buffers(driDrawable, width, height, attachments, 79 count, out_count, surf->dri_private); 80 } 81 82 static void 83 dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data) 84 { 85 struct gbm_dri_surface *surf = data; 86 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 87 88 if (dri->flush_front_buffer != NULL) 89 dri->flush_front_buffer(driDrawable, surf->dri_private); 90 } 91 92 static __DRIbuffer * 93 dri_get_buffers_with_format(__DRIdrawable * driDrawable, 94 int *width, int *height, 95 unsigned int *attachments, int count, 96 int *out_count, void *data) 97 { 98 struct gbm_dri_surface *surf = data; 99 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 100 101 if (dri->get_buffers_with_format == NULL) 102 return NULL; 103 104 return 105 dri->get_buffers_with_format(driDrawable, width, height, attachments, 106 count, out_count, surf->dri_private); 107 } 108 109 static int 110 image_get_buffers(__DRIdrawable *driDrawable, 111 unsigned int format, 112 uint32_t *stamp, 113 void *loaderPrivate, 114 uint32_t buffer_mask, 115 struct __DRIimageList *buffers) 116 { 117 struct gbm_dri_surface *surf = loaderPrivate; 118 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 119 120 if (dri->image_get_buffers == NULL) 121 return 0; 122 123 return dri->image_get_buffers(driDrawable, format, stamp, 124 surf->dri_private, buffer_mask, buffers); 125 } 126 127 static void 128 swrast_get_drawable_info(__DRIdrawable *driDrawable, 129 int *x, 130 int *y, 131 int *width, 132 int *height, 133 void *loaderPrivate) 134 { 135 struct gbm_dri_surface *surf = loaderPrivate; 136 137 *x = 0; 138 *y = 0; 139 *width = surf->base.width; 140 *height = surf->base.height; 141 } 142 143 static void 144 swrast_put_image2(__DRIdrawable *driDrawable, 145 int op, 146 int x, 147 int y, 148 int width, 149 int height, 150 int stride, 151 char *data, 152 void *loaderPrivate) 153 { 154 struct gbm_dri_surface *surf = loaderPrivate; 155 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 156 157 dri->swrast_put_image2(driDrawable, 158 op, x, y, 159 width, height, stride, 160 data, surf->dri_private); 161 } 162 163 static void 164 swrast_put_image(__DRIdrawable *driDrawable, 165 int op, 166 int x, 167 int y, 168 int width, 169 int height, 170 char *data, 171 void *loaderPrivate) 172 { 173 return swrast_put_image2(driDrawable, op, x, y, width, height, 174 width * 4, data, loaderPrivate); 175 } 176 177 static void 178 swrast_get_image(__DRIdrawable *driDrawable, 179 int x, 180 int y, 181 int width, 182 int height, 183 char *data, 184 void *loaderPrivate) 185 { 186 struct gbm_dri_surface *surf = loaderPrivate; 187 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 188 189 dri->swrast_get_image(driDrawable, 190 x, y, 191 width, height, 192 data, surf->dri_private); 193 } 194 195 static const __DRIuseInvalidateExtension use_invalidate = { 196 .base = { __DRI_USE_INVALIDATE, 1 } 197 }; 198 199 static const __DRIimageLookupExtension image_lookup_extension = { 200 .base = { __DRI_IMAGE_LOOKUP, 1 }, 201 202 .lookupEGLImage = dri_lookup_egl_image 203 }; 204 205 static const __DRIdri2LoaderExtension dri2_loader_extension = { 206 .base = { __DRI_DRI2_LOADER, 3 }, 207 208 .getBuffers = dri_get_buffers, 209 .flushFrontBuffer = dri_flush_front_buffer, 210 .getBuffersWithFormat = dri_get_buffers_with_format, 211 }; 212 213 static const __DRIimageLoaderExtension image_loader_extension = { 214 .base = { __DRI_IMAGE_LOADER, 1 }, 215 216 .getBuffers = image_get_buffers, 217 .flushFrontBuffer = dri_flush_front_buffer, 218 }; 219 220 static const __DRIswrastLoaderExtension swrast_loader_extension = { 221 .base = { __DRI_SWRAST_LOADER, 2 }, 222 223 .getDrawableInfo = swrast_get_drawable_info, 224 .putImage = swrast_put_image, 225 .getImage = swrast_get_image, 226 .putImage2 = swrast_put_image2 227 }; 228 229 static const __DRIextension *gbm_dri_screen_extensions[] = { 230 &image_lookup_extension.base, 231 &use_invalidate.base, 232 &dri2_loader_extension.base, 233 &image_loader_extension.base, 234 &swrast_loader_extension.base, 235 NULL, 236 }; 237 238 struct dri_extension_match { 239 const char *name; 240 int version; 241 int offset; 242 int optional; 243 }; 244 245 static struct dri_extension_match dri_core_extensions[] = { 246 { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) }, 247 { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) }, 248 { __DRI2_FENCE, 1, offsetof(struct gbm_dri_device, fence), 1 }, 249 { __DRI2_INTEROP, 1, offsetof(struct gbm_dri_device, interop), 1 }, 250 { NULL, 0, 0 } 251 }; 252 253 static struct dri_extension_match gbm_dri_device_extensions[] = { 254 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) }, 255 { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) }, 256 { NULL, 0, 0 } 257 }; 258 259 static struct dri_extension_match gbm_swrast_device_extensions[] = { 260 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), }, 261 { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) }, 262 { NULL, 0, 0 } 263 }; 264 265 static int 266 dri_bind_extensions(struct gbm_dri_device *dri, 267 struct dri_extension_match *matches, 268 const __DRIextension **extensions) 269 { 270 int i, j, ret = 0; 271 void *field; 272 273 for (i = 0; extensions[i]; i++) { 274 for (j = 0; matches[j].name; j++) { 275 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 276 extensions[i]->version >= matches[j].version) { 277 field = ((char *) dri + matches[j].offset); 278 *(const __DRIextension **) field = extensions[i]; 279 } 280 } 281 } 282 283 for (j = 0; matches[j].name; j++) { 284 field = ((char *) dri + matches[j].offset); 285 if ((*(const __DRIextension **) field == NULL) && !matches[j].optional) { 286 ret = -1; 287 } 288 } 289 290 return ret; 291 } 292 293 static const __DRIextension ** 294 dri_open_driver(struct gbm_dri_device *dri) 295 { 296 const __DRIextension **extensions = NULL; 297 char path[PATH_MAX], *search_paths, *p, *next, *end; 298 char *get_extensions_name; 299 300 search_paths = NULL; 301 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */ 302 if (geteuid() == getuid()) { 303 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH 304 * is recommended over GBM_DRIVERS_PATH. 305 */ 306 search_paths = getenv("GBM_DRIVERS_PATH"); 307 308 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set. 309 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH. 310 */ 311 if (search_paths == NULL) { 312 search_paths = getenv("LIBGL_DRIVERS_PATH"); 313 } 314 } 315 if (search_paths == NULL) 316 search_paths = DEFAULT_DRIVER_DIR; 317 318 /* Temporarily work around dri driver libs that need symbols in libglapi 319 * but don't automatically link it in. 320 */ 321 /* XXX: Library name differs on per platforms basis. Update this as 322 * osx/cygwin/windows/bsd gets support for GBM.. 323 */ 324 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); 325 326 dri->driver = NULL; 327 end = search_paths + strlen(search_paths); 328 for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) { 329 int len; 330 next = strchr(p, ':'); 331 if (next == NULL) 332 next = end; 333 334 len = next - p; 335 #if GLX_USE_TLS 336 snprintf(path, sizeof path, 337 "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name); 338 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 339 #endif 340 if (dri->driver == NULL) { 341 snprintf(path, sizeof path, 342 "%.*s/%s_dri.so", len, p, dri->base.driver_name); 343 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 344 } 345 /* not need continue to loop all paths once the driver is found */ 346 if (dri->driver != NULL) 347 break; 348 349 #ifdef ANDROID 350 snprintf(path, sizeof path, "%.*s/gallium_dri.so", len, p); 351 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 352 if (dri->driver == NULL) 353 sprintf("failed to open %s: %s\n", path, dlerror()); 354 else 355 break; 356 #endif 357 } 358 359 if (dri->driver == NULL) { 360 fprintf(stderr, "gbm: failed to open any driver (search paths %s)\n", 361 search_paths); 362 fprintf(stderr, "gbm: Last dlopen error: %s\n", dlerror()); 363 return NULL; 364 } 365 366 get_extensions_name = loader_get_extensions_name(dri->base.driver_name); 367 if (get_extensions_name) { 368 const __DRIextension **(*get_extensions)(void); 369 370 get_extensions = dlsym(dri->driver, get_extensions_name); 371 free(get_extensions_name); 372 373 if (get_extensions) 374 extensions = get_extensions(); 375 } 376 377 if (!extensions) 378 extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS); 379 if (extensions == NULL) { 380 fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror()); 381 dlclose(dri->driver); 382 } 383 384 return extensions; 385 } 386 387 static int 388 dri_load_driver(struct gbm_dri_device *dri) 389 { 390 const __DRIextension **extensions; 391 392 extensions = dri_open_driver(dri); 393 if (!extensions) 394 return -1; 395 396 if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { 397 dlclose(dri->driver); 398 fprintf(stderr, "failed to bind extensions\n"); 399 return -1; 400 } 401 402 dri->driver_extensions = extensions; 403 404 return 0; 405 } 406 407 static int 408 dri_load_driver_swrast(struct gbm_dri_device *dri) 409 { 410 const __DRIextension **extensions; 411 412 extensions = dri_open_driver(dri); 413 if (!extensions) 414 return -1; 415 416 if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) { 417 dlclose(dri->driver); 418 fprintf(stderr, "failed to bind extensions\n"); 419 return -1; 420 } 421 422 dri->driver_extensions = extensions; 423 424 return 0; 425 } 426 427 static int 428 dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name) 429 { 430 const __DRIextension **extensions; 431 int ret = 0; 432 433 dri->base.driver_name = driver_name; 434 if (dri->base.driver_name == NULL) 435 return -1; 436 437 ret = dri_load_driver(dri); 438 if (ret) { 439 fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name); 440 return ret; 441 }; 442 443 dri->loader_extensions = gbm_dri_screen_extensions; 444 445 if (dri->dri2 == NULL) 446 return -1; 447 448 if (dri->dri2->base.version >= 4) { 449 dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd, 450 dri->loader_extensions, 451 dri->driver_extensions, 452 &dri->driver_configs, dri); 453 } else { 454 dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd, 455 dri->loader_extensions, 456 &dri->driver_configs, dri); 457 } 458 if (dri->screen == NULL) 459 return -1; 460 461 extensions = dri->core->getExtensions(dri->screen); 462 if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) { 463 ret = -1; 464 goto free_screen; 465 } 466 467 dri->lookup_image = NULL; 468 dri->lookup_user_data = NULL; 469 470 return 0; 471 472 free_screen: 473 dri->core->destroyScreen(dri->screen); 474 475 return ret; 476 } 477 478 static int 479 dri_screen_create_swrast(struct gbm_dri_device *dri) 480 { 481 int ret; 482 483 dri->base.driver_name = strdup("swrast"); 484 if (dri->base.driver_name == NULL) 485 return -1; 486 487 ret = dri_load_driver_swrast(dri); 488 if (ret) { 489 fprintf(stderr, "failed to load swrast driver\n"); 490 return ret; 491 } 492 493 dri->loader_extensions = gbm_dri_screen_extensions; 494 495 if (dri->swrast == NULL) 496 return -1; 497 498 if (dri->swrast->base.version >= 4) { 499 dri->screen = dri->swrast->createNewScreen2(0, dri->loader_extensions, 500 dri->driver_extensions, 501 &dri->driver_configs, dri); 502 } else { 503 dri->screen = dri->swrast->createNewScreen(0, dri->loader_extensions, 504 &dri->driver_configs, dri); 505 } 506 if (dri->screen == NULL) 507 return -1; 508 509 dri->lookup_image = NULL; 510 dri->lookup_user_data = NULL; 511 512 return 0; 513 } 514 515 static int 516 dri_screen_create(struct gbm_dri_device *dri) 517 { 518 char *driver_name; 519 520 driver_name = loader_get_driver_for_fd(dri->base.base.fd); 521 if (!driver_name) 522 return -1; 523 524 return dri_screen_create_dri2(dri, driver_name); 525 } 526 527 static int 528 dri_screen_create_sw(struct gbm_dri_device *dri) 529 { 530 char *driver_name; 531 int ret; 532 533 driver_name = strdup("kms_swrast"); 534 if (!driver_name) 535 return -errno; 536 537 ret = dri_screen_create_dri2(dri, driver_name); 538 if (ret == 0) 539 return ret; 540 541 return dri_screen_create_swrast(dri); 542 } 543 544 static int 545 gbm_dri_is_format_supported(struct gbm_device *gbm, 546 uint32_t format, 547 uint32_t usage) 548 { 549 switch (format) { 550 case GBM_BO_FORMAT_XRGB8888: 551 case GBM_FORMAT_XBGR8888: 552 case GBM_FORMAT_XRGB8888: 553 break; 554 case GBM_BO_FORMAT_ARGB8888: 555 case GBM_FORMAT_ARGB8888: 556 if (usage & GBM_BO_USE_SCANOUT) 557 return 0; 558 break; 559 default: 560 return 0; 561 } 562 563 if (usage & GBM_BO_USE_CURSOR && 564 usage & GBM_BO_USE_RENDERING) 565 return 0; 566 567 return 1; 568 } 569 570 static int 571 gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count) 572 { 573 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 574 575 if (bo->image != NULL) { 576 errno = EINVAL; 577 return -1; 578 } 579 580 memcpy(bo->map, buf, count); 581 582 return 0; 583 } 584 585 static int 586 gbm_dri_bo_get_fd(struct gbm_bo *_bo) 587 { 588 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 589 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 590 int fd; 591 592 if (bo->image == NULL) 593 return -1; 594 595 if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) 596 return -1; 597 598 return fd; 599 } 600 601 static void 602 gbm_dri_bo_destroy(struct gbm_bo *_bo) 603 { 604 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 605 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 606 struct drm_mode_destroy_dumb arg; 607 608 if (bo->image != NULL) { 609 dri->image->destroyImage(bo->image); 610 } else { 611 gbm_dri_bo_unmap_dumb(bo); 612 memset(&arg, 0, sizeof(arg)); 613 arg.handle = bo->handle; 614 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 615 } 616 617 free(bo); 618 } 619 620 static uint32_t 621 gbm_dri_to_gbm_format(uint32_t dri_format) 622 { 623 uint32_t ret = 0; 624 625 switch (dri_format) { 626 case __DRI_IMAGE_FORMAT_RGB565: 627 ret = GBM_FORMAT_RGB565; 628 break; 629 case __DRI_IMAGE_FORMAT_XRGB8888: 630 ret = GBM_FORMAT_XRGB8888; 631 break; 632 case __DRI_IMAGE_FORMAT_ARGB8888: 633 ret = GBM_FORMAT_ARGB8888; 634 break; 635 case __DRI_IMAGE_FORMAT_XBGR8888: 636 ret = GBM_FORMAT_XBGR8888; 637 break; 638 case __DRI_IMAGE_FORMAT_ABGR8888: 639 ret = GBM_FORMAT_ABGR8888; 640 break; 641 default: 642 ret = 0; 643 break; 644 } 645 646 return ret; 647 } 648 649 static struct gbm_bo * 650 gbm_dri_bo_import(struct gbm_device *gbm, 651 uint32_t type, void *buffer, uint32_t usage) 652 { 653 struct gbm_dri_device *dri = gbm_dri_device(gbm); 654 struct gbm_dri_bo *bo; 655 __DRIimage *image; 656 unsigned dri_use = 0; 657 int gbm_format; 658 659 /* Required for query image WIDTH & HEIGHT */ 660 if (dri->image == NULL || dri->image->base.version < 4) { 661 errno = ENOSYS; 662 return NULL; 663 } 664 665 switch (type) { 666 #if HAVE_WAYLAND_PLATFORM 667 case GBM_BO_IMPORT_WL_BUFFER: 668 { 669 struct wl_drm_buffer *wb; 670 671 if (!dri->wl_drm) { 672 errno = EINVAL; 673 return NULL; 674 } 675 676 wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer); 677 if (!wb) { 678 errno = EINVAL; 679 return NULL; 680 } 681 682 image = dri->image->dupImage(wb->driver_buffer, NULL); 683 684 switch (wb->format) { 685 case WL_DRM_FORMAT_XRGB8888: 686 gbm_format = GBM_FORMAT_XRGB8888; 687 break; 688 case WL_DRM_FORMAT_ARGB8888: 689 gbm_format = GBM_FORMAT_ARGB8888; 690 break; 691 case WL_DRM_FORMAT_RGB565: 692 gbm_format = GBM_FORMAT_RGB565; 693 break; 694 case WL_DRM_FORMAT_YUYV: 695 gbm_format = GBM_FORMAT_YUYV; 696 break; 697 default: 698 return NULL; 699 } 700 break; 701 } 702 #endif 703 704 case GBM_BO_IMPORT_EGL_IMAGE: 705 { 706 int dri_format; 707 if (dri->lookup_image == NULL) { 708 errno = EINVAL; 709 return NULL; 710 } 711 712 image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data); 713 image = dri->image->dupImage(image, NULL); 714 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format); 715 gbm_format = gbm_dri_to_gbm_format(dri_format); 716 if (gbm_format == 0) { 717 errno = EINVAL; 718 return NULL; 719 } 720 break; 721 } 722 723 case GBM_BO_IMPORT_FD: 724 { 725 struct gbm_import_fd_data *fd_data = buffer; 726 int stride = fd_data->stride, offset = 0; 727 int dri_format; 728 729 switch (fd_data->format) { 730 case GBM_BO_FORMAT_XRGB8888: 731 dri_format = GBM_FORMAT_XRGB8888; 732 break; 733 case GBM_BO_FORMAT_ARGB8888: 734 dri_format = GBM_FORMAT_ARGB8888; 735 break; 736 default: 737 dri_format = fd_data->format; 738 } 739 740 image = dri->image->createImageFromFds(dri->screen, 741 fd_data->width, 742 fd_data->height, 743 dri_format, 744 &fd_data->fd, 1, 745 &stride, &offset, 746 NULL); 747 if (image == NULL) { 748 errno = EINVAL; 749 return NULL; 750 } 751 gbm_format = fd_data->format; 752 break; 753 } 754 755 default: 756 errno = ENOSYS; 757 return NULL; 758 } 759 760 761 bo = calloc(1, sizeof *bo); 762 if (bo == NULL) 763 return NULL; 764 765 bo->image = image; 766 767 if (usage & GBM_BO_USE_SCANOUT) 768 dri_use |= __DRI_IMAGE_USE_SCANOUT; 769 if (usage & GBM_BO_USE_CURSOR) 770 dri_use |= __DRI_IMAGE_USE_CURSOR; 771 if (dri->image->base.version >= 2 && 772 !dri->image->validateUsage(bo->image, dri_use)) { 773 errno = EINVAL; 774 free(bo); 775 return NULL; 776 } 777 778 bo->base.base.gbm = gbm; 779 bo->base.base.format = gbm_format; 780 781 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH, 782 (int*)&bo->base.base.width); 783 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT, 784 (int*)&bo->base.base.height); 785 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 786 (int*)&bo->base.base.stride); 787 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 788 &bo->base.base.handle.s32); 789 790 return &bo->base.base; 791 } 792 793 static struct gbm_bo * 794 create_dumb(struct gbm_device *gbm, 795 uint32_t width, uint32_t height, 796 uint32_t format, uint32_t usage) 797 { 798 struct gbm_dri_device *dri = gbm_dri_device(gbm); 799 struct drm_mode_create_dumb create_arg; 800 struct gbm_dri_bo *bo; 801 struct drm_mode_destroy_dumb destroy_arg; 802 int ret; 803 int is_cursor, is_scanout; 804 805 is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 && 806 format == GBM_FORMAT_ARGB8888; 807 is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 && 808 format == GBM_FORMAT_XRGB8888; 809 if (!is_cursor && !is_scanout) { 810 errno = EINVAL; 811 return NULL; 812 } 813 814 bo = calloc(1, sizeof *bo); 815 if (bo == NULL) 816 return NULL; 817 818 memset(&create_arg, 0, sizeof(create_arg)); 819 create_arg.bpp = 32; 820 create_arg.width = width; 821 create_arg.height = height; 822 823 ret = drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg); 824 if (ret) 825 goto free_bo; 826 827 bo->base.base.gbm = gbm; 828 bo->base.base.width = width; 829 bo->base.base.height = height; 830 bo->base.base.stride = create_arg.pitch; 831 bo->base.base.format = format; 832 bo->base.base.handle.u32 = create_arg.handle; 833 bo->handle = create_arg.handle; 834 bo->size = create_arg.size; 835 836 if (gbm_dri_bo_map_dumb(bo) == NULL) 837 goto destroy_dumb; 838 839 return &bo->base.base; 840 841 destroy_dumb: 842 memset(&destroy_arg, 0, sizeof destroy_arg); 843 destroy_arg.handle = create_arg.handle; 844 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); 845 free_bo: 846 free(bo); 847 848 return NULL; 849 } 850 851 static struct gbm_bo * 852 gbm_dri_bo_create(struct gbm_device *gbm, 853 uint32_t width, uint32_t height, 854 uint32_t format, uint32_t usage) 855 { 856 struct gbm_dri_device *dri = gbm_dri_device(gbm); 857 struct gbm_dri_bo *bo; 858 int dri_format; 859 unsigned dri_use = 0; 860 861 if (usage & GBM_BO_USE_WRITE || dri->image == NULL) 862 return create_dumb(gbm, width, height, format, usage); 863 864 bo = calloc(1, sizeof *bo); 865 if (bo == NULL) 866 return NULL; 867 868 bo->base.base.gbm = gbm; 869 bo->base.base.width = width; 870 bo->base.base.height = height; 871 bo->base.base.format = format; 872 873 switch (format) { 874 case GBM_FORMAT_R8: 875 dri_format = __DRI_IMAGE_FORMAT_R8; 876 break; 877 case GBM_FORMAT_GR88: 878 dri_format = __DRI_IMAGE_FORMAT_GR88; 879 break; 880 case GBM_FORMAT_RGB565: 881 dri_format = __DRI_IMAGE_FORMAT_RGB565; 882 break; 883 case GBM_FORMAT_XRGB8888: 884 case GBM_BO_FORMAT_XRGB8888: 885 dri_format = __DRI_IMAGE_FORMAT_XRGB8888; 886 break; 887 case GBM_FORMAT_ARGB8888: 888 case GBM_BO_FORMAT_ARGB8888: 889 dri_format = __DRI_IMAGE_FORMAT_ARGB8888; 890 break; 891 case GBM_FORMAT_ABGR8888: 892 dri_format = __DRI_IMAGE_FORMAT_ABGR8888; 893 break; 894 case GBM_FORMAT_XBGR8888: 895 dri_format = __DRI_IMAGE_FORMAT_XBGR8888; 896 break; 897 case GBM_FORMAT_ARGB2101010: 898 dri_format = __DRI_IMAGE_FORMAT_ARGB2101010; 899 break; 900 case GBM_FORMAT_XRGB2101010: 901 dri_format = __DRI_IMAGE_FORMAT_XRGB2101010; 902 break; 903 default: 904 errno = EINVAL; 905 goto failed; 906 } 907 908 if (usage & GBM_BO_USE_SCANOUT) 909 dri_use |= __DRI_IMAGE_USE_SCANOUT; 910 if (usage & GBM_BO_USE_CURSOR) 911 dri_use |= __DRI_IMAGE_USE_CURSOR; 912 if (usage & GBM_BO_USE_LINEAR) 913 dri_use |= __DRI_IMAGE_USE_LINEAR; 914 915 /* Gallium drivers requires shared in order to get the handle/stride */ 916 dri_use |= __DRI_IMAGE_USE_SHARE; 917 918 bo->image = 919 dri->image->createImage(dri->screen, 920 width, height, 921 dri_format, dri_use, 922 bo); 923 if (bo->image == NULL) 924 goto failed; 925 926 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 927 &bo->base.base.handle.s32); 928 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 929 (int *) &bo->base.base.stride); 930 931 return &bo->base.base; 932 933 failed: 934 free(bo); 935 return NULL; 936 } 937 938 static void * 939 gbm_dri_bo_map(struct gbm_bo *_bo, 940 uint32_t x, uint32_t y, 941 uint32_t width, uint32_t height, 942 uint32_t flags, uint32_t *stride, void **map_data) 943 { 944 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 945 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 946 947 /* If it's a dumb buffer, we already have a mapping */ 948 if (bo->map) { 949 *map_data = (char *)bo->map + (bo->base.base.stride * y) + (x * 4); 950 *stride = bo->base.base.stride; 951 return *map_data; 952 } 953 954 if (!dri->image || dri->image->base.version < 12 || !dri->image->mapImage) { 955 errno = ENOSYS; 956 return NULL; 957 } 958 959 mtx_lock(&dri->mutex); 960 if (!dri->context) 961 dri->context = dri->dri2->createNewContext(dri->screen, NULL, 962 NULL, NULL); 963 assert(dri->context); 964 mtx_unlock(&dri->mutex); 965 966 /* GBM flags and DRI flags are the same, so just pass them on */ 967 return dri->image->mapImage(dri->context, bo->image, x, y, 968 width, height, flags, (int *)stride, 969 map_data); 970 } 971 972 static void 973 gbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data) 974 { 975 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 976 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 977 978 /* Check if it's a dumb buffer and check the pointer is in range */ 979 if (bo->map) { 980 assert(map_data >= bo->map); 981 assert(map_data < (bo->map + bo->size)); 982 return; 983 } 984 985 if (!dri->context || !dri->image || 986 dri->image->base.version < 12 || !dri->image->unmapImage) 987 return; 988 989 dri->image->unmapImage(dri->context, bo->image, map_data); 990 991 /* 992 * Not all DRI drivers use direct maps. They may queue up DMA operations 993 * on the mapping context. Since there is no explicit gbm flush 994 * mechanism, we need to flush here. 995 */ 996 if (dri->flush->base.version >= 4) 997 dri->flush->flush_with_flags(dri->context, NULL, __DRI2_FLUSH_CONTEXT, 0); 998 } 999 1000 1001 static struct gbm_surface * 1002 gbm_dri_surface_create(struct gbm_device *gbm, 1003 uint32_t width, uint32_t height, 1004 uint32_t format, uint32_t flags) 1005 { 1006 struct gbm_dri_surface *surf; 1007 1008 surf = calloc(1, sizeof *surf); 1009 if (surf == NULL) 1010 return NULL; 1011 1012 surf->base.gbm = gbm; 1013 surf->base.width = width; 1014 surf->base.height = height; 1015 surf->base.format = format; 1016 surf->base.flags = flags; 1017 1018 return &surf->base; 1019 } 1020 1021 static void 1022 gbm_dri_surface_destroy(struct gbm_surface *_surf) 1023 { 1024 struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 1025 1026 free(surf); 1027 } 1028 1029 static void 1030 dri_destroy(struct gbm_device *gbm) 1031 { 1032 struct gbm_dri_device *dri = gbm_dri_device(gbm); 1033 unsigned i; 1034 1035 if (dri->context) 1036 dri->core->destroyContext(dri->context); 1037 1038 dri->core->destroyScreen(dri->screen); 1039 for (i = 0; dri->driver_configs[i]; i++) 1040 free((__DRIconfig *) dri->driver_configs[i]); 1041 free(dri->driver_configs); 1042 dlclose(dri->driver); 1043 free(dri->base.driver_name); 1044 1045 free(dri); 1046 } 1047 1048 static struct gbm_device * 1049 dri_device_create(int fd) 1050 { 1051 struct gbm_dri_device *dri; 1052 int ret, force_sw; 1053 1054 dri = calloc(1, sizeof *dri); 1055 if (!dri) 1056 return NULL; 1057 1058 dri->base.base.fd = fd; 1059 dri->base.base.bo_create = gbm_dri_bo_create; 1060 dri->base.base.bo_import = gbm_dri_bo_import; 1061 dri->base.base.bo_map = gbm_dri_bo_map; 1062 dri->base.base.bo_unmap = gbm_dri_bo_unmap; 1063 dri->base.base.is_format_supported = gbm_dri_is_format_supported; 1064 dri->base.base.bo_write = gbm_dri_bo_write; 1065 dri->base.base.bo_get_fd = gbm_dri_bo_get_fd; 1066 dri->base.base.bo_destroy = gbm_dri_bo_destroy; 1067 dri->base.base.destroy = dri_destroy; 1068 dri->base.base.surface_create = gbm_dri_surface_create; 1069 dri->base.base.surface_destroy = gbm_dri_surface_destroy; 1070 1071 dri->base.type = GBM_DRM_DRIVER_TYPE_DRI; 1072 dri->base.base.name = "drm"; 1073 1074 mtx_init(&dri->mutex, mtx_plain); 1075 1076 force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL; 1077 if (!force_sw) { 1078 ret = dri_screen_create(dri); 1079 if (ret) 1080 ret = dri_screen_create_sw(dri); 1081 } else { 1082 ret = dri_screen_create_sw(dri); 1083 } 1084 1085 if (ret) 1086 goto err_dri; 1087 1088 return &dri->base.base; 1089 1090 err_dri: 1091 free(dri); 1092 1093 return NULL; 1094 } 1095 1096 struct gbm_backend gbm_dri_backend = { 1097 .backend_name = "dri", 1098 .create_device = dri_device_create, 1099 }; 1100