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