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