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