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