From http://www.jwz.org/xscreensaver/xscreensaver-5.37.tar.gz
[xscreensaver] / utils / visual.c
index cc8b5729cfb17751f4e9aae1110184c632dfe1f7..c6764ba929f9edc0fd92bea1b596002705c65db9 100644 (file)
@@ -1,5 +1,4 @@
-/* xscreensaver, Copyright (c) 1993, 1994, 1995 
- * Jamie Zawinski <jwz@netscape.com>
+/* xscreensaver, Copyright (c) 1993-2017 by Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
  */
 
 /* This file contains some code for intelligently picking the best visual
-   (where "best" is biased in the direction of high color counts...)
+   (where "best" is biased in the direction of either: high color counts;
+   or: having writable color cells...)
  */
 
-#if __STDC__
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#endif
+#include "utils.h"
+#include "resources.h"  /* for get_string_resource() */
+#include "visual.h"
 
-#include <stdio.h>
-#include <X11/Xlib.h>
+#include <string.h>
+#ifndef HAVE_ANDROID
 #include <X11/Xutil.h>
-
-#if __STDC__
-# define P(x)x
 #else
-#define P(x)()
+#include "../android/android-visual.h"
 #endif
 
+extern char *progname;
+
 #ifndef isupper
 # define isupper(c)  ((c) >= 'A' && (c) <= 'Z')
 #endif
 # define _tolower(c)  ((c) - 'A' + 'a')
 #endif
 
-extern char *progname;
-extern char *get_string_resource P((char *, char *));
 
-static Visual *pick_best_visual P ((Screen *));
-static Visual *pick_best_visual_of_class P((Screen *, int));
-static Visual *id_to_visual P((Screen *, int));
-static int screen_number P((Screen *));
-static Visual *id_to_visual P((Screen *screen, int id));
-int get_visual_depth P((Display *dpy, Visual *visual));
+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 *pick_best_gl_visual (Screen *);
 
 
 #define DEFAULT_VISUAL -1
 #define BEST_VISUAL    -2
-#define SPECIFIC_VISUAL        -3
+#define MONO_VISUAL    -3
+#define GRAY_VISUAL    -4
+#define COLOR_VISUAL   -5
+#define GL_VISUAL      -6
+#define SPECIFIC_VISUAL        -7
 
 Visual *
-get_visual_resource (dpy, name, class)
-     Display *dpy;
-     char *name, *class;
+get_visual (Screen *screen, const char *string, Bool prefer_writable_cells,
+           Bool verbose_p)
 {
-  Screen *screen = DefaultScreenOfDisplay (dpy);
-  char c, *v = get_string_resource (name, class);
-  char *tmp;
+  char *v = (string ? strdup(string) : 0);
+  char c, *tmp;
   int vclass;
   unsigned long id;
+  Visual *result = 0;
 
   if (v)
     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;
+  else if (!strcmp (v, "monochrome"))            vclass = MONO_VISUAL;
+  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;
   else if (!strcmp (v, "grayscale"))             vclass = GrayScale;
+  else if (!strcmp (v, "greyscale"))             vclass = GrayScale;
   else if (!strcmp (v, "pseudocolor"))           vclass = PseudoColor;
   else if (!strcmp (v, "directcolor"))           vclass = DirectColor;
-  else if (1 == sscanf (v, " %ld %c", &id, &c))          vclass = SPECIFIC_VISUAL;
+  else if (1 == sscanf (v, " %lu %c", &id, &c))          vclass = SPECIFIC_VISUAL;
   else if (1 == sscanf (v, " 0x%lx %c", &id, &c)) vclass = SPECIFIC_VISUAL;
   else
     {
       fprintf (stderr, "%s: unrecognized visual \"%s\".\n", progname, v);
       vclass = DEFAULT_VISUAL;
     }
-  if (v) free (v);
 
   if (vclass == DEFAULT_VISUAL)
-    return DefaultVisualOfScreen (screen);
+    result = DefaultVisualOfScreen (screen);
   else if (vclass == BEST_VISUAL)
-    return pick_best_visual (screen);
+    result = pick_best_visual (screen, prefer_writable_cells, False);
+  else if (vclass == MONO_VISUAL)
+    {
+      result = pick_mono_visual (screen);
+      if (!result && verbose_p)
+       fprintf (stderr, "%s: no monochrome visuals.\n", progname);
+    }
+  else if (vclass == GRAY_VISUAL)
+    {
+      if (prefer_writable_cells)
+       result = pick_best_visual_of_class (screen, GrayScale);
+      if (!result)
+       result = pick_best_visual_of_class (screen, StaticGray);
+      if (!result)
+       result = pick_best_visual_of_class (screen, GrayScale);
+      if (!result && verbose_p)
+       fprintf (stderr, "%s: no GrayScale or StaticGray visuals.\n",
+                progname);
+    }
+  else if (vclass == COLOR_VISUAL)
+    {
+      int class;
+      /* First see if the default visual will do. */
+      result = DefaultVisualOfScreen (screen);
+      class = visual_class(screen, result);
+      if (class != TrueColor &&
+         class != PseudoColor &&
+         class != DirectColor &&
+         class != StaticColor)
+       result = 0;
+      if (result && visual_depth(screen, result) <= 1)
+       result = 0;
+
+      /* Else, find the best non-default color visual */
+      if (!result)
+       result = pick_best_visual (screen, prefer_writable_cells, True);
+
+      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)
     {
-      Visual *visual = id_to_visual (screen, id);
-      if (visual) return visual;
-      fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
-              (unsigned int) id);
-      return DefaultVisualOfScreen (screen);
+      result = id_to_visual (screen, id);
+      if (!result && verbose_p)
+       fprintf (stderr, "%s: no visual with id 0x%x.\n", progname,
+                (unsigned int) id);
     }
   else
     {
       Visual *visual = pick_best_visual_of_class (screen, vclass);
-      if (visual) return visual;
-      fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
-      return DefaultVisualOfScreen (screen);
+      if (visual)
+       result = visual;
+      else if (verbose_p)
+       fprintf (stderr, "%s: no visual of class %s.\n", progname, v);
     }
+
+  if (v) free (v);
+  return result;
 }
 
-static Visual *
-pick_best_visual (screen)
-       Screen *screen;
+Visual *
+get_visual_resource (Screen *screen, char *name, char *class,
+                    Bool prefer_writable_cells)
 {
-  /* The "best" visual is the one on which we can allocate the largest
-     range and number of colors.
+  char *string = get_string_resource (DisplayOfScreen (screen), name, class);
+  Visual *v = get_visual (screen, string, prefer_writable_cells, True);
+  if (string)
+    free(string);
+  if (v)
+    return v;
+  else
+    return DefaultVisualOfScreen (screen);
+}
 
-     Therefore, a TrueColor visual which is at least 16 bits deep is best.
-     (The assumption here being that a TrueColor of less than 16 bits is
-     really just a PseudoColor visual with a pre-allocated color cube.)
 
-     The next best thing is a PseudoColor visual of any type.  After that
-     come the non-colormappable visuals, and non-color visuals.
-   */
-  Display *dpy = DisplayOfScreen (screen);
+static Visual *
+pick_best_visual (Screen *screen, Bool prefer_writable_cells, Bool color_only)
+{
   Visual *visual;
-  if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
-      get_visual_depth (dpy, visual) >= 16)
-    return visual;
-  if ((visual = pick_best_visual_of_class (screen, PseudoColor)))
-    return visual;
-  if ((visual = pick_best_visual_of_class (screen, TrueColor)))
-    return visual;
-  if ((visual = pick_best_visual_of_class (screen, DirectColor)))
-    return visual;
-  if ((visual = pick_best_visual_of_class (screen, GrayScale)))
-    return visual;
-  if ((visual = pick_best_visual_of_class (screen, StaticGray)))
+
+  if (!prefer_writable_cells)
+    {
+      /* If we don't prefer writable cells, then the "best" visual is the one
+        on which we can allocate the largest range and number of colors.
+
+        Therefore, a TrueColor visual which is at least 16 bits deep is best.
+        (The assumption here being that a TrueColor of less than 16 bits is
+        really just a PseudoColor visual with a pre-allocated color cube.)
+
+        The next best thing is a PseudoColor visual of any type.  After that
+        come the non-colormappable visuals, and non-color visuals.
+       */
+      if ((visual = pick_best_visual_of_class (screen, TrueColor)) &&
+         visual_depth (screen, visual) >= 16)
+       return visual;
+    }
+
+#define TRY_CLASS(CLASS) \
+  if ((visual = pick_best_visual_of_class (screen, CLASS)) && \
+      (!color_only || visual_depth(screen, visual) > 1)) \
+    return visual
+  TRY_CLASS(PseudoColor);
+  TRY_CLASS(TrueColor);
+  TRY_CLASS(DirectColor);
+  TRY_CLASS(StaticColor);
+  if (!color_only)
+    {
+      TRY_CLASS(GrayScale);
+      TRY_CLASS(StaticGray);
+    }
+#undef TRY_CLASS
+
+  visual = DefaultVisualOfScreen (screen);
+  if (!color_only || visual_depth(screen, visual) > 1)
     return visual;
-  return DefaultVisualOfScreen (screen);
+  else
+    return 0;
+}
+
+static Visual *
+pick_mono_visual (Screen *screen)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  XVisualInfo vi_in, *vi_out;
+  int out_count;
+
+  vi_in.depth = 1;
+  vi_in.screen = screen_number (screen);
+  vi_out = XGetVisualInfo (dpy, (VisualDepthMask | VisualScreenMask),
+                          &vi_in, &out_count);
+  if (vi_out)
+    {
+      Visual *v = (out_count > 0 ? vi_out [0].visual : 0);
+      if (v && vi_out[0].depth != 1)
+       v = 0;
+      XFree ((char *) vi_out);
+      return v;
+    }
+  else
+    return 0;
 }
 
+
 static Visual *
-pick_best_visual_of_class (screen, visual_class)
-     Screen *screen;
-     int visual_class;
+pick_best_visual_of_class (Screen *screen, int visual_class)
 {
   /* The best visual of a class is the one which on which we can allocate
      the largest range and number of colors, which means the one with the
      greatest depth and number of cells.
+
+     (But actually, for XDaliClock, all visuals of the same class are
+     probably equivalent - either we have writable cells or we don't.)
    */
   Display *dpy = DisplayOfScreen (screen);
   XVisualInfo vi_in, *vi_out;
@@ -160,14 +264,15 @@ pick_best_visual_of_class (screen, 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) ||
            ((vi_out [i].depth == vi_out [best].depth) &&
             (vi_out [i].colormap_size > vi_out [best].colormap_size)))
          best = i;
-      visual = vi_out [best].visual;
+      visual = (best < out_count ? vi_out [best].visual : 0);
       XFree ((char *) vi_out);
       return visual;
     }
@@ -176,17 +281,88 @@ pick_best_visual_of_class (screen, visual_class)
 }
 
 static Visual *
-id_to_visual (screen, id)
-     Screen *screen;
-     int id;
+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) ? depths[ndepths - 1] : 0;
+  XFree (depths);
+
+  vi_in.class = TrueColor;
   vi_in.screen = screen_number (screen);
-  vi_in.visualid = id;
-  vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualIDMask),
+  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;
+}
+
+
+static XVisualInfo *
+visual_info_id (Screen *screen, int id)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  XVisualInfo vi_in;
+  int out_count;
+  vi_in.screen = screen_number (screen);
+  vi_in.visualid = id;
+  return XGetVisualInfo (dpy, VisualScreenMask | VisualIDMask,
+                         &vi_in, &out_count);
+}
+
+static XVisualInfo *
+visual_info (Screen *screen, Visual *visual)
+{
+  XVisualInfo *vi_out = visual_info_id (screen, XVisualIDFromVisual (visual));
+  if (! vi_out) abort ();
+  return vi_out;
+}
+
+Visual *
+id_to_visual (Screen *screen, int id)
+{
+  XVisualInfo *vi_out = visual_info_id (screen, id);
   if (vi_out)
     {
       Visual *v = vi_out[0].visual;
@@ -197,55 +373,101 @@ id_to_visual (screen, id)
 }
 
 int
-get_visual_depth (dpy, visual)
-     Display *dpy;
-     Visual *visual;
+visual_depth (Screen *screen, Visual *visual)
 {
-  XVisualInfo vi_in, *vi_out;
-  int out_count, d;
-  vi_in.screen = DefaultScreen (dpy);
-  vi_in.visualid = XVisualIDFromVisual (visual);
-  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
-                          &vi_in, &out_count);
-  if (! vi_out) abort ();
-  d = vi_out [0].depth;
+  XVisualInfo *vi_out = visual_info (screen, visual);
+  int d = vi_out [0].depth;
   XFree ((char *) vi_out);
   return d;
 }
 
 
+/* 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.)
+
+   Still, it can be useful to know bits_per_pixel before the XImage exists.
+
+   XCreateImage calls _XGetBitsPerPixel to figure this out, but that function
+   is private to Xlib.
+
+   For some reason, _XGetBitsPerPixel tries a hard-coded list of depths if
+   it doesn't find a matching pixmap format, but I (Dave Odell) couldn't
+   find any justification for this in the X11 spec. And the XFree86 CVS
+   repository doesn't quite go back far enough to shed any light on what
+   the deal is with that.
+   http://cvsweb.xfree86.org/cvsweb/xc/lib/X11/ImUtil.c
+
+   The hard-coded list apparently was added between X11R5 and X11R6.
+   See <ftp://ftp.x.org/pub/>.
+ */
 int
-get_visual_class (dpy, visual)
-     Display *dpy;
-     Visual *visual;
+visual_pixmap_depth (Screen *screen, Visual *visual)
 {
-  XVisualInfo vi_in, *vi_out;
-  int out_count, c;
-  vi_in.screen = DefaultScreen (dpy);
-  vi_in.visualid = XVisualIDFromVisual (visual);
-  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
-                          &vi_in, &out_count);
-  if (! vi_out) abort ();
-  c = vi_out [0].class;
+  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;
+}
+
+
+int
+visual_class (Screen *screen, Visual *visual)
+{
+  XVisualInfo *vi_out = visual_info (screen, visual);
+  int c = vi_out [0].class;
   XFree ((char *) vi_out);
   return c;
 }
 
+Bool
+has_writable_cells (Screen *screen, Visual *visual)
+{
+  switch (visual_class (screen, 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:  /* Like PseudoColor with an unmodifiable colormap. */
+      return False;
+    default:
+      abort();
+      return False;
+    }
+}
+
 void
-describe_visual (f, dpy, visual)
-     FILE *f;
-     Display *dpy;
-     Visual *visual;
+describe_visual (FILE *f, Screen *screen, Visual *visual, Bool private_cmap_p)
 {
-  Screen *screen = DefaultScreenOfDisplay (dpy);
-  XVisualInfo vi_in, *vi_out;
-  int out_count;
-  vi_in.screen = screen_number (screen);
-  vi_in.visualid = XVisualIDFromVisual (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",
+  char n[10];
+  XVisualInfo *vi_out = visual_info (screen, visual);
+  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," :
@@ -254,13 +476,12 @@ describe_visual (f, dpy, 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);
 }
 
-static int
-screen_number (screen)
-       Screen *screen;
+int
+screen_number (Screen *screen)
 {
   Display *dpy = DisplayOfScreen (screen);
   int i;
@@ -268,21 +489,67 @@ screen_number (screen)
     if (ScreenOfDisplay (dpy, i) == screen)
       return i;
   abort ();
+  return 0;
 }
 
 int
-visual_cells (dpy, visual)
-       Display *dpy;
-       Visual *visual;
+visual_cells (Screen *screen, Visual *visual)
+{
+  XVisualInfo *vi_out = visual_info (screen, visual);
+  int c = vi_out [0].colormap_size;
+  XFree ((char *) vi_out);
+  return c;
+}
+
+Visual *
+find_similar_visual(Screen *screen, Visual *old_visual)
 {
+  Display *dpy = DisplayOfScreen (screen);
   XVisualInfo vi_in, *vi_out;
-  int out_count, c;
-  vi_in.screen = DefaultScreen (dpy);
-  vi_in.visualid = XVisualIDFromVisual (visual);
-  vi_out = XGetVisualInfo (dpy, VisualScreenMask|VisualIDMask,
+  Visual *result = 0;
+  int out_count;
+
+  vi_in.screen = screen_number (screen);
+  vi_in.class  = visual_class (screen, old_visual);
+  vi_in.depth  = visual_depth (screen, old_visual);
+
+  /* Look for a visual of the same class and depth.
+   */
+  vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask |
+                                VisualDepthMask),
                           &vi_in, &out_count);
-  if (! vi_out) abort ();
-  c = vi_out [0].colormap_size;
+  if (vi_out && out_count > 0)
+    result = vi_out[0].visual;
+  if (vi_out) XFree (vi_out);
+  vi_out = 0;
+
+  /* Failing that, look for a visual of the same class.
+   */
+  if (!result)
+    {
+      vi_out = XGetVisualInfo (dpy, (VisualScreenMask | VisualClassMask),
+                              &vi_in, &out_count);
+      if (vi_out && out_count > 0)
+       result = vi_out[0].visual;
+      if (vi_out) XFree (vi_out);
+      vi_out = 0;
+    }
+
+  /* Failing that, return the default visual. */
+  if (!result)
+    result = DefaultVisualOfScreen (screen);
+
+  return result;
+}
+
+
+void
+visual_rgb_masks (Screen *screen, Visual *visual, unsigned long *red_mask,
+                  unsigned long *green_mask, unsigned long *blue_mask)
+{
+  XVisualInfo *vi_out = visual_info (screen, visual);
+  *red_mask = vi_out->red_mask;
+  *green_mask = vi_out->green_mask;
+  *blue_mask = vi_out->blue_mask;
   XFree ((char *) vi_out);
-  return c;
 }