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