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