gbm_dri.c revision 1463c08d
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 <stdbool.h> 33#include <string.h> 34#include <errno.h> 35#include <limits.h> 36#include <assert.h> 37 38#include <sys/types.h> 39#include <unistd.h> 40#include <dlfcn.h> 41#include <xf86drm.h> 42#include "drm-uapi/drm_fourcc.h" 43 44#include <GL/gl.h> /* dri_interface needs GL types */ 45#include <GL/internal/dri_interface.h> 46 47#include "gbm_driint.h" 48 49#include "gbmint.h" 50#include "loader_dri_helper.h" 51#include "loader.h" 52#include "util/debug.h" 53#include "util/macros.h" 54 55/* For importing wl_buffer */ 56#if HAVE_WAYLAND_PLATFORM 57#include "wayland-drm.h" 58#endif 59 60static __DRIimage * 61dri_lookup_egl_image(__DRIscreen *screen, void *image, void *data) 62{ 63 struct gbm_dri_device *dri = data; 64 65 if (dri->lookup_image == NULL) 66 return NULL; 67 68 return dri->lookup_image(screen, image, dri->lookup_user_data); 69} 70 71static GLboolean 72dri_validate_egl_image(void *image, void *data) 73{ 74 struct gbm_dri_device *dri = data; 75 76 if (dri->validate_image == NULL) 77 return false; 78 79 return dri->validate_image(image, dri->lookup_user_data); 80} 81 82static __DRIimage * 83dri_lookup_egl_image_validated(void *image, void *data) 84{ 85 struct gbm_dri_device *dri = data; 86 87 if (dri->lookup_image_validated == NULL) 88 return NULL; 89 90 return dri->lookup_image_validated(image, dri->lookup_user_data); 91} 92 93static __DRIbuffer * 94dri_get_buffers(__DRIdrawable * driDrawable, 95 int *width, int *height, 96 unsigned int *attachments, int count, 97 int *out_count, void *data) 98{ 99 struct gbm_dri_surface *surf = data; 100 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 101 102 if (dri->get_buffers == NULL) 103 return NULL; 104 105 return dri->get_buffers(driDrawable, width, height, attachments, 106 count, out_count, surf->dri_private); 107} 108 109static void 110dri_flush_front_buffer(__DRIdrawable * driDrawable, void *data) 111{ 112 struct gbm_dri_surface *surf = data; 113 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 114 115 if (dri->flush_front_buffer != NULL) 116 dri->flush_front_buffer(driDrawable, surf->dri_private); 117} 118 119static __DRIbuffer * 120dri_get_buffers_with_format(__DRIdrawable * driDrawable, 121 int *width, int *height, 122 unsigned int *attachments, int count, 123 int *out_count, void *data) 124{ 125 struct gbm_dri_surface *surf = data; 126 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 127 128 if (dri->get_buffers_with_format == NULL) 129 return NULL; 130 131 return 132 dri->get_buffers_with_format(driDrawable, width, height, attachments, 133 count, out_count, surf->dri_private); 134} 135 136static unsigned 137dri_get_capability(void *loaderPrivate, enum dri_loader_cap cap) 138{ 139 /* Note: loaderPrivate is _EGLDisplay* */ 140 switch (cap) { 141 case DRI_LOADER_CAP_FP16: 142 return 1; 143 default: 144 return 0; 145 } 146} 147 148static int 149image_get_buffers(__DRIdrawable *driDrawable, 150 unsigned int format, 151 uint32_t *stamp, 152 void *loaderPrivate, 153 uint32_t buffer_mask, 154 struct __DRIimageList *buffers) 155{ 156 struct gbm_dri_surface *surf = loaderPrivate; 157 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 158 159 if (dri->image_get_buffers == NULL) 160 return 0; 161 162 return dri->image_get_buffers(driDrawable, format, stamp, 163 surf->dri_private, buffer_mask, buffers); 164} 165 166static void 167swrast_get_drawable_info(__DRIdrawable *driDrawable, 168 int *x, 169 int *y, 170 int *width, 171 int *height, 172 void *loaderPrivate) 173{ 174 struct gbm_dri_surface *surf = loaderPrivate; 175 176 *x = 0; 177 *y = 0; 178 *width = surf->base.v0.width; 179 *height = surf->base.v0.height; 180} 181 182static void 183swrast_put_image2(__DRIdrawable *driDrawable, 184 int op, 185 int x, 186 int y, 187 int width, 188 int height, 189 int stride, 190 char *data, 191 void *loaderPrivate) 192{ 193 struct gbm_dri_surface *surf = loaderPrivate; 194 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 195 196 dri->swrast_put_image2(driDrawable, 197 op, x, y, 198 width, height, stride, 199 data, surf->dri_private); 200} 201 202static void 203swrast_put_image(__DRIdrawable *driDrawable, 204 int op, 205 int x, 206 int y, 207 int width, 208 int height, 209 char *data, 210 void *loaderPrivate) 211{ 212 swrast_put_image2(driDrawable, op, x, y, width, height, 213 width * 4, data, loaderPrivate); 214} 215 216static void 217swrast_get_image(__DRIdrawable *driDrawable, 218 int x, 219 int y, 220 int width, 221 int height, 222 char *data, 223 void *loaderPrivate) 224{ 225 struct gbm_dri_surface *surf = loaderPrivate; 226 struct gbm_dri_device *dri = gbm_dri_device(surf->base.gbm); 227 228 dri->swrast_get_image(driDrawable, 229 x, y, 230 width, height, 231 data, surf->dri_private); 232} 233 234static const __DRIuseInvalidateExtension use_invalidate = { 235 .base = { __DRI_USE_INVALIDATE, 1 } 236}; 237 238static const __DRIimageLookupExtension image_lookup_extension = { 239 .base = { __DRI_IMAGE_LOOKUP, 2 }, 240 241 .lookupEGLImage = dri_lookup_egl_image, 242 .validateEGLImage = dri_validate_egl_image, 243 .lookupEGLImageValidated = dri_lookup_egl_image_validated, 244}; 245 246static const __DRIdri2LoaderExtension dri2_loader_extension = { 247 .base = { __DRI_DRI2_LOADER, 4 }, 248 249 .getBuffers = dri_get_buffers, 250 .flushFrontBuffer = dri_flush_front_buffer, 251 .getBuffersWithFormat = dri_get_buffers_with_format, 252 .getCapability = dri_get_capability, 253}; 254 255static const __DRIimageLoaderExtension image_loader_extension = { 256 .base = { __DRI_IMAGE_LOADER, 2 }, 257 258 .getBuffers = image_get_buffers, 259 .flushFrontBuffer = dri_flush_front_buffer, 260 .getCapability = dri_get_capability, 261}; 262 263static const __DRIswrastLoaderExtension swrast_loader_extension = { 264 .base = { __DRI_SWRAST_LOADER, 2 }, 265 266 .getDrawableInfo = swrast_get_drawable_info, 267 .putImage = swrast_put_image, 268 .getImage = swrast_get_image, 269 .putImage2 = swrast_put_image2 270}; 271 272static const __DRIextension *gbm_dri_screen_extensions[] = { 273 &image_lookup_extension.base, 274 &use_invalidate.base, 275 &dri2_loader_extension.base, 276 &image_loader_extension.base, 277 &swrast_loader_extension.base, 278 NULL, 279}; 280 281struct dri_extension_match { 282 const char *name; 283 int version; 284 int offset; 285 bool optional; 286}; 287 288static struct dri_extension_match dri_core_extensions[] = { 289 { __DRI2_FLUSH, 1, offsetof(struct gbm_dri_device, flush), false }, 290 { __DRI_IMAGE, 1, offsetof(struct gbm_dri_device, image), false }, 291 { __DRI2_FENCE, 1, offsetof(struct gbm_dri_device, fence), true }, 292}; 293 294static struct dri_extension_match gbm_dri_device_extensions[] = { 295 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), false }, 296 { __DRI_DRI2, 1, offsetof(struct gbm_dri_device, dri2), false }, 297}; 298 299static struct dri_extension_match gbm_swrast_device_extensions[] = { 300 { __DRI_CORE, 1, offsetof(struct gbm_dri_device, core), false }, 301 { __DRI_SWRAST, 1, offsetof(struct gbm_dri_device, swrast), false }, 302}; 303 304static bool 305dri_bind_extensions(struct gbm_dri_device *dri, 306 struct dri_extension_match *matches, size_t num_matches, 307 const __DRIextension **extensions) 308{ 309 bool ret = true; 310 void *field; 311 312 for (size_t i = 0; extensions[i]; i++) { 313 for (size_t j = 0; j < num_matches; j++) { 314 if (strcmp(extensions[i]->name, matches[j].name) == 0 && 315 extensions[i]->version >= matches[j].version) { 316 field = ((char *) dri + matches[j].offset); 317 *(const __DRIextension **) field = extensions[i]; 318 } 319 } 320 } 321 322 for (size_t j = 0; j < num_matches; j++) { 323 field = ((char *) dri + matches[j].offset); 324 if ((*(const __DRIextension **) field == NULL) && !matches[j].optional) { 325 fprintf(stderr, "gbm: did not find extension %s version %d\n", 326 matches[j].name, matches[j].version); 327 ret = false; 328 } 329 } 330 331 return ret; 332} 333 334static const __DRIextension ** 335dri_open_driver(struct gbm_dri_device *dri) 336{ 337 /* Temporarily work around dri driver libs that need symbols in libglapi 338 * but don't automatically link it in. 339 */ 340 /* XXX: Library name differs on per platforms basis. Update this as 341 * osx/cygwin/windows/bsd gets support for GBM.. 342 */ 343 dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL); 344 345 static const char *search_path_vars[] = { 346 /* Read GBM_DRIVERS_PATH first for compatibility, but LIBGL_DRIVERS_PATH 347 * is recommended over GBM_DRIVERS_PATH. 348 */ 349 "GBM_DRIVERS_PATH", 350 /* Read LIBGL_DRIVERS_PATH if GBM_DRIVERS_PATH was not set. 351 * LIBGL_DRIVERS_PATH is recommended over GBM_DRIVERS_PATH. 352 */ 353 "LIBGL_DRIVERS_PATH", 354 NULL 355 }; 356 return loader_open_driver(dri->driver_name, &dri->driver, search_path_vars); 357} 358 359static int 360dri_load_driver(struct gbm_dri_device *dri) 361{ 362 const __DRIextension **extensions; 363 364 extensions = dri_open_driver(dri); 365 if (!extensions) 366 return -1; 367 368 if (!dri_bind_extensions(dri, gbm_dri_device_extensions, 369 ARRAY_SIZE(gbm_dri_device_extensions), 370 extensions)) { 371 dlclose(dri->driver); 372 fprintf(stderr, "failed to bind extensions\n"); 373 return -1; 374 } 375 376 dri->driver_extensions = extensions; 377 378 return 0; 379} 380 381static int 382dri_load_driver_swrast(struct gbm_dri_device *dri) 383{ 384 const __DRIextension **extensions; 385 386 extensions = dri_open_driver(dri); 387 if (!extensions) 388 return -1; 389 390 if (!dri_bind_extensions(dri, gbm_swrast_device_extensions, 391 ARRAY_SIZE(gbm_swrast_device_extensions), 392 extensions)) { 393 dlclose(dri->driver); 394 fprintf(stderr, "failed to bind extensions\n"); 395 return -1; 396 } 397 398 dri->driver_extensions = extensions; 399 400 return 0; 401} 402 403static int 404dri_screen_create_dri2(struct gbm_dri_device *dri, char *driver_name) 405{ 406 const __DRIextension **extensions; 407 int ret = 0; 408 409 dri->driver_name = driver_name; 410 if (dri->driver_name == NULL) 411 return -1; 412 413 ret = dri_load_driver(dri); 414 if (ret) { 415 fprintf(stderr, "failed to load driver: %s\n", dri->driver_name); 416 return ret; 417 } 418 419 dri->loader_extensions = gbm_dri_screen_extensions; 420 421 if (dri->dri2 == NULL) 422 return -1; 423 424 if (dri->dri2->base.version >= 4) { 425 dri->screen = dri->dri2->createNewScreen2(0, dri->base.v0.fd, 426 dri->loader_extensions, 427 dri->driver_extensions, 428 &dri->driver_configs, dri); 429 } else { 430 dri->screen = dri->dri2->createNewScreen(0, dri->base.v0.fd, 431 dri->loader_extensions, 432 &dri->driver_configs, dri); 433 } 434 if (dri->screen == NULL) 435 return -1; 436 437 extensions = dri->core->getExtensions(dri->screen); 438 if (!dri_bind_extensions(dri, dri_core_extensions, 439 ARRAY_SIZE(dri_core_extensions), 440 extensions)) { 441 ret = -1; 442 goto free_screen; 443 } 444 445 dri->lookup_image = NULL; 446 dri->lookup_user_data = NULL; 447 448 return 0; 449 450free_screen: 451 dri->core->destroyScreen(dri->screen); 452 453 return ret; 454} 455 456static int 457dri_screen_create_swrast(struct gbm_dri_device *dri) 458{ 459 int ret; 460 461 dri->driver_name = strdup("swrast"); 462 if (dri->driver_name == NULL) 463 return -1; 464 465 ret = dri_load_driver_swrast(dri); 466 if (ret) { 467 fprintf(stderr, "failed to load swrast driver\n"); 468 return ret; 469 } 470 471 dri->loader_extensions = gbm_dri_screen_extensions; 472 473 if (dri->swrast == NULL) 474 return -1; 475 476 if (dri->swrast->base.version >= 4) { 477 dri->screen = dri->swrast->createNewScreen2(0, dri->loader_extensions, 478 dri->driver_extensions, 479 &dri->driver_configs, dri); 480 } else { 481 dri->screen = dri->swrast->createNewScreen(0, dri->loader_extensions, 482 &dri->driver_configs, dri); 483 } 484 if (dri->screen == NULL) 485 return -1; 486 487 dri->lookup_image = NULL; 488 dri->lookup_user_data = NULL; 489 490 return 0; 491} 492 493static int 494dri_screen_create(struct gbm_dri_device *dri) 495{ 496 char *driver_name; 497 498 driver_name = loader_get_driver_for_fd(dri->base.v0.fd); 499 if (!driver_name) 500 return -1; 501 502 return dri_screen_create_dri2(dri, driver_name); 503} 504 505static int 506dri_screen_create_sw(struct gbm_dri_device *dri) 507{ 508 char *driver_name; 509 int ret; 510 511 driver_name = strdup("kms_swrast"); 512 if (!driver_name) 513 return -errno; 514 515 ret = dri_screen_create_dri2(dri, driver_name); 516 if (ret != 0) 517 ret = dri_screen_create_swrast(dri); 518 if (ret != 0) 519 return ret; 520 521 dri->software = true; 522 return 0; 523} 524 525static const struct gbm_dri_visual gbm_dri_visuals_table[] = { 526 { 527 GBM_FORMAT_R8, __DRI_IMAGE_FORMAT_R8, 528 { 0, -1, -1, -1 }, 529 { 8, 0, 0, 0 }, 530 }, 531 { 532 GBM_FORMAT_R16, __DRI_IMAGE_FORMAT_R16, 533 { 0, -1, -1, -1 }, 534 { 16, 0, 0, 0 }, 535 }, 536 { 537 GBM_FORMAT_GR88, __DRI_IMAGE_FORMAT_GR88, 538 { 0, 8, -1, -1 }, 539 { 8, 8, 0, 0 }, 540 }, 541 { 542 GBM_FORMAT_ARGB1555, __DRI_IMAGE_FORMAT_ARGB1555, 543 { 10, 5, 0, 11 }, 544 { 5, 5, 5, 1 }, 545 }, 546 { 547 GBM_FORMAT_RGB565, __DRI_IMAGE_FORMAT_RGB565, 548 { 11, 5, 0, -1 }, 549 { 5, 6, 5, 0 }, 550 }, 551 { 552 GBM_FORMAT_XRGB8888, __DRI_IMAGE_FORMAT_XRGB8888, 553 { 16, 8, 0, -1 }, 554 { 8, 8, 8, 0 }, 555 }, 556 { 557 GBM_FORMAT_ARGB8888, __DRI_IMAGE_FORMAT_ARGB8888, 558 { 16, 8, 0, 24 }, 559 { 8, 8, 8, 8 }, 560 }, 561 { 562 GBM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888, 563 { 0, 8, 16, -1 }, 564 { 8, 8, 8, 0 }, 565 }, 566 { 567 GBM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888, 568 { 0, 8, 16, 24 }, 569 { 8, 8, 8, 8 }, 570 }, 571 { 572 GBM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010, 573 { 20, 10, 0, -1 }, 574 { 10, 10, 10, 0 }, 575 }, 576 { 577 GBM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010, 578 { 20, 10, 0, 30 }, 579 { 10, 10, 10, 2 }, 580 }, 581 { 582 GBM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010, 583 { 0, 10, 20, -1 }, 584 { 10, 10, 10, 0 }, 585 }, 586 { 587 GBM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010, 588 { 0, 10, 20, 30 }, 589 { 10, 10, 10, 2 }, 590 }, 591 { 592 GBM_FORMAT_XBGR16161616F, __DRI_IMAGE_FORMAT_XBGR16161616F, 593 { 0, 16, 32, -1 }, 594 { 16, 16, 16, 0 }, 595 true, 596 }, 597 { 598 GBM_FORMAT_ABGR16161616F, __DRI_IMAGE_FORMAT_ABGR16161616F, 599 { 0, 16, 32, 48 }, 600 { 16, 16, 16, 16 }, 601 true, 602 }, 603}; 604 605static int 606gbm_format_to_dri_format(uint32_t gbm_format) 607{ 608 gbm_format = gbm_core.v0.format_canonicalize(gbm_format); 609 for (size_t i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) { 610 if (gbm_dri_visuals_table[i].gbm_format == gbm_format) 611 return gbm_dri_visuals_table[i].dri_image_format; 612 } 613 614 return 0; 615} 616 617static uint32_t 618gbm_dri_to_gbm_format(int dri_format) 619{ 620 for (size_t i = 0; i < ARRAY_SIZE(gbm_dri_visuals_table); i++) { 621 if (gbm_dri_visuals_table[i].dri_image_format == dri_format) 622 return gbm_dri_visuals_table[i].gbm_format; 623 } 624 625 return 0; 626} 627 628static int 629gbm_dri_is_format_supported(struct gbm_device *gbm, 630 uint32_t format, 631 uint32_t usage) 632{ 633 struct gbm_dri_device *dri = gbm_dri_device(gbm); 634 int count; 635 636 if ((usage & GBM_BO_USE_CURSOR) && (usage & GBM_BO_USE_RENDERING)) 637 return 0; 638 639 format = gbm_core.v0.format_canonicalize(format); 640 if (gbm_format_to_dri_format(format) == 0) 641 return 0; 642 643 /* If there is no query, fall back to the small table which was originally 644 * here. */ 645 if (dri->image->base.version <= 15 || !dri->image->queryDmaBufModifiers) { 646 switch (format) { 647 case GBM_FORMAT_XRGB8888: 648 case GBM_FORMAT_ARGB8888: 649 case GBM_FORMAT_XBGR8888: 650 return 1; 651 default: 652 return 0; 653 } 654 } 655 656 /* This returns false if the format isn't supported */ 657 if (!dri->image->queryDmaBufModifiers(dri->screen, format, 0, NULL, NULL, 658 &count)) 659 return 0; 660 661 return 1; 662} 663 664static int 665gbm_dri_get_format_modifier_plane_count(struct gbm_device *gbm, 666 uint32_t format, 667 uint64_t modifier) 668{ 669 struct gbm_dri_device *dri = gbm_dri_device(gbm); 670 uint64_t plane_count; 671 672 if (dri->image->base.version < 16 || 673 !dri->image->queryDmaBufFormatModifierAttribs) 674 return -1; 675 676 format = gbm_core.v0.format_canonicalize(format); 677 if (gbm_format_to_dri_format(format) == 0) 678 return -1; 679 680 if (!dri->image->queryDmaBufFormatModifierAttribs( 681 dri->screen, format, modifier, 682 __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, &plane_count)) 683 return -1; 684 685 return plane_count; 686} 687 688static int 689gbm_dri_bo_write(struct gbm_bo *_bo, const void *buf, size_t count) 690{ 691 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 692 693 if (bo->image != NULL) { 694 errno = EINVAL; 695 return -1; 696 } 697 698 memcpy(bo->map, buf, count); 699 700 return 0; 701} 702 703static int 704gbm_dri_bo_get_fd(struct gbm_bo *_bo) 705{ 706 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 707 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 708 int fd; 709 710 if (bo->image == NULL) 711 return -1; 712 713 if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd)) 714 return -1; 715 716 return fd; 717} 718 719static int 720get_number_planes(struct gbm_dri_device *dri, __DRIimage *image) 721{ 722 int num_planes = 0; 723 724 /* Dumb buffers are single-plane only. */ 725 if (!image) 726 return 1; 727 728 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_NUM_PLANES, &num_planes); 729 730 if (num_planes <= 0) 731 num_planes = 1; 732 733 return num_planes; 734} 735 736static int 737gbm_dri_bo_get_planes(struct gbm_bo *_bo) 738{ 739 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 740 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 741 742 return get_number_planes(dri, bo->image); 743} 744 745static union gbm_bo_handle 746gbm_dri_bo_get_handle_for_plane(struct gbm_bo *_bo, int plane) 747{ 748 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 749 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 750 union gbm_bo_handle ret; 751 ret.s32 = -1; 752 753 if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) { 754 /* Preserve legacy behavior if plane is 0 */ 755 if (plane == 0) { 756 /* NOTE: return _bo->handle, *NOT* bo->handle which is invalid at this point */ 757 return _bo->v0.handle; 758 } 759 760 errno = ENOSYS; 761 return ret; 762 } 763 764 if (plane >= get_number_planes(dri, bo->image)) { 765 errno = EINVAL; 766 return ret; 767 } 768 769 /* dumb BOs can only utilize non-planar formats */ 770 if (!bo->image) { 771 assert(plane == 0); 772 ret.s32 = bo->handle; 773 return ret; 774 } 775 776 __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL); 777 if (image) { 778 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32); 779 dri->image->destroyImage(image); 780 } else { 781 assert(plane == 0); 782 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, &ret.s32); 783 } 784 785 return ret; 786} 787 788static int 789gbm_dri_bo_get_plane_fd(struct gbm_bo *_bo, int plane) 790{ 791 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 792 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 793 int fd = -1; 794 795 if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) { 796 /* Preserve legacy behavior if plane is 0 */ 797 if (plane == 0) 798 return gbm_dri_bo_get_fd(_bo); 799 800 errno = ENOSYS; 801 return -1; 802 } 803 804 /* dumb BOs can only utilize non-planar formats */ 805 if (!bo->image) { 806 errno = EINVAL; 807 return -1; 808 } 809 810 if (plane >= get_number_planes(dri, bo->image)) { 811 errno = EINVAL; 812 return -1; 813 } 814 815 __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL); 816 if (image) { 817 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FD, &fd); 818 dri->image->destroyImage(image); 819 } else { 820 assert(plane == 0); 821 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_FD, &fd); 822 } 823 824 return fd; 825} 826 827static uint32_t 828gbm_dri_bo_get_stride(struct gbm_bo *_bo, int plane) 829{ 830 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 831 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 832 __DRIimage *image; 833 int stride = 0; 834 835 if (!dri->image || dri->image->base.version < 11 || !dri->image->fromPlanar) { 836 /* Preserve legacy behavior if plane is 0 */ 837 if (plane == 0) 838 return _bo->v0.stride; 839 840 errno = ENOSYS; 841 return 0; 842 } 843 844 if (plane >= get_number_planes(dri, bo->image)) { 845 errno = EINVAL; 846 return 0; 847 } 848 849 if (bo->image == NULL) { 850 assert(plane == 0); 851 return _bo->v0.stride; 852 } 853 854 image = dri->image->fromPlanar(bo->image, plane, NULL); 855 if (image) { 856 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 857 dri->image->destroyImage(image); 858 } else { 859 assert(plane == 0); 860 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, &stride); 861 } 862 863 return (uint32_t)stride; 864} 865 866static uint32_t 867gbm_dri_bo_get_offset(struct gbm_bo *_bo, int plane) 868{ 869 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 870 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 871 int offset = 0; 872 873 /* These error cases do not actually return an error code, as the user 874 * will also fail to obtain the handle/FD from the BO. In that case, the 875 * offset is irrelevant, as they have no buffer to offset into, so 876 * returning 0 is harmless. 877 */ 878 if (!dri->image || dri->image->base.version < 13 || !dri->image->fromPlanar) 879 return 0; 880 881 if (plane >= get_number_planes(dri, bo->image)) 882 return 0; 883 884 /* Dumb images have no offset */ 885 if (bo->image == NULL) { 886 assert(plane == 0); 887 return 0; 888 } 889 890 __DRIimage *image = dri->image->fromPlanar(bo->image, plane, NULL); 891 if (image) { 892 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_OFFSET, &offset); 893 dri->image->destroyImage(image); 894 } else { 895 assert(plane == 0); 896 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_OFFSET, &offset); 897 } 898 899 return (uint32_t)offset; 900} 901 902static uint64_t 903gbm_dri_bo_get_modifier(struct gbm_bo *_bo) 904{ 905 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 906 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 907 908 if (!dri->image || dri->image->base.version < 14) { 909 errno = ENOSYS; 910 return DRM_FORMAT_MOD_INVALID; 911 } 912 913 /* Dumb buffers have no modifiers */ 914 if (!bo->image) 915 return DRM_FORMAT_MOD_LINEAR; 916 917 uint64_t ret = 0; 918 int mod; 919 if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_UPPER, 920 &mod)) 921 return DRM_FORMAT_MOD_INVALID; 922 923 ret = (uint64_t)mod << 32; 924 925 if (!dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_MODIFIER_LOWER, 926 &mod)) 927 return DRM_FORMAT_MOD_INVALID; 928 929 ret |= (uint64_t)(mod & 0xffffffff); 930 931 return ret; 932} 933 934static void 935gbm_dri_bo_destroy(struct gbm_bo *_bo) 936{ 937 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 938 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 939 struct drm_mode_destroy_dumb arg; 940 941 if (bo->image != NULL) { 942 dri->image->destroyImage(bo->image); 943 } else { 944 gbm_dri_bo_unmap_dumb(bo); 945 memset(&arg, 0, sizeof(arg)); 946 arg.handle = bo->handle; 947 drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg); 948 } 949 950 free(bo); 951} 952 953static struct gbm_bo * 954gbm_dri_bo_import(struct gbm_device *gbm, 955 uint32_t type, void *buffer, uint32_t usage) 956{ 957 struct gbm_dri_device *dri = gbm_dri_device(gbm); 958 struct gbm_dri_bo *bo; 959 __DRIimage *image; 960 unsigned dri_use = 0; 961 int gbm_format; 962 963 /* Required for query image WIDTH & HEIGHT */ 964 if (dri->image == NULL || dri->image->base.version < 4) { 965 errno = ENOSYS; 966 return NULL; 967 } 968 969 switch (type) { 970#if HAVE_WAYLAND_PLATFORM 971 case GBM_BO_IMPORT_WL_BUFFER: 972 { 973 struct wl_drm_buffer *wb; 974 975 if (!dri->wl_drm) { 976 errno = EINVAL; 977 return NULL; 978 } 979 980 wb = wayland_drm_buffer_get(dri->wl_drm, (struct wl_resource *) buffer); 981 if (!wb) { 982 errno = EINVAL; 983 return NULL; 984 } 985 986 image = dri->image->dupImage(wb->driver_buffer, NULL); 987 988 /* GBM_FORMAT_* is identical to WL_DRM_FORMAT_*, so no conversion 989 * required. */ 990 gbm_format = wb->format; 991 break; 992 } 993#endif 994 995 case GBM_BO_IMPORT_EGL_IMAGE: 996 { 997 int dri_format; 998 if (dri->lookup_image == NULL) { 999 errno = EINVAL; 1000 return NULL; 1001 } 1002 1003 image = dri->lookup_image(dri->screen, buffer, dri->lookup_user_data); 1004 image = dri->image->dupImage(image, NULL); 1005 dri->image->queryImage(image, __DRI_IMAGE_ATTRIB_FORMAT, &dri_format); 1006 gbm_format = gbm_dri_to_gbm_format(dri_format); 1007 if (gbm_format == 0) { 1008 errno = EINVAL; 1009 dri->image->destroyImage(image); 1010 return NULL; 1011 } 1012 break; 1013 } 1014 1015 case GBM_BO_IMPORT_FD: 1016 { 1017 struct gbm_import_fd_data *fd_data = buffer; 1018 int stride = fd_data->stride, offset = 0; 1019 int fourcc; 1020 1021 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC 1022 * tokens accepted by createImageFromFds, except for not supporting 1023 * the sARGB format. */ 1024 fourcc = gbm_core.v0.format_canonicalize(fd_data->format); 1025 1026 image = dri->image->createImageFromFds(dri->screen, 1027 fd_data->width, 1028 fd_data->height, 1029 fourcc, 1030 &fd_data->fd, 1, 1031 &stride, &offset, 1032 NULL); 1033 if (image == NULL) { 1034 errno = EINVAL; 1035 return NULL; 1036 } 1037 gbm_format = fd_data->format; 1038 break; 1039 } 1040 1041 case GBM_BO_IMPORT_FD_MODIFIER: 1042 { 1043 struct gbm_import_fd_modifier_data *fd_data = buffer; 1044 unsigned int error; 1045 int fourcc; 1046 1047 /* Import with modifier requires createImageFromDmaBufs2 */ 1048 if (dri->image == NULL || dri->image->base.version < 15 || 1049 dri->image->createImageFromDmaBufs2 == NULL) { 1050 errno = ENOSYS; 1051 return NULL; 1052 } 1053 1054 /* GBM's GBM_FORMAT_* tokens are a strict superset of the DRI FourCC 1055 * tokens accepted by createImageFromDmaBufs2, except for not supporting 1056 * the sARGB format. */ 1057 fourcc = gbm_core.v0.format_canonicalize(fd_data->format); 1058 1059 image = dri->image->createImageFromDmaBufs2(dri->screen, fd_data->width, 1060 fd_data->height, fourcc, 1061 fd_data->modifier, 1062 fd_data->fds, 1063 fd_data->num_fds, 1064 fd_data->strides, 1065 fd_data->offsets, 1066 0, 0, 0, 0, 1067 &error, NULL); 1068 if (image == NULL) { 1069 errno = ENOSYS; 1070 return NULL; 1071 } 1072 1073 gbm_format = fourcc; 1074 break; 1075 } 1076 1077 default: 1078 errno = ENOSYS; 1079 return NULL; 1080 } 1081 1082 1083 bo = calloc(1, sizeof *bo); 1084 if (bo == NULL) { 1085 dri->image->destroyImage(image); 1086 return NULL; 1087 } 1088 1089 bo->image = image; 1090 1091 if (usage & GBM_BO_USE_SCANOUT) 1092 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1093 if (usage & GBM_BO_USE_CURSOR) 1094 dri_use |= __DRI_IMAGE_USE_CURSOR; 1095 if (dri->image->base.version >= 2 && 1096 !dri->image->validateUsage(bo->image, dri_use)) { 1097 errno = EINVAL; 1098 dri->image->destroyImage(bo->image); 1099 free(bo); 1100 return NULL; 1101 } 1102 1103 bo->base.gbm = gbm; 1104 bo->base.v0.format = gbm_format; 1105 1106 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_WIDTH, 1107 (int*)&bo->base.v0.width); 1108 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HEIGHT, 1109 (int*)&bo->base.v0.height); 1110 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 1111 (int*)&bo->base.v0.stride); 1112 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 1113 &bo->base.v0.handle.s32); 1114 1115 return &bo->base; 1116} 1117 1118static struct gbm_bo * 1119create_dumb(struct gbm_device *gbm, 1120 uint32_t width, uint32_t height, 1121 uint32_t format, uint32_t usage) 1122{ 1123 struct gbm_dri_device *dri = gbm_dri_device(gbm); 1124 struct drm_mode_create_dumb create_arg; 1125 struct gbm_dri_bo *bo; 1126 struct drm_mode_destroy_dumb destroy_arg; 1127 int ret; 1128 int is_cursor, is_scanout; 1129 1130 is_cursor = (usage & GBM_BO_USE_CURSOR) != 0 && 1131 format == GBM_FORMAT_ARGB8888; 1132 is_scanout = (usage & GBM_BO_USE_SCANOUT) != 0 && 1133 (format == GBM_FORMAT_XRGB8888 || format == GBM_FORMAT_XBGR8888); 1134 if (!is_cursor && !is_scanout) { 1135 errno = EINVAL; 1136 return NULL; 1137 } 1138 1139 bo = calloc(1, sizeof *bo); 1140 if (bo == NULL) 1141 return NULL; 1142 1143 memset(&create_arg, 0, sizeof(create_arg)); 1144 create_arg.bpp = 32; 1145 create_arg.width = width; 1146 create_arg.height = height; 1147 1148 ret = drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg); 1149 if (ret) 1150 goto free_bo; 1151 1152 bo->base.gbm = gbm; 1153 bo->base.v0.width = width; 1154 bo->base.v0.height = height; 1155 bo->base.v0.stride = create_arg.pitch; 1156 bo->base.v0.format = format; 1157 bo->base.v0.handle.u32 = create_arg.handle; 1158 bo->handle = create_arg.handle; 1159 bo->size = create_arg.size; 1160 1161 if (gbm_dri_bo_map_dumb(bo) == NULL) 1162 goto destroy_dumb; 1163 1164 return &bo->base; 1165 1166destroy_dumb: 1167 memset(&destroy_arg, 0, sizeof destroy_arg); 1168 destroy_arg.handle = create_arg.handle; 1169 drmIoctl(dri->base.v0.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg); 1170free_bo: 1171 free(bo); 1172 1173 return NULL; 1174} 1175 1176static struct gbm_bo * 1177gbm_dri_bo_create(struct gbm_device *gbm, 1178 uint32_t width, uint32_t height, 1179 uint32_t format, uint32_t usage, 1180 const uint64_t *modifiers, 1181 const unsigned int count) 1182{ 1183 struct gbm_dri_device *dri = gbm_dri_device(gbm); 1184 struct gbm_dri_bo *bo; 1185 int dri_format; 1186 unsigned dri_use = 0; 1187 1188 format = gbm_core.v0.format_canonicalize(format); 1189 1190 if (usage & GBM_BO_USE_WRITE || dri->image == NULL) 1191 return create_dumb(gbm, width, height, format, usage); 1192 1193 bo = calloc(1, sizeof *bo); 1194 if (bo == NULL) 1195 return NULL; 1196 1197 bo->base.gbm = gbm; 1198 bo->base.v0.width = width; 1199 bo->base.v0.height = height; 1200 bo->base.v0.format = format; 1201 1202 dri_format = gbm_format_to_dri_format(format); 1203 if (dri_format == 0) { 1204 errno = EINVAL; 1205 goto failed; 1206 } 1207 1208 if (usage & GBM_BO_USE_SCANOUT) 1209 dri_use |= __DRI_IMAGE_USE_SCANOUT; 1210 if (usage & GBM_BO_USE_CURSOR) 1211 dri_use |= __DRI_IMAGE_USE_CURSOR; 1212 if (usage & GBM_BO_USE_LINEAR) 1213 dri_use |= __DRI_IMAGE_USE_LINEAR; 1214 if (usage & GBM_BO_USE_PROTECTED) 1215 dri_use |= __DRI_IMAGE_USE_PROTECTED; 1216 1217 /* Gallium drivers requires shared in order to get the handle/stride */ 1218 dri_use |= __DRI_IMAGE_USE_SHARE; 1219 1220 if (modifiers && (dri->image->base.version < 14 || 1221 !dri->image->createImageWithModifiers)) { 1222 errno = ENOSYS; 1223 goto failed; 1224 } 1225 1226 bo->image = loader_dri_create_image(dri->screen, dri->image, width, height, 1227 dri_format, dri_use, modifiers, count, 1228 bo); 1229 if (bo->image == NULL) 1230 goto failed; 1231 1232 if (modifiers) 1233 assert(gbm_dri_bo_get_modifier(&bo->base) != DRM_FORMAT_MOD_INVALID); 1234 1235 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_HANDLE, 1236 &bo->base.v0.handle.s32); 1237 dri->image->queryImage(bo->image, __DRI_IMAGE_ATTRIB_STRIDE, 1238 (int *) &bo->base.v0.stride); 1239 1240 return &bo->base; 1241 1242failed: 1243 free(bo); 1244 return NULL; 1245} 1246 1247static void * 1248gbm_dri_bo_map(struct gbm_bo *_bo, 1249 uint32_t x, uint32_t y, 1250 uint32_t width, uint32_t height, 1251 uint32_t flags, uint32_t *stride, void **map_data) 1252{ 1253 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 1254 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 1255 1256 /* If it's a dumb buffer, we already have a mapping */ 1257 if (bo->map) { 1258 *map_data = (char *)bo->map + (bo->base.v0.stride * y) + (x * 4); 1259 *stride = bo->base.v0.stride; 1260 return *map_data; 1261 } 1262 1263 if (!dri->image || dri->image->base.version < 12 || !dri->image->mapImage) { 1264 errno = ENOSYS; 1265 return NULL; 1266 } 1267 1268 mtx_lock(&dri->mutex); 1269 if (!dri->context) 1270 dri->context = dri->dri2->createNewContext(dri->screen, NULL, 1271 NULL, NULL); 1272 assert(dri->context); 1273 mtx_unlock(&dri->mutex); 1274 1275 /* GBM flags and DRI flags are the same, so just pass them on */ 1276 return dri->image->mapImage(dri->context, bo->image, x, y, 1277 width, height, flags, (int *)stride, 1278 map_data); 1279} 1280 1281static void 1282gbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data) 1283{ 1284 struct gbm_dri_device *dri = gbm_dri_device(_bo->gbm); 1285 struct gbm_dri_bo *bo = gbm_dri_bo(_bo); 1286 1287 /* Check if it's a dumb buffer and check the pointer is in range */ 1288 if (bo->map) { 1289 assert(map_data >= bo->map); 1290 assert(map_data < (bo->map + bo->size)); 1291 return; 1292 } 1293 1294 if (!dri->context || !dri->image || 1295 dri->image->base.version < 12 || !dri->image->unmapImage) 1296 return; 1297 1298 dri->image->unmapImage(dri->context, bo->image, map_data); 1299 1300 /* 1301 * Not all DRI drivers use direct maps. They may queue up DMA operations 1302 * on the mapping context. Since there is no explicit gbm flush 1303 * mechanism, we need to flush here. 1304 */ 1305 if (dri->flush->base.version >= 4) 1306 dri->flush->flush_with_flags(dri->context, NULL, __DRI2_FLUSH_CONTEXT, 0); 1307} 1308 1309 1310static struct gbm_surface * 1311gbm_dri_surface_create(struct gbm_device *gbm, 1312 uint32_t width, uint32_t height, 1313 uint32_t format, uint32_t flags, 1314 const uint64_t *modifiers, const unsigned count) 1315{ 1316 struct gbm_dri_device *dri = gbm_dri_device(gbm); 1317 struct gbm_dri_surface *surf; 1318 1319 if (modifiers && 1320 (!dri->image || dri->image->base.version < 14 || 1321 !dri->image->createImageWithModifiers)) { 1322 errno = ENOSYS; 1323 return NULL; 1324 } 1325 1326 if (count) 1327 assert(modifiers); 1328 1329 /* It's acceptable to create an image with INVALID modifier in the list, 1330 * but it cannot be on the only modifier (since it will certainly fail 1331 * later). While we could easily catch this after modifier creation, doing 1332 * the check here is a convenient debug check likely pointing at whatever 1333 * interface the client is using to build its modifier list. 1334 */ 1335 if (count == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID) { 1336 fprintf(stderr, "Only invalid modifier specified\n"); 1337 errno = EINVAL; 1338 } 1339 1340 surf = calloc(1, sizeof *surf); 1341 if (surf == NULL) { 1342 errno = ENOMEM; 1343 return NULL; 1344 } 1345 1346 surf->base.gbm = gbm; 1347 surf->base.v0.width = width; 1348 surf->base.v0.height = height; 1349 surf->base.v0.format = gbm_core.v0.format_canonicalize(format); 1350 surf->base.v0.flags = flags; 1351 if (!modifiers) { 1352 assert(!count); 1353 return &surf->base; 1354 } 1355 1356 surf->base.v0.modifiers = calloc(count, sizeof(*modifiers)); 1357 if (count && !surf->base.v0.modifiers) { 1358 errno = ENOMEM; 1359 free(surf); 1360 return NULL; 1361 } 1362 1363 /* TODO: We are deferring validation of modifiers until the image is actually 1364 * created. This deferred creation can fail due to a modifier-format 1365 * mismatch. The result is the client has a surface but no object to back it. 1366 */ 1367 surf->base.v0.count = count; 1368 memcpy(surf->base.v0.modifiers, modifiers, count * sizeof(*modifiers)); 1369 1370 return &surf->base; 1371} 1372 1373static void 1374gbm_dri_surface_destroy(struct gbm_surface *_surf) 1375{ 1376 struct gbm_dri_surface *surf = gbm_dri_surface(_surf); 1377 1378 free(surf->base.v0.modifiers); 1379 free(surf); 1380} 1381 1382static void 1383dri_destroy(struct gbm_device *gbm) 1384{ 1385 struct gbm_dri_device *dri = gbm_dri_device(gbm); 1386 unsigned i; 1387 1388 if (dri->context) 1389 dri->core->destroyContext(dri->context); 1390 1391 dri->core->destroyScreen(dri->screen); 1392 for (i = 0; dri->driver_configs[i]; i++) 1393 free((__DRIconfig *) dri->driver_configs[i]); 1394 free(dri->driver_configs); 1395 dlclose(dri->driver); 1396 free(dri->driver_name); 1397 1398 free(dri); 1399} 1400 1401static struct gbm_device * 1402dri_device_create(int fd, uint32_t gbm_backend_version) 1403{ 1404 struct gbm_dri_device *dri; 1405 int ret; 1406 bool force_sw; 1407 1408 /* 1409 * Since the DRI backend is built-in to the loader, the loader ABI version is 1410 * guaranteed to match this backend's ABI version 1411 */ 1412 assert(gbm_core.v0.core_version == GBM_BACKEND_ABI_VERSION); 1413 assert(gbm_core.v0.core_version == gbm_backend_version); 1414 1415 dri = calloc(1, sizeof *dri); 1416 if (!dri) 1417 return NULL; 1418 1419 dri->base.v0.fd = fd; 1420 dri->base.v0.backend_version = gbm_backend_version; 1421 dri->base.v0.bo_create = gbm_dri_bo_create; 1422 dri->base.v0.bo_import = gbm_dri_bo_import; 1423 dri->base.v0.bo_map = gbm_dri_bo_map; 1424 dri->base.v0.bo_unmap = gbm_dri_bo_unmap; 1425 dri->base.v0.is_format_supported = gbm_dri_is_format_supported; 1426 dri->base.v0.get_format_modifier_plane_count = 1427 gbm_dri_get_format_modifier_plane_count; 1428 dri->base.v0.bo_write = gbm_dri_bo_write; 1429 dri->base.v0.bo_get_fd = gbm_dri_bo_get_fd; 1430 dri->base.v0.bo_get_planes = gbm_dri_bo_get_planes; 1431 dri->base.v0.bo_get_handle = gbm_dri_bo_get_handle_for_plane; 1432 dri->base.v0.bo_get_plane_fd = gbm_dri_bo_get_plane_fd; 1433 dri->base.v0.bo_get_stride = gbm_dri_bo_get_stride; 1434 dri->base.v0.bo_get_offset = gbm_dri_bo_get_offset; 1435 dri->base.v0.bo_get_modifier = gbm_dri_bo_get_modifier; 1436 dri->base.v0.bo_destroy = gbm_dri_bo_destroy; 1437 dri->base.v0.destroy = dri_destroy; 1438 dri->base.v0.surface_create = gbm_dri_surface_create; 1439 dri->base.v0.surface_destroy = gbm_dri_surface_destroy; 1440 1441 dri->base.v0.name = "drm"; 1442 1443 dri->visual_table = gbm_dri_visuals_table; 1444 dri->num_visuals = ARRAY_SIZE(gbm_dri_visuals_table); 1445 1446 mtx_init(&dri->mutex, mtx_plain); 1447 1448 force_sw = env_var_as_boolean("GBM_ALWAYS_SOFTWARE", false); 1449 if (!force_sw) { 1450 ret = dri_screen_create(dri); 1451 if (ret) 1452 ret = dri_screen_create_sw(dri); 1453 } else { 1454 ret = dri_screen_create_sw(dri); 1455 } 1456 1457 if (ret) 1458 goto err_dri; 1459 1460 return &dri->base; 1461 1462err_dri: 1463 free(dri); 1464 1465 return NULL; 1466} 1467 1468struct gbm_backend gbm_dri_backend = { 1469 .v0.backend_version = GBM_BACKEND_ABI_VERSION, 1470 .v0.backend_name = "dri", 1471 .v0.create_device = dri_device_create, 1472}; 1473