native_dri2.c revision 7c4e9dcdceec1112c91206619fe8b0885be99a79
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#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 48struct 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 69struct 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 87struct dri2_config { 88 struct native_config base; 89}; 90 91static INLINE struct dri2_display * 92dri2_display(const struct native_display *ndpy) 93{ 94 return (struct dri2_display *) ndpy; 95} 96 97static INLINE struct dri2_surface * 98dri2_surface(const struct native_surface *nsurf) 99{ 100 return (struct dri2_surface *) nsurf; 101} 102 103static INLINE struct dri2_config * 104dri2_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 */ 112static void 113dri2_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 */ 194static void 195dri2_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 */ 273static boolean 274dri2_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 */ 286static INLINE boolean 287dri2_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 293static boolean 294dri2_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 315static boolean 316dri2_surface_swap_buffers(struct native_surface *nsurf) 317{ 318 struct dri2_surface *dri2surf = dri2_surface(nsurf); 319 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 320 321 /* copy to front buffer */ 322 if (dri2surf->have_back) 323 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 324 0, 0, dri2surf->width, dri2surf->height, 325 DRI2BufferBackLeft, DRI2BufferFrontLeft); 326 327 /* and update fake front buffer */ 328 if (dri2surf->have_fake) 329 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 330 0, 0, dri2surf->width, dri2surf->height, 331 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 332 333 /* force buffers to be updated in next validation call */ 334 if (!dri2_surface_receive_events(&dri2surf->base)) { 335 dri2surf->server_stamp++; 336 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 337 &dri2surf->base, dri2surf->server_stamp); 338 } 339 340 return TRUE; 341} 342 343static boolean 344dri2_surface_present(struct native_surface *nsurf, 345 enum native_attachment natt, 346 boolean preserve, 347 uint swap_interval) 348{ 349 boolean ret; 350 351 if (swap_interval) 352 return FALSE; 353 354 switch (natt) { 355 case NATIVE_ATTACHMENT_FRONT_LEFT: 356 ret = dri2_surface_flush_frontbuffer(nsurf); 357 break; 358 case NATIVE_ATTACHMENT_BACK_LEFT: 359 ret = dri2_surface_swap_buffers(nsurf); 360 break; 361 default: 362 ret = FALSE; 363 break; 364 } 365 366 return ret; 367} 368 369static boolean 370dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, 371 unsigned int *seq_num, struct pipe_resource **textures, 372 int *width, int *height) 373{ 374 struct dri2_surface *dri2surf = dri2_surface(nsurf); 375 376 if (dri2surf->server_stamp != dri2surf->client_stamp || 377 (dri2surf->valid_mask & attachment_mask) != attachment_mask) { 378 if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) 379 return FALSE; 380 } 381 382 if (seq_num) 383 *seq_num = dri2surf->client_stamp; 384 385 if (textures) { 386 int att; 387 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 388 if (native_attachment_mask_test(attachment_mask, att)) { 389 struct pipe_resource *ptex = dri2surf->textures[att]; 390 391 textures[att] = NULL; 392 pipe_resource_reference(&textures[att], ptex); 393 } 394 } 395 } 396 397 if (width) 398 *width = dri2surf->width; 399 if (height) 400 *height = dri2surf->height; 401 402 return TRUE; 403} 404 405static void 406dri2_surface_wait(struct native_surface *nsurf) 407{ 408 struct dri2_surface *dri2surf = dri2_surface(nsurf); 409 struct dri2_display *dri2dpy = dri2surf->dri2dpy; 410 411 if (dri2surf->have_fake) { 412 x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, 413 0, 0, dri2surf->width, dri2surf->height, 414 DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); 415 } 416} 417 418static void 419dri2_surface_destroy(struct native_surface *nsurf) 420{ 421 struct dri2_surface *dri2surf = dri2_surface(nsurf); 422 int i; 423 424 if (dri2surf->last_xbufs) 425 FREE(dri2surf->last_xbufs); 426 427 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { 428 struct pipe_resource *ptex = dri2surf->textures[i]; 429 pipe_resource_reference(&ptex, NULL); 430 } 431 432 if (dri2surf->drawable) { 433 x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, 434 dri2surf->drawable, FALSE); 435 436 util_hash_table_remove(dri2surf->dri2dpy->surfaces, 437 (void *) dri2surf->drawable); 438 } 439 FREE(dri2surf); 440} 441 442static struct dri2_surface * 443dri2_display_create_surface(struct native_display *ndpy, 444 Drawable drawable, 445 enum pipe_format color_format) 446{ 447 struct dri2_display *dri2dpy = dri2_display(ndpy); 448 struct dri2_surface *dri2surf; 449 450 dri2surf = CALLOC_STRUCT(dri2_surface); 451 if (!dri2surf) 452 return NULL; 453 454 dri2surf->dri2dpy = dri2dpy; 455 dri2surf->drawable = drawable; 456 dri2surf->color_format = color_format; 457 458 dri2surf->base.destroy = dri2_surface_destroy; 459 dri2surf->base.present = dri2_surface_present; 460 dri2surf->base.validate = dri2_surface_validate; 461 dri2surf->base.wait = dri2_surface_wait; 462 463 if (drawable) { 464 x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); 465 /* initialize the geometry */ 466 dri2_surface_update_buffers(&dri2surf->base, 0x0); 467 468 util_hash_table_set(dri2surf->dri2dpy->surfaces, 469 (void *) dri2surf->drawable, (void *) &dri2surf->base); 470 } 471 472 return dri2surf; 473} 474 475static struct native_surface * 476dri2_display_create_window_surface(struct native_display *ndpy, 477 EGLNativeWindowType win, 478 const struct native_config *nconf) 479{ 480 struct dri2_surface *dri2surf; 481 482 dri2surf = dri2_display_create_surface(ndpy, 483 (Drawable) win, nconf->color_format); 484 return (dri2surf) ? &dri2surf->base : NULL; 485} 486 487static struct native_surface * 488dri2_display_create_pixmap_surface(struct native_display *ndpy, 489 EGLNativePixmapType pix, 490 const struct native_config *nconf) 491{ 492 struct dri2_surface *dri2surf; 493 494 if (!nconf) { 495 struct dri2_display *dri2dpy = dri2_display(ndpy); 496 uint depth, nconf_depth; 497 int i; 498 499 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 500 for (i = 0; i < dri2dpy->num_configs; i++) { 501 nconf_depth = util_format_get_blocksizebits( 502 dri2dpy->configs[i].base.color_format); 503 /* simple depth match for now */ 504 if (depth == nconf_depth || 505 (depth == 24 && depth + 8 == nconf_depth)) { 506 nconf = &dri2dpy->configs[i].base; 507 break; 508 } 509 } 510 511 if (!nconf) 512 return NULL; 513 } 514 515 dri2surf = dri2_display_create_surface(ndpy, 516 (Drawable) pix, nconf->color_format); 517 return (dri2surf) ? &dri2surf->base : NULL; 518} 519 520static int 521choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) 522{ 523 int count = 0; 524 525 switch (mode->rgbBits) { 526 case 32: 527 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 528 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 529 break; 530 case 24: 531 formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM; 532 formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; 533 formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; 534 formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; 535 break; 536 case 16: 537 formats[count++] = PIPE_FORMAT_B5G6R5_UNORM; 538 break; 539 default: 540 break; 541 } 542 543 return count; 544} 545 546static boolean 547is_format_supported(struct pipe_screen *screen, 548 enum pipe_format fmt, unsigned sample_count, boolean is_color) 549{ 550 return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, sample_count, 551 (is_color) ? PIPE_BIND_RENDER_TARGET : 552 PIPE_BIND_DEPTH_STENCIL); 553} 554 555static boolean 556dri2_display_convert_config(struct native_display *ndpy, 557 const __GLcontextModes *mode, 558 struct native_config *nconf) 559{ 560 enum pipe_format formats[32]; 561 int num_formats, i; 562 int sample_count = 0; 563 564 if (!(mode->renderType & GLX_RGBA_BIT) || !mode->rgbMode) 565 return FALSE; 566 567 /* only interested in native renderable configs */ 568 if (!mode->xRenderable || !mode->drawableType) 569 return FALSE; 570 571 /* fast/slow configs are probably not relevant */ 572 if (mode->visualRating == GLX_SLOW_CONFIG) 573 return FALSE; 574 575 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; 576 if (mode->doubleBufferMode) 577 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; 578 if (mode->stereoMode) { 579 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; 580 if (mode->doubleBufferMode) 581 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; 582 } 583 584 /* choose color format */ 585 num_formats = choose_color_format(mode, formats); 586 for (i = 0; i < num_formats; i++) { 587 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) { 588 nconf->color_format = formats[i]; 589 break; 590 } 591 } 592 if (nconf->color_format == PIPE_FORMAT_NONE) 593 return FALSE; 594 595 if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID) 596 nconf->window_bit = TRUE; 597 if (mode->drawableType & GLX_PIXMAP_BIT) 598 nconf->pixmap_bit = TRUE; 599 600 nconf->native_visual_id = mode->visualID; 601 switch (mode->visualType) { 602 case GLX_TRUE_COLOR: 603 nconf->native_visual_type = TrueColor; 604 break; 605 case GLX_DIRECT_COLOR: 606 nconf->native_visual_type = DirectColor; 607 break; 608 case GLX_PSEUDO_COLOR: 609 nconf->native_visual_type = PseudoColor; 610 break; 611 case GLX_STATIC_COLOR: 612 nconf->native_visual_type = StaticColor; 613 break; 614 case GLX_GRAY_SCALE: 615 nconf->native_visual_type = GrayScale; 616 break; 617 case GLX_STATIC_GRAY: 618 nconf->native_visual_type = StaticGray; 619 break; 620 } 621 nconf->level = mode->level; 622 623 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { 624 nconf->transparent_rgb = TRUE; 625 nconf->transparent_rgb_values[0] = mode->transparentRed; 626 nconf->transparent_rgb_values[1] = mode->transparentGreen; 627 nconf->transparent_rgb_values[2] = mode->transparentBlue; 628 } 629 630 return TRUE; 631} 632 633static const struct native_config ** 634dri2_display_get_configs(struct native_display *ndpy, int *num_configs) 635{ 636 struct dri2_display *dri2dpy = dri2_display(ndpy); 637 const struct native_config **configs; 638 int i; 639 640 /* first time */ 641 if (!dri2dpy->configs) { 642 const __GLcontextModes *modes; 643 int num_modes, count; 644 645 modes = x11_screen_get_glx_configs(dri2dpy->xscr); 646 if (!modes) 647 return NULL; 648 num_modes = x11_context_modes_count(modes); 649 650 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); 651 if (!dri2dpy->configs) 652 return NULL; 653 654 count = 0; 655 for (i = 0; i < num_modes; i++) { 656 struct native_config *nconf = &dri2dpy->configs[count].base; 657 658 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) { 659 int j; 660 /* look for duplicates */ 661 for (j = 0; j < count; j++) { 662 if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0) 663 break; 664 } 665 if (j == count) 666 count++; 667 } 668 modes = modes->next; 669 } 670 671 dri2dpy->num_configs = count; 672 } 673 674 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); 675 if (configs) { 676 for (i = 0; i < dri2dpy->num_configs; i++) 677 configs[i] = (const struct native_config *) &dri2dpy->configs[i]; 678 if (num_configs) 679 *num_configs = dri2dpy->num_configs; 680 } 681 682 return configs; 683} 684 685static boolean 686dri2_display_is_pixmap_supported(struct native_display *ndpy, 687 EGLNativePixmapType pix, 688 const struct native_config *nconf) 689{ 690 struct dri2_display *dri2dpy = dri2_display(ndpy); 691 uint depth, nconf_depth; 692 693 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 694 nconf_depth = util_format_get_blocksizebits(nconf->color_format); 695 696 /* simple depth match for now */ 697 return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); 698} 699 700static int 701dri2_display_get_param(struct native_display *ndpy, 702 enum native_param_type param) 703{ 704 int val; 705 706 switch (param) { 707 case NATIVE_PARAM_USE_NATIVE_BUFFER: 708 /* DRI2GetBuffers uses the native buffers */ 709 val = TRUE; 710 break; 711 case NATIVE_PARAM_PRESERVE_BUFFER: 712 /* DRI2CopyRegion is used */ 713 val = TRUE; 714 break; 715 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 716 default: 717 val = 0; 718 break; 719 } 720 721 return val; 722} 723 724static void 725dri2_display_destroy(struct native_display *ndpy) 726{ 727 struct dri2_display *dri2dpy = dri2_display(ndpy); 728 729 if (dri2dpy->configs) 730 FREE(dri2dpy->configs); 731 732 if (dri2dpy->base.screen) 733 dri2dpy->base.screen->destroy(dri2dpy->base.screen); 734 735 if (dri2dpy->surfaces) 736 util_hash_table_destroy(dri2dpy->surfaces); 737 738 if (dri2dpy->xscr) 739 x11_screen_destroy(dri2dpy->xscr); 740 if (dri2dpy->own_dpy) 741 XCloseDisplay(dri2dpy->dpy); 742 FREE(dri2dpy); 743} 744 745static void 746dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, 747 void *user_data) 748{ 749 struct native_display *ndpy = (struct native_display* ) user_data; 750 struct dri2_display *dri2dpy = dri2_display(ndpy); 751 struct native_surface *nsurf; 752 struct dri2_surface *dri2surf; 753 754 nsurf = (struct native_surface *) 755 util_hash_table_get(dri2dpy->surfaces, (void *) drawable); 756 if (!nsurf) 757 return; 758 759 dri2surf = dri2_surface(nsurf); 760 761 dri2surf->server_stamp++; 762 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 763 &dri2surf->base, dri2surf->server_stamp); 764} 765 766/** 767 * Initialize DRI2 and pipe screen. 768 */ 769static boolean 770dri2_display_init_screen(struct native_display *ndpy) 771{ 772 struct dri2_display *dri2dpy = dri2_display(ndpy); 773 int fd; 774 775 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || 776 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) { 777 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported"); 778 return FALSE; 779 } 780 781 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, 782 &dri2dpy->dri_major, &dri2dpy->dri_minor); 783 784 fd = x11_screen_enable_dri2(dri2dpy->xscr, 785 dri2_display_invalidate_buffers, &dri2dpy->base); 786 if (fd < 0) 787 return FALSE; 788 789 dri2dpy->base.screen = 790 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, 791 dri2dpy->dri_driver, fd); 792 if (!dri2dpy->base.screen) { 793 _eglLog(_EGL_DEBUG, "failed to create DRM screen"); 794 return FALSE; 795 } 796 797 return TRUE; 798} 799 800static unsigned 801dri2_display_hash_table_hash(void *key) 802{ 803 XID drawable = pointer_to_uintptr(key); 804 return (unsigned) drawable; 805} 806 807static int 808dri2_display_hash_table_compare(void *key1, void *key2) 809{ 810 return ((char *) key1 - (char *) key2); 811} 812 813static int 814dri2_display_authenticate(void *user_data, uint32_t magic) 815{ 816 struct native_display *ndpy = user_data; 817 struct dri2_display *dri2dpy = dri2_display(ndpy); 818 819 return x11_screen_authenticate(dri2dpy->xscr, magic); 820} 821 822#ifdef HAVE_WAYLAND_BACKEND 823 824static struct wayland_drm_callbacks wl_drm_callbacks = { 825 dri2_display_authenticate, 826 egl_g3d_wl_drm_helper_reference_buffer, 827 egl_g3d_wl_drm_helper_unreference_buffer 828}; 829 830static boolean 831dri2_display_bind_wayland_display(struct native_display *ndpy, 832 struct wl_display *wl_dpy) 833{ 834 struct dri2_display *dri2dpy = dri2_display(ndpy); 835 836 if (dri2dpy->wl_server_drm) 837 return FALSE; 838 839 dri2dpy->wl_server_drm = wayland_drm_init(wl_dpy, 840 x11_screen_get_device_name(dri2dpy->xscr), 841 &wl_drm_callbacks, ndpy); 842 843 if (!dri2dpy->wl_server_drm) 844 return FALSE; 845 846 return TRUE; 847} 848 849static boolean 850dri2_display_unbind_wayland_display(struct native_display *ndpy, 851 struct wl_display *wl_dpy) 852{ 853 struct dri2_display *dri2dpy = dri2_display(ndpy); 854 855 if (!dri2dpy->wl_server_drm) 856 return FALSE; 857 858 wayland_drm_uninit(dri2dpy->wl_server_drm); 859 dri2dpy->wl_server_drm = NULL; 860 861 return TRUE; 862} 863 864static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = { 865 dri2_display_bind_wayland_display, 866 dri2_display_unbind_wayland_display, 867 egl_g3d_wl_drm_common_wl_buffer_get_resource 868}; 869 870#endif /* HAVE_WAYLAND_BACKEND */ 871 872struct native_display * 873x11_create_dri2_display(Display *dpy, 874 const struct native_event_handler *event_handler) 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 884 dri2dpy->dpy = dpy; 885 if (!dri2dpy->dpy) { 886 dri2dpy->dpy = XOpenDisplay(NULL); 887 if (!dri2dpy->dpy) { 888 dri2_display_destroy(&dri2dpy->base); 889 return NULL; 890 } 891 dri2dpy->own_dpy = TRUE; 892 } 893 894 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy); 895 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number); 896 if (!dri2dpy->xscr) { 897 dri2_display_destroy(&dri2dpy->base); 898 return NULL; 899 } 900 901 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, 902 dri2_display_hash_table_compare); 903 if (!dri2dpy->surfaces) { 904 dri2_display_destroy(&dri2dpy->base); 905 return NULL; 906 } 907 908 dri2dpy->base.init_screen = dri2_display_init_screen; 909 dri2dpy->base.destroy = dri2_display_destroy; 910 dri2dpy->base.get_param = dri2_display_get_param; 911 dri2dpy->base.get_configs = dri2_display_get_configs; 912 dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; 913 dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap; 914 dri2dpy->base.create_window_surface = dri2_display_create_window_surface; 915 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; 916#ifdef HAVE_WAYLAND_BACKEND 917 dri2dpy->base.wayland_bufmgr = &dri2_display_wayland_bufmgr; 918#endif 919 920 return &dri2dpy->base; 921} 922 923#else /* GLX_DIRECT_RENDERING */ 924 925struct native_display * 926x11_create_dri2_display(Display *dpy, 927 struct native_event_handler *event_handler, 928 void *user_data) 929{ 930 return NULL; 931} 932 933#endif /* GLX_DIRECT_RENDERING */ 934