1 /* xscreensaver, Copyright (c) 1993, 1994, 1995 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 biased in the direction of high color counts...)
24 #include <X11/Xutil.h>
33 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
36 # define _tolower(c) ((c) - 'A' + 'a')
39 extern char *progname;
40 extern char *get_string_resource P((char *, char *));
42 static Visual *pick_best_visual P ((Screen *));
43 static Visual *pick_best_visual_of_class P((Screen *, int));
44 static Visual *id_to_visual P((Screen *, int));
45 static int screen_number P((Screen *));
46 static Visual *id_to_visual P((Screen *screen, int id));
47 int get_visual_depth P((Display *dpy, Visual *visual));
50 #define DEFAULT_VISUAL -1
51 #define BEST_VISUAL -2
52 #define SPECIFIC_VISUAL -3
55 get_visual_resource (dpy, name, class)
59 Screen *screen = DefaultScreenOfDisplay (dpy);
60 char c, *v = get_string_resource (name, class);
66 for (tmp = v; *tmp; tmp++)
67 if (isupper (*tmp)) *tmp = _tolower (*tmp);
69 if (!v) vclass = BEST_VISUAL;
70 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
71 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
72 else if (!strcmp (v, "staticgray")) vclass = StaticGray;
73 else if (!strcmp (v, "staticcolor")) vclass = StaticColor;
74 else if (!strcmp (v, "truecolor")) vclass = TrueColor;
75 else if (!strcmp (v, "grayscale")) vclass = GrayScale;
76 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
77 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
78 else if (1 == sscanf (v, " %ld %c", &id, &c)) vclass = SPECIFIC_VISUAL;
79 else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
82 fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
83 vclass = DEFAULT_VISUAL;
87 if (vclass == DEFAULT_VISUAL)
88 return DefaultVisualOfScreen (screen);
89 else if (vclass == BEST_VISUAL)
90 return pick_best_visual (screen);
91 else if (vclass == SPECIFIC_VISUAL)
93 Visual *visual = id_to_visual (screen, id);
94 if (visual) return visual;
95 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
97 return DefaultVisualOfScreen (screen);
101 Visual *visual = pick_best_visual_of_class (screen, vclass);
102 if (visual) return visual;
103 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
104 return DefaultVisualOfScreen (screen);
109 pick_best_visual (screen)
112 /* The "best" visual is the one on which we can allocate the largest
113 range and number of colors.
115 Therefore, a TrueColor visual which is at least 16 bits deep is best.
116 (The assumption here being that a TrueColor of less than 16 bits is
117 really just a PseudoColor visual with a pre-allocated color cube.)
119 The next best thing is a PseudoColor visual of any type. After that
120 come the non-colormappable visuals, and non-color visuals.
122 Display *dpy = DisplayOfScreen (screen);
124 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
125 get_visual_depth (dpy, visual) >= 16)
127 if ((visual = pick_best_visual_of_class (screen, PseudoColor)))
129 if ((visual = pick_best_visual_of_class (screen, TrueColor)))
131 if ((visual = pick_best_visual_of_class (screen, DirectColor)))
133 if ((visual = pick_best_visual_of_class (screen, GrayScale)))
135 if ((visual = pick_best_visual_of_class (screen, StaticGray)))
137 return DefaultVisualOfScreen (screen);
141 pick_best_visual_of_class (screen, visual_class)
145 /* The best visual of a class is the one which on which we can allocate
146 the largest range and number of colors, which means the one with the
147 greatest depth and number of cells.
149 Display *dpy = DisplayOfScreen (screen);
150 XVisualInfo vi_in, *vi_out;
153 vi_in.class = visual_class;
154 vi_in.screen = screen_number (screen);
155 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
159 /* choose the 'best' one, if multiple */
162 for (i = 0, best = 0; i < out_count; i++)
163 /* It's better if it's deeper, or if it's the same depth with
164 more cells (does that ever happen? Well, it could...) */
165 if ((vi_out [i].depth > vi_out [best].depth) ||
166 ((vi_out [i].depth == vi_out [best].depth) &&
167 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
169 visual = vi_out [best].visual;
170 XFree ((char *) vi_out);
178 id_to_visual (screen, id)
182 Display *dpy = DisplayOfScreen (screen);
183 XVisualInfo vi_in, *vi_out;
185 vi_in.screen = screen_number (screen);
187 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
191 Visual *v = vi_out[0].visual;
192 XFree ((char *) vi_out);
199 get_visual_depth (dpy, visual)
203 XVisualInfo vi_in, *vi_out;
205 vi_in.screen = DefaultScreen (dpy);
206 vi_in.visualid = XVisualIDFromVisual (visual);
207 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
209 if (! vi_out) abort ();
210 d = vi_out [0].depth;
211 XFree ((char *) vi_out);
217 get_visual_class (dpy, visual)
221 XVisualInfo vi_in, *vi_out;
223 vi_in.screen = DefaultScreen (dpy);
224 vi_in.visualid = XVisualIDFromVisual (visual);
225 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
227 if (! vi_out) abort ();
228 c = vi_out [0].class;
229 XFree ((char *) vi_out);
234 describe_visual (f, dpy, visual)
239 Screen *screen = DefaultScreenOfDisplay (dpy);
240 XVisualInfo vi_in, *vi_out;
242 vi_in.screen = screen_number (screen);
243 vi_in.visualid = XVisualIDFromVisual (visual);
244 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
246 if (! vi_out) abort ();
247 fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n",
248 (unsigned int) vi_out->visualid,
249 (vi_out->class == StaticGray ? "StaticGray, " :
250 vi_out->class == StaticColor ? "StaticColor," :
251 vi_out->class == TrueColor ? "TrueColor, " :
252 vi_out->class == GrayScale ? "GrayScale, " :
253 vi_out->class == PseudoColor ? "PseudoColor," :
254 vi_out->class == DirectColor ? "DirectColor," :
256 vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/);
257 XFree ((char *) vi_out);
261 screen_number (screen)
264 Display *dpy = DisplayOfScreen (screen);
266 for (i = 0; i < ScreenCount (dpy); i++)
267 if (ScreenOfDisplay (dpy, i) == screen)
273 visual_cells (dpy, visual)
277 XVisualInfo vi_in, *vi_out;
279 vi_in.screen = DefaultScreen (dpy);
280 vi_in.visualid = XVisualIDFromVisual (visual);
281 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
283 if (! vi_out) abort ();
284 c = vi_out [0].colormap_size;
285 XFree ((char *) vi_out);