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