1 /* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2006
4 * by Jamie Zawinski <jwz@jwz.org>
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation. No representations are made about the suitability of this
11 * software for any purpose. It is provided "as is" without express or
15 /* This file contains some code for intelligently picking the best visual
16 (where "best" is biased in the direction of either: high color counts;
17 or: having writable color cells...)
21 #include "resources.h" /* for get_string_resource() */
25 #include <X11/Xutil.h>
27 extern char *progname;
31 # define isupper(c) ((c) >= 'A' && (c) <= 'Z')
34 # define _tolower(c) ((c) - 'A' + 'a')
38 static Visual *pick_best_visual (Screen *, Bool, Bool);
39 static Visual *pick_mono_visual (Screen *);
40 static Visual *pick_best_visual_of_class (Screen *, int);
41 static Visual *pick_best_gl_visual (Screen *);
44 #define DEFAULT_VISUAL -1
45 #define BEST_VISUAL -2
46 #define MONO_VISUAL -3
47 #define GRAY_VISUAL -4
48 #define COLOR_VISUAL -5
50 #define SPECIFIC_VISUAL -7
53 get_visual (Screen *screen, const char *string, Bool prefer_writable_cells,
56 char *v = (string ? strdup(string) : 0);
63 for (tmp = v; *tmp; tmp++)
64 if (isupper (*tmp)) *tmp = _tolower (*tmp);
66 if (!v || !*v) vclass = BEST_VISUAL;
67 else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL;
68 else if (!strcmp (v, "best")) vclass = BEST_VISUAL;
69 else if (!strcmp (v, "mono")) vclass = MONO_VISUAL;
70 else if (!strcmp (v, "monochrome")) vclass = MONO_VISUAL;
71 else if (!strcmp (v, "gray")) vclass = GRAY_VISUAL;
72 else if (!strcmp (v, "grey")) vclass = GRAY_VISUAL;
73 else if (!strcmp (v, "color")) vclass = COLOR_VISUAL;
74 else if (!strcmp (v, "gl")) vclass = GL_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, "greyscale")) vclass = GrayScale;
80 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
81 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
82 else if (1 == sscanf (v, " %lu %c", &id, &c)) vclass = SPECIFIC_VISUAL;
83 else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
86 fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
87 vclass = DEFAULT_VISUAL;
90 if (vclass == DEFAULT_VISUAL)
91 result = DefaultVisualOfScreen (screen);
92 else if (vclass == BEST_VISUAL)
93 result = pick_best_visual (screen, prefer_writable_cells, False);
94 else if (vclass == MONO_VISUAL)
96 result = pick_mono_visual (screen);
97 if (!result && verbose_p)
98 fprintf (stderr, "%s: no monochrome visuals.\n", progname);
100 else if (vclass == GRAY_VISUAL)
102 if (prefer_writable_cells)
103 result = pick_best_visual_of_class (screen, GrayScale);
105 result = pick_best_visual_of_class (screen, StaticGray);
107 result = pick_best_visual_of_class (screen, GrayScale);
108 if (!result && verbose_p)
109 fprintf (stderr, "%s: no GrayScale or StaticGray visuals.\n",
112 else if (vclass == COLOR_VISUAL)
115 /* First see if the default visual will do. */
116 result = DefaultVisualOfScreen (screen);
117 class = visual_class(screen, result);
118 if (class != TrueColor &&
119 class != PseudoColor &&
120 class != DirectColor &&
121 class != StaticColor)
123 if (result && visual_depth(screen, result) <= 1)
126 /* Else, find the best non-default color visual */
128 result = pick_best_visual (screen, prefer_writable_cells, True);
130 if (!result && verbose_p)
131 fprintf (stderr, "%s: no color visuals.\n", progname);
133 else if (vclass == GL_VISUAL)
135 Visual *visual = pick_best_gl_visual (screen);
139 fprintf (stderr, "%s: no visual suitable for GL.\n", progname);
141 else if (vclass == SPECIFIC_VISUAL)
143 result = id_to_visual (screen, id);
144 if (!result && verbose_p)
145 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
150 Visual *visual = pick_best_visual_of_class (screen, vclass);
154 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
162 get_visual_resource (Screen *screen, char *name, char *class,
163 Bool prefer_writable_cells)
165 char *string = get_string_resource (DisplayOfScreen (screen), name, class);
166 Visual *v = get_visual (screen, string, prefer_writable_cells, True);
172 return DefaultVisualOfScreen (screen);
177 pick_best_visual (Screen *screen, Bool prefer_writable_cells, Bool color_only)
181 if (!prefer_writable_cells)
183 /* If we don't prefer writable cells, then the "best" visual is the one
184 on which we can allocate the largest range and number of colors.
186 Therefore, a TrueColor visual which is at least 16 bits deep is best.
187 (The assumption here being that a TrueColor of less than 16 bits is
188 really just a PseudoColor visual with a pre-allocated color cube.)
190 The next best thing is a PseudoColor visual of any type. After that
191 come the non-colormappable visuals, and non-color visuals.
193 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
194 visual_depth (screen, visual) >= 16)
198 #define TRY_CLASS(CLASS) \
199 if ((visual = pick_best_visual_of_class (screen, CLASS)) && \
200 (!color_only || visual_depth(screen, visual) > 1)) \
202 TRY_CLASS(PseudoColor);
203 TRY_CLASS(TrueColor);
204 TRY_CLASS(DirectColor);
205 TRY_CLASS(StaticColor);
208 TRY_CLASS(GrayScale);
209 TRY_CLASS(StaticGray);
213 visual = DefaultVisualOfScreen (screen);
214 if (!color_only || visual_depth(screen, visual) > 1)
221 pick_mono_visual (Screen *screen)
223 Display *dpy = DisplayOfScreen (screen);
224 XVisualInfo vi_in, *vi_out;
228 vi_in.screen = screen_number (screen);
229 vi_out = XGetVisualInfo (dpy, (VisualDepthMask | VisualScreenMask),
233 Visual *v = (out_count > 0 ? vi_out [0].visual : 0);
234 if (v && vi_out[0].depth != 1)
236 XFree ((char *) vi_out);
245 pick_best_visual_of_class (Screen *screen, int visual_class)
247 /* The best visual of a class is the one which on which we can allocate
248 the largest range and number of colors, which means the one with the
249 greatest depth and number of cells.
251 (But actually, for XDaliClock, all visuals of the same class are
252 probably equivalent - either we have writable cells or we don't.)
254 Display *dpy = DisplayOfScreen (screen);
255 XVisualInfo vi_in, *vi_out;
258 vi_in.class = visual_class;
259 vi_in.screen = screen_number (screen);
260 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
264 /* choose the 'best' one, if multiple */
267 /* for (i = 0, best = 0; i < out_count; i++) */
268 for (i = out_count-1, best = i; i >= 0; i--) /* go backwards */
269 /* It's better if it's deeper, or if it's the same depth with
270 more cells (does that ever happen? Well, it could...) */
271 if ((vi_out [i].depth > vi_out [best].depth) ||
272 ((vi_out [i].depth == vi_out [best].depth) &&
273 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
275 visual = (best < out_count ? vi_out [best].visual : 0);
276 XFree ((char *) vi_out);
284 pick_best_gl_visual (Screen *screen)
286 /* The best visual for GL is a TrueColor visual that is half as deep as
287 the screen. If such a thing doesn't exist, then TrueColor is best.
288 Failing that, the deepest available color visual is best.
290 Compare this function to get_gl_visual() in visual-gl.c.
291 This function tries to find the best GL visual using Xlib calls,
292 whereas that function does the same thing using GLX calls.
294 Display *dpy = DisplayOfScreen (screen);
295 XVisualInfo vi_in, *vi_out;
300 int *depths = XListDepths (dpy, screen_number (screen), &ndepths);
301 int screen_depth = depths[ndepths];
304 vi_in.class = TrueColor;
305 vi_in.screen = screen_number (screen);
306 vi_in.depth = screen_depth / 2;
307 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask |
311 result = vi_out[0].visual;
314 XFree ((char *) vi_out);
316 if (!result && screen_depth > 24)
318 /* If it's a 32-deep screen and we didn't find a depth-16 visual,
319 see if there's a depth-12 visual. */
320 vi_in.class = TrueColor;
321 vi_in.screen = screen_number (screen);
323 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask |
327 result = vi_out[0].visual;
331 /* No half-depth TrueColor? Ok, try for any TrueColor (the deepest.) */
332 result = pick_best_visual_of_class (screen, TrueColor);
335 /* No TrueColor? Ok, try for anything. */
336 result = pick_best_visual (screen, False, False);
343 id_to_visual (Screen *screen, int id)
345 Display *dpy = DisplayOfScreen (screen);
346 XVisualInfo vi_in, *vi_out;
348 vi_in.screen = screen_number (screen);
350 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
354 Visual *v = vi_out[0].visual;
355 XFree ((char *) vi_out);
362 visual_depth (Screen *screen, Visual *visual)
364 Display *dpy = DisplayOfScreen (screen);
365 XVisualInfo vi_in, *vi_out;
367 vi_in.screen = screen_number (screen);
368 vi_in.visualid = XVisualIDFromVisual (visual);
369 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
371 if (! vi_out) abort ();
372 d = vi_out [0].depth;
373 XFree ((char *) vi_out);
379 /* You very probably don't want to be using this.
380 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
381 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
382 To get this info, you should be looking at XImage->bits_per_pixel
383 instead. (And allocating the data for your XImage structures by
384 multiplying ximage->bytes_per_line by ximage->height.)
387 visual_pixmap_depth (Screen *screen, Visual *visual)
389 Display *dpy = DisplayOfScreen (screen);
390 int vdepth = visual_depth (screen, visual);
393 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
395 /* Return the first matching depth in the pixmap formats. If there are no
396 matching pixmap formats (which shouldn't be able to happen at all) then
397 return the visual depth instead. */
398 for (i = 0; i < pfvc; i++)
399 if (pfv[i].depth == vdepth)
401 pdepth = pfv[i].bits_per_pixel;
412 visual_class (Screen *screen, Visual *visual)
414 Display *dpy = DisplayOfScreen (screen);
415 XVisualInfo vi_in, *vi_out;
417 vi_in.screen = screen_number (screen);
418 vi_in.visualid = XVisualIDFromVisual (visual);
419 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
421 if (! vi_out) abort ();
422 c = vi_out [0].class;
423 XFree ((char *) vi_out);
428 has_writable_cells (Screen *screen, Visual *visual)
430 switch (visual_class (screen, visual))
432 case GrayScale: /* Mappable grays. */
433 case PseudoColor: /* Mappable colors. */
434 case DirectColor: /* Like TrueColor, but with three colormaps:
435 one each for red, green, and blue. */
437 case StaticGray: /* Fixed grays. */
438 case TrueColor: /* Fixed colors. */
439 case StaticColor: /* Like PseudoColor with an unmodifiable colormap. */
448 describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
451 Display *dpy = DisplayOfScreen (screen);
452 XVisualInfo vi_in, *vi_out;
454 vi_in.screen = screen_number (screen);
455 vi_in.visualid = XVisualIDFromVisual (visual);
456 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
458 if (! vi_out) abort ();
460 sprintf(n, "%3d", vi_out->colormap_size);
462 strcpy(n, "default");
464 fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n",
465 (unsigned int) vi_out->visualid,
466 (vi_out->class == StaticGray ? "StaticGray, " :
467 vi_out->class == StaticColor ? "StaticColor," :
468 vi_out->class == TrueColor ? "TrueColor, " :
469 vi_out->class == GrayScale ? "GrayScale, " :
470 vi_out->class == PseudoColor ? "PseudoColor," :
471 vi_out->class == DirectColor ? "DirectColor," :
474 XFree ((char *) vi_out);
478 screen_number (Screen *screen)
480 Display *dpy = DisplayOfScreen (screen);
482 for (i = 0; i < ScreenCount (dpy); i++)
483 if (ScreenOfDisplay (dpy, i) == screen)
490 visual_cells (Screen *screen, Visual *visual)
492 Display *dpy = DisplayOfScreen (screen);
493 XVisualInfo vi_in, *vi_out;
495 vi_in.screen = screen_number (screen);
496 vi_in.visualid = XVisualIDFromVisual (visual);
497 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
499 if (! vi_out) abort ();
500 c = vi_out [0].colormap_size;
501 XFree ((char *) vi_out);
506 find_similar_visual(Screen *screen, Visual *old_visual)
508 Display *dpy = DisplayOfScreen (screen);
509 XVisualInfo vi_in, *vi_out;
513 vi_in.screen = screen_number (screen);
514 vi_in.class = visual_class (screen, old_visual);
515 vi_in.depth = visual_depth (screen, old_visual);
517 /* Look for a visual of the same class and depth.
519 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
522 if (vi_out && out_count > 0)
523 result = vi_out[0].visual;
524 if (vi_out) XFree (vi_out);
527 /* Failing that, look for a visual of the same class.
531 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
533 if (vi_out && out_count > 0)
534 result = vi_out[0].visual;
535 if (vi_out) XFree (vi_out);
539 /* Failing that, return the default visual. */
541 result = DefaultVisualOfScreen (screen);