74e77051d7e87860dcd10d565db6c285b4026d2f
[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 int
117 get_visual_class (dpy, visual)
118      Display *dpy;
119      Visual *visual;
120 {
121   XVisualInfo vi_in, *vi_out;
122   int out_count, c;
123   vi_in.screen = DefaultScreen (dpy);
124   vi_in.visualid = XVisualIDFromVisual (visual);
125   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
126                            &vi_in, &out_count);
127   if (! vi_out) abort ();
128   c = vi_out [0].class;
129   XFree ((char *) vi_out);
130   return c;
131 }
132
133
134 Visual *
135 get_visual_resource (dpy, name, class)
136      Display *dpy;
137      char *name, *class;
138 {
139   char c, *s = get_string_resource (name, class);
140   char *tmp;
141   int vclass;
142   int id;
143
144   if (s)
145     for (tmp = s; *tmp; tmp++)
146       if (isupper (*tmp)) *tmp = _tolower (*tmp);
147
148   if      (!s || !strcmp (s, "best"))  vclass = -1;
149   else if (!strcmp (s, "default"))     vclass = -2;
150   else if (!strcmp (s, "staticgray"))  vclass = StaticGray;
151   else if (!strcmp (s, "staticcolor")) vclass = StaticColor;
152   else if (!strcmp (s, "truecolor"))   vclass = TrueColor;
153   else if (!strcmp (s, "grayscale"))   vclass = GrayScale;
154   else if (!strcmp (s, "pseudocolor")) vclass = PseudoColor;
155   else if (!strcmp (s, "directcolor")) vclass = DirectColor;
156   else if (1 == sscanf (s, " %ld %c", &id, &c))   vclass = -3;
157   else if (1 == sscanf (s, " 0x%lx %c", &id, &c)) vclass = -3;
158   else
159     {
160       fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, s);
161       vclass = -1;
162     }
163   if (s) free (s);
164
165   if (vclass == -1)
166     return pick_best_visual (dpy);
167   else if (vclass == -2)
168     return DefaultVisual (dpy, DefaultScreen (dpy));
169   else if (vclass == -3)
170     {
171       Visual *v = id_to_visual (dpy, id);
172       if (v) return v;
173       fprintf (stderr, "%s: no visual with id 0x%x.\n", progname, id);
174       return pick_best_visual (dpy);
175     }
176   else
177     return pick_best_visual_of_class (dpy, vclass);
178 }
179
180 void
181 describe_visual (f, dpy, visual)
182      FILE *f;
183      Display *dpy;
184      Visual *visual;
185 {
186   XVisualInfo vi_in, *vi_out;
187   int out_count, d;
188   vi_in.screen = DefaultScreen (dpy);
189   vi_in.visualid = XVisualIDFromVisual (visual);
190   vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
191                            &vi_in, &out_count);
192   if (! vi_out) abort ();
193   fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d @ %d)\n", vi_out->visualid,
194            (vi_out->class == StaticGray  ? "StaticGray, " :
195             vi_out->class == StaticColor ? "StaticColor," :
196             vi_out->class == TrueColor   ? "TrueColor,  " :
197             vi_out->class == GrayScale   ? "GrayScale,  " :
198             vi_out->class == PseudoColor ? "PseudoColor," :
199             vi_out->class == DirectColor ? "DirectColor," :
200             "???"),
201            vi_out->depth, vi_out->colormap_size, vi_out->bits_per_rgb);
202   XFree ((char *) vi_out);
203 }