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