X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utils%2Fvisual.c;h=2e3b9a9619007a5605cc23b3649560b75b4dbfd2;hb=4cecfc89e5e889c7232693897c06168fb378bd5c;hp=42ce36e88ab2ac1eff3a8d53fb27922382a42525;hpb=f3e0240915ed9f9b3a61781f5c7002d587563fe0;p=xscreensaver diff --git a/utils/visual.c b/utils/visual.c index 42ce36e8..2e3b9a96 100644 --- a/utils/visual.c +++ b/utils/visual.c @@ -1,5 +1,5 @@ -/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997 - * by Jamie Zawinski +/* xscreensaver, Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000 + * by Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -19,6 +19,7 @@ #include "resources.h" /* for get_string_resource() */ #include "visual.h" +#include #include extern char *progname; @@ -35,8 +36,7 @@ extern char *progname; static Visual *pick_best_visual (Screen *, Bool, Bool); static Visual *pick_mono_visual (Screen *); static Visual *pick_best_visual_of_class (Screen *, int); -static Visual *id_to_visual (Screen *, int); -static Visual *id_to_visual (Screen *screen, int id); +static Visual *pick_best_gl_visual (Screen *); #define DEFAULT_VISUAL -1 @@ -44,7 +44,8 @@ static Visual *id_to_visual (Screen *screen, int id); #define MONO_VISUAL -3 #define GRAY_VISUAL -4 #define COLOR_VISUAL -5 -#define SPECIFIC_VISUAL -6 +#define GL_VISUAL -6 +#define SPECIFIC_VISUAL -7 Visual * get_visual (Screen *screen, const char *string, Bool prefer_writable_cells, @@ -60,7 +61,7 @@ get_visual (Screen *screen, const char *string, Bool prefer_writable_cells, for (tmp = v; *tmp; tmp++) if (isupper (*tmp)) *tmp = _tolower (*tmp); - if (!v) vclass = BEST_VISUAL; + if (!v || !*v) vclass = BEST_VISUAL; else if (!strcmp (v, "default")) vclass = DEFAULT_VISUAL; else if (!strcmp (v, "best")) vclass = BEST_VISUAL; else if (!strcmp (v, "mono")) vclass = MONO_VISUAL; @@ -68,6 +69,7 @@ get_visual (Screen *screen, const char *string, Bool prefer_writable_cells, else if (!strcmp (v, "gray")) vclass = GRAY_VISUAL; else if (!strcmp (v, "grey")) vclass = GRAY_VISUAL; else if (!strcmp (v, "color")) vclass = COLOR_VISUAL; + else if (!strcmp (v, "gl")) vclass = GL_VISUAL; else if (!strcmp (v, "staticgray")) vclass = StaticGray; else if (!strcmp (v, "staticcolor")) vclass = StaticColor; else if (!strcmp (v, "truecolor")) vclass = TrueColor; @@ -126,6 +128,14 @@ get_visual (Screen *screen, const char *string, Bool prefer_writable_cells, if (!result && verbose_p) fprintf (stderr, "%s: no color visuals.\n", progname); } + else if (vclass == GL_VISUAL) + { + Visual *visual = pick_best_gl_visual (screen); + if (visual) + result = visual; + else if (verbose_p) + fprintf (stderr, "%s: no visual suitable for GL.\n", progname); + } else if (vclass == SPECIFIC_VISUAL) { result = id_to_visual (screen, id); @@ -252,7 +262,8 @@ pick_best_visual_of_class (Screen *screen, int visual_class) /* choose the 'best' one, if multiple */ int i, best; Visual *visual; - for (i = 0, best = 0; i < out_count; i++) +/* for (i = 0, best = 0; i < out_count; i++) */ + for (i = out_count-1, best = i; i >= 0; i--) /* go backwards */ /* It's better if it's deeper, or if it's the same depth with more cells (does that ever happen? Well, it could...) */ if ((vi_out [i].depth > vi_out [best].depth) || @@ -268,6 +279,65 @@ pick_best_visual_of_class (Screen *screen, int visual_class) } static Visual * +pick_best_gl_visual (Screen *screen) +{ + /* The best visual for GL is a TrueColor visual that is half as deep as + the screen. If such a thing doesn't exist, then TrueColor is best. + Failing that, the deepest available color visual is best. + + Compare this function to get_gl_visual() in visual-gl.c. + This function tries to find the best GL visual using Xlib calls, + whereas that function does the same thing using GLX calls. + */ + Display *dpy = DisplayOfScreen (screen); + XVisualInfo vi_in, *vi_out; + int out_count; + Visual *result = 0; + + int ndepths = 0; + int *depths = XListDepths (dpy, screen_number (screen), &ndepths); + int screen_depth = depths[ndepths]; + XFree (depths); + + vi_in.class = TrueColor; + vi_in.screen = screen_number (screen); + vi_in.depth = screen_depth / 2; + vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask | + VisualDepthMask), + &vi_in, &out_count); + if (out_count > 0) + result = vi_out[0].visual; + + if (vi_out) + XFree ((char *) vi_out); + + if (!result && screen_depth > 24) + { + /* If it's a 32-deep screen and we didn't find a depth-16 visual, + see if there's a depth-12 visual. */ + vi_in.class = TrueColor; + vi_in.screen = screen_number (screen); + vi_in.depth = 12; + vi_out = XGetVisualInfo (dpy, (VisualClassMask | VisualScreenMask | + VisualDepthMask), + &vi_in, &out_count); + if (out_count > 0) + result = vi_out[0].visual; + } + + if (!result) + /* No half-depth TrueColor? Ok, try for any TrueColor (the deepest.) */ + result = pick_best_visual_of_class (screen, TrueColor); + + if (!result) + /* No TrueColor? Ok, try for anything. */ + result = pick_best_visual (screen, False, False); + + return result; +} + + +Visual * id_to_visual (Screen *screen, int id) { Display *dpy = DisplayOfScreen (screen); @@ -303,6 +373,39 @@ visual_depth (Screen *screen, Visual *visual) } +#if 0 +/* You very probably don't want to be using this. + Pixmap depth doesn't refer to the depths of pixmaps, but rather, to + the depth of protocol-level on-the-wire pixmap data, that is, XImages. + To get this info, you should be looking at XImage->bits_per_pixel + instead. (And allocating the data for your XImage structures by + multiplying ximage->bytes_per_line by ximage->height.) + */ +int +visual_pixmap_depth (Screen *screen, Visual *visual) +{ + Display *dpy = DisplayOfScreen (screen); + int vdepth = visual_depth (screen, visual); + int pdepth = vdepth; + int i, pfvc = 0; + XPixmapFormatValues *pfv = XListPixmapFormats (dpy, &pfvc); + + /* Return the first matching depth in the pixmap formats. If there are no + matching pixmap formats (which shouldn't be able to happen at all) then + return the visual depth instead. */ + for (i = 0; i < pfvc; i++) + if (pfv[i].depth == vdepth) + { + pdepth = pfv[i].bits_per_pixel; + break; + } + if (pfv) + XFree (pfv); + return pdepth; +} +#endif /* 0 */ + + int visual_class (Screen *screen, Visual *visual) { @@ -326,22 +429,23 @@ has_writable_cells (Screen *screen, Visual *visual) { case GrayScale: /* Mappable grays. */ case PseudoColor: /* Mappable colors. */ + case DirectColor: /* Like TrueColor, but with three colormaps: + one each for red, green, and blue. */ return True; case StaticGray: /* Fixed grays. */ case TrueColor: /* Fixed colors. */ - case StaticColor: /* (What's the difference again?) */ - case DirectColor: /* DirectColor visuals are like TrueColor, but have - three colormaps - one for each component of RGB. - Screw it. */ + case StaticColor: /* Like PseudoColor with an unmodifiable colormap. */ return False; default: abort(); + return False; } } void -describe_visual (FILE *f, Screen *screen, Visual *visual) +describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p) { + char n[10]; Display *dpy = DisplayOfScreen (screen); XVisualInfo vi_in, *vi_out; int out_count; @@ -350,7 +454,12 @@ describe_visual (FILE *f, Screen *screen, Visual *visual) vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask), &vi_in, &out_count); if (! vi_out) abort (); - fprintf (f, "0x%02x (%s depth: %2d, cmap: %3d)\n", + if (private_cmap_p) + sprintf(n, "%3d", vi_out->colormap_size); + else + strcpy(n, "default"); + + fprintf (f, "0x%02x (%s depth: %2d, cmap: %s)\n", (unsigned int) vi_out->visualid, (vi_out->class == StaticGray ? "StaticGray, " : vi_out->class == StaticColor ? "StaticColor," : @@ -359,7 +468,7 @@ describe_visual (FILE *f, Screen *screen, Visual *visual) vi_out->class == PseudoColor ? "PseudoColor," : vi_out->class == DirectColor ? "DirectColor," : "UNKNOWN: "), - vi_out->depth, vi_out->colormap_size /*, vi_out->bits_per_rgb*/); + vi_out->depth, n); XFree ((char *) vi_out); } @@ -372,6 +481,7 @@ screen_number (Screen *screen) if (ScreenOfDisplay (dpy, i) == screen) return i; abort (); + return 0; } int