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