1 /* xscreensaver, Copyright (c) 1993-2014 by Jamie Zawinski <jwz@jwz.org>
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 either: high color counts;
14 or: having writable color cells...)
18 #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 *pick_best_gl_visual (Screen *);
41 #define DEFAULT_VISUAL -1
42 #define BEST_VISUAL -2
43 #define MONO_VISUAL -3
44 #define GRAY_VISUAL -4
45 #define COLOR_VISUAL -5
47 #define SPECIFIC_VISUAL -7
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 || !*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, "gl")) vclass = GL_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, "greyscale")) vclass = GrayScale;
77 else if (!strcmp (v, "pseudocolor")) vclass = PseudoColor;
78 else if (!strcmp (v, "directcolor")) vclass = DirectColor;
79 else if (1 == sscanf (v, " %lu %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;
87 if (vclass == DEFAULT_VISUAL)
88 result = DefaultVisualOfScreen (screen);
89 else if (vclass == BEST_VISUAL)
90 result = pick_best_visual (screen, prefer_writable_cells, False);
91 else if (vclass == MONO_VISUAL)
93 result = pick_mono_visual (screen);
94 if (!result && verbose_p)
95 fprintf (stderr, "%s: no monochrome visuals.\n", progname);
97 else if (vclass == GRAY_VISUAL)
99 if (prefer_writable_cells)
100 result = pick_best_visual_of_class (screen, GrayScale);
102 result = pick_best_visual_of_class (screen, StaticGray);
104 result = pick_best_visual_of_class (screen, GrayScale);
105 if (!result && verbose_p)
106 fprintf (stderr, "%s: no GrayScale or StaticGray visuals.\n",
109 else if (vclass == COLOR_VISUAL)
112 /* First see if the default visual will do. */
113 result = DefaultVisualOfScreen (screen);
114 class = visual_class(screen, result);
115 if (class != TrueColor &&
116 class != PseudoColor &&
117 class != DirectColor &&
118 class != StaticColor)
120 if (result && visual_depth(screen, result) <= 1)
123 /* Else, find the best non-default color visual */
125 result = pick_best_visual (screen, prefer_writable_cells, True);
127 if (!result && verbose_p)
128 fprintf (stderr, "%s: no color visuals.\n", progname);
130 else if (vclass == GL_VISUAL)
132 Visual *visual = pick_best_gl_visual (screen);
136 fprintf (stderr, "%s: no visual suitable for GL.\n", progname);
138 else if (vclass == SPECIFIC_VISUAL)
140 result = id_to_visual (screen, id);
141 if (!result && verbose_p)
142 fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
147 Visual *visual = pick_best_visual_of_class (screen, vclass);
151 fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
159 get_visual_resource (Screen *screen, char *name, char *class,
160 Bool prefer_writable_cells)
162 char *string = get_string_resource (DisplayOfScreen (screen), name, class);
163 Visual *v = get_visual (screen, string, prefer_writable_cells, True);
169 return DefaultVisualOfScreen (screen);
174 pick_best_visual (Screen *screen, Bool prefer_writable_cells, Bool color_only)
178 if (!prefer_writable_cells)
180 /* If we don't prefer writable cells, then the "best" visual is the one
181 on which we can allocate the largest range and number of colors.
183 Therefore, a TrueColor visual which is at least 16 bits deep is best.
184 (The assumption here being that a TrueColor of less than 16 bits is
185 really just a PseudoColor visual with a pre-allocated color cube.)
187 The next best thing is a PseudoColor visual of any type. After that
188 come the non-colormappable visuals, and non-color visuals.
190 if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
191 visual_depth (screen, visual) >= 16)
195 #define TRY_CLASS(CLASS) \
196 if ((visual = pick_best_visual_of_class (screen, CLASS)) && \
197 (!color_only || visual_depth(screen, visual) > 1)) \
199 TRY_CLASS(PseudoColor);
200 TRY_CLASS(TrueColor);
201 TRY_CLASS(DirectColor);
202 TRY_CLASS(StaticColor);
205 TRY_CLASS(GrayScale);
206 TRY_CLASS(StaticGray);
210 visual = DefaultVisualOfScreen (screen);
211 if (!color_only || visual_depth(screen, visual) > 1)
218 pick_mono_visual (Screen *screen)
220 Display *dpy = DisplayOfScreen (screen);
221 XVisualInfo vi_in, *vi_out;
225 vi_in.screen = screen_number (screen);
226 vi_out = XGetVisualInfo (dpy, (VisualDepthMask | VisualScreenMask),
230 Visual *v = (out_count > 0 ? vi_out [0].visual : 0);
231 if (v && vi_out[0].depth != 1)
233 XFree ((char *) vi_out);
242 pick_best_visual_of_class (Screen *screen, int visual_class)
244 /* The best visual of a class is the one which on which we can allocate
245 the largest range and number of colors, which means the one with the
246 greatest depth and number of cells.
248 (But actually, for XDaliClock, all visuals of the same class are
249 probably equivalent - either we have writable cells or we don't.)
251 Display *dpy = DisplayOfScreen (screen);
252 XVisualInfo vi_in, *vi_out;
255 vi_in.class = visual_class;
256 vi_in.screen = screen_number (screen);
257 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask),
261 /* choose the 'best' one, if multiple */
264 /* for (i = 0, best = 0; i < out_count; i++) */
265 for (i = out_count-1, best = i; i >= 0; i--) /* go backwards */
266 /* It's better if it's deeper, or if it's the same depth with
267 more cells (does that ever happen? Well, it could...) */
268 if ((vi_out [i].depth > vi_out [best].depth) ||
269 ((vi_out [i].depth == vi_out [best].depth) &&
270 (vi_out [i].colormap_size > vi_out [best].colormap_size)))
272 visual = (best < out_count ? vi_out [best].visual : 0);
273 XFree ((char *) vi_out);
281 pick_best_gl_visual (Screen *screen)
283 /* The best visual for GL is a TrueColor visual that is half as deep as
284 the screen. If such a thing doesn't exist, then TrueColor is best.
285 Failing that, the deepest available color visual is best.
287 Compare this function to get_gl_visual() in visual-gl.c.
288 This function tries to find the best GL visual using Xlib calls,
289 whereas that function does the same thing using GLX calls.
291 Display *dpy = DisplayOfScreen (screen);
292 XVisualInfo vi_in, *vi_out;
297 int *depths = XListDepths (dpy, screen_number (screen), &ndepths);
298 int screen_depth = (depths && ndepths) ? depths[ndepths - 1] : 0;
301 vi_in.class = TrueColor;
302 vi_in.screen = screen_number (screen);
303 vi_in.depth = screen_depth / 2;
304 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask |
308 result = vi_out[0].visual;
311 XFree ((char *) vi_out);
313 if (!result && screen_depth > 24)
315 /* If it's a 32-deep screen and we didn't find a depth-16 visual,
316 see if there's a depth-12 visual. */
317 vi_in.class = TrueColor;
318 vi_in.screen = screen_number (screen);
320 vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask |
324 result = vi_out[0].visual;
328 /* No half-depth TrueColor? Ok, try for any TrueColor (the deepest.) */
329 result = pick_best_visual_of_class (screen, TrueColor);
332 /* No TrueColor? Ok, try for anything. */
333 result = pick_best_visual (screen, False, False);
340 id_to_visual (Screen *screen, int id)
342 Display *dpy = DisplayOfScreen (screen);
343 XVisualInfo vi_in, *vi_out;
345 vi_in.screen = screen_number (screen);
347 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
351 Visual *v = vi_out[0].visual;
352 XFree ((char *) vi_out);
359 visual_depth (Screen *screen, Visual *visual)
361 Display *dpy = DisplayOfScreen (screen);
362 XVisualInfo vi_in, *vi_out;
364 vi_in.screen = screen_number (screen);
365 vi_in.visualid = XVisualIDFromVisual (visual);
366 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
368 if (! vi_out) abort ();
369 d = vi_out [0].depth;
370 XFree ((char *) vi_out);
376 /* You very probably don't want to be using this.
377 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
378 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
379 To get this info, you should be looking at XImage->bits_per_pixel
380 instead. (And allocating the data for your XImage structures by
381 multiplying ximage->bytes_per_line by ximage->height.)
384 visual_pixmap_depth (Screen *screen, Visual *visual)
386 Display *dpy = DisplayOfScreen (screen);
387 int vdepth = visual_depth (screen, visual);
390 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
392 /* Return the first matching depth in the pixmap formats. If there are no
393 matching pixmap formats (which shouldn't be able to happen at all) then
394 return the visual depth instead. */
395 for (i = 0; i < pfvc; i++)
396 if (pfv[i].depth == vdepth)
398 pdepth = pfv[i].bits_per_pixel;
409 visual_class (Screen *screen, Visual *visual)
411 Display *dpy = DisplayOfScreen (screen);
412 XVisualInfo vi_in, *vi_out;
414 vi_in.screen = screen_number (screen);
415 vi_in.visualid = XVisualIDFromVisual (visual);
416 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
418 if (! vi_out) abort ();
419 c = vi_out [0].class;
420 XFree ((char *) vi_out);
425 has_writable_cells (Screen *screen, Visual *visual)
427 switch (visual_class (screen, visual))
429 case GrayScale: /* Mappable grays. */
430 case PseudoColor: /* Mappable colors. */
431 case DirectColor: /* Like TrueColor, but with three colormaps:
432 one each for red, green, and blue. */
434 case StaticGray: /* Fixed grays. */
435 case TrueColor: /* Fixed colors. */
436 case StaticColor: /* Like PseudoColor with an unmodifiable colormap. */
445 describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
448 Display *dpy = DisplayOfScreen (screen);
449 XVisualInfo vi_in, *vi_out;
451 vi_in.screen = screen_number (screen);
452 vi_in.visualid = XVisualIDFromVisual (visual);
453 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
455 if (! vi_out) abort ();
457 sprintf(n, "%3d", vi_out->colormap_size);
459 strcpy(n, "default");
461 fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n",
462 (unsigned int) vi_out->visualid,
463 (vi_out->class == StaticGray ? "StaticGray, " :
464 vi_out->class == StaticColor ? "StaticColor," :
465 vi_out->class == TrueColor ? "TrueColor, " :
466 vi_out->class == GrayScale ? "GrayScale, " :
467 vi_out->class == PseudoColor ? "PseudoColor," :
468 vi_out->class == DirectColor ? "DirectColor," :
471 XFree ((char *) vi_out);
475 screen_number (Screen *screen)
477 Display *dpy = DisplayOfScreen (screen);
479 for (i = 0; i < ScreenCount (dpy); i++)
480 if (ScreenOfDisplay (dpy, i) == screen)
487 visual_cells (Screen *screen, Visual *visual)
489 Display *dpy = DisplayOfScreen (screen);
490 XVisualInfo vi_in, *vi_out;
492 vi_in.screen = screen_number (screen);
493 vi_in.visualid = XVisualIDFromVisual (visual);
494 vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
496 if (! vi_out) abort ();
497 c = vi_out [0].colormap_size;
498 XFree ((char *) vi_out);
503 find_similar_visual(Screen *screen, Visual *old_visual)
505 Display *dpy = DisplayOfScreen (screen);
506 XVisualInfo vi_in, *vi_out;
510 vi_in.screen = screen_number (screen);
511 vi_in.class = visual_class (screen, old_visual);
512 vi_in.depth = visual_depth (screen, old_visual);
514 /* Look for a visual of the same class and depth.
516 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
519 if (vi_out && out_count > 0)
520 result = vi_out[0].visual;
521 if (vi_out) XFree (vi_out);
524 /* Failing that, look for a visual of the same class.
528 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
530 if (vi_out && out_count > 0)
531 result = vi_out[0].visual;
532 if (vi_out) XFree (vi_out);
536 /* Failing that, return the default visual. */
538 result = DefaultVisualOfScreen (screen);
545 get_bits_per_pixel(Display *dpy, int depth)
549 XPixmapFormatValues *formats = XListPixmapFormats(dpy, &count);
551 /* XCreateImage calls _XGetBitsPerPixel to figure this out, but that function
554 For some reason, _XGetBitsPerPixel tries a hard-coded list of depths if
555 it doesn't find a matching pixmap format, but I (Dave Odell) couldn't
556 find any justification for this in the X11 spec. And the XFree86 CVS
557 repository doesn't quite go back far enough to shed any light on what
558 the deal is with that.
559 http://cvsweb.xfree86.org/cvsweb/xc/lib/X11/ImUtil.c
561 The hard-coded list apparently was added between X11R5 and X11R6.
562 See <ftp://ftp.x.org/pub/>.
565 if (!formats) return 0;
569 if (i == (unsigned)count)
575 if (formats[i].depth == depth)
577 result = formats[i].bits_per_pixel;