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