gbm_dri.c revision af69d88d
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@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 36#include <sys/types.h> 37#include <unistd.h> 38#include <dlfcn.h> 39#include <xf86drm.h> 40 41#include <GL/gl.h> /* dri_interface needs GL types */ 42#include <GL/internal/dri_interface.h> 43 44#include "gbm_driint.h" 45 46#include "gbmint.h" 47#include "loader.h" 48 49/* For importing wl_buffer */ 50#if HAVE_WAYLAND_PLATFORM 51#include "../../../egl/wayland/wayland-drm/wayland-drm.h" 52#endif 53 54static __DRIimage * 55dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 56{ 57 struct gbm_dri_device *dri = data; 58 59 if (dri->lookup_image == NULL) 60 return NULL; 61 62 return dri->lookup_image(screen, image, dri->lookup_user_data); 63} 64 65static __DRIbuffer * 66dri_get_buffers(__DRIdrawable * driDrawable, 67 int *width, int *height, 68 unsigned int *attachments, int count, 69 int *out_count, void *data) 70{ 71 struct gbm_dri_surface *surf = data; 72 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 73 74 if (dri->get_buffers == NULL) 75 return NULL; 76 77 return dri->get_buffers(driDrawable, width, height, attachments, 78 count, out_count, surf->dri_private); 79} 80 81static void 82dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data) 83{ 84 struct gbm_dri_surface *surf = data; 85 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 86 87 if (dri->flush_front_buffer != NULL) 88 dri->flush_front_buffer(driDrawable, surf->dri_private); 89} 90 91static __DRIbuffer * 92dri_get_buffers_with_format(__DRIdrawable * driDrawable, 93 int *width, int *height, 94 unsigned int *attachments, int count, 95 int *out_count, void *data) 96{ 97 struct gbm_dri_surface *surf = data; 98 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 99 100 if (dri->get_buffers_with_format == NULL) 101 return NULL; 102 103 return 104 dri->get_buffers_with_format(driDrawable, width, height, attachments, 105 count, out_count, surf->dri_private); 106} 107 108static int 109image_get_buffers(__DRIdrawable *driDrawable, 110 unsigned int format, 111 uint32_t *stamp, 112 void *loaderPrivate, 113 uint32_t buffer_mask, 114 struct __DRIimageList *buffers) 115{ 116 struct gbm_dri_surface *surf = loaderPrivate; 117 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 118 119 if (dri->image_get_buffers == NULL) 120 return 0; 121 122 return dri->image_get_buffers(driDrawable, format, stamp, 123 surf->dri_private, buffer_mask, buffers); 124} 125 126static void 127swrast_get_drawable_info(__DRIdrawable *driDrawable, 128 int *x, 129 int *y, 130 int *width, 131 int *height, 132 void *loaderPrivate) 133{ 134 struct gbm_dri_surface *surf = loaderPrivate; 135 136 *x = 0; 137 *y = 0; 138 *width = surf->base.width; 139 *height = surf->base.height; 140} 141 142static void 143swrast_put_image2(__DRIdrawable *driDrawable, 144 int op, 145 int x, 146 int y, 147 int width, 148 int height, 149 int stride, 150 char *data, 151 void *loaderPrivate) 152{ 153 struct gbm_dri_surface *surf = loaderPrivate; 154 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 155 156 dri->swrast_put_image2(driDrawable, 157 op, x, y, 158 width, height, stride, 159 data, surf->dri_private); 160} 161 162static void 163swrast_put_image(__DRIdrawable *driDrawable, 164 int op, 165 int x, 166 int y, 167 int width, 168 int height, 169 char *data, 170 void *loaderPrivate) 171{ 172 return swrast_put_image2(driDrawable, op, x, y, width, height, 173 width * 4, data, loaderPrivate); 174} 175 176static void 177swrast_get_image(__DRIdrawable *driDrawable, 178 int x, 179 int y, 180 int width, 181 int height, 182 char *data, 183 void *loaderPrivate) 184{ 185 struct gbm_dri_surface *surf = loaderPrivate; 186 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 187 188 dri->swrast_get_image(driDrawable, 189 x, y, 190 width, height, 191 data, surf->dri_private); 192} 193 194static const __DRIuseInvalidateExtension use_invalidate = { 195 .base = { __DRI_USE_INVALIDATE, 1 } 196}; 197 198static const __DRIimageLookupExtension image_lookup_extension = { 199 .base = { __DRI_IMAGE_LOOKUP, 1 }, 200 201 .lookupEGLImage = dri_lookup_egl_image 202}; 203 204static const __DRIdri2LoaderExtension dri2_loader_extension = { 205 .base = { __DRI_DRI2_LOADER, 3 }, 206 207 .getBuffers = dri_get_buffers, 208 .flushFrontBuffer = dri_flush_front_buffer, 209 .getBuffersWithFormat = dri_get_buffers_with_format, 210}; 211 212static const __DRIimageLoaderExtension image_loader_extension = { 213 .base = { __DRI_IMAGE_LOADER, 1 }, 214 215 .getBuffers = image_get_buffers, 216 .flushFrontBuffer = dri_flush_front_buffer, 217}; 218 219static const __DRIswrastLoaderExtension swrast_loader_extension = { 220 .base = { __DRI_SWRAST_LOADER, 2 }, 221 222 .getDrawableInfo = swrast_get_drawable_info, 223 .putImage = swrast_put_image, 224 .getImage = swrast_get_image, 225 .putImage2 = swrast_put_image2 226}; 227 228static const __DRIextension *gbm_dri_screen_extensions[] = { 229 &image_lookup_extension.base, 230 &use_invalidate.base, 231 &dri2_loader_extension.base, 232 &image_loader_extension.base, 233 &swrast_loader_extension.base, 234 NULL, 235}; 236 237struct dri_extension_match { 238 const char *name; 239 int version; 240 int offset; 241}; 242 243static struct dri_extension_match dri_core_extensions[] = { 244 { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush) }, 245 { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image) }, 246 { NULL, 0, 0 } 247}; 248 249static struct dri_extension_match gbm_dri_device_extensions[] = { 250 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core) }, 251 { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2) }, 252 { NULL, 0, 0 } 253}; 254 255static struct dri_extension_match gbm_swrast_device_extensions[] = { 256 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), }, 257 { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast) }, 258 { NULL, 0, 0 } 259}; 260 261static int 262dri_bind_extensions(struct gbm_dri_device *dri, 263 struct dri_extension_match *matches, 264 const __DRIextension **extensions) 265{ 266 int i, j, ret = 0; 267 void *field; 268 269 for (i = 0; extensions[i]; i++) { 270 for (j = 0; matches[j].name; j++) { 271 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 272 extensions[i]->version >= matches[j].version) { 273 field = ((char *) dri + matches[j].offset); 274 *(const __DRIextension **) field = extensions[i]; 275 } 276 } 277 } 278 279 for (j = 0; matches[j].name; j++) { 280 field = ((char *) dri + matches[j].offset); 281 if (*(const __DRIextension **) field == NULL) { 282 ret = -1; 283 } 284 } 285 286 return ret; 287} 288 289static const __DRIextension ** 290dri_open_driver(struct gbm_dri_device *dri) 291{ 292 const __DRIextension **extensions = NULL; 293 char path[PATH_MAX], *search_paths, *p, *next, *end; 294 char *get_extensions_name; 295 296 search_paths = NULL; 297 /* don't allow setuid apps to use LIBGL_DRIVERS_PATH or GBM_DRIVERS_PATH */ 298 if (geteuid() == getuid()) { 299 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH 300 * is recommended over GBM_DRIVERS_PATH. 301 */ 302 search_paths = getenv("GBM_DRIVERS_PATH"); 303 304 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set. 305 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH. 306 */ 307 if (search_paths == NULL) { 308 search_paths = getenv("LIBGL_DRIVERS_PATH"); 309 } 310 } 311 if (search_paths == NULL) 312 search_paths = DEFAULT_DRIVER_DIR; 313 314 dri->driver = NULL; 315 end = search_paths + strlen(search_paths); 316 for (p = search_paths; p < end && dri->driver == NULL; p = next + 1) { 317 int len; 318 next = strchr(p, ':'); 319 if (next == NULL) 320 next = end; 321 322 len = next - p; 323#if GLX_USE_TLS 324 snprintf(path, sizeof path, 325 "%.*s/tls/%s_dri.so", len, p, dri->base.driver_name); 326 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 327#endif 328 if (dri->driver == NULL) { 329 snprintf(path, sizeof path, 330 "%.*s/%s_dri.so", len, p, dri->base.driver_name); 331 dri->driver = dlopen(path, RTLD_NOW | RTLD_GLOBAL); 332 } 333 /* not need continue to loop all paths once the driver is found */ 334 if (dri->driver != NULL) 335 break; 336 } 337 338 if (dri->driver == NULL) { 339 fprintf(stderr, "gbm: failed to open any driver (search paths %s)\n", 340 search_paths); 341 fprintf(stderr, "gbm: Last dlopen error: %s\n", dlerror()); 342 return NULL; 343 } 344 345 if (asprintf(&get_extensions_name, "%s_%s", 346 __DRI_DRIVER_GET_EXTENSIONS, dri->base.driver_name) != -1) { 347 const __DRIextension **(*get_extensions)(void); 348 349 get_extensions = dlsym(dri->driver, get_extensions_name); 350 free(get_extensions_name); 351 352 if (get_extensions) 353 extensions = get_extensions(); 354 } 355 356 if (!extensions) 357 extensions = dlsym(dri->driver, __DRI_DRIVER_EXTENSIONS); 358 if (extensions == NULL) { 359 fprintf(stderr, "gbm: driver exports no extensions (%s)", dlerror()); 360 dlclose(dri->driver); 361 } 362 363 return extensions; 364} 365 366static int 367dri_load_driver(struct gbm_dri_device *dri) 368{ 369 const __DRIextension **extensions; 370 371 extensions = dri_open_driver(dri); 372 if (!extensions) 373 return -1; 374 375 if (dri_bind_extensions(dri, gbm_dri_device_extensions, extensions) < 0) { 376 dlclose(dri->driver); 377 fprintf(stderr, "failed to bind extensions\n"); 378 return -1; 379 } 380 381 dri->driver_extensions = extensions; 382 383 return 0; 384} 385 386static int 387dri_load_driver_swrast(struct gbm_dri_device *dri) 388{ 389 const __DRIextension **extensions; 390 391 extensions = dri_open_driver(dri); 392 if (!extensions) 393 return -1; 394 395 if (dri_bind_extensions(dri, gbm_swrast_device_extensions, extensions) < 0) { 396 dlclose(dri->driver); 397 fprintf(stderr, "failed to bind extensions\n"); 398 return -1; 399 } 400 401 dri->driver_extensions = extensions; 402 403 return 0; 404} 405 406static int 407dri_screen_create_dri2(struct gbm_dri_device *dri, 408 const char *driver_name) 409{ 410 const __DRIextension **extensions; 411 int ret = 0; 412 413 dri->base.driver_name = driver_name; 414 if (dri->base.driver_name == NULL) 415 return -1; 416 417 ret = dri_load_driver(dri); 418 if (ret) { 419 fprintf(stderr, "failed to load driver: %s\n", dri->base.driver_name); 420 return ret; 421 }; 422 423 dri->extensions = gbm_dri_screen_extensions; 424 425 if (dri->dri2 == NULL) 426 return -1; 427 428 if (dri->dri2->base.version >= 4) { 429 dri->screen = dri->dri2->createNewScreen2(0, dri->base.base.fd, 430 dri->extensions, 431 dri->driver_extensions, 432 &dri->driver_configs, dri); 433 } else { 434 dri->screen = dri->dri2->createNewScreen(0, dri->base.base.fd, 435 dri->extensions, 436 &dri->driver_configs, dri); 437 } 438 if (dri->screen == NULL) 439 return -1; 440 441 extensions = dri->core->getExtensions(dri->screen); 442 if (dri_bind_extensions(dri, dri_core_extensions, extensions) < 0) { 443 ret = -1; 444 goto free_screen; 445 } 446 447 dri->lookup_image = NULL; 448 dri->lookup_user_data = NULL; 449 450 return 0; 451 452free_screen: 453 dri->core->destroyScreen(dri->screen); 454 455 return ret; 456} 457 458static int 459dri_screen_create_swrast(struct gbm_dri_device *dri) 460{ 461 int ret; 462 463 dri->base.driver_name = strdup("swrast"); 464 if (dri->base.driver_name == NULL) 465 return -1; 466 467 ret = dri_load_driver_swrast(dri); 468 if (ret) { 469 fprintf(stderr, "failed to load swrast driver\n"); 470 return ret; 471 } 472 473 dri->extensions = gbm_dri_screen_extensions; 474 475 if (dri->swrast == NULL) 476 return -1; 477 478 if (dri->swrast->base.version >= 4) { 479 dri->screen = dri->swrast->createNewScreen2(0, dri->extensions, 480 dri->driver_extensions, 481 &dri->driver_configs, dri); 482 } else { 483 dri->screen = dri->swrast->createNewScreen(0, dri->extensions, 484 &dri->driver_configs, dri); 485 } 486 if (dri->screen == NULL) 487 return -1; 488 489 dri->lookup_image = NULL; 490 dri->lookup_user_data = NULL; 491 492 return 0; 493} 494 495static int 496dri_screen_create(struct gbm_dri_device *dri) 497{ 498 const char *driver_name; 499 500 driver_name = loader_get_driver_for_fd(dri->base.base.fd, 0); 501 if (!driver_name) 502 return -1; 503 504 return dri_screen_create_dri2(dri, driver_name); 505} 506 507static int 508dri_screen_create_sw(struct gbm_dri_device *dri) 509{ 510 const char *driver_name; 511 int ret; 512 513 driver_name = strdup("kms_swrast"); 514 if (!driver_name) 515 return -errno; 516 517 ret = dri_screen_create_dri2(dri, driver_name); 518 if (ret == 0) 519 return ret; 520 521 return dri_screen_create_swrast(dri); 522} 523 524static int 525gbm_dri_is_format_supported(struct gbm_device *gbm, 526 uint32_t format, 527 uint32_t usage) 528{ 529 switch (format) { 530 case GBM_BO_FORMAT_XRGB8888: 531 case GBM_FORMAT_XRGB8888: 532 break; 533 case GBM_BO_FORMAT_ARGB8888: 534 case GBM_FORMAT_ARGB8888: 535 if (usage & GBM_BO_USE_SCANOUT) 536 return 0; 537 break; 538 default: 539 return 0; 540 } 541 542 if (usage & GBM_BO_USE_CURSOR && 543 usage & GBM_BO_USE_RENDERING) 544 return 0; 545 546 return 1; 547} 548 549static int 550gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count) 551{ 552 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 553 554 if (bo->image != NULL) { 555 errno = EINVAL; 556 return -1; 557 } 558 559 memcpy(bo->map, buf, count); 560 561 return 0; 562} 563 564static int 565gbm_dri_bo_get_fd(struct gbm_bo *_bo) 566{ 567 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 568 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 569 int fd; 570 571 if (bo->image == NULL) 572 return -1; 573 574 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd); 575 576 return fd; 577} 578 579static void 580gbm_dri_bo_destroy(struct gbm_bo *_bo) 581{ 582 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 583 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 584 struct drm_mode_destroy_dumb arg; 585 586 if (bo->image != NULL) { 587 dri->image->destroyImage(bo->image); 588 } else { 589 gbm_dri_bo_unmap(bo); 590 memset(&arg, 0, sizeof(arg)); 591 arg.handle = bo->handle; 592 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 593 } 594 595 free(bo); 596} 597 598static uint32_t 599gbm_dri_to_gbm_format(uint32_t dri_format) 600{ 601 uint32_t ret = 0; 602 603 switch (dri_format) { 604 case __DRI_IMAGE_FORMAT_RGB565: 605 ret = GBM_FORMAT_RGB565; 606 break; 607 case __DRI_IMAGE_FORMAT_XRGB8888: 608 ret = GBM_FORMAT_XRGB8888; 609 break; 610 case __DRI_IMAGE_FORMAT_ARGB8888: 611 ret = GBM_FORMAT_ARGB8888; 612 break; 613 case __DRI_IMAGE_FORMAT_ABGR8888: 614 ret = GBM_FORMAT_ABGR8888; 615 break; 616 default: 617 ret = 0; 618 break; 619 } 620 621 return ret; 622} 623 624static struct gbm_bo * 625gbm_dri_bo_import(struct gbm_device *gbm, 626 uint32_t type, void *buffer, uint32_t usage) 627{ 628 struct gbm_dri_device *dri = gbm_dri_device(gbm); 629 struct gbm_dri_bo *bo; 630 __DRIimage *image; 631 unsigned dri_use = 0; 632 int gbm_format; 633 634 /* Required for query image WIDTH & HEIGHT */ 635 if (dri->image == NULL || dri->image->base.version < 4) { 636 errno = ENOSYS; 637 return NULL; 638 } 639 640 switch (type) { 641#if HAVE_WAYLAND_PLATFORM 642 case GBM_BO_IMPORT_WL_BUFFER: 643 { 644 struct wl_drm_buffer *wb; 645 646 if (!dri->wl_drm) { 647 errno = EINVAL; 648 return NULL; 649 } 650 651 wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer); 652 if (!wb) { 653 errno = EINVAL; 654 return NULL; 655 } 656 657 image = dri->image->dupImage(wb->driver_buffer, NULL); 658 659 switch (wb->format) { 660 case WL_DRM_FORMAT_XRGB8888: 661 gbm_format = GBM_FORMAT_XRGB8888; 662 break; 663 case WL_DRM_FORMAT_ARGB8888: 664 gbm_format = GBM_FORMAT_ARGB8888; 665 break; 666 case WL_DRM_FORMAT_RGB565: 667 gbm_format = GBM_FORMAT_RGB565; 668 break; 669 case WL_DRM_FORMAT_YUYV: 670 gbm_format = GBM_FORMAT_YUYV; 671 break; 672 default: 673 return NULL; 674 } 675 break; 676 } 677#endif 678 679 case GBM_BO_IMPORT_EGL_IMAGE: 680 { 681 int dri_format; 682 if (dri->lookup_image == NULL) { 683 errno = EINVAL; 684 return NULL; 685 } 686 687 image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data); 688 image = dri->image->dupImage(image, NULL); 689 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format); 690 gbm_format = gbm_dri_to_gbm_format(dri_format); 691 if (gbm_format == 0) { 692 errno = EINVAL; 693 return NULL; 694 } 695 break; 696 } 697 698 case GBM_BO_IMPORT_FD: 699 { 700 struct gbm_import_fd_data *fd_data = buffer; 701 int stride = fd_data->stride, offset = 0; 702 703 image = dri->image->createImageFromFds(dri->screen, 704 fd_data->width, 705 fd_data->height, 706 fd_data->format, 707 &fd_data->fd, 1, 708 &stride, &offset, 709 NULL); 710 gbm_format = fd_data->format; 711 break; 712 } 713 714 default: 715 errno = ENOSYS; 716 return NULL; 717 } 718 719 720 bo = calloc(1, sizeof *bo); 721 if (bo == NULL) 722 return NULL; 723 724 bo->image = image; 725 726 if (usage & GBM_BO_USE_SCANOUT) 727 dri_use |= __DRI_IMAGE_USE_SCANOUT; 728 if (usage & GBM_BO_USE_CURSOR) 729 dri_use |= __DRI_IMAGE_USE_CURSOR; 730 if (dri->image->base.version >= 2 && 731 !dri->image->validateUsage(bo->image, dri_use)) { 732 errno = EINVAL; 733 free(bo); 734 return NULL; 735 } 736 737 bo->base.base.gbm = gbm; 738 bo->base.base.format = gbm_format; 739 740 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH, 741 (int*)&bo->base.base.width); 742 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT, 743 (int*)&bo->base.base.height); 744 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 745 (int*)&bo->base.base.stride); 746 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 747 &bo->base.base.handle.s32); 748 749 return &bo->base.base; 750} 751 752static struct gbm_bo * 753create_dumb(struct gbm_device *gbm, 754 uint32_t width, uint32_t height, 755 uint32_t format, uint32_t usage) 756{ 757 struct gbm_dri_device *dri = gbm_dri_device(gbm); 758 struct drm_mode_create_dumb create_arg; 759 struct gbm_dri_bo *bo; 760 struct drm_mode_destroy_dumb destroy_arg; 761 int ret; 762 int is_cursor, is_scanout; 763 764 is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 && 765 format == GBM_FORMAT_ARGB8888; 766 is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 && 767 format == GBM_FORMAT_XRGB8888; 768 if (!is_cursor && !is_scanout) { 769 errno = EINVAL; 770 return NULL; 771 } 772 773 bo = calloc(1, sizeof *bo); 774 if (bo == NULL) 775 return NULL; 776 777 create_arg.bpp = 32; 778 create_arg.width = width; 779 create_arg.height = height; 780 781 ret = drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg); 782 if (ret) 783 goto free_bo; 784 785 bo->base.base.gbm = gbm; 786 bo->base.base.width = width; 787 bo->base.base.height = height; 788 bo->base.base.stride = create_arg.pitch; 789 bo->base.base.format = format; 790 bo->base.base.handle.u32 = create_arg.handle; 791 bo->handle = create_arg.handle; 792 bo->size = create_arg.size; 793 794 if (gbm_dri_bo_map(bo) == NULL) 795 goto destroy_dumb; 796 797 return &bo->base.base; 798 799destroy_dumb: 800 memset(&destroy_arg, 0, sizeof destroy_arg); 801 destroy_arg.handle = create_arg.handle; 802 drmIoctl(dri->base.base.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); 803free_bo: 804 free(bo); 805 806 return NULL; 807} 808 809static struct gbm_bo * 810gbm_dri_bo_create(struct gbm_device *gbm, 811 uint32_t width, uint32_t height, 812 uint32_t format, uint32_t usage) 813{ 814 struct gbm_dri_device *dri = gbm_dri_device(gbm); 815 struct gbm_dri_bo *bo; 816 int dri_format; 817 unsigned dri_use = 0; 818 819 if (usage & GBM_BO_USE_WRITE || dri->image == NULL) 820 return create_dumb(gbm, width, height, format, usage); 821 822 bo = calloc(1, sizeof *bo); 823 if (bo == NULL) 824 return NULL; 825 826 bo->base.base.gbm = gbm; 827 bo->base.base.width = width; 828 bo->base.base.height = height; 829 bo->base.base.format = format; 830 831 switch (format) { 832 case GBM_FORMAT_RGB565: 833 dri_format =__DRI_IMAGE_FORMAT_RGB565; 834 break; 835 case GBM_FORMAT_XRGB8888: 836 case GBM_BO_FORMAT_XRGB8888: 837 dri_format = __DRI_IMAGE_FORMAT_XRGB8888; 838 break; 839 case GBM_FORMAT_ARGB8888: 840 case GBM_BO_FORMAT_ARGB8888: 841 dri_format = __DRI_IMAGE_FORMAT_ARGB8888; 842 break; 843 case GBM_FORMAT_ABGR8888: 844 dri_format = __DRI_IMAGE_FORMAT_ABGR8888; 845 break; 846 case GBM_FORMAT_ARGB2101010: 847 dri_format = __DRI_IMAGE_FORMAT_ARGB2101010; 848 break; 849 case GBM_FORMAT_XRGB2101010: 850 dri_format = __DRI_IMAGE_FORMAT_XRGB2101010; 851 break; 852 default: 853 errno = EINVAL; 854 goto failed; 855 } 856 857 if (usage & GBM_BO_USE_SCANOUT) 858 dri_use |= __DRI_IMAGE_USE_SCANOUT; 859 if (usage & GBM_BO_USE_CURSOR) 860 dri_use |= __DRI_IMAGE_USE_CURSOR; 861 862 /* Gallium drivers requires shared in order to get the handle/stride */ 863 dri_use |= __DRI_IMAGE_USE_SHARE; 864 865 bo->image = 866 dri->image->createImage(dri->screen, 867 width, height, 868 dri_format, dri_use, 869 bo); 870 if (bo->image == NULL) 871 goto failed; 872 873 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 874 &bo->base.base.handle.s32); 875 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 876 (int *) &bo->base.base.stride); 877 878 return &bo->base.base; 879 880failed: 881 free(bo); 882 return NULL; 883} 884 885static struct gbm_surface * 886gbm_dri_surface_create(struct gbm_device *gbm, 887 uint32_t width, uint32_t height, 888 uint32_t format, uint32_t flags) 889{ 890 struct gbm_dri_surface *surf; 891 892 surf = calloc(1, sizeof *surf); 893 if (surf == NULL) 894 return NULL; 895 896 surf->base.gbm = gbm; 897 surf->base.width = width; 898 surf->base.height = height; 899 surf->base.format = format; 900 surf->base.flags = flags; 901 902 return &surf->base; 903} 904 905static void 906gbm_dri_surface_destroy(struct gbm_surface *_surf) 907{ 908 struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 909 910 free(surf); 911} 912 913static void 914dri_destroy(struct gbm_device *gbm) 915{ 916 struct gbm_dri_device *dri = gbm_dri_device(gbm); 917 918 dri->core->destroyScreen(dri->screen); 919 free(dri->driver_configs); 920 dlclose(dri->driver); 921 free(dri->base.driver_name); 922 923 free(dri); 924} 925 926static struct gbm_device * 927dri_device_create(int fd) 928{ 929 struct gbm_dri_device *dri; 930 int ret, force_sw; 931 932 dri = calloc(1, sizeof *dri); 933 if (!dri) 934 return NULL; 935 936 dri->base.base.fd = fd; 937 dri->base.base.bo_create = gbm_dri_bo_create; 938 dri->base.base.bo_import = gbm_dri_bo_import; 939 dri->base.base.is_format_supported = gbm_dri_is_format_supported; 940 dri->base.base.bo_write = gbm_dri_bo_write; 941 dri->base.base.bo_get_fd = gbm_dri_bo_get_fd; 942 dri->base.base.bo_destroy = gbm_dri_bo_destroy; 943 dri->base.base.destroy = dri_destroy; 944 dri->base.base.surface_create = gbm_dri_surface_create; 945 dri->base.base.surface_destroy = gbm_dri_surface_destroy; 946 947 dri->base.type = GBM_DRM_DRIVER_TYPE_DRI; 948 dri->base.base.name = "drm"; 949 950 force_sw = getenv("GBM_ALWAYS_SOFTWARE") != NULL; 951 if (!force_sw) { 952 ret = dri_screen_create(dri); 953 if (ret) 954 ret = dri_screen_create_sw(dri); 955 } else { 956 ret = dri_screen_create_sw(dri); 957 } 958 959 if (ret) 960 goto err_dri; 961 962 return &dri->base.base; 963 964err_dri: 965 free(dri); 966 967 return NULL; 968} 969 970struct gbm_backend gbm_dri_backend = { 971 .backend_name = "dri", 972 .create_device = dri_device_create, 973}; 974