native_ximage.c revision 6f4ce4a4fed9f0f0f0ee89a63e406ab86dae7150
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 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include <assert.h> 26#include <sys/ipc.h> 27#include <sys/types.h> 28#include <sys/shm.h> 29#include <X11/Xlib.h> 30#include <X11/Xutil.h> 31#include <X11/extensions/XShm.h> 32#include "util/u_memory.h" 33#include "util/u_math.h" 34#include "util/u_format.h" 35#include "pipe/p_compiler.h" 36#include "util/u_simple_screen.h" 37#include "util/u_inlines.h" 38#include "softpipe/sp_winsys.h" 39#include "egllog.h" 40 41#include "sw_winsys.h" 42#include "native_x11.h" 43#include "x11_screen.h" 44 45enum ximage_surface_type { 46 XIMAGE_SURFACE_TYPE_WINDOW, 47 XIMAGE_SURFACE_TYPE_PIXMAP, 48 XIMAGE_SURFACE_TYPE_PBUFFER 49}; 50 51struct ximage_display { 52 struct native_display base; 53 Display *dpy; 54 boolean own_dpy; 55 56 struct x11_screen *xscr; 57 int xscr_number; 58 59 struct native_event_handler *event_handler; 60 61 boolean use_xshm; 62 63 struct pipe_winsys *winsys; 64 struct ximage_config *configs; 65 int num_configs; 66}; 67 68struct ximage_buffer { 69 XImage *ximage; 70 71 struct pipe_texture *texture; 72 XShmSegmentInfo *shm_info; 73 boolean xshm_attached; 74}; 75 76struct ximage_surface { 77 struct native_surface base; 78 Drawable drawable; 79 enum ximage_surface_type type; 80 enum pipe_format color_format; 81 XVisualInfo visual; 82 struct ximage_display *xdpy; 83 84 GC gc; 85 86 unsigned int server_stamp; 87 unsigned int client_stamp; 88 int width, height; 89 struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; 90 uint valid_mask; 91}; 92 93struct ximage_config { 94 struct native_config base; 95 const XVisualInfo *visual; 96}; 97 98static INLINE struct ximage_display * 99ximage_display(const struct native_display *ndpy) 100{ 101 return (struct ximage_display *) ndpy; 102} 103 104static INLINE struct ximage_surface * 105ximage_surface(const struct native_surface *nsurf) 106{ 107 return (struct ximage_surface *) nsurf; 108} 109 110static INLINE struct ximage_config * 111ximage_config(const struct native_config *nconf) 112{ 113 return (struct ximage_config *) nconf; 114} 115 116static void 117ximage_surface_free_buffer(struct native_surface *nsurf, 118 enum native_attachment which) 119{ 120 struct ximage_surface *xsurf = ximage_surface(nsurf); 121 struct ximage_buffer *xbuf = &xsurf->buffers[which]; 122 123 pipe_texture_reference(&xbuf->texture, NULL); 124 125 if (xbuf->shm_info) { 126 if (xbuf->xshm_attached) 127 XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); 128 if (xbuf->shm_info->shmaddr != (void *) -1) 129 shmdt(xbuf->shm_info->shmaddr); 130 if (xbuf->shm_info->shmid != -1) 131 shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); 132 133 xbuf->shm_info->shmaddr = (void *) -1; 134 xbuf->shm_info->shmid = -1; 135 } 136} 137 138static boolean 139ximage_surface_alloc_buffer(struct native_surface *nsurf, 140 enum native_attachment which) 141{ 142 struct ximage_surface *xsurf = ximage_surface(nsurf); 143 struct ximage_buffer *xbuf = &xsurf->buffers[which]; 144 struct pipe_screen *screen = xsurf->xdpy->base.screen; 145 struct pipe_texture templ; 146 147 /* free old data */ 148 if (xbuf->texture) 149 ximage_surface_free_buffer(&xsurf->base, which); 150 151 memset(&templ, 0, sizeof(templ)); 152 templ.target = PIPE_TEXTURE_2D; 153 templ.format = xsurf->color_format; 154 templ.width0 = xsurf->width; 155 templ.height0 = xsurf->height; 156 templ.depth0 = 1; 157 templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; 158 159#if 0 160 /* Interesting and suprising use of texture_blanket + 161 * user_buffer_create... To be superceded by the sw_winsys branch, 162 * but currently disabled. 163 */ 164 if (xbuf->shm_info) { 165 struct pipe_buffer *pbuf; 166 unsigned stride, size; 167 void *addr = NULL; 168 169 stride = util_format_get_stride(xsurf->color_format, xsurf->width); 170 /* alignment should depend on visual? */ 171 stride = align(stride, 4); 172 size = stride * xsurf->height; 173 174 /* create and attach shm object */ 175 xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); 176 if (xbuf->shm_info->shmid != -1) { 177 xbuf->shm_info->shmaddr = 178 shmat(xbuf->shm_info->shmid, NULL, 0); 179 if (xbuf->shm_info->shmaddr != (void *) -1) { 180 if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { 181 addr = xbuf->shm_info->shmaddr; 182 xbuf->xshm_attached = TRUE; 183 } 184 } 185 } 186 187 if (addr) { 188 pbuf = screen->user_buffer_create(screen, addr, size); 189 if (pbuf) { 190 xbuf->texture = 191 screen->texture_blanket(screen, &templ, &stride, pbuf); 192 pipe_buffer_reference(&pbuf, NULL); 193 } 194 } 195 } 196 else 197#endif 198 { 199 xbuf->texture = screen->texture_create(screen, &templ); 200 } 201 202 /* clean up the buffer if allocation failed */ 203 if (!xbuf->texture) 204 ximage_surface_free_buffer(&xsurf->base, which); 205 206 return (xbuf->texture != NULL); 207} 208 209/** 210 * Update the geometry of the surface. Return TRUE if the geometry has changed 211 * since last call. 212 */ 213static boolean 214ximage_surface_update_geometry(struct native_surface *nsurf) 215{ 216 struct ximage_surface *xsurf = ximage_surface(nsurf); 217 Status ok; 218 Window root; 219 int x, y; 220 unsigned int w, h, border, depth; 221 boolean updated = FALSE; 222 223 /* pbuffer has fixed geometry */ 224 if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) 225 return FALSE; 226 227 ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, 228 &root, &x, &y, &w, &h, &border, &depth); 229 if (ok && (xsurf->width != w || xsurf->height != h)) { 230 xsurf->width = w; 231 xsurf->height = h; 232 233 xsurf->server_stamp++; 234 updated = TRUE; 235 } 236 237 return updated; 238} 239 240static void 241ximage_surface_notify_invalid(struct native_surface *nsurf) 242{ 243 struct ximage_surface *xsurf = ximage_surface(nsurf); 244 struct ximage_display *xdpy = xsurf->xdpy; 245 246 xdpy->event_handler->invalid_surface(&xdpy->base, 247 &xsurf->base, xsurf->server_stamp); 248} 249 250/** 251 * Update the buffers of the surface. It is a slow function due to the 252 * round-trip to the server. 253 */ 254static boolean 255ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) 256{ 257 struct ximage_surface *xsurf = ximage_surface(nsurf); 258 boolean updated; 259 uint new_valid; 260 int att; 261 262 updated = ximage_surface_update_geometry(&xsurf->base); 263 if (updated) { 264 /* all buffers become invalid */ 265 xsurf->valid_mask = 0x0; 266 } 267 else { 268 buffer_mask &= ~xsurf->valid_mask; 269 /* all requested buffers are valid */ 270 if (!buffer_mask) { 271 xsurf->client_stamp = xsurf->server_stamp; 272 return TRUE; 273 } 274 } 275 276 new_valid = 0x0; 277 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 278 if (native_attachment_mask_test(buffer_mask, att)) { 279 struct ximage_buffer *xbuf = &xsurf->buffers[att]; 280 281 /* reallocate the texture */ 282 if (!ximage_surface_alloc_buffer(&xsurf->base, att)) 283 break; 284 285 /* update ximage */ 286 if (xbuf->ximage) { 287 xbuf->ximage->width = xsurf->width; 288 xbuf->ximage->height = xsurf->height; 289 } 290 291 new_valid |= (1 << att); 292 if (buffer_mask == new_valid) 293 break; 294 } 295 } 296 297 xsurf->valid_mask |= new_valid; 298 xsurf->client_stamp = xsurf->server_stamp; 299 300 return (new_valid == buffer_mask); 301} 302 303static boolean 304ximage_surface_draw_buffer(struct native_surface *nsurf, 305 enum native_attachment which) 306{ 307 struct ximage_surface *xsurf = ximage_surface(nsurf); 308 struct ximage_buffer *xbuf = &xsurf->buffers[which]; 309 struct pipe_screen *screen = xsurf->xdpy->base.screen; 310 struct pipe_transfer *transfer; 311 312 if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) 313 return TRUE; 314 315 assert(xsurf->drawable && xbuf->ximage && xbuf->texture); 316 317 transfer = screen->get_tex_transfer(screen, xbuf->texture, 318 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); 319 if (!transfer) 320 return FALSE; 321 322 xbuf->ximage->bytes_per_line = transfer->stride; 323 xbuf->ximage->data = screen->transfer_map(screen, transfer); 324 if (!xbuf->ximage->data) { 325 screen->tex_transfer_destroy(transfer); 326 return FALSE; 327 } 328 329 330 if (xbuf->shm_info) 331 XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, 332 xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); 333 else 334 XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, 335 xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); 336 337 xbuf->ximage->data = NULL; 338 screen->transfer_unmap(screen, transfer); 339 340 /* 341 * softpipe allows the pipe transfer to be re-used, but we don't want to 342 * rely on that behavior. 343 */ 344 screen->tex_transfer_destroy(transfer); 345 346 XSync(xsurf->xdpy->dpy, FALSE); 347 348 return TRUE; 349} 350 351static boolean 352ximage_surface_flush_frontbuffer(struct native_surface *nsurf) 353{ 354 struct ximage_surface *xsurf = ximage_surface(nsurf); 355 boolean ret; 356 357 ret = ximage_surface_draw_buffer(&xsurf->base, 358 NATIVE_ATTACHMENT_FRONT_LEFT); 359 /* force buffers to be updated in next validation call */ 360 xsurf->server_stamp++; 361 ximage_surface_notify_invalid(&xsurf->base); 362 363 return ret; 364} 365 366static boolean 367ximage_surface_swap_buffers(struct native_surface *nsurf) 368{ 369 struct ximage_surface *xsurf = ximage_surface(nsurf); 370 struct ximage_buffer *xfront, *xback, xtmp; 371 boolean ret; 372 373 /* display the back buffer first */ 374 ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); 375 /* force buffers to be updated in next validation call */ 376 xsurf->server_stamp++; 377 ximage_surface_notify_invalid(&xsurf->base); 378 379 xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; 380 xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; 381 382 /* skip swapping so that the front buffer is allocated only when needed */ 383 if (!xfront->texture) 384 return ret; 385 386 xtmp = *xfront; 387 *xfront = *xback; 388 *xback = xtmp; 389 390 return ret; 391} 392 393static boolean 394ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, 395 unsigned int *seq_num, struct pipe_texture **textures, 396 int *width, int *height) 397{ 398 struct ximage_surface *xsurf = ximage_surface(nsurf); 399 400 if (xsurf->client_stamp != xsurf->server_stamp || 401 (xsurf->valid_mask & attachment_mask) != attachment_mask) { 402 if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) 403 return FALSE; 404 } 405 406 if (seq_num) 407 *seq_num = xsurf->client_stamp; 408 409 if (textures) { 410 int att; 411 for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { 412 if (native_attachment_mask_test(attachment_mask, att)) { 413 struct ximage_buffer *xbuf = &xsurf->buffers[att]; 414 415 textures[att] = NULL; 416 pipe_texture_reference(&textures[att], xbuf->texture); 417 } 418 } 419 } 420 421 if (width) 422 *width = xsurf->width; 423 if (height) 424 *height = xsurf->height; 425 426 return TRUE; 427} 428 429static void 430ximage_surface_wait(struct native_surface *nsurf) 431{ 432 struct ximage_surface *xsurf = ximage_surface(nsurf); 433 XSync(xsurf->xdpy->dpy, FALSE); 434 /* TODO XGetImage and update the front texture */ 435} 436 437static void 438ximage_surface_destroy(struct native_surface *nsurf) 439{ 440 struct ximage_surface *xsurf = ximage_surface(nsurf); 441 int i; 442 443 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { 444 struct ximage_buffer *xbuf = &xsurf->buffers[i]; 445 ximage_surface_free_buffer(&xsurf->base, i); 446 /* xbuf->shm_info is owned by xbuf->ximage? */ 447 if (xbuf->ximage) { 448 XDestroyImage(xbuf->ximage); 449 xbuf->ximage = NULL; 450 } 451 } 452 453 if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) 454 XFreeGC(xsurf->xdpy->dpy, xsurf->gc); 455 free(xsurf); 456} 457 458static struct ximage_surface * 459ximage_display_create_surface(struct native_display *ndpy, 460 enum ximage_surface_type type, 461 Drawable drawable, 462 const struct native_config *nconf) 463{ 464 struct ximage_display *xdpy = ximage_display(ndpy); 465 struct ximage_config *xconf = ximage_config(nconf); 466 struct ximage_surface *xsurf; 467 int i; 468 469 xsurf = CALLOC_STRUCT(ximage_surface); 470 if (!xsurf) 471 return NULL; 472 473 xsurf->xdpy = xdpy; 474 xsurf->type = type; 475 xsurf->color_format = xconf->base.color_format; 476 xsurf->drawable = drawable; 477 478 if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { 479 xsurf->drawable = drawable; 480 xsurf->visual = *xconf->visual; 481 482 xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); 483 if (!xsurf->gc) { 484 free(xsurf); 485 return NULL; 486 } 487 488 /* initialize the geometry */ 489 ximage_surface_update_buffers(&xsurf->base, 0x0); 490 491 for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { 492 struct ximage_buffer *xbuf = &xsurf->buffers[i]; 493 494 if (xdpy->use_xshm) { 495 xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); 496 if (xbuf->shm_info) { 497 /* initialize shm info */ 498 xbuf->shm_info->shmid = -1; 499 xbuf->shm_info->shmaddr = (void *) -1; 500 xbuf->shm_info->readOnly = TRUE; 501 502 xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, 503 xsurf->visual.visual, 504 xsurf->visual.depth, 505 ZPixmap, NULL, 506 xbuf->shm_info, 507 0, 0); 508 } 509 } 510 else { 511 xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, 512 xsurf->visual.visual, 513 xsurf->visual.depth, 514 ZPixmap, 0, /* format, offset */ 515 NULL, /* data */ 516 0, 0, /* size */ 517 8, /* bitmap_pad */ 518 0); /* bytes_per_line */ 519 } 520 521 if (!xbuf->ximage) { 522 XFreeGC(xdpy->dpy, xsurf->gc); 523 free(xsurf); 524 return NULL; 525 } 526 } 527 } 528 529 xsurf->base.destroy = ximage_surface_destroy; 530 xsurf->base.swap_buffers = ximage_surface_swap_buffers; 531 xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer; 532 xsurf->base.validate = ximage_surface_validate; 533 xsurf->base.wait = ximage_surface_wait; 534 535 return xsurf; 536} 537 538static struct native_surface * 539ximage_display_create_window_surface(struct native_display *ndpy, 540 EGLNativeWindowType win, 541 const struct native_config *nconf) 542{ 543 struct ximage_surface *xsurf; 544 545 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_WINDOW, 546 (Drawable) win, nconf); 547 return (xsurf) ? &xsurf->base : NULL; 548} 549 550static struct native_surface * 551ximage_display_create_pixmap_surface(struct native_display *ndpy, 552 EGLNativePixmapType pix, 553 const struct native_config *nconf) 554{ 555 struct ximage_surface *xsurf; 556 557 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PIXMAP, 558 (Drawable) pix, nconf); 559 return (xsurf) ? &xsurf->base : NULL; 560} 561 562static struct native_surface * 563ximage_display_create_pbuffer_surface(struct native_display *ndpy, 564 const struct native_config *nconf, 565 uint width, uint height) 566{ 567 struct ximage_surface *xsurf; 568 569 xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER, 570 (Drawable) None, nconf); 571 if (xsurf) { 572 xsurf->width = width; 573 xsurf->height = height; 574 } 575 return (xsurf) ? &xsurf->base : NULL; 576} 577 578static enum pipe_format 579choose_format(const XVisualInfo *vinfo) 580{ 581 enum pipe_format fmt; 582 /* TODO elaborate the formats */ 583 switch (vinfo->depth) { 584 case 32: 585 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 586 break; 587 case 24: 588 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 589 break; 590 case 16: 591 fmt = PIPE_FORMAT_B5G6R5_UNORM; 592 break; 593 default: 594 fmt = PIPE_FORMAT_NONE; 595 break; 596 } 597 598 return fmt; 599} 600 601static const struct native_config ** 602ximage_display_get_configs(struct native_display *ndpy, int *num_configs) 603{ 604 struct ximage_display *xdpy = ximage_display(ndpy); 605 const struct native_config **configs; 606 int i; 607 608 /* first time */ 609 if (!xdpy->configs) { 610 const XVisualInfo *visuals; 611 int num_visuals, count, j; 612 613 visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); 614 if (!visuals) 615 return NULL; 616 617 /* 618 * Create two configs for each visual. 619 * One with depth/stencil buffer; one without 620 */ 621 xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs)); 622 if (!xdpy->configs) 623 return NULL; 624 625 count = 0; 626 for (i = 0; i < num_visuals; i++) { 627 for (j = 0; j < 2; j++) { 628 struct ximage_config *xconf = &xdpy->configs[count]; 629 __GLcontextModes *mode = &xconf->base.mode; 630 631 xconf->visual = &visuals[i]; 632 xconf->base.color_format = choose_format(xconf->visual); 633 if (xconf->base.color_format == PIPE_FORMAT_NONE) 634 continue; 635 636 x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode); 637 /* support double buffer mode */ 638 mode->doubleBufferMode = TRUE; 639 640 xconf->base.depth_format = PIPE_FORMAT_NONE; 641 xconf->base.stencil_format = PIPE_FORMAT_NONE; 642 /* create the second config with depth/stencil buffer */ 643 if (j == 1) { 644 xconf->base.depth_format = PIPE_FORMAT_Z24S8_UNORM; 645 xconf->base.stencil_format = PIPE_FORMAT_Z24S8_UNORM; 646 mode->depthBits = 24; 647 mode->stencilBits = 8; 648 mode->haveDepthBuffer = TRUE; 649 mode->haveStencilBuffer = TRUE; 650 } 651 652 mode->maxPbufferWidth = 4096; 653 mode->maxPbufferHeight = 4096; 654 mode->maxPbufferPixels = 4096 * 4096; 655 mode->drawableType = 656 GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 657 mode->swapMethod = GLX_SWAP_EXCHANGE_OML; 658 659 if (mode->alphaBits) 660 mode->bindToTextureRgba = TRUE; 661 else 662 mode->bindToTextureRgb = TRUE; 663 664 count++; 665 } 666 } 667 668 xdpy->num_configs = count; 669 } 670 671 configs = malloc(xdpy->num_configs * sizeof(*configs)); 672 if (configs) { 673 for (i = 0; i < xdpy->num_configs; i++) 674 configs[i] = (const struct native_config *) &xdpy->configs[i]; 675 if (num_configs) 676 *num_configs = xdpy->num_configs; 677 } 678 return configs; 679} 680 681static boolean 682ximage_display_is_pixmap_supported(struct native_display *ndpy, 683 EGLNativePixmapType pix, 684 const struct native_config *nconf) 685{ 686 struct ximage_display *xdpy = ximage_display(ndpy); 687 enum pipe_format fmt; 688 uint depth; 689 690 depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); 691 switch (depth) { 692 case 32: 693 fmt = PIPE_FORMAT_B8G8R8A8_UNORM; 694 break; 695 case 24: 696 fmt = PIPE_FORMAT_B8G8R8X8_UNORM; 697 break; 698 case 16: 699 fmt = PIPE_FORMAT_B5G6R5_UNORM; 700 break; 701 default: 702 fmt = PIPE_FORMAT_NONE; 703 break; 704 } 705 706 return (fmt == nconf->color_format); 707} 708 709static int 710ximage_display_get_param(struct native_display *ndpy, 711 enum native_param_type param) 712{ 713 int val; 714 715 switch (param) { 716 case NATIVE_PARAM_USE_NATIVE_BUFFER: 717 /* private buffers are allocated */ 718 val = FALSE; 719 break; 720 default: 721 val = 0; 722 break; 723 } 724 725 return val; 726} 727 728static void 729ximage_display_destroy(struct native_display *ndpy) 730{ 731 struct ximage_display *xdpy = ximage_display(ndpy); 732 733 if (xdpy->configs) 734 free(xdpy->configs); 735 736 xdpy->base.screen->destroy(xdpy->base.screen); 737 free(xdpy->winsys); 738 739 x11_screen_destroy(xdpy->xscr); 740 if (xdpy->own_dpy) 741 XCloseDisplay(xdpy->dpy); 742 free(xdpy); 743} 744 745struct native_display * 746x11_create_ximage_display(EGLNativeDisplayType dpy, 747 struct native_event_handler *event_handler, 748 boolean use_xshm) 749{ 750 struct ximage_display *xdpy; 751 752 xdpy = CALLOC_STRUCT(ximage_display); 753 if (!xdpy) 754 return NULL; 755 756 xdpy->dpy = dpy; 757 if (!xdpy->dpy) { 758 xdpy->dpy = XOpenDisplay(NULL); 759 if (!xdpy->dpy) { 760 free(xdpy); 761 return NULL; 762 } 763 xdpy->own_dpy = TRUE; 764 } 765 766 xdpy->xscr_number = DefaultScreen(xdpy->dpy); 767 xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); 768 if (!xdpy->xscr) { 769 free(xdpy); 770 return NULL; 771 } 772 773 xdpy->event_handler = event_handler; 774 775 xdpy->use_xshm = 776 (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); 777 778 xdpy->winsys = create_sw_winsys(); 779 xdpy->base.screen = softpipe_create_screen(xdpy->winsys); 780 781 xdpy->base.destroy = ximage_display_destroy; 782 xdpy->base.get_param = ximage_display_get_param; 783 784 xdpy->base.get_configs = ximage_display_get_configs; 785 xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; 786 xdpy->base.create_window_surface = ximage_display_create_window_surface; 787 xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; 788 xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface; 789 790 return &xdpy->base; 791} 792