b9d1897034cc1524f3239ba11c5c5b72c47f8bdc
[xscreensaver] / driver / visual.c
1 /* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@lucid.com>
2  *
3  * Permission to use, copy, modify, distribute, and sell this software and its
4  * documentation for any purpose is hereby granted without fee, provided that
5  * the above copyright notice appear in all copies and that both that
6  * copyright notice and this permission notice appear in supporting
7  * documentation.  No representations are made about the suitability of this
8  * software for any purpose.  It is provided "as is" without express or 
9  * implied warranty.
10  */
11
12 /* This file contains some code for intelligently picking the best visual
13    (where "best" is somewhat biased in the direction of writable cells...)
14  */
15
16 #if __STDC__
17 #include <stdlib.h>
18 #endif
19
20 #include <stdio.h>
21 #include <X11/Xlib.h>
22 #include <X11/Xutil.h>
23
24 #ifndef isupper
25 # define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
26 #endif
27 #ifndef _tolower
28 # define _tolower(c)  ((c) - 'A' + 'a')
29 #endif
30
31 extern char *progname;
32 extern char *get_string_resource ();
33
34 static Visual *
35 pick_best_visual_of_class (display, visual_class)
36      Display *display;
37      int visual_class;
38 {
39   XVisualInfo vi_in, *vi_out;
40   int out_count;
41
42   vi_in.class = visual_class;
43   vi_in.screen = DefaultScreen (display);
44   vi_out = XGetVisualInfo (display, VisualClassMask|VisualScreenMask,
45                            &vi_in, &out_count);
46   if (vi_out)
47     {       /* choose the 'best' one, if multiple */
48       int i, best;
49       Visual *visual;
50       for (i = 0, best = 0; i < out_count; i++)
51         if (vi_out [i].depth > vi_out [best].depth)
52           best = i;
53       visual = vi_out [best].visual;
54       XFree ((char *) vi_out);
55       return visual;
56     }
57   else
58     return 0;
59 }
60
61 static Visual *
62 pick_best_visual (display)
63      Display *display;
64 {
65   Visual *visual;
66   if (visual = pick_best_visual_of_class (display, PseudoColor))
67     return visual;
68   if (visual = pick_best_visual_of_class (display, DirectColor))
69     return visual;
70   if (visual = pick_best_visual_of_class (display, GrayScale))
71     return visual;
72   if (visual = pick_best_visual_of_class (display, StaticGray))
73     return visual;
74   return DefaultVisual (display, DefaultScreen (display));
75 }
76
77
78 static Visual *
79 id_to_visual (dpy, id)
80      Display *dpy;
81      int id;
82 {
83   XVisualInfo vi_in, *vi_out;
84   int out_count;
85   vi_in.screen = DefaultScreen (dpy);
86   vi_in.visualid = id;
87   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
88                            &vi_in, &out_count);
89   if (vi_out)
90     {
91       Visual *v = vi_out[0].visual;
92       XFree ((char *) vi_out);
93       return v;
94     }
95   return 0;
96 }
97
98 int
99 get_visual_depth (dpy, visual)
100      Display *dpy;
101      Visual *visual;
102 {
103   XVisualInfo vi_in, *vi_out;
104   int out_count, d;
105   vi_in.screen = DefaultScreen (dpy);
106   vi_in.visualid = XVisualIDFromVisual (visual);
107   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
108                            &vi_in, &out_count);
109   if (! vi_out) abort ();
110   d = vi_out [0].depth;
111   XFree ((char *) vi_out);
112   return d;
113 }
114
115
116 Visual *
117 get_visual_resource (dpy, name, class)
118      Display *dpy;
119      char *name, *class;
120 {
121   char c, *s = get_string_resource (name, class);
122   char *tmp;
123   int vclass;
124   int id;
125
126   if (s)
127     for (tmp = s; *tmp; tmp++)
128       if (isupper (*tmp)) *tmp = _tolower (*tmp);
129
130   if      (!s || !strcmp (s, "best"))  vclass = -1;
131   else if (!strcmp (s, "default"))     vclass = -2;
132   else if (!strcmp (s, "staticgray"))  vclass = StaticGray;
133   else if (!strcmp (s, "staticcolor")) vclass = StaticColor;
134   else if (!strcmp (s, "truecolor"))   vclass = TrueColor;
135   else if (!strcmp (s, "grayscale"))   vclass = GrayScale;
136   else if (!strcmp (s, "pseudocolor")) vclass = PseudoColor;
137   else if (!strcmp (s, "directcolor")) vclass = DirectColor;
138   else if (1 == sscanf (s, " %ld %c", &id, &c))   vclass = -3;
139   else if (1 == sscanf (s, " 0x%lx %c", &id, &c)) vclass = -3;
140   else
141     {
142       fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, s);
143       vclass = -1;
144     }
145   if (s) free (s);
146
147   if (vclass == -1)
148     return pick_best_visual (dpy);
149   else if (vclass == -2)
150     return DefaultVisual (dpy, DefaultScreen (dpy));
151   else if (vclass == -3)
152     {
153       Visual *v = id_to_visual (dpy, id);
154       if (v) return v;
155       fprintf (stderr, "%s: no visual with id 0x%x.\n", progname, id);
156       return pick_best_visual (dpy);
157     }
158   else
159     return pick_best_visual_of_class (dpy, vclass);
160 }
161
162 void
163 describe_visual (f, dpy, visual)
164      FILE *f;
165      Display *dpy;
166      Visual *visual;
167 {
168   XVisualInfo vi_in, *vi_out;
169   int out_count, d;
170   vi_in.screen = DefaultScreen (dpy);
171   vi_in.visualid = XVisualIDFromVisual (visual);
172   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
173                            &vi_in, &out_count);
174   if (! vi_out) abort ();
175   fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d @ %d)\n", vi_out->visualid,
176            (vi_out->class == StaticGray  ? "StaticGray, " :
177             vi_out->class == StaticColor ? "StaticColor," :
178             vi_out->class == TrueColor   ? "TrueColor,  " :
179             vi_out->class == GrayScale   ? "GrayScale,  " :
180             vi_out->class == PseudoColor ? "PseudoColor," :
181             vi_out->class == DirectColor ? "DirectColor," :
182             "???"),
183            vi_out->depth, vi_out->colormap_size, vi_out->bits_per_rgb);
184   XFree ((char *) vi_out);
185 }