1 /* xscreensaver, Copyright (c) 1993, 1994, 1995
2 * Jamie Zawinski <jwz@netscape.com>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
13 /* This file contains some code for intelligently picking the best visual
14 (where "best" is biased in the direction of high color counts...)
25 #include <X11/Xutil.h>
34 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
37 # define _tolower(c) ((c) - 'A' + 'a')
40 extern char *progname;
41 extern char *get_string_resource P((char *, char *));
43 static Visual *pick_best_visual P ((Screen *));
44 static Visual *pick_best_visual_of_class P((Screen *, int));
45 static Visual *id_to_visual P((Screen *, int));
46 static int screen_number P((Screen *));
47 static Visual *id_to_visual P((Screen *screen, int id));
48 int get_visual_depth P((Display *dpy, Visual *visual));
51 #define DEFAULT_VISUAL -1
52 #define BEST_VISUAL -2
53 #define SPECIFIC_VISUAL -3
56 get_visual_resource (dpy, name, class)
60 Screen *screen = DefaultScreenOfDisplay (dpy);
61 char c, *v = get_string_resource (name, class);
67 for (tmp = v; *tmp; tmp++)
68 if (isupper (*tmp)) *tmp = _tolower (*tmp);
70 if (!v) vclass = BEST_VISUAL;
71 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
72 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
73 else if (!strcmp (v, "staticgray")) vclass = StaticGray;
74 else if (!strcmp (v, "staticcolor")) vclass = StaticColor;
75 else if (!strcmp (v, "truecolor")) vclass = TrueColor;
76 else if (!strcmp (v, "grayscale")) vclass = GrayScale;
77 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
78 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
79 else if (1 == sscanf (v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL;
80 else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
83 fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
84 vclass = DEFAULT_VISUAL;
88 if (vclass == DEFAULT_VISUAL)
89 return DefaultVisualOfScreen (screen);
90 else if (vclass == BEST_VISUAL)
91 return pick_best_visual (screen);
92 else if (vclass == SPECIFIC_VISUAL)
94 Visual *visual = id_to_visual (screen, id);
95 if (visual) return visual;
96 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
98 return DefaultVisualOfScreen (screen);
102 Visual *visual = pick_best_visual_of_class (screen, vclass);
103 if (visual) return visual;
104 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
105 return DefaultVisualOfScreen (screen);
110 pick_best_visual (screen)
113 /* The "best" visual is the one on which we can allocate the largest
114 range and number of colors.
116 Therefore, a TrueColor visual which is at least 16 bits deep is best.
117 (The assumption here being that a TrueColor of less than 16 bits is
118 really just a PseudoColor visual with a pre-allocated color cube.)
120 The next best thing is a PseudoColor visual of any type. After that
121 come the non-colormappable visuals, and non-color visuals.
123 Display *dpy = DisplayOfScreen (screen);
125 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
126 get_visual_depth (dpy, visual) >= 16)
128 if ((visual = pick_best_visual_of_class (screen, PseudoColor)))
130 if ((visual = pick_best_visual_of_class (screen, TrueColor)))
132 if ((visual = pick_best_visual_of_class (screen, DirectColor)))
134 if ((visual = pick_best_visual_of_class (screen, GrayScale)))
136 if ((visual = pick_best_visual_of_class (screen, StaticGray)))
138 return DefaultVisualOfScreen (screen);
142 pick_best_visual_of_class (screen, visual_class)
146 /* The best visual of a class is the one which on which we can allocate
147 the largest range and number of colors, which means the one with the
148 greatest depth and number of cells.
150 Display *dpy = DisplayOfScreen (screen);
151 XVisualInfo vi_in, *vi_out;
154 vi_in.class = visual_class;
155 vi_in.screen = screen_number (screen);
156 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
160 /* choose the 'best' one, if multiple */
163 for (i = 0, best = 0; i < out_count; i++)
164 /* It's better if it's deeper, or if it's the same depth with
165 more cells (does that ever happen? Well, it could...) */
166 if ((vi_out [i].depth > vi_out [best].depth) ||
167 ((vi_out [i].depth == vi_out [best].depth) &&
168 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
170 visual = vi_out [best].visual;
171 XFree ((char *) vi_out);
179 id_to_visual (screen, id)
183 Display *dpy = DisplayOfScreen (screen);
184 XVisualInfo vi_in, *vi_out;
186 vi_in.screen = screen_number (screen);
188 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
192 Visual *v = vi_out[0].visual;
193 XFree ((char *) vi_out);
200 get_visual_depth (dpy, visual)
204 XVisualInfo vi_in, *vi_out;
206 vi_in.screen = DefaultScreen (dpy);
207 vi_in.visualid = XVisualIDFromVisual (visual);
208 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
210 if (! vi_out) abort ();
211 d = vi_out [0].depth;
212 XFree ((char *) vi_out);
218 get_visual_class (dpy, visual)
222 XVisualInfo vi_in, *vi_out;
224 vi_in.screen = DefaultScreen (dpy);
225 vi_in.visualid = XVisualIDFromVisual (visual);
226 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
228 if (! vi_out) abort ();
229 c = vi_out [0].class;
230 XFree ((char *) vi_out);
235 describe_visual (f, dpy, visual)
240 Screen *screen = DefaultScreenOfDisplay (dpy);
241 XVisualInfo vi_in, *vi_out;
243 vi_in.screen = screen_number (screen);
244 vi_in.visualid = XVisualIDFromVisual (visual);
245 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
247 if (! vi_out) abort ();
248 fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n",
249 (unsigned int) vi_out->visualid,
250 (vi_out->class == StaticGray ? "StaticGray, " :
251 vi_out->class == StaticColor ? "StaticColor," :
252 vi_out->class == TrueColor ? "TrueColor, " :
253 vi_out->class == GrayScale ? "GrayScale, " :
254 vi_out->class == PseudoColor ? "PseudoColor," :
255 vi_out->class == DirectColor ? "DirectColor," :
257 vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
258 XFree ((char *) vi_out);
262 screen_number (screen)
265 Display *dpy = DisplayOfScreen (screen);
267 for (i = 0; i < ScreenCount (dpy); i++)
268 if (ScreenOfDisplay (dpy, i) == screen)
274 visual_cells (dpy, visual)
278 XVisualInfo vi_in, *vi_out;
280 vi_in.screen = DefaultScreen (dpy);
281 vi_in.visualid = XVisualIDFromVisual (visual);
282 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
284 if (! vi_out) abort ();
285 c = vi_out [0].colormap_size;
286 XFree ((char *) vi_out);