1 /* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
2 * by 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 either: high color counts;
15 or: having writable color cells...)
19 #include "resources.h" /* for get_string_resource() */
22 #include <X11/Xutil.h>
24 extern char *progname;
28 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
31 # define _tolower(c) ((c) - 'A' + 'a')
35 static Visual *pick_best_visual (Screen *, Bool, Bool);
36 static Visual *pick_mono_visual (Screen *);
37 static Visual *pick_best_visual_of_class (Screen *, int);
38 static Visual *id_to_visual (Screen *, int);
39 static Visual *id_to_visual (Screen *screen, int id);
42 #define DEFAULT_VISUAL -1
43 #define BEST_VISUAL -2
44 #define MONO_VISUAL -3
45 #define GRAY_VISUAL -4
46 #define COLOR_VISUAL -5
47 #define SPECIFIC_VISUAL -6
50 get_visual (Screen *screen, const char *string, Bool prefer_writable_cells,
53 char *v = (string ? strdup(string) : 0);
60 for (tmp = v; *tmp; tmp++)
61 if (isupper (*tmp)) *tmp = _tolower (*tmp);
63 if (!v) vclass = BEST_VISUAL;
64 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
65 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
66 else if (!strcmp (v, "mono")) vclass = MONO_VISUAL;
67 else if (!strcmp (v, "monochrome")) vclass = MONO_VISUAL;
68 else if (!strcmp (v, "gray")) vclass = GRAY_VISUAL;
69 else if (!strcmp (v, "grey")) vclass = GRAY_VISUAL;
70 else if (!strcmp (v, "color")) vclass = COLOR_VISUAL;
71 else if (!strcmp (v, "staticgray")) vclass = StaticGray;
72 else if (!strcmp (v, "staticcolor")) vclass = StaticColor;
73 else if (!strcmp (v, "truecolor")) vclass = TrueColor;
74 else if (!strcmp (v, "grayscale")) vclass = GrayScale;
75 else if (!strcmp (v, "greyscale")) 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;
86 if (vclass == DEFAULT_VISUAL)
87 result = DefaultVisualOfScreen (screen);
88 else if (vclass == BEST_VISUAL)
89 result = pick_best_visual (screen, prefer_writable_cells, False);
90 else if (vclass == MONO_VISUAL)
92 result = pick_mono_visual (screen);
93 if (!result && verbose_p)
94 fprintf (stderr, "%s: no monochrome visuals.\n", progname);
96 else if (vclass == GRAY_VISUAL)
98 if (prefer_writable_cells)
99 result = pick_best_visual_of_class (screen, GrayScale);
101 result = pick_best_visual_of_class (screen, StaticGray);
103 result = pick_best_visual_of_class (screen, GrayScale);
104 if (!result && verbose_p)
105 fprintf (stderr, "%s: no GrayScale or StaticGray visuals.\n",
108 else if (vclass == COLOR_VISUAL)
111 /* First see if the default visual will do. */
112 result = DefaultVisualOfScreen (screen);
113 class = visual_class(screen, result);
114 if (class != TrueColor &&
115 class != PseudoColor &&
116 class != DirectColor &&
117 class != StaticColor)
119 if (result && visual_depth(screen, result) <= 1)
122 /* Else, find the best non-default color visual */
124 result = pick_best_visual (screen, prefer_writable_cells, True);
126 if (!result && verbose_p)
127 fprintf (stderr, "%s: no color visuals.\n", progname);
129 else if (vclass == SPECIFIC_VISUAL)
131 result = id_to_visual (screen, id);
132 if (!result && verbose_p)
133 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
138 Visual *visual = pick_best_visual_of_class (screen, vclass);
142 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
150 get_visual_resource (Screen *screen, char *name, char *class,
151 Bool prefer_writable_cells)
153 char *string = get_string_resource (name, class);
154 Visual *v = get_visual (screen, string, prefer_writable_cells, True);
160 return DefaultVisualOfScreen (screen);
165 pick_best_visual (Screen *screen, Bool prefer_writable_cells, Bool color_only)
169 if (!prefer_writable_cells)
171 /* If we don't prefer writable cells, then the "best" visual is the one
172 on which we can allocate the largest range and number of colors.
174 Therefore, a TrueColor visual which is at least 16 bits deep is best.
175 (The assumption here being that a TrueColor of less than 16 bits is
176 really just a PseudoColor visual with a pre-allocated color cube.)
178 The next best thing is a PseudoColor visual of any type. After that
179 come the non-colormappable visuals, and non-color visuals.
181 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
182 visual_depth (screen, visual) >= 16)
186 #define TRY_CLASS(CLASS) \
187 if ((visual = pick_best_visual_of_class (screen, CLASS)) && \
188 (!color_only || visual_depth(screen, visual) > 1)) \
190 TRY_CLASS(PseudoColor);
191 TRY_CLASS(TrueColor);
192 TRY_CLASS(DirectColor);
193 TRY_CLASS(StaticColor);
196 TRY_CLASS(GrayScale);
197 TRY_CLASS(StaticGray);
201 visual = DefaultVisualOfScreen (screen);
202 if (!color_only || visual_depth(screen, visual) > 1)
209 pick_mono_visual (Screen *screen)
211 Display *dpy = DisplayOfScreen (screen);
212 XVisualInfo vi_in, *vi_out;
216 vi_in.screen = screen_number (screen);
217 vi_out = XGetVisualInfo (dpy, (VisualDepthMask | VisualScreenMask),
221 Visual *v = (out_count > 0 ? vi_out [0].visual : 0);
222 if (v && vi_out[0].depth != 1)
224 XFree ((char *) vi_out);
233 pick_best_visual_of_class (Screen *screen, int visual_class)
235 /* The best visual of a class is the one which on which we can allocate
236 the largest range and number of colors, which means the one with the
237 greatest depth and number of cells.
239 (But actually, for XDaliClock, all visuals of the same class are
240 probably equivalent - either we have writable cells or we don't.)
242 Display *dpy = DisplayOfScreen (screen);
243 XVisualInfo vi_in, *vi_out;
246 vi_in.class = visual_class;
247 vi_in.screen = screen_number (screen);
248 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
252 /* choose the 'best' one, if multiple */
255 for (i = 0, best = 0; i < out_count; i++)
256 /* It's better if it's deeper, or if it's the same depth with
257 more cells (does that ever happen? Well, it could...) */
258 if ((vi_out [i].depth > vi_out [best].depth) ||
259 ((vi_out [i].depth == vi_out [best].depth) &&
260 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
262 visual = (best < out_count ? vi_out [best].visual : 0);
263 XFree ((char *) vi_out);
271 id_to_visual (Screen *screen, int id)
273 Display *dpy = DisplayOfScreen (screen);
274 XVisualInfo vi_in, *vi_out;
276 vi_in.screen = screen_number (screen);
278 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
282 Visual *v = vi_out[0].visual;
283 XFree ((char *) vi_out);
290 visual_depth (Screen *screen, Visual *visual)
292 Display *dpy = DisplayOfScreen (screen);
293 XVisualInfo vi_in, *vi_out;
295 vi_in.screen = screen_number (screen);
296 vi_in.visualid = XVisualIDFromVisual (visual);
297 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
299 if (! vi_out) abort ();
300 d = vi_out [0].depth;
301 XFree ((char *) vi_out);
307 /* You very probably don't want to be using this.
308 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
309 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
310 To get this info, you should be looking at XImage->bits_per_pixel
311 instead. (And allocating the data for your XImage structures by
312 multiplying ximage->bytes_per_line by ximage->height.)
315 visual_pixmap_depth (Screen *screen, Visual *visual)
317 Display *dpy = DisplayOfScreen (screen);
318 int vdepth = visual_depth (screen, visual);
321 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
323 /* Return the first matching depth in the pixmap formats. If there are no
324 matching pixmap formats (which shouldn't be able to happen at all) then
325 return the visual depth instead. */
326 for (i = 0; i < pfvc; i++)
327 if (pfv[i].depth == vdepth)
329 pdepth = pfv[i].bits_per_pixel;
340 visual_class (Screen *screen, Visual *visual)
342 Display *dpy = DisplayOfScreen (screen);
343 XVisualInfo vi_in, *vi_out;
345 vi_in.screen = screen_number (screen);
346 vi_in.visualid = XVisualIDFromVisual (visual);
347 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
349 if (! vi_out) abort ();
350 c = vi_out [0].class;
351 XFree ((char *) vi_out);
356 has_writable_cells (Screen *screen, Visual *visual)
358 switch (visual_class (screen, visual))
360 case GrayScale: /* Mappable grays. */
361 case PseudoColor: /* Mappable colors. */
363 case StaticGray: /* Fixed grays. */
364 case TrueColor: /* Fixed colors. */
365 case StaticColor: /* (What's the difference again?) */
366 case DirectColor: /* DirectColor visuals are like TrueColor, but have
367 three colormaps - one for each component of RGB.
376 describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
379 Display *dpy = DisplayOfScreen (screen);
380 XVisualInfo vi_in, *vi_out;
382 vi_in.screen = screen_number (screen);
383 vi_in.visualid = XVisualIDFromVisual (visual);
384 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
386 if (! vi_out) abort ();
388 sprintf(n, "%3d", vi_out->colormap_size);
390 strcpy(n, "default");
392 fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n",
393 (unsigned int) vi_out->visualid,
394 (vi_out->class == StaticGray ? "StaticGray, " :
395 vi_out->class == StaticColor ? "StaticColor," :
396 vi_out->class == TrueColor ? "TrueColor, " :
397 vi_out->class == GrayScale ? "GrayScale, " :
398 vi_out->class == PseudoColor ? "PseudoColor," :
399 vi_out->class == DirectColor ? "DirectColor," :
402 XFree ((char *) vi_out);
406 screen_number (Screen *screen)
408 Display *dpy = DisplayOfScreen (screen);
410 for (i = 0; i < ScreenCount (dpy); i++)
411 if (ScreenOfDisplay (dpy, i) == screen)
417 visual_cells (Screen *screen, Visual *visual)
419 Display *dpy = DisplayOfScreen (screen);
420 XVisualInfo vi_in, *vi_out;
422 vi_in.screen = screen_number (screen);
423 vi_in.visualid = XVisualIDFromVisual (visual);
424 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
426 if (! vi_out) abort ();
427 c = vi_out [0].colormap_size;
428 XFree ((char *) vi_out);
433 find_similar_visual(Screen *screen, Visual *old_visual)
435 Display *dpy = DisplayOfScreen (screen);
436 XVisualInfo vi_in, *vi_out;
440 vi_in.screen = screen_number (screen);
441 vi_in.class = visual_class (screen, old_visual);
442 vi_in.depth = visual_depth (screen, old_visual);
444 /* Look for a visual of the same class and depth.
446 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
449 if (vi_out && out_count > 0)
450 result = vi_out[0].visual;
451 if (vi_out) XFree (vi_out);
454 /* Failing that, look for a visual of the same class.
458 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
460 if (vi_out && out_count > 0)
461 result = vi_out[0].visual;
462 if (vi_out) XFree (vi_out);
466 /* Failing that, return the default visual. */
468 result = DefaultVisualOfScreen (screen);