native_dri2.c revision 97e9a0e23f0e06d020883c37b9d065e8978a47f4
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 /* fast/slow configs are probably not relevant */ 564 if (mode->visualRating == GLX_SLOW_CONFIG) 565 return FALSE; 566 567 nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; 568 if (mode->doubleBufferMode) 569 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; 570 if (mode->stereoMode) { 571 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; 572 if (mode->doubleBufferMode) 573 nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; 574 } 575 576 /* choose color format */ 577 num_formats = choose_color_format(mode, formats); 578 for (i = 0; i < num_formats; i++) { 579 if (is_format_supported(ndpy->screen, formats[i], sample_count, TRUE)) { 580 nconf->color_format = formats[i]; 581 break; 582 } 583 } 584 if (nconf->color_format == PIPE_FORMAT_NONE) 585 return FALSE; 586 587 if ((mode->drawableType & GLX_WINDOW_BIT) && mode->visualID) 588 nconf->window_bit = TRUE; 589 if (mode->drawableType & GLX_PIXMAP_BIT) 590 nconf->pixmap_bit = TRUE; 591 592 nconf->native_visual_id = mode->visualID; 593 switch (mode->visualType) { 594 case GLX_TRUE_COLOR: 595 nconf->native_visual_type = TrueColor; 596 break; 597 case GLX_DIRECT_COLOR: 598 nconf->native_visual_type = DirectColor; 599 break; 600 case GLX_PSEUDO_COLOR: 601 nconf->native_visual_type = PseudoColor; 602 break; 603 case GLX_STATIC_COLOR: 604 nconf->native_visual_type = StaticColor; 605 break; 606 case GLX_GRAY_SCALE: 607 nconf->native_visual_type = GrayScale; 608 break; 609 case GLX_STATIC_GRAY: 610 nconf->native_visual_type = StaticGray; 611 break; 612 } 613 nconf->level = mode->level; 614 615 if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { 616 nconf->transparent_rgb = TRUE; 617 nconf->transparent_rgb_values[0] = mode->transparentRed; 618 nconf->transparent_rgb_values[1] = mode->transparentGreen; 619 nconf->transparent_rgb_values[2] = mode->transparentBlue; 620 } 621 622 return TRUE; 623} 624 625static const struct native_config ** 626dri2_display_get_configs(struct native_display *ndpy, int *num_configs) 627{ 628 struct dri2_display *dri2dpy = dri2_display(ndpy); 629 const struct native_config **configs; 630 int i; 631 632 /* first time */ 633 if (!dri2dpy->configs) { 634 const __GLcontextModes *modes; 635 int num_modes, count; 636 637 modes = x11_screen_get_glx_configs(dri2dpy->xscr); 638 if (!modes) 639 return NULL; 640 num_modes = x11_context_modes_count(modes); 641 642 dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); 643 if (!dri2dpy->configs) 644 return NULL; 645 646 count = 0; 647 for (i = 0; i < num_modes; i++) { 648 struct native_config *nconf = &dri2dpy->configs[count].base; 649 650 if (dri2_display_convert_config(&dri2dpy->base, modes, nconf)) { 651 int j; 652 /* look for duplicates */ 653 for (j = 0; j < count; j++) { 654 if (memcmp(&dri2dpy->configs[j], nconf, sizeof(*nconf)) == 0) 655 break; 656 } 657 if (j == count) 658 count++; 659 } 660 modes = modes->next; 661 } 662 663 dri2dpy->num_configs = count; 664 } 665 666 configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); 667 if (configs) { 668 for (i = 0; i < dri2dpy->num_configs; i++) 669 configs[i] = (const struct native_config *) &dri2dpy->configs[i]; 670 if (num_configs) 671 *num_configs = dri2dpy->num_configs; 672 } 673 674 return configs; 675} 676 677static boolean 678dri2_display_is_pixmap_supported(struct native_display *ndpy, 679 EGLNativePixmapType pix, 680 const struct native_config *nconf) 681{ 682 struct dri2_display *dri2dpy = dri2_display(ndpy); 683 uint depth, nconf_depth; 684 685 depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); 686 nconf_depth = util_format_get_blocksizebits(nconf->color_format); 687 688 /* simple depth match for now */ 689 return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); 690} 691 692static int 693dri2_display_get_param(struct native_display *ndpy, 694 enum native_param_type param) 695{ 696 int val; 697 698 switch (param) { 699 case NATIVE_PARAM_USE_NATIVE_BUFFER: 700 /* DRI2GetBuffers uses the native buffers */ 701 val = TRUE; 702 break; 703 case NATIVE_PARAM_PRESERVE_BUFFER: 704 /* DRI2CopyRegion is used */ 705 val = TRUE; 706 break; 707 case NATIVE_PARAM_MAX_SWAP_INTERVAL: 708 default: 709 val = 0; 710 break; 711 } 712 713 return val; 714} 715 716static void 717dri2_display_destroy(struct native_display *ndpy) 718{ 719 struct dri2_display *dri2dpy = dri2_display(ndpy); 720 721 if (dri2dpy->configs) 722 FREE(dri2dpy->configs); 723 724 if (dri2dpy->base.screen) 725 dri2dpy->base.screen->destroy(dri2dpy->base.screen); 726 727 if (dri2dpy->surfaces) 728 util_hash_table_destroy(dri2dpy->surfaces); 729 730 if (dri2dpy->xscr) 731 x11_screen_destroy(dri2dpy->xscr); 732 if (dri2dpy->own_dpy) 733 XCloseDisplay(dri2dpy->dpy); 734 FREE(dri2dpy); 735} 736 737static void 738dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, 739 void *user_data) 740{ 741 struct native_display *ndpy = (struct native_display* ) user_data; 742 struct dri2_display *dri2dpy = dri2_display(ndpy); 743 struct native_surface *nsurf; 744 struct dri2_surface *dri2surf; 745 746 nsurf = (struct native_surface *) 747 util_hash_table_get(dri2dpy->surfaces, (void *) drawable); 748 if (!nsurf) 749 return; 750 751 dri2surf = dri2_surface(nsurf); 752 753 dri2surf->server_stamp++; 754 dri2dpy->event_handler->invalid_surface(&dri2dpy->base, 755 &dri2surf->base, dri2surf->server_stamp); 756} 757 758/** 759 * Initialize DRI2 and pipe screen. 760 */ 761static boolean 762dri2_display_init_screen(struct native_display *ndpy) 763{ 764 struct dri2_display *dri2dpy = dri2_display(ndpy); 765 int fd; 766 767 if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || 768 !x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_GLX)) { 769 _eglLog(_EGL_WARNING, "GLX/DRI2 is not supported"); 770 return FALSE; 771 } 772 773 dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, 774 &dri2dpy->dri_major, &dri2dpy->dri_minor); 775 776 fd = x11_screen_enable_dri2(dri2dpy->xscr, 777 dri2_display_invalidate_buffers, &dri2dpy->base); 778 if (fd < 0) 779 return FALSE; 780 781 dri2dpy->base.screen = 782 dri2dpy->event_handler->new_drm_screen(&dri2dpy->base, 783 dri2dpy->dri_driver, fd); 784 if (!dri2dpy->base.screen) { 785 _eglLog(_EGL_WARNING, "failed to create DRM screen"); 786 return FALSE; 787 } 788 789 return TRUE; 790} 791 792static unsigned 793dri2_display_hash_table_hash(void *key) 794{ 795 XID drawable = pointer_to_uintptr(key); 796 return (unsigned) drawable; 797} 798 799static int 800dri2_display_hash_table_compare(void *key1, void *key2) 801{ 802 return ((char *) key1 - (char *) key2); 803} 804 805struct native_display * 806x11_create_dri2_display(Display *dpy, 807 struct native_event_handler *event_handler, 808 void *user_data) 809{ 810 struct dri2_display *dri2dpy; 811 812 dri2dpy = CALLOC_STRUCT(dri2_display); 813 if (!dri2dpy) 814 return NULL; 815 816 dri2dpy->event_handler = event_handler; 817 dri2dpy->base.user_data = user_data; 818 819 dri2dpy->dpy = dpy; 820 if (!dri2dpy->dpy) { 821 dri2dpy->dpy = XOpenDisplay(NULL); 822 if (!dri2dpy->dpy) { 823 dri2_display_destroy(&dri2dpy->base); 824 return NULL; 825 } 826 dri2dpy->own_dpy = TRUE; 827 } 828 829 dri2dpy->xscr_number = DefaultScreen(dri2dpy->dpy); 830 dri2dpy->xscr = x11_screen_create(dri2dpy->dpy, dri2dpy->xscr_number); 831 if (!dri2dpy->xscr) { 832 dri2_display_destroy(&dri2dpy->base); 833 return NULL; 834 } 835 836 if (!dri2_display_init_screen(&dri2dpy->base)) { 837 dri2_display_destroy(&dri2dpy->base); 838 return NULL; 839 } 840 841 dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, 842 dri2_display_hash_table_compare); 843 if (!dri2dpy->surfaces) { 844 dri2_display_destroy(&dri2dpy->base); 845 return NULL; 846 } 847 848 dri2dpy->base.destroy = dri2_display_destroy; 849 dri2dpy->base.get_param = dri2_display_get_param; 850 dri2dpy->base.get_configs = dri2_display_get_configs; 851 dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; 852 dri2dpy->base.create_window_surface = dri2_display_create_window_surface; 853 dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; 854 855 return &dri2dpy->base; 856} 857 858#else /* GLX_DIRECT_RENDERING */ 859 860struct native_display * 861x11_create_dri2_display(Display *dpy, 862 struct native_event_handler *event_handler, 863 void *user_data) 864{ 865 return NULL; 866} 867 868#endif /* GLX_DIRECT_RENDERING */ 869