1 /* xscreensaver, Copyright (c) 1993-2017 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() */
23 #include <X11/Xutil.h>
25 #include "../android/android-visual.h"
28 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) ? depths[ndepths - 1] : 0;
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 visual_info_id (Screen *screen, int id)
345 Display *dpy = DisplayOfScreen (screen);
348 vi_in.screen = screen_number (screen);
350 return XGetVisualInfo (dpy, VisualScreenMask | VisualIDMask,
355 visual_info (Screen *screen, Visual *visual)
357 XVisualInfo *vi_out = visual_info_id (screen, XVisualIDFromVisual (visual));
358 if (! vi_out) abort ();
363 id_to_visual (Screen *screen, int id)
365 XVisualInfo *vi_out = visual_info_id (screen, id);
368 Visual *v = vi_out[0].visual;
369 XFree ((char *) vi_out);
376 visual_depth (Screen *screen, Visual *visual)
378 XVisualInfo *vi_out = visual_info (screen, visual);
379 int d = vi_out [0].depth;
380 XFree ((char *) vi_out);
385 /* You very probably don't want to be using this.
386 Pixmap depth doesn't refer to the depths of pixmaps, but rather, to
387 the depth of protocol-level on-the-wire pixmap data, that is, XImages.
388 To get this info, you should be looking at XImage->bits_per_pixel
389 instead. (And allocating the data for your XImage structures by
390 multiplying ximage->bytes_per_line by ximage->height.)
392 Still, it can be useful to know bits_per_pixel before the XImage exists.
394 XCreateImage calls _XGetBitsPerPixel to figure this out, but that function
397 For some reason, _XGetBitsPerPixel tries a hard-coded list of depths if
398 it doesn't find a matching pixmap format, but I (Dave Odell) couldn't
399 find any justification for this in the X11 spec. And the XFree86 CVS
400 repository doesn't quite go back far enough to shed any light on what
401 the deal is with that.
402 http://cvsweb.xfree86.org/cvsweb/xc/lib/X11/ImUtil.c
404 The hard-coded list apparently was added between X11R5 and X11R6.
405 See <ftp://ftp.x.org/pub/>.
408 visual_pixmap_depth (Screen *screen, Visual *visual)
410 Display *dpy = DisplayOfScreen (screen);
411 int vdepth = visual_depth (screen, visual);
414 XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc);
416 /* Return the first matching depth in the pixmap formats. If there are no
417 matching pixmap formats (which shouldn't be able to happen at all) then
418 return the visual depth instead. */
419 for (i = 0; i < pfvc; i++)
420 if (pfv[i].depth == vdepth)
422 pdepth = pfv[i].bits_per_pixel;
432 visual_class (Screen *screen, Visual *visual)
434 XVisualInfo *vi_out = visual_info (screen, visual);
435 int c = vi_out [0].class;
436 XFree ((char *) vi_out);
441 has_writable_cells (Screen *screen, Visual *visual)
443 switch (visual_class (screen, visual))
445 case GrayScale: /* Mappable grays. */
446 case PseudoColor: /* Mappable colors. */
447 case DirectColor: /* Like TrueColor, but with three colormaps:
448 one each for red, green, and blue. */
450 case StaticGray: /* Fixed grays. */
451 case TrueColor: /* Fixed colors. */
452 case StaticColor: /* Like PseudoColor with an unmodifiable colormap. */
461 describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
464 XVisualInfo *vi_out = visual_info (screen, visual);
466 sprintf(n, "%3d", vi_out->colormap_size);
468 strcpy(n, "default");
470 fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n",
471 (unsigned int) vi_out->visualid,
472 (vi_out->class == StaticGray ? "StaticGray, " :
473 vi_out->class == StaticColor ? "StaticColor," :
474 vi_out->class == TrueColor ? "TrueColor, " :
475 vi_out->class == GrayScale ? "GrayScale, " :
476 vi_out->class == PseudoColor ? "PseudoColor," :
477 vi_out->class == DirectColor ? "DirectColor," :
480 XFree ((char *) vi_out);
484 screen_number (Screen *screen)
486 Display *dpy = DisplayOfScreen (screen);
488 for (i = 0; i < ScreenCount (dpy); i++)
489 if (ScreenOfDisplay (dpy, i) == screen)
496 visual_cells (Screen *screen, Visual *visual)
498 XVisualInfo *vi_out = visual_info (screen, visual);
499 int c = vi_out [0].colormap_size;
500 XFree ((char *) vi_out);
505 find_similar_visual(Screen *screen, Visual *old_visual)
507 Display *dpy = DisplayOfScreen (screen);
508 XVisualInfo vi_in, *vi_out;
512 vi_in.screen = screen_number (screen);
513 vi_in.class = visual_class (screen, old_visual);
514 vi_in.depth = visual_depth (screen, old_visual);
516 /* Look for a visual of the same class and depth.
518 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
521 if (vi_out && out_count > 0)
522 result = vi_out[0].visual;
523 if (vi_out) XFree (vi_out);
526 /* Failing that, look for a visual of the same class.
530 vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
532 if (vi_out && out_count > 0)
533 result = vi_out[0].visual;
534 if (vi_out) XFree (vi_out);
538 /* Failing that, return the default visual. */
540 result = DefaultVisualOfScreen (screen);
547 visual_rgb_masks (Screen *screen, Visual *visual, unsigned long *red_mask,
548 unsigned long *green_mask, unsigned long *blue_mask)
550 XVisualInfo *vi_out = visual_info (screen, visual);
551 *red_mask = vi_out->red_mask;
552 *green_mask = vi_out->green_mask;
553 *blue_mask = vi_out->blue_mask;
554 XFree ((char *) vi_out);