1 /* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@mcom.com>
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
12 /* This file contains some code for intelligently picking the best visual
13 (where "best" is somewhat biased in the direction of writable cells...)
22 typedef char * caddr_t;
27 #include <X11/Xutil.h>
36 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
39 # define _tolower(c) ((c) - 'A' + 'a')
42 extern char *progname;
43 extern char *get_string_resource P((char *, char *));
45 static Visual *pick_best_visual P ((Screen *));
46 static Visual *pick_best_visual_of_class P((Screen *, int));
47 static Visual *id_to_visual P((Screen *, int));
48 static int visual_depth P((Display *, Visual *));
49 static int screen_number P((Screen *));
50 static Visual *id_to_visual P((Screen *screen, int id));
53 #define DEFAULT_VISUAL -1
54 #define BEST_VISUAL -2
55 #define SPECIFIC_VISUAL -3
58 get_visual_resource (dpy, name, class)
62 Screen *screen = DefaultScreenOfDisplay (dpy);
63 char c, *v = get_string_resource (name, class);
69 for (tmp = v; *tmp; tmp++)
70 if (isupper (*tmp)) *tmp = _tolower (*tmp);
72 if (!v) vclass = BEST_VISUAL;
73 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
74 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
75 else if (!strcmp (v, "staticgray")) vclass = StaticGray;
76 else if (!strcmp (v, "staticcolor")) vclass = StaticColor;
77 else if (!strcmp (v, "truecolor")) vclass = TrueColor;
78 else if (!strcmp (v, "grayscale")) vclass = GrayScale;
79 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
80 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
81 else if (1 == sscanf (v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL;
82 else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
85 fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
86 vclass = DEFAULT_VISUAL;
90 if (vclass == DEFAULT_VISUAL)
91 return DefaultVisualOfScreen (screen);
92 else if (vclass == BEST_VISUAL)
93 return pick_best_visual (screen);
94 else if (vclass == SPECIFIC_VISUAL)
96 Visual *visual = id_to_visual (screen, id);
97 if (visual) return visual;
98 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
100 return DefaultVisualOfScreen (screen);
104 Visual *visual = pick_best_visual_of_class (screen, vclass);
105 if (visual) return visual;
106 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
107 return DefaultVisualOfScreen (screen);
112 pick_best_visual (screen)
115 /* The "best" visual is the one on which we can allocate the largest
116 range and number of colors.
118 Therefore, a TrueColor visual which is at least 16 bits deep is best.
119 (The assumption here being that a TrueColor of less than 16 bits is
120 really just a PseudoColor visual with a pre-allocated color cube.)
122 The next best thing is a PseudoColor visual of any type. After that
123 come the non-colormappable visuals, and non-color visuals.
125 Display *dpy = DisplayOfScreen (screen);
127 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
128 visual_depth (dpy, visual) >= 16)
130 if ((visual = pick_best_visual_of_class (screen, PseudoColor)))
132 if ((visual = pick_best_visual_of_class (screen, TrueColor)))
134 if ((visual = pick_best_visual_of_class (screen, DirectColor)))
136 if ((visual = pick_best_visual_of_class (screen, GrayScale)))
138 if ((visual = pick_best_visual_of_class (screen, StaticGray)))
140 return DefaultVisualOfScreen (screen);
144 pick_best_visual_of_class (screen, visual_class)
148 /* The best visual of a class is the one which on which we can allocate
149 the largest range and number of colors, which means the one with the
150 greatest depth and number of cells.
152 Display *dpy = DisplayOfScreen (screen);
153 XVisualInfo vi_in, *vi_out;
156 vi_in.class = visual_class;
157 vi_in.screen = screen_number (screen);
158 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
162 /* choose the 'best' one, if multiple */
165 for (i = 0, best = 0; i < out_count; i++)
166 /* It's better if it's deeper, or if it's the same depth with
167 more cells (does that ever happen? Well, it could...) */
168 if ((vi_out [i].depth > vi_out [best].depth) ||
169 ((vi_out [i].depth == vi_out [best].depth) &&
170 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
172 visual = vi_out [best].visual;
173 XFree ((char *) vi_out);
181 id_to_visual (screen, id)
185 Display *dpy = DisplayOfScreen (screen);
186 XVisualInfo vi_in, *vi_out;
188 vi_in.screen = screen_number (screen);
190 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
194 Visual *v = vi_out[0].visual;
195 XFree ((char *) vi_out);
202 get_visual_depth (dpy, visual)
206 XVisualInfo vi_in, *vi_out;
208 vi_in.screen = DefaultScreen (dpy);
209 vi_in.visualid = XVisualIDFromVisual (visual);
210 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
212 if (! vi_out) abort ();
213 d = vi_out [0].depth;
214 XFree ((char *) vi_out);
220 get_visual_class (dpy, visual)
224 XVisualInfo vi_in, *vi_out;
226 vi_in.screen = DefaultScreen (dpy);
227 vi_in.visualid = XVisualIDFromVisual (visual);
228 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
230 if (! vi_out) abort ();
231 c = vi_out [0].class;
232 XFree ((char *) vi_out);
237 describe_visual (f, dpy, visual)
242 Screen *screen = DefaultScreenOfDisplay (dpy);
243 XVisualInfo vi_in, *vi_out;
245 vi_in.screen = screen_number (screen);
246 vi_in.visualid = XVisualIDFromVisual (visual);
247 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
249 if (! vi_out) abort ();
250 fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n",
251 (unsigned int) vi_out->visualid,
252 (vi_out->class == StaticGray ? "StaticGray, " :
253 vi_out->class == StaticColor ? "StaticColor," :
254 vi_out->class == TrueColor ? "TrueColor, " :
255 vi_out->class == GrayScale ? "GrayScale, " :
256 vi_out->class == PseudoColor ? "PseudoColor," :
257 vi_out->class == DirectColor ? "DirectColor," :
259 vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
260 XFree ((char *) vi_out);
264 screen_number (screen)
267 Display *dpy = DisplayOfScreen (screen);
269 for (i = 0; i < ScreenCount (dpy); i++)
270 if (ScreenOfDisplay (dpy, i) == screen)
276 visual_depth (dpy, visual)
280 XVisualInfo vi_in, *vi_out;
282 vi_in.screen = DefaultScreen (dpy);
283 vi_in.visualid = XVisualIDFromVisual (visual);
284 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
286 if (! vi_out) abort ();
287 d = vi_out [0].depth;
288 XFree ((char *) vi_out);
293 visual_cells (dpy, visual)
297 XVisualInfo vi_in, *vi_out;
299 vi_in.screen = DefaultScreen (dpy);
300 vi_in.visualid = XVisualIDFromVisual (visual);
301 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
303 if (! vi_out) abort ();
304 c = vi_out [0].colormap_size;
305 XFree ((char *) vi_out);