1 /* 2 * Mesa 3-D graphics library 3 * Version: 7.8 4 * 5 * Copyright (C) 2009-2010 Chia-I Wu <olv (at) 0xlab.org> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 */ 25 26 #include "util/u_memory.h" 27 #include "util/u_math.h" 28 #include "util/u_format.h" 29 #include "util/u_inlines.h" 30 #include "util/u_hash_table.h" 31 #include "pipe/p_compiler.h" 32 #include "pipe/p_screen.h" 33 #include "pipe/p_context.h" 34 #include "pipe/p_state.h" 35 #include "state_tracker/drm_driver.h" 36 #include "egllog.h" 37 38 #include "native_x11.h" 39 #include "x11_screen.h" 40 41 #include "common/native_helper.h" 42 #ifdef HAVE_WAYLAND_BACKEND 43 #include "common/native_wayland_drm_bufmgr_helper.h" 44 #endif 45 46 #ifdef GLX_DIRECT_RENDERING 47 48 struct dri2_display { 49 struct native_display base; 50 Display *dpy; 51 boolean own_dpy; 52 53 const struct native_event_handler *event_handler; 54 55 struct x11_screen *xscr; 56 int xscr_number; 57 const char *dri_driver; 58 int dri_major, dri_minor; 59 60 struct dri2_config *configs; 61 int num_configs; 62 63 struct util_hash_table *surfaces; 64 #ifdef HAVE_WAYLAND_BACKEND 65 struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */ 66 #endif 67 }; 68 69 struct dri2_surface { 70 struct native_surface base; 71 Drawable drawable; 72 enum pipe_format color_format; 73 struct dri2_display *dri2dpy; 74 75 unsigned int server_stamp; 76 unsigned int client_stamp; 77 int width, height; 78 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 79 uint valid_mask; 80 81 boolean have_back, have_fake; 82 83 struct x11_drawable_buffer *last_xbufs; 84 int last_num_xbufs; 85 }; 86 87 struct dri2_config { 88 struct native_config base; 89 }; 90 91 static INLINE struct dri2_display * 92 dri2_display(const struct native_display *ndpy) 93 { 94 return (struct dri2_display *) ndpy; 95 } 96 97 static INLINE struct dri2_surface * 98 dri2_surface(const struct native_surface *nsurf) 99 { 100 return (struct dri2_surface *) nsurf; 101 } 102 103 static INLINE struct dri2_config * 104 dri2_config(const struct native_config *nconf) 105 { 106 return (struct dri2_config *) nconf; 107 } 108 109 /** 110 * Process the buffers returned by the server. 111 */ 112 static void 113 dri2_surface_process_drawable_buffers(struct native_surface *nsurf, 114 struct x11_drawable_buffer *xbufs, 115 int num_xbufs) 116 { 117 struct dri2_surface *dri2surf = dri2_surface(nsurf); 118 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 119 struct pipe_resource templ; 120 struct winsys_handle whandle; 121 uint valid_mask; 122 int i; 123 124 /* free the old textures */ 125 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) 126 pipe_resource_reference(&dri2surf->textures[i], NULL); 127 dri2surf->valid_mask = 0x0; 128 129 dri2surf->have_back = FALSE; 130 dri2surf->have_fake = FALSE; 131 132 if (!xbufs) 133 return; 134 135 memset(&templ, 0, sizeof(templ)); 136 templ.target = PIPE_TEXTURE_2D; 137 templ.last_level = 0; 138 templ.width0 = dri2surf->width; 139 templ.height0 = dri2surf->height; 140 templ.depth0 = 1; 141 templ.array_size = 1; 142 templ.format = dri2surf->color_format; 143 templ.bind = PIPE_BIND_RENDER_TARGET; 144 145 valid_mask = 0x0; 146 for (i = 0; i < num_xbufs; i++) { 147 struct x11_drawable_buffer *xbuf = &xbufs[i]; 148 const char *desc; 149 enum native_attachment natt; 150 151 switch (xbuf->attachment) { 152 case DRI2BufferFrontLeft: 153 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 154 desc = "DRI2 Front Buffer"; 155 break; 156 case DRI2BufferFakeFrontLeft: 157 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 158 desc = "DRI2 Fake Front Buffer"; 159 dri2surf->have_fake = TRUE; 160 break; 161 case DRI2BufferBackLeft: 162 natt = NATIVE_ATTACHMENT_BACK_LEFT; 163 desc = "DRI2 Back Buffer"; 164 dri2surf->have_back = TRUE; 165 break; 166 default: 167 desc = NULL; 168 break; 169 } 170 171 if (!desc || dri2surf->textures[natt]) { 172 if (!desc) 173 _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); 174 else 175 _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); 176 continue; 177 } 178 179 memset(&whandle, 0, sizeof(whandle)); 180 whandle.stride = xbuf->pitch; 181 whandle.handle = xbuf->name; 182 dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( 183 dri2dpy->base.screen, &templ, &whandle); 184 if (dri2surf->textures[natt]) 185 valid_mask |= 1 << natt; 186 } 187 188 dri2surf->valid_mask = valid_mask; 189 } 190 191 /** 192 * Get the buffers from the server. 193 */ 194 static void 195 dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) 196 { 197 struct dri2_surface *dri2surf = dri2_surface(nsurf); 198 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 199 unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2]; 200 int num_ins, num_outs, att; 201 struct x11_drawable_buffer *xbufs; 202 uint bpp = util_format_get_blocksizebits(dri2surf->color_format); 203 boolean with_format = FALSE; /* never ask for depth/stencil */ 204 205 /* We must get the front on servers which doesn't support with format 206 * due to a silly bug in core dri2. You can't copy to/from a buffer 207 * that you haven't requested and you recive BadValue errors */ 208 if (dri2surf->dri2dpy->dri_minor < 1) { 209 with_format = FALSE; 210 buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT); 211 } 212 213 /* prepare the attachments */ 214 num_ins = 0; 215 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 216 if (native_attachment_mask_test(buffer_mask, att)) { 217 unsigned int dri2att; 218 219 switch (att) { 220 case NATIVE_ATTACHMENT_FRONT_LEFT: 221 dri2att = DRI2BufferFrontLeft; 222 break; 223 case NATIVE_ATTACHMENT_BACK_LEFT: 224 dri2att = DRI2BufferBackLeft; 225 break; 226 case NATIVE_ATTACHMENT_FRONT_RIGHT: 227 dri2att = DRI2BufferFrontRight; 228 break; 229 case NATIVE_ATTACHMENT_BACK_RIGHT: 230 dri2att = DRI2BufferBackRight; 231 break; 232 default: 233 assert(0); 234 dri2att = 0; 235 break; 236 } 237 238 dri2atts[num_ins++] = dri2att; 239 if (with_format) 240 dri2atts[num_ins++] = bpp; 241 } 242 } 243 if (with_format) 244 num_ins /= 2; 245 246 xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, 247 &dri2surf->width, &dri2surf->height, 248 dri2atts, with_format, num_ins, &num_outs); 249 250 /* we should be able to do better... */ 251 if (xbufs && dri2surf->last_num_xbufs == num_outs && 252 memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { 253 FREE(xbufs); 254 dri2surf->client_stamp = dri2surf->server_stamp; 255 return; 256 } 257 258 dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs); 259 260 dri2surf->server_stamp++; 261 dri2surf->client_stamp = dri2surf->server_stamp; 262 263 if (dri2surf->last_xbufs) 264 FREE(dri2surf->last_xbufs); 265 dri2surf->last_xbufs = xbufs; 266 dri2surf->last_num_xbufs = num_outs; 267 } 268 269 /** 270 * Update the buffers of the surface. This is a slow function due to the 271 * round-trip to the server. 272 */ 273 static boolean 274 dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) 275 { 276 struct dri2_surface *dri2surf = dri2_surface(nsurf); 277 278 dri2_surface_get_buffers(&dri2surf->base, buffer_mask); 279 280 return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); 281 } 282 283 /** 284 * Return TRUE if the surface receives DRI2_InvalidateBuffers events. 285 */ 286 static INLINE boolean 287 dri2_surface_receive_events(struct native_surface *nsurf) 288 { 289 struct dri2_surface *dri2surf = dri2_surface(nsurf); 290 return (dri2surf->dri2dpy->dri_minor >= 3); 291 } 292 293 static boolean 294 dri2_surface_flush_frontbuffer(struct native_surface *nsurf) 295 { 296 struct dri2_surface *dri2surf = dri2_surface(nsurf); 297 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 298 299 /* copy to real front buffer */ 300 if (dri2surf->have_fake) 301 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 302 0, 0, dri2surf->width, dri2surf->height, 303 DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); 304 305 /* force buffers to be updated in next validation call */ 306 if (!dri2_surface_receive_events(&dri2surf->base)) { 307 dri2surf->server_stamp++; 308 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 309 &dri2surf->base, dri2surf->server_stamp); 310 } 311 312 return TRUE; 313 } 314 315 static boolean 316 dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects, 317 const int *rects) 318 { 319 struct dri2_surface *dri2surf = dri2_surface(nsurf); 320 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 321 322 /* copy to front buffer */ 323 if (dri2surf->have_back) { 324 if (num_rects > 0) 325 x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, 326 num_rects, rects, 327 DRI2BufferBackLeft, DRI2BufferFrontLeft); 328 else 329 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 330 0, 0, dri2surf->width, dri2surf->height, 331 DRI2BufferBackLeft, DRI2BufferFrontLeft); 332 } 333 334 /* and update fake front buffer */ 335 if (dri2surf->have_fake) { 336 if (num_rects > 0) 337 x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable, 338 num_rects, rects, 339 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 340 else 341 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 342 0, 0, dri2surf->width, dri2surf->height, 343 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 344 } 345 346 /* force buffers to be updated in next validation call */ 347 if (!dri2_surface_receive_events(&dri2surf->base)) { 348 dri2surf->server_stamp++; 349 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 350 &dri2surf->base, dri2surf->server_stamp); 351 } 352 353 return TRUE; 354 } 355 356 static boolean 357 dri2_surface_present(struct native_surface *nsurf, 358 const struct native_present_control *ctrl) 359 { 360 boolean ret; 361 362 if (ctrl->swap_interval) 363 return FALSE; 364 365 switch (ctrl->natt) { 366 case NATIVE_ATTACHMENT_FRONT_LEFT: 367 ret = dri2_surface_flush_frontbuffer(nsurf); 368 break; 369 case NATIVE_ATTACHMENT_BACK_LEFT: 370 ret = dri2_surface_swap_buffers(nsurf, ctrl->num_rects, ctrl->rects); 371 break; 372 default: 373 ret = FALSE; 374 break; 375 } 376 377 return ret; 378 } 379 380 static boolean 381 dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, 382 unsigned int *seq_num, struct pipe_resource **textures, 383 int *width, int *height) 384 { 385 struct dri2_surface *dri2surf = dri2_surface(nsurf); 386 387 if (dri2surf->server_stamp != dri2surf->client_stamp || 388 (dri2surf->valid_mask & attachment_mask) != attachment_mask) { 389 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) 390 return FALSE; 391 } 392 393 if (seq_num) 394 *seq_num = dri2surf->client_stamp; 395 396 if (textures) { 397 int att; 398 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 399 if (native_attachment_mask_test(attachment_mask, att)) { 400 struct pipe_resource *ptex = dri2surf->textures[att]; 401 402 textures[att] = NULL; 403 pipe_resource_reference(&textures[att], ptex); 404 } 405 } 406 } 407 408 if (width) 409 *width = dri2surf->width; 410 if (height) 411 *height = dri2surf->height; 412 413 return TRUE; 414 } 415 416 static void 417 dri2_surface_wait(struct native_surface *nsurf) 418 { 419 struct dri2_surface *dri2surf = dri2_surface(nsurf); 420 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 421 422 if (dri2surf->have_fake) { 423 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 424 0, 0, dri2surf->width, dri2surf->height, 425 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 426 } 427 } 428 429 static void 430 dri2_surface_destroy(struct native_surface *nsurf) 431 { 432 struct dri2_surface *dri2surf = dri2_surface(nsurf); 433 int i; 434 435 if (dri2surf->last_xbufs) 436 FREE(dri2surf->last_xbufs); 437 438 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { 439 struct pipe_resource *ptex = dri2surf->textures[i]; 440 pipe_resource_reference(&ptex, NULL); 441 } 442 443 if (dri2surf->drawable) { 444 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, 445 dri2surf->drawable, FALSE); 446 447 util_hash_table_remove(dri2surf->dri2dpy->surfaces, 448 (void *) dri2surf->drawable); 449 } 450 FREE(dri2surf); 451 } 452 453 static struct dri2_surface * 454 dri2_display_create_surface(struct native_display *ndpy, 455 Drawable drawable, 456 enum pipe_format color_format) 457 { 458 struct dri2_display *dri2dpy = dri2_display(ndpy); 459 struct dri2_surface *dri2surf; 460 461 dri2surf = CALLOC_STRUCT(dri2_surface); 462 if (!dri2surf) 463 return NULL; 464 465 dri2surf->dri2dpy = dri2dpy; 466 dri2surf->drawable = drawable; 467 dri2surf->color_format = color_format; 468 469 dri2surf->base.destroy = dri2_surface_destroy; 470 dri2surf->base.present = dri2_surface_present; 471 dri2surf->base.validate = dri2_surface_validate; 472 dri2surf->base.wait = dri2_surface_wait; 473 474 if (drawable) { 475 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); 476 /* initialize the geometry */ 477 dri2_surface_update_buffers(&dri2surf->base, 0x0); 478 479 util_hash_table_set(dri2surf->dri2dpy->surfaces, 480 (void *) dri2surf->drawable, (void *) &dri2surf->base); 481 } 482 483 return dri2surf; 484 } 485 486 static struct native_surface * 487 dri2_display_create_window_surface(struct native_display *ndpy, 488 EGLNativeWindowType win, 489 const struct native_config *nconf) 490 { 491 struct dri2_surface *dri2surf; 492 493 dri2surf = dri2_display_create_surface(ndpy, 494 (Drawable) win, nconf->color_format); 495 return (dri2surf) ? &dri2surf->base : NULL; 496 } 497 498 static struct native_surface * 499 dri2_display_create_pixmap_surface(struct native_display *ndpy, 500 EGLNativePixmapType pix, 501 const struct native_config *nconf) 502 { 503 struct dri2_surface *dri2surf; 504 505 if (!nconf) { 506 struct dri2_display *dri2dpy = dri2_display(ndpy); 507 uint depth, nconf_depth; 508 int i; 509 510 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 511 for (i = 0; i < dri2dpy->num_configs; i++) { 512 nconf_depth = util_format_get_blocksizebits( 513 dri2dpy->configs[i].base.color_format); 514 /* simple depth match for now */ 515 if (depth == nconf_depth || 516 (depth == 24 && depth + 8 == nconf_depth)) { 517 nconf = &dri2dpy->configs[i].base; 518 break; 519 } 520 } 521 522 if (!nconf) 523 return NULL; 524 } 525 526 dri2surf = dri2_display_create_surface(ndpy, 527 (Drawable) pix, nconf->color_format); 528 return (dri2surf) ? &dri2surf->base : NULL; 529 } 530 531 static int 532 choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) 533 { 534 int count = 0; 535 536 switch (mode->rgbBits) { 537 case 32: 538 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 539 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 540 break; 541 case 24: 542 formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM; 543 formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; 544 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 545 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 546 break; 547 case 16: 548 formats[count++] = PIPE_FORMAT_B5G6R5_UNORM; 549 break; 550 default: 551 break; 552 } 553 554 return count; 555 } 556 557 static boolean 558 is_format_supported(struct pipe_screen *screen, 559 enum pipe_format fmt, unsigned sample_count, boolean is_color) 560 { 561 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count, 562 (is_color) ? PIPE_BIND_RENDER_TARGET : 563 PIPE_BIND_DEPTH_STENCIL); 564 } 565 566 static boolean 567 dri2_display_convert_config(struct native_display *ndpy, 568 const __GLcontextModes *mode, 569 struct native_config *nconf) 570 { 571 enum pipe_format formats[32]; 572 int num_formats, i; 573 int sample_count = 0; 574 575 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode) 576 return FALSE; 577 578 /* only interested in native renderable configs */ 579 if (!mode->xRenderable || !mode->drawableType) 580 return FALSE; 581 582 /* fast/slow configs are probably not relevant */ 583 if (mode->visualRating == GLX_SLOW_CONFIG) 584 return FALSE; 585 586 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; 587 if (mode->doubleBufferMode) 588 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; 589 if (mode->stereoMode) { 590 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; 591 if (mode->doubleBufferMode) 592 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; 593 } 594 595 /* choose color format */ 596 num_formats = choose_color_format(mode, formats); 597 for (i = 0; i < num_formats; i++) { 598 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) { 599 nconf->color_format = formats[i]; 600 break; 601 } 602 } 603 if (nconf->color_format == PIPE_FORMAT_NONE) 604 return FALSE; 605 606 if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID) 607 nconf->window_bit = TRUE; 608 if (mode->drawableType & GLX_PIXMAP_BIT) 609 nconf->pixmap_bit = TRUE; 610 611 nconf->native_visual_id = mode->visualID; 612 switch (mode->visualType) { 613 case GLX_TRUE_COLOR: 614 nconf->native_visual_type = TrueColor; 615 break; 616 case GLX_DIRECT_COLOR: 617 nconf->native_visual_type = DirectColor; 618 break; 619 case GLX_PSEUDO_COLOR: 620 nconf->native_visual_type = PseudoColor; 621 break; 622 case GLX_STATIC_COLOR: 623 nconf->native_visual_type = StaticColor; 624 break; 625 case GLX_GRAY_SCALE: 626 nconf->native_visual_type = GrayScale; 627 break; 628 case GLX_STATIC_GRAY: 629 nconf->native_visual_type = StaticGray; 630 break; 631 } 632 nconf->level = mode->level; 633 634 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { 635 nconf->transparent_rgb = TRUE; 636 nconf->transparent_rgb_values[0] = mode->transparentRed; 637 nconf->transparent_rgb_values[1] = mode->transparentGreen; 638 nconf->transparent_rgb_values[2] = mode->transparentBlue; 639 } 640 641 return TRUE; 642 } 643 644 static const struct native_config ** 645 dri2_display_get_configs(struct native_display *ndpy, int *num_configs) 646 { 647 struct dri2_display *dri2dpy = dri2_display(ndpy); 648 const struct native_config **configs; 649 int i; 650 651 /* first time */ 652 if (!dri2dpy->configs) { 653 const __GLcontextModes *modes; 654 int num_modes, count; 655 656 modes = x11_screen_get_glx_configs(dri2dpy->xscr); 657 if (!modes) 658 return NULL; 659 num_modes = x11_context_modes_count(modes); 660 661 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); 662 if (!dri2dpy->configs) 663 return NULL; 664 665 count = 0; 666 for (i = 0; i < num_modes; i++) { 667 struct native_config *nconf = &dri2dpy->configs[count].base; 668 669 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) { 670 int j; 671 /* look for duplicates */ 672 for (j = 0; j < count; j++) { 673 if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0) 674 break; 675 } 676 if (j == count) 677 count++; 678 } 679 modes = modes->next; 680 } 681 682 dri2dpy->num_configs = count; 683 } 684 685 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); 686 if (configs) { 687 for (i = 0; i < dri2dpy->num_configs; i++) 688 configs[i] = (const struct native_config *) &dri2dpy->configs[i]; 689 if (num_configs) 690 *num_configs = dri2dpy->num_configs; 691 } 692 693 return configs; 694 } 695 696 static boolean 697 dri2_display_get_pixmap_format(struct native_display *ndpy, 698 EGLNativePixmapType pix, 699 enum pipe_format *format) 700 { 701 struct dri2_display *dri2dpy = dri2_display(ndpy); 702 boolean ret = EGL_TRUE; 703 uint depth; 704 705 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 706 switch (depth) { 707 case 32: 708 case 24: 709 *format = PIPE_FORMAT_B8G8R8A8_UNORM; 710 break; 711 case 16: 712 *format = PIPE_FORMAT_B5G6R5_UNORM; 713 break; 714 default: 715 *format = PIPE_FORMAT_NONE; 716 ret = EGL_FALSE; 717 break; 718 } 719 720 return ret; 721 } 722 723 static int 724 dri2_display_get_param(struct native_display *ndpy, 725 enum native_param_type param) 726 { 727 int val; 728 729 switch (param) { 730 case NATIVE_PARAM_USE_NATIVE_BUFFER: 731 /* DRI2GetBuffers uses the native buffers */ 732 val = TRUE; 733 break; 734 case NATIVE_PARAM_PRESERVE_BUFFER: 735 /* DRI2CopyRegion is used */ 736 val = TRUE; 737 break; 738 case NATIVE_PARAM_PRESENT_REGION: 739 val = TRUE; 740 break; 741 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 742 default: 743 val = 0; 744 break; 745 } 746 747 return val; 748 } 749 750 static void 751 dri2_display_destroy(struct native_display *ndpy) 752 { 753 struct dri2_display *dri2dpy = dri2_display(ndpy); 754 755 if (dri2dpy->configs) 756 FREE(dri2dpy->configs); 757 758 if (dri2dpy->base.screen) 759 dri2dpy->base.screen->destroy(dri2dpy->base.screen); 760 761 if (dri2dpy->surfaces) 762 util_hash_table_destroy(dri2dpy->surfaces); 763 764 if (dri2dpy->xscr) 765 x11_screen_destroy(dri2dpy->xscr); 766 if (dri2dpy->own_dpy) 767 XCloseDisplay(dri2dpy->dpy); 768 FREE(dri2dpy); 769 } 770 771 static void 772 dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, 773 void *user_data) 774 { 775 struct native_display *ndpy = (struct native_display* ) user_data; 776 struct dri2_display *dri2dpy = dri2_display(ndpy); 777 struct native_surface *nsurf; 778 struct dri2_surface *dri2surf; 779 780 nsurf = (struct native_surface *) 781 util_hash_table_get(dri2dpy->surfaces, (void *) drawable); 782 if (!nsurf) 783 return; 784 785 dri2surf = dri2_surface(nsurf); 786 787 dri2surf->server_stamp++; 788 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 789 &dri2surf->base, dri2surf->server_stamp); 790 } 791 792 /** 793 * Initialize DRI2 and pipe screen. 794 */ 795 static boolean 796 dri2_display_init_screen(struct native_display *ndpy) 797 { 798 struct dri2_display *dri2dpy = dri2_display(ndpy); 799 int fd; 800 801 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || 802 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) { 803 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported"); 804 return FALSE; 805 } 806 807 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, 808 &dri2dpy->dri_major, &dri2dpy->dri_minor); 809 810 fd = x11_screen_enable_dri2(dri2dpy->xscr, 811 dri2_display_invalidate_buffers, &dri2dpy->base); 812 if (fd < 0) 813 return FALSE; 814 815 dri2dpy->base.screen = 816 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, 817 dri2dpy->dri_driver, fd); 818 if (!dri2dpy->base.screen) { 819 _eglLog(_EGL_DEBUG, "failed to create DRM screen"); 820 return FALSE; 821 } 822 823 return TRUE; 824 } 825 826 static unsigned 827 dri2_display_hash_table_hash(void *key) 828 { 829 XID drawable = pointer_to_uintptr(key); 830 return (unsigned) drawable; 831 } 832 833 static int 834 dri2_display_hash_table_compare(void *key1, void *key2) 835 { 836 return ((char *) key1 - (char *) key2); 837 } 838 839 #ifdef HAVE_WAYLAND_BACKEND 840 841 static int 842 dri2_display_authenticate(void *user_data, uint32_t magic) 843 { 844 struct native_display *ndpy = user_data; 845 struct dri2_display *dri2dpy = dri2_display(ndpy); 846 847 return x11_screen_authenticate(dri2dpy->xscr, magic); 848 } 849 850 static struct wayland_drm_callbacks wl_drm_callbacks = { 851 dri2_display_authenticate, 852 egl_g3d_wl_drm_helper_reference_buffer, 853 egl_g3d_wl_drm_helper_unreference_buffer 854 }; 855 856 static boolean 857 dri2_display_bind_wayland_display(struct native_display *ndpy, 858 struct wl_display *wl_dpy) 859 { 860 struct dri2_display *dri2dpy = dri2_display(ndpy); 861 862 if (dri2dpy->wl_server_drm) 863 return FALSE; 864 865 dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy, 866 x11_screen_get_device_name(dri2dpy->xscr), 867 &wl_drm_callbacks, ndpy); 868 869 if (!dri2dpy->wl_server_drm) 870 return FALSE; 871 872 return TRUE; 873 } 874 875 static boolean 876 dri2_display_unbind_wayland_display(struct native_display *ndpy, 877 struct wl_display *wl_dpy) 878 { 879 struct dri2_display *dri2dpy = dri2_display(ndpy); 880 881 if (!dri2dpy->wl_server_drm) 882 return FALSE; 883 884 wayland_drm_uninit(dri2dpy->wl_server_drm); 885 dri2dpy->wl_server_drm = NULL; 886 887 return TRUE; 888 } 889 890 static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = { 891 dri2_display_bind_wayland_display, 892 dri2_display_unbind_wayland_display, 893 egl_g3d_wl_drm_common_wl_buffer_get_resource, 894 egl_g3d_wl_drm_common_query_buffer 895 }; 896 897 #endif /* HAVE_WAYLAND_BACKEND */ 898 899 struct native_display * 900 x11_create_dri2_display(Display *dpy, 901 const struct native_event_handler *event_handler) 902 { 903 struct dri2_display *dri2dpy; 904 905 dri2dpy = CALLOC_STRUCT(dri2_display); 906 if (!dri2dpy) 907 return NULL; 908 909 dri2dpy->event_handler = event_handler; 910 911 dri2dpy->dpy = dpy; 912 if (!dri2dpy->dpy) { 913 dri2dpy->dpy = XOpenDisplay(NULL); 914 if (!dri2dpy->dpy) { 915 dri2_display_destroy(&dri2dpy->base); 916 return NULL; 917 } 918 dri2dpy->own_dpy = TRUE; 919 } 920 921 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy); 922 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number); 923 if (!dri2dpy->xscr) { 924 dri2_display_destroy(&dri2dpy->base); 925 return NULL; 926 } 927 928 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, 929 dri2_display_hash_table_compare); 930 if (!dri2dpy->surfaces) { 931 dri2_display_destroy(&dri2dpy->base); 932 return NULL; 933 } 934 935 dri2dpy->base.init_screen = dri2_display_init_screen; 936 dri2dpy->base.destroy = dri2_display_destroy; 937 dri2dpy->base.get_param = dri2_display_get_param; 938 dri2dpy->base.get_configs = dri2_display_get_configs; 939 dri2dpy->base.get_pixmap_format = dri2_display_get_pixmap_format; 940 dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap; 941 dri2dpy->base.create_window_surface = dri2_display_create_window_surface; 942 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; 943 #ifdef HAVE_WAYLAND_BACKEND 944 dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr; 945 #endif 946 947 return &dri2dpy->base; 948 } 949 950 #else /* GLX_DIRECT_RENDERING */ 951 952 struct native_display * 953 x11_create_dri2_display(Display *dpy, 954 const struct native_event_handler *event_handler) 955 { 956 return NULL; 957 } 958 959 #endif /* GLX_DIRECT_RENDERING */ 960