http://www.jwz.org/xscreensaver/xscreensaver-5.13.tar.gz
[xscreensaver] / driver / xdpyinfo.c
1 /*
2  * $ TOG: xdpyinfo.c /main/35 1998/02/09 13:57:05 kaleb $
3  * 
4  * xdpyinfo - print information about X display connecton
5  *
6  * 
7 Copyright 1988, 1998  The Open Group
8
9 All Rights Reserved.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24  *
25  * Author:  Jim Fulton, MIT X Consortium
26  *
27  * GLX and Overlay support added by Jamie Zawinski <jwz@jwz.org>, 11-Nov-99
28  *
29  *      To compile:
30  *         cc -DHAVE_GLX xdpyinfo.c -o xdpyinfo -lGL -lX11 -lXext [-lXtst] -lm
31  *
32  *      Other defines to consider:
33  *         -DMITSHM -DHAVE_XDBE -DHAVE_XIE -DHAVE_XTEST -DHAVE_SYNC
34  *         -DHAVE_XRECORD
35  */
36
37 #include <X11/Xlib.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xproto.h> /* for CARD32 */
40 #include <X11/extensions/multibuf.h>
41 #ifdef HAVE_XIE
42 #include <X11/extensions/XIElib.h>
43 #endif /* HAVE_XIE */
44 #ifdef HAVE_XTEST
45 #include <X11/extensions/XTest.h>
46 #endif /* HAVE_XTEST */
47 #ifdef HAVE_XSYNC
48 #include <X11/extensions/sync.h>
49 #endif /* HAVE_XSYNC */
50 #ifdef HAVE_XDBE
51 #include <X11/extensions/Xdbe.h>
52 #endif /* HAVE_XDBE */
53 #ifdef HAVE_XRECORD
54 #include <X11/extensions/record.h>
55 #endif /* HAVE_XRECORD */
56 #ifdef MITSHM
57 #include <X11/extensions/XShm.h>
58 #endif
59 #include <X11/Xos.h>
60 #include <stdio.h>
61
62 #ifdef HAVE_GLX
63 # include <GL/gl.h>
64 # include <GL/glx.h>
65 #endif /* HAVE_GLX */
66
67 #define HAVE_OVERLAY /* jwz: no compile-time deps, so do this all the time */
68
69 char *ProgramName;
70 Bool queryExtensions = False;
71
72 static int StrCmp(a, b)
73     char **a, **b;
74 {
75     return strcmp(*a, *b);
76 }
77
78
79 #ifdef HAVE_GLX  /* Added by jwz, 11-Nov-99 */
80
81 static void
82 print_glx_versions (dpy)
83     Display *dpy;
84 {
85   /* Note: with Mesa 3.0, this lies: it prints the info from the
86      client's GL library, rather than the info from the GLX server.
87
88      Note also that we can't protect these calls by only doing
89      them when the GLX extension is present, because with Mesa,
90      the server doesn't have that extension (but the GL library
91      works anyway.)
92    */
93       int scr = DefaultScreen (dpy);
94       const char *vend, *vers;
95       vend = glXQueryServerString (dpy, scr, GLX_VENDOR);
96       if (!vend) return;
97       vers = glXQueryServerString (dpy, scr, GLX_VERSION);
98       printf ("GLX vendor:    %s (%s)\n",
99               vend, (vers ? vers : "unknown version"));
100 }
101
102 static void
103 print_glx_visual_info (dpy, vip)
104     Display *dpy;
105     XVisualInfo *vip;
106 {
107   int status, value = False;
108
109   status = glXGetConfig (dpy, vip, GLX_USE_GL, &value);
110   if (status == GLX_NO_EXTENSION)
111     /* dpy does not support the GLX extension. */
112     return;
113
114   if (status == GLX_BAD_VISUAL || value == False)
115     {
116       printf ("    GLX supported:     no\n");
117       return;
118     }
119   else
120     {
121       printf ("    GLX supported:     yes\n");
122     }
123     
124   if (!glXGetConfig (dpy, vip, GLX_LEVEL, &value) &&
125       value != 0)
126     printf ("    GLX level:         %d\n", value);
127
128   if (!glXGetConfig (dpy, vip, GLX_RGBA, &value) && value)
129     {
130       int r=0, g=0, b=0, a=0;
131       glXGetConfig (dpy, vip, GLX_RED_SIZE,   &r);
132       glXGetConfig (dpy, vip, GLX_GREEN_SIZE, &g);
133       glXGetConfig (dpy, vip, GLX_BLUE_SIZE,  &b);
134       glXGetConfig (dpy, vip, GLX_ALPHA_SIZE, &a);
135       printf ("    GLX type:          RGBA (%2d, %2d, %2d, %2d)\n",
136               r, g, b, a);
137
138       r=0, g=0, b=0, a=0;
139       glXGetConfig (dpy, vip, GLX_ACCUM_RED_SIZE,   &r);
140       glXGetConfig (dpy, vip, GLX_ACCUM_GREEN_SIZE, &g);
141       glXGetConfig (dpy, vip, GLX_ACCUM_BLUE_SIZE,  &b);
142       glXGetConfig (dpy, vip, GLX_ACCUM_ALPHA_SIZE, &a);
143       printf ("    GLX accum:         RGBA (%2d, %2d, %2d, %2d)\n",
144               r, g, b, a);
145     }
146   else
147     {
148       value = 0;
149       glXGetConfig (dpy, vip, GLX_BUFFER_SIZE, &value);
150       printf ("    GLX type:          indexed (%d)\n", value);
151     }
152
153 # if 0  /* redundant */
154   if (!glXGetConfig (dpy, vip, GLX_X_VISUAL_TYPE_EXT, &value))
155       printf ("    GLX class:         %s\n",
156               (value == GLX_TRUE_COLOR_EXT ? "TrueColor" :
157                value == GLX_DIRECT_COLOR_EXT ? "DirectColor" :
158                value == GLX_PSEUDO_COLOR_EXT ? "PseudoColor" :
159                value == GLX_STATIC_COLOR_EXT ? "StaticColor" :
160                value == GLX_GRAY_SCALE_EXT ? "Grayscale" :
161                value == GLX_STATIC_GRAY_EXT ? "StaticGray" : "???"));
162 # endif
163
164 # ifdef GLX_VISUAL_CAVEAT_EXT
165   if (!glXGetConfig (dpy, vip, GLX_VISUAL_CAVEAT_EXT, &value) &&
166       value != GLX_NONE_EXT)
167     printf ("    GLX rating:        %s\n",
168             (value == GLX_NONE_EXT ? "none" :
169              value == GLX_SLOW_VISUAL_EXT ? "slow" :
170 #   ifdef GLX_NON_CONFORMANT_EXT
171              value == GLX_NON_CONFORMANT_EXT ? "non-conformant" :
172 #   endif
173              "???"));
174 # endif
175
176   if (!glXGetConfig (dpy, vip, GLX_DOUBLEBUFFER, &value))
177     printf ("    GLX double-buffer: %s\n", (value ? "yes" : "no"));
178
179   if (!glXGetConfig (dpy, vip, GLX_STEREO, &value) &&
180       value)
181     printf ("    GLX stereo:        %s\n", (value ? "yes" : "no"));
182
183   if (!glXGetConfig (dpy, vip, GLX_AUX_BUFFERS, &value) &&
184       value != 0)
185     printf ("    GLX aux buffers:   %d\n", value);
186
187   if (!glXGetConfig (dpy, vip, GLX_DEPTH_SIZE, &value))
188     printf ("    GLX depth size:    %d\n", value);
189
190   if (!glXGetConfig (dpy, vip, GLX_STENCIL_SIZE, &value) &&
191       value != 0)
192     printf ("    GLX stencil size:  %d\n", value);
193
194 # if defined(GL_SAMPLE_BUFFERS)
195 #  define SB GL_SAMPLE_BUFFERS
196 #  define SM GL_SAMPLES
197 # elif defined(GLX_SAMPLE_BUFFERS)
198 #  define SB GLX_SAMPLE_BUFFERS
199 #  define SM GLX_SAMPLES
200 # elif defined(GLX_SAMPLE_BUFFERS_ARB)
201 #  define SB GLX_SAMPLE_BUFFERS_ARB
202 #  define SM GLX_SAMPLES_ARB
203 # elif defined(GLX_SAMPLE_BUFFERS_SGIS)
204 #  define SB GLX_SAMPLE_BUFFERS_SGIS
205 #  define SM GLX_SAMPLES_SGIS
206 # endif
207
208 # ifdef SB
209   if (!glXGetConfig (dpy, vip, SB, &value) && value != 0)
210     {
211       int bufs = value;
212       if (!glXGetConfig (dpy, vip, SM, &value))
213         printf ("    GLX multisample:   %d, %d\n", bufs, value);
214     }
215 # endif /* SB */
216
217   if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_TYPE_EXT, &value) &&
218       value != GLX_NONE_EXT)
219     {
220       if (value == GLX_NONE_EXT)
221         printf ("    GLX transparency:  none\n");
222       else if (value == GLX_TRANSPARENT_INDEX_EXT)
223         {
224           if (!glXGetConfig (dpy, vip, GLX_TRANSPARENT_INDEX_VALUE_EXT,&value))
225             printf ("    GLX transparency:  indexed (%d)\n", value);
226         }
227       else if (value == GLX_TRANSPARENT_RGB_EXT)
228         {
229           int r=0, g=0, b=0, a=0;
230           glXGetConfig (dpy, vip, GLX_TRANSPARENT_RED_VALUE_EXT,   &r);
231           glXGetConfig (dpy, vip, GLX_TRANSPARENT_GREEN_VALUE_EXT, &g);
232           glXGetConfig (dpy, vip, GLX_TRANSPARENT_BLUE_VALUE_EXT,  &b);
233           glXGetConfig (dpy, vip, GLX_TRANSPARENT_ALPHA_VALUE_EXT, &a);
234           printf ("    GLX transparency:  RGBA (%2d, %2d, %2d, %2d)\n",
235                   r, g, b, a);
236         }
237     }
238 }
239 #endif /* HAVE_GLX */
240
241
242 #ifdef HAVE_OVERLAY  /* Added by jwz, 11-Nov-99 */
243
244  /* If the server's root window contains a SERVER_OVERLAY_VISUALS property,
245     then that identifies the visuals which correspond to the video hardware's
246     overlay planes.  Windows created in these kinds of visuals may have
247     transparent pixels that let other layers shine through.
248
249     This might not be an X Consortium standard, but it turns out that
250     SGI, HP, DEC, and IBM all use this same mechanism.  So that's close
251     enough for me.
252
253     Documentation on the SERVER_OVERLAY_VISUALS property can be found at:
254     http://www.hp.com/xwindow/sharedInfo/Whitepapers/Visuals/server_overlay_visuals.html
255   */
256
257 struct overlay
258 {
259   CARD32 visual_id;
260   CARD32 transparency;  /* 0: none; 1: pixel; 2: mask */
261   CARD32 value;         /* the transparent pixel */
262   CARD32 layer;         /* -1: underlay; 0: normal; 1: popup; 2: overlay */
263 };
264
265 struct overlay_list
266 {
267   int count;
268   struct overlay *list;
269 };
270
271 static struct overlay_list *overlays = 0;
272
273 static void
274 find_overlay_info (dpy)
275   Display *dpy;
276 {
277   int screen;
278   Atom OVERLAY = XInternAtom (dpy, "SERVER_OVERLAY_VISUALS", False);
279
280   overlays = (struct overlay_list *) calloc (sizeof (struct overlay_list),
281                                              ScreenCount (dpy));
282
283   for (screen = 0; screen < ScreenCount (dpy); screen++)
284     {
285       Window window = RootWindow (dpy, screen);
286       Atom actual_type;
287       int actual_format;
288       unsigned long nitems, bytes_after;
289       struct overlay *data = 0;
290       int result = XGetWindowProperty (dpy, window, OVERLAY,
291                                        0, (65536 / sizeof (long)), False, 
292                                        OVERLAY, &actual_type, &actual_format,
293                                        &nitems, &bytes_after,
294                                        (unsigned char **) &data);
295       if (result == Success &&
296           actual_type == OVERLAY &&
297           actual_format == 32 &&
298           nitems > 0)
299         {
300           overlays[screen].count = (nitems /
301                                     (sizeof(struct overlay) / sizeof(CARD32)));
302           overlays[screen].list = data;
303         }
304       else if (data)
305         XFree((char *) data);
306     }
307 }
308
309 static void
310 print_overlay_visual_info (vip)
311     XVisualInfo *vip;
312 {
313   int i;
314   int vis = vip->visualid;
315   int scr = vip->screen;
316   if (!overlays) return;
317   for (i = 0; i < overlays[scr].count; i++)
318     if (vis == overlays[scr].list[i].visual_id)
319       {
320         struct overlay *ov = &overlays[scr].list[i];
321         printf ("    Overlay info:      layer %ld (%s), ",
322                 (long) ov->layer,
323                 (ov->layer == -1 ? "underlay" :
324                  ov->layer ==  0 ? "normal" :
325                  ov->layer ==  1 ? "popup" :
326                  ov->layer ==  2 ? "overlay" : "???"));
327         if (ov->transparency == 1)
328           printf ("transparent pixel %lu\n", (unsigned long) ov->value);
329         else if (ov->transparency == 2)
330           printf ("transparent mask 0x%x\n", (unsigned long) ov->value);
331         else
332           printf ("opaque\n");
333       }
334 }
335 #endif /* HAVE_OVERLAY */
336
337
338 void
339 print_extension_info (dpy)
340     Display *dpy;
341 {
342     int n = 0;
343     char **extlist = XListExtensions (dpy, &n);
344
345     printf ("number of extensions:    %d\n", n);
346
347     if (extlist) {
348         register int i;
349         int opcode, event, error;
350
351         qsort(extlist, n, sizeof(char *), StrCmp);
352         for (i = 0; i < n; i++) {
353             if (!queryExtensions) {
354                 printf ("    %s\n", extlist[i]);
355                 continue;
356             }
357             XQueryExtension(dpy, extlist[i], &opcode, &event, &error);
358             printf ("    %s  (opcode: %d", extlist[i], opcode);
359             if (event)
360                 printf (", base event: %d", event);
361             if (error)
362                 printf (", base error: %d", error);
363             printf(")\n");
364         }
365         /* do not free, Xlib can depend on contents being unaltered */
366         /* XFreeExtensionList (extlist); */
367     }
368 }
369
370 void
371 print_display_info (dpy)
372     Display *dpy;
373 {
374     char dummybuf[40];
375     char *cp;
376     int minkeycode, maxkeycode;
377     int i, n;
378     long req_size;
379     XPixmapFormatValues *pmf;
380     Window focuswin;
381     int focusrevert;
382
383     printf ("name of display:    %s\n", DisplayString (dpy));
384     printf ("version number:    %d.%d\n",
385             ProtocolVersion (dpy), ProtocolRevision (dpy));
386     printf ("vendor string:    %s\n", ServerVendor (dpy));
387     printf ("vendor release number:    %d\n", VendorRelease (dpy));
388
389 #ifdef HAVE_GLX
390     print_glx_versions (dpy);
391 #endif /* HAVE_GLX */
392
393     req_size = XExtendedMaxRequestSize (dpy);
394     if (!req_size) req_size = XMaxRequestSize (dpy);
395     printf ("maximum request size:  %ld bytes\n", req_size * 4);
396     printf ("motion buffer size:  %d\n", XDisplayMotionBufferSize (dpy));
397
398     switch (BitmapBitOrder (dpy)) {
399       case LSBFirst:    cp = "LSBFirst"; break;
400       case MSBFirst:    cp = "MSBFirst"; break;
401       default:    
402         sprintf (dummybuf, "unknown order %d", BitmapBitOrder (dpy));
403         cp = dummybuf;
404         break;
405     }
406     printf ("bitmap unit, bit order, padding:    %d, %s, %d\n",
407             BitmapUnit (dpy), cp, BitmapPad (dpy));
408
409     switch (ImageByteOrder (dpy)) {
410       case LSBFirst:    cp = "LSBFirst"; break;
411       case MSBFirst:    cp = "MSBFirst"; break;
412       default:    
413         sprintf (dummybuf, "unknown order %d", ImageByteOrder (dpy));
414         cp = dummybuf;
415         break;
416     }
417     printf ("image byte order:    %s\n", cp);
418
419     pmf = XListPixmapFormats (dpy, &n);
420     printf ("number of supported pixmap formats:    %d\n", n);
421     if (pmf) {
422         printf ("supported pixmap formats:\n");
423         for (i = 0; i < n; i++) {
424             printf ("    depth %d, bits_per_pixel %d, scanline_pad %d\n",
425                     pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad);
426         }
427         XFree ((char *) pmf);
428     }
429
430
431     /*
432      * when we get interfaces to the PixmapFormat stuff, insert code here
433      */
434
435     XDisplayKeycodes (dpy, &minkeycode, &maxkeycode);
436     printf ("keycode range:    minimum %d, maximum %d\n",
437             minkeycode, maxkeycode);
438
439     XGetInputFocus (dpy, &focuswin, &focusrevert);
440     printf ("focus:  ");
441     switch (focuswin) {
442       case PointerRoot:
443         printf ("PointerRoot\n");
444         break;
445       case None:
446         printf ("None\n");
447         break;
448       default:
449         printf("window 0x%lx, revert to ", focuswin);
450         switch (focusrevert) {
451           case RevertToParent:
452             printf ("Parent\n");
453             break;
454           case RevertToNone:
455             printf ("None\n");
456             break;
457           case RevertToPointerRoot:
458             printf ("PointerRoot\n");
459             break;
460           default:                      /* should not happen */
461             printf ("%d\n", focusrevert);
462             break;
463         }
464         break;
465     }
466
467     print_extension_info (dpy);
468
469     printf ("default screen number:    %d\n", DefaultScreen (dpy));
470     printf ("number of screens:    %d\n", ScreenCount (dpy));
471 }
472
473 void
474 print_visual_info (vip)
475     XVisualInfo *vip;
476 {
477     char errorbuf[40];                  /* for sprintfing into */
478     char *class = NULL;                 /* for printing */
479
480     switch (vip->class) {
481       case StaticGray:    class = "StaticGray"; break;
482       case GrayScale:    class = "GrayScale"; break;
483       case StaticColor:    class = "StaticColor"; break;
484       case PseudoColor:    class = "PseudoColor"; break;
485       case TrueColor:    class = "TrueColor"; break;
486       case DirectColor:    class = "DirectColor"; break;
487       default:    
488         sprintf (errorbuf, "unknown class %d", vip->class);
489         class = errorbuf;
490         break;
491     }
492
493     printf ("  visual:\n");
494     printf ("    visual id:    0x%lx\n", vip->visualid);
495     printf ("    class:    %s\n", class);
496     printf ("    depth:    %d plane%s\n", vip->depth, 
497             vip->depth == 1 ? "" : "s");
498     if (vip->class == TrueColor || vip->class == DirectColor)
499         printf ("    available colormap entries:    %d per subfield\n",
500                 vip->colormap_size);
501     else
502         printf ("    available colormap entries:    %d\n",
503                 vip->colormap_size);
504     printf ("    red, green, blue masks:    0x%lx, 0x%lx, 0x%lx\n",
505             vip->red_mask, vip->green_mask, vip->blue_mask);
506     printf ("    significant bits in color specification:    %d bits\n",
507             vip->bits_per_rgb);
508 }
509
510 void
511 print_screen_info (dpy, scr)
512     Display *dpy;
513     int scr;
514 {
515     Screen *s = ScreenOfDisplay (dpy, scr);  /* opaque structure */
516     XVisualInfo viproto;                /* fill in for getting info */
517     XVisualInfo *vip;                   /* retured info */
518     int nvi;                            /* number of elements returned */
519     int i;                              /* temp variable: iterator */
520     char eventbuf[80];                  /* want 79 chars per line + nul */
521     static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED";
522     double xres, yres;
523     int ndepths = 0, *depths = NULL;
524     unsigned int width, height;
525
526
527     /*
528      * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
529      *
530      *     dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch))
531      *         = N pixels / (M inch / 25.4)
532      *         = N * 25.4 pixels / M inch
533      */
534
535     xres = ((((double) DisplayWidth(dpy,scr)) * 25.4) / 
536             ((double) DisplayWidthMM(dpy,scr)));
537     yres = ((((double) DisplayHeight(dpy,scr)) * 25.4) / 
538             ((double) DisplayHeightMM(dpy,scr)));
539
540     printf ("\n");
541     printf ("screen #%d:\n", scr);
542     printf ("  dimensions:    %dx%d pixels (%dx%d millimeters)\n",
543             DisplayWidth (dpy, scr), DisplayHeight (dpy, scr),
544             DisplayWidthMM(dpy, scr), DisplayHeightMM (dpy, scr));
545     printf ("  resolution:    %dx%d dots per inch\n", 
546             (int) (xres + 0.5), (int) (yres + 0.5));
547     depths = XListDepths (dpy, scr, &ndepths);
548     if (!depths) ndepths = 0;
549     printf ("  depths (%d):    ", ndepths);
550     for (i = 0; i < ndepths; i++) {
551         printf ("%d", depths[i]);
552         if (i < ndepths - 1) { 
553             putchar (',');
554             putchar (' ');
555         }
556     }
557     putchar ('\n');
558     if (depths) XFree ((char *) depths);
559     printf ("  root window id:    0x%lx\n", RootWindow (dpy, scr));
560     printf ("  depth of root window:    %d plane%s\n",
561             DisplayPlanes (dpy, scr),
562             DisplayPlanes (dpy, scr) == 1 ? "" : "s");
563     printf ("  number of colormaps:    minimum %d, maximum %d\n",
564             MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
565     printf ("  default colormap:    0x%lx\n", DefaultColormap (dpy, scr));
566     printf ("  default number of colormap cells:    %d\n",
567             DisplayCells (dpy, scr));
568     printf ("  preallocated pixels:    black %d, white %d\n",
569             BlackPixel (dpy, scr), WhitePixel (dpy, scr));
570     printf ("  options:    backing-store %s, save-unders %s\n",
571             (DoesBackingStore (s) == NotUseful) ? no :
572             ((DoesBackingStore (s) == Always) ? yes : when),
573             DoesSaveUnders (s) ? yes : no);
574     XQueryBestSize (dpy, CursorShape, RootWindow (dpy, scr), 65535, 65535,
575                     &width, &height);
576     if (width == 65535 && height == 65535)
577         printf ("  largest cursor:    unlimited\n");
578     else
579         printf ("  largest cursor:    %dx%d\n", width, height);
580     printf ("  current input event mask:    0x%lx\n", EventMaskOfScreen (s));
581     (void) print_event_mask (eventbuf, 79, 4, EventMaskOfScreen (s));
582                       
583
584     nvi = 0;
585     viproto.screen = scr;
586     vip = XGetVisualInfo (dpy, VisualScreenMask, &viproto, &nvi);
587     printf ("  number of visuals:    %d\n", nvi);
588     printf ("  default visual id:  0x%lx\n", 
589             XVisualIDFromVisual (DefaultVisual (dpy, scr)));
590     for (i = 0; i < nvi; i++) {
591         print_visual_info (vip+i);
592 #ifdef HAVE_OVERLAY
593         print_overlay_visual_info (vip+i);
594 #endif /* HAVE_OVERLAY */
595 #ifdef HAVE_GLX
596         print_glx_visual_info (dpy, vip+i);
597 #endif /* HAVE_GLX */
598     }
599     if (vip) XFree ((char *) vip);
600 }
601
602 /*
603  * The following routine prints out an event mask, wrapping events at nice
604  * boundaries.
605  */
606
607 #define MASK_NAME_WIDTH 25
608
609 static struct _event_table {
610     char *name;
611     long value;
612 } event_table[] = {
613     { "KeyPressMask             ", KeyPressMask },
614     { "KeyReleaseMask           ", KeyReleaseMask },
615     { "ButtonPressMask          ", ButtonPressMask },
616     { "ButtonReleaseMask        ", ButtonReleaseMask },
617     { "EnterWindowMask          ", EnterWindowMask },
618     { "LeaveWindowMask          ", LeaveWindowMask },
619     { "PointerMotionMask        ", PointerMotionMask },
620     { "PointerMotionHintMask    ", PointerMotionHintMask },
621     { "Button1MotionMask        ", Button1MotionMask },
622     { "Button2MotionMask        ", Button2MotionMask },
623     { "Button3MotionMask        ", Button3MotionMask },
624     { "Button4MotionMask        ", Button4MotionMask },
625     { "Button5MotionMask        ", Button5MotionMask },
626     { "ButtonMotionMask         ", ButtonMotionMask },
627     { "KeymapStateMask          ", KeymapStateMask },
628     { "ExposureMask             ", ExposureMask },
629     { "VisibilityChangeMask     ", VisibilityChangeMask },
630     { "StructureNotifyMask      ", StructureNotifyMask },
631     { "ResizeRedirectMask       ", ResizeRedirectMask },
632     { "SubstructureNotifyMask   ", SubstructureNotifyMask },
633     { "SubstructureRedirectMask ", SubstructureRedirectMask },
634     { "FocusChangeMask          ", FocusChangeMask },
635     { "PropertyChangeMask       ", PropertyChangeMask },
636     { "ColormapChangeMask       ", ColormapChangeMask },
637     { "OwnerGrabButtonMask      ", OwnerGrabButtonMask },
638     { NULL, 0 }};
639
640 int print_event_mask (buf, lastcol, indent, mask)
641     char *buf;                          /* string to write into */
642     int lastcol;                        /* strlen(buf)+1 */
643     int indent;                         /* amount by which to indent */
644     long mask;                          /* event mask */
645 {
646     struct _event_table *etp;
647     int len;
648     int bitsfound = 0;
649
650     buf[0] = buf[lastcol] = '\0';       /* just in case */
651
652 #define INDENT() { register int i; len = indent; \
653                    for (i = 0; i < indent; i++) buf[i] = ' '; }
654
655     INDENT ();
656
657     for (etp = event_table; etp->name; etp++) {
658         if (mask & etp->value) {
659             if (len + MASK_NAME_WIDTH > lastcol) {
660                 puts (buf);
661                 INDENT ();
662             }
663             strcpy (buf+len, etp->name);
664             len += MASK_NAME_WIDTH;
665             bitsfound++;
666         }
667     }
668
669     if (bitsfound) puts (buf);
670
671 #undef INDENT
672
673     return (bitsfound);
674 }
675
676 void
677 print_standard_extension_info(dpy, extname, majorrev, minorrev)
678     Display *dpy;
679     char *extname;
680     int majorrev, minorrev;
681 {
682     int opcode, event, error;
683
684     printf("%s version %d.%d ", extname, majorrev, minorrev);
685
686     XQueryExtension(dpy, extname, &opcode, &event, &error);
687     printf ("opcode: %d", opcode);
688     if (event)
689         printf (", base event: %d", event);
690     if (error)
691         printf (", base error: %d", error);
692     printf("\n");
693 }
694
695 int
696 print_multibuf_info(dpy, extname)
697     Display *dpy;
698     char *extname;
699 {
700     int i, j;                   /* temp variable: iterator */
701     int nmono, nstereo;         /* count */
702     XmbufBufferInfo *mono_info = NULL, *stereo_info = NULL; /* arrays */
703     static char *fmt = 
704         "    visual id, max buffers, depth:    0x%lx, %d, %d\n";
705     int scr = 0;
706     int majorrev, minorrev;
707
708     if (!XmbufGetVersion(dpy, &majorrev, &minorrev))
709         return 0;
710
711     print_standard_extension_info(dpy, extname, majorrev, minorrev);
712
713     for (i = 0; i < ScreenCount (dpy); i++)
714     {
715         if (!XmbufGetScreenInfo (dpy, RootWindow(dpy, scr), &nmono, &mono_info,
716                                  &nstereo, &stereo_info)) {
717             fprintf (stderr,
718                      "%s:  unable to get multibuffer info for screen %d\n",
719                      ProgramName, scr);
720         } else {
721             printf ("  screen %d number of mono multibuffer types:    %d\n", i, nmono);
722             for (j = 0; j < nmono; j++) {
723                 printf (fmt, mono_info[j].visualid, mono_info[j].max_buffers,
724                         mono_info[j].depth);
725             }
726             printf ("  number of stereo multibuffer types:    %d\n", nstereo);
727             for (j = 0; j < nstereo; j++) {
728                 printf (fmt, stereo_info[j].visualid,
729                         stereo_info[j].max_buffers, stereo_info[j].depth);
730             }
731             if (mono_info) XFree ((char *) mono_info);
732             if (stereo_info) XFree ((char *) stereo_info);
733         }
734     }
735     return 1;
736 } /* end print_multibuf_info */
737
738
739 /* XIE stuff */
740
741 #ifdef HAVE_XIE
742
743 char *subset_names[] = { NULL, "FULL", "DIS" };
744 char *align_names[] = { NULL, "Alignable", "Arbitrary" };
745 char *group_names[] = { /* 0  */ "Default",
746                             /* 2  */ "ColorAlloc",
747                             /* 4  */ "Constrain",
748                             /* 6  */ "ConvertFromRGB",
749                             /* 8  */ "ConvertToRGB",
750                             /* 10 */ "Convolve",
751                             /* 12 */ "Decode",
752                             /* 14 */ "Dither",
753                             /* 16 */ "Encode",
754                             /* 18 */ "Gamut",
755                             /* 20 */ "Geometry",
756                             /* 22 */ "Histogram",
757                             /* 24 */ "WhiteAdjust"
758                             };
759
760 int
761 print_xie_info(dpy, extname)
762     Display *dpy;
763     char *extname;
764 {
765     XieExtensionInfo *xieInfo;
766     int i;
767     int ntechs;
768     XieTechnique *techs;
769     XieTechniqueGroup prevGroup;
770
771     if (!XieInitialize(dpy, &xieInfo ))
772         return 0;
773
774     print_standard_extension_info(dpy, extname,
775         xieInfo->server_major_rev, xieInfo->server_minor_rev);
776
777     printf("  service class: %s\n", subset_names[xieInfo->service_class]);
778     printf("  alignment: %s\n", align_names[xieInfo->alignment]);
779     printf("  uncnst_mantissa: %d\n", xieInfo->uncnst_mantissa);
780     printf("  uncnst_min_exp: %d\n", xieInfo->uncnst_min_exp);
781     printf("  uncnst_max_exp: %d\n", xieInfo->uncnst_max_exp);
782     printf("  cnst_levels:"); 
783     for (i = 0; i < xieInfo->n_cnst_levels; i++)
784         printf(" %d", xieInfo->cnst_levels[i]);
785     printf("\n");
786
787     if (!XieQueryTechniques(dpy, xieValAll, &ntechs, &techs))
788         return 1;
789
790     prevGroup = -1;
791
792     for (i = 0; i < ntechs; i++)
793     {
794         if (techs[i].group != prevGroup)
795         {
796             printf("  technique group: %s\n", group_names[techs[i].group >> 1]);
797             prevGroup = techs[i].group;
798         }
799         printf("    %s\tspeed: %d  needs_param: %s  number: %d\n",
800                techs[i].name,
801                techs[i].speed, (techs[i].needs_param ? "True " : "False"),
802                techs[i].number);
803     }
804     return 1;
805 } /* end print_xie_info */
806
807 #endif /* HAVE_XIE */
808
809
810 #ifdef HAVE_XTEST
811 int
812 print_xtest_info(dpy, extname)
813     Display *dpy;
814     char *extname;
815 {
816     int majorrev, minorrev, foo;
817
818     if (!XTestQueryExtension(dpy, &foo, &foo, &majorrev, &minorrev))
819         return 0;
820     print_standard_extension_info(dpy, extname, majorrev, minorrev);
821     return 1;
822 }
823 #endif /* HAVE_XTEST */
824
825 #ifdef HAVE_XSYNC
826 int
827 print_sync_info(dpy, extname)
828     Display *dpy;
829     char *extname;
830 {
831     int majorrev, minorrev;
832     XSyncSystemCounter *syscounters;
833     int ncounters, i;
834
835     if (!XSyncInitialize(dpy, &majorrev, &minorrev))
836         return 0;
837     print_standard_extension_info(dpy, extname, majorrev, minorrev);
838
839     syscounters = XSyncListSystemCounters(dpy, &ncounters);
840     printf("  system counters: %d\n", ncounters);
841     for (i = 0; i < ncounters; i++)
842     {
843         printf("    %s  id: 0x%08x  resolution_lo: %d  resolution_hi: %d\n",
844                syscounters[i].name, syscounters[i].counter,
845                XSyncValueLow32(syscounters[i].resolution),
846                XSyncValueHigh32(syscounters[i].resolution));
847     }
848     XSyncFreeSystemCounterList(syscounters);
849     return 1;
850 }
851 #endif /* HAVE_XSYNC */
852
853 int
854 print_shape_info(dpy, extname)
855     Display *dpy;
856     char *extname;
857 {
858     int majorrev, minorrev;
859
860     if (!XShapeQueryVersion(dpy, &majorrev, &minorrev))
861         return 0;
862     print_standard_extension_info(dpy, extname, majorrev, minorrev);
863     return 1;
864 }
865
866 #ifdef MITSHM
867 int
868 print_mitshm_info(dpy, extname)
869     Display *dpy;
870     char *extname;
871 {
872     int majorrev, minorrev;
873     Bool sharedPixmaps;
874
875     if (!XShmQueryVersion(dpy, &majorrev, &minorrev, &sharedPixmaps))
876         return 0;
877     print_standard_extension_info(dpy, extname, majorrev, minorrev);
878     printf("  shared pixmaps: ");
879     if (sharedPixmaps)
880     {
881         int format = XShmPixmapFormat(dpy);
882         printf("yes, format: %d\n", format);
883     }
884     else
885     {
886         printf("no\n");
887     }
888     return 1;
889 }
890 #endif /* MITSHM */
891
892 #ifdef HAVE_XDBE
893 int
894 print_dbe_info(dpy, extname)
895     Display *dpy;
896     char *extname;
897 {
898     int majorrev, minorrev;
899     XdbeScreenVisualInfo *svi;
900     int numscreens = 0;
901     int iscrn, ivis;
902
903     if (!XdbeQueryExtension(dpy, &majorrev, &minorrev))
904         return 0;
905
906     print_standard_extension_info(dpy, extname, majorrev, minorrev);
907     svi = XdbeGetVisualInfo(dpy, (Drawable *)NULL, &numscreens);
908     for (iscrn = 0; iscrn < numscreens; iscrn++)
909     {
910         printf("  Double-buffered visuals on screen %d\n", iscrn);
911         for (ivis = 0; ivis < svi[iscrn].count; ivis++)
912         {
913             printf("    visual id 0x%lx  depth %d  perflevel %d\n",
914                    svi[iscrn].visinfo[ivis].visual,
915                    svi[iscrn].visinfo[ivis].depth,
916                    svi[iscrn].visinfo[ivis].perflevel);
917         }
918     }
919     XdbeFreeVisualInfo(svi);
920     return 1;
921 }
922 #endif /* HAVE_XDBE */
923
924 #ifdef HAVE_XRECORD
925 int
926 print_record_info(dpy, extname)
927     Display *dpy;
928     char *extname;
929 {
930     int majorrev, minorrev;
931
932     if (!XRecordQueryVersion(dpy, &majorrev, &minorrev))
933         return 0;
934     print_standard_extension_info(dpy, extname, majorrev, minorrev);
935     return 1;
936 }
937 #endif /* HAVE_XRECORD */
938
939 /* utilities to manage the list of recognized extensions */
940
941
942 typedef int (*ExtensionPrintFunc)(
943 #if NeedFunctionPrototypes
944     Display *, char *
945 #endif
946 );
947
948 typedef struct {
949     char *extname;
950     ExtensionPrintFunc printfunc;
951     Bool printit;
952 } ExtensionPrintInfo;
953
954 ExtensionPrintInfo known_extensions[] =
955 {
956 #ifdef MITSHM
957     {"MIT-SHM", print_mitshm_info, False},
958 #endif /* MITSHM */
959     {MULTIBUFFER_PROTOCOL_NAME, print_multibuf_info, False},
960     {"SHAPE", print_shape_info, False},
961 #ifdef HAVE_XSYNC
962     {SYNC_NAME, print_sync_info, False},
963 #endif /* HAVE_XSYNC */
964 #ifdef HAVE_XIE
965     {xieExtName, print_xie_info, False},
966 #endif /* HAVE_XIE */
967 #ifdef HAVE_XTEST
968     {XTestExtensionName, print_xtest_info, False},
969 #endif /* HAVE_XTEST */
970 #ifdef HAVE_XDBE
971     {"DOUBLE-BUFFER", print_dbe_info, False},
972 #endif /* HAVE_XDBE */
973 #ifdef HAVE_XRECORD
974     {"RECORD", print_record_info, False}    
975 #endif /* HAVE_XRECORD */
976     /* add new extensions here */
977     /* wish list: PEX XKB LBX */
978 };
979
980 int num_known_extensions = sizeof known_extensions / sizeof known_extensions[0];
981
982 void
983 print_known_extensions(f)
984     FILE *f;
985 {
986     int i;
987     for (i = 0; i < num_known_extensions; i++)
988     {
989         fprintf(f, "%s ", known_extensions[i].extname);
990     }
991 }
992
993 void
994 mark_extension_for_printing(extname)
995     char *extname;
996 {
997     int i;
998
999     if (strcmp(extname, "all") == 0)
1000     {
1001         for (i = 0; i < num_known_extensions; i++)
1002             known_extensions[i].printit = True;
1003     }
1004     else
1005     {
1006         for (i = 0; i < num_known_extensions; i++)
1007         {
1008             if (strcmp(extname, known_extensions[i].extname) == 0)
1009             {
1010                 known_extensions[i].printit = True;
1011                 return;
1012             }
1013         }
1014         printf("%s extension not supported by %s\n", extname, ProgramName);
1015     }
1016 }
1017
1018 void
1019 print_marked_extensions(dpy)
1020     Display *dpy;
1021 {
1022     int i;
1023     for (i = 0; i < num_known_extensions; i++)
1024     {
1025         if (known_extensions[i].printit)
1026         {
1027             printf("\n");
1028             if (! (*known_extensions[i].printfunc)(dpy,
1029                                         known_extensions[i].extname))
1030             {
1031                 printf("%s extension not supported by server\n",
1032                        known_extensions[i].extname);
1033             }
1034         }
1035     }
1036 }
1037
1038 static void usage ()
1039 {
1040     fprintf (stderr, "usage:  %s [options]\n", ProgramName);
1041     fprintf (stderr, "-display displayname\tserver to query\n");
1042     fprintf (stderr, "-queryExtensions\tprint info returned by XQueryExtension\n");
1043     fprintf (stderr, "-ext all\t\tprint detailed info for all supported extensions\n");
1044     fprintf (stderr, "-ext extension-name\tprint detailed info for extension-name if one of:\n     ");
1045     print_known_extensions(stderr);
1046     fprintf (stderr, "\n");
1047     exit (1);
1048 }
1049
1050 int main (argc, argv)
1051     int argc;
1052     char *argv[];
1053 {
1054     Display *dpy;                       /* X connection */
1055     char *displayname = NULL;           /* server to contact */
1056     int i;                              /* temp variable:  iterator */
1057     Bool multibuf = False;
1058     int mbuf_event_base, mbuf_error_base;
1059
1060     ProgramName = argv[0];
1061
1062     for (i = 1; i < argc; i++) {
1063         char *arg = argv[i];
1064         int len = strlen(arg);
1065         
1066         if (!strncmp("-display", arg, len)) {
1067             if (++i >= argc) usage ();
1068             displayname = argv[i];
1069         } else if (!strncmp("-queryExtensions", arg, len)) {
1070             queryExtensions = True;
1071         } else if (!strncmp("-ext", arg, len)) {
1072             if (++i >= argc) usage ();
1073             mark_extension_for_printing(argv[i]);
1074         } else
1075             usage ();
1076     }
1077
1078     dpy = XOpenDisplay (displayname);
1079     if (!dpy) {
1080         fprintf (stderr, "%s:  unable to open display \"%s\".\n",
1081                  ProgramName, XDisplayName (displayname));
1082         exit (1);
1083     }
1084
1085 #ifdef HAVE_OVERLAY
1086         find_overlay_info (dpy);
1087 #endif /* HAVE_OVERLAY */
1088
1089     print_display_info (dpy);
1090     for (i = 0; i < ScreenCount (dpy); i++) {
1091         print_screen_info (dpy, i);
1092     }
1093
1094     print_marked_extensions(dpy);
1095
1096     XCloseDisplay (dpy);
1097     exit (0);
1098 }