[BACK]Return to xglinfo.c CVS log [TXT][DIR] Up to [Development] / projects / ogl-sample / main / gfx / samples / xglinfo

File: [Development] / projects / ogl-sample / main / gfx / samples / xglinfo / xglinfo.c (download)

Revision 1.1.1.1 (vendor branch), Wed Jan 26 10:31:09 2000 UTC (17 years, 9 months ago) by ljp
Branch: SGI, MAIN
CVS Tags: tested_with_xf86_3_3, oglsi1_2_1, HEAD
Changes since 1.1: +0 -0 lines

Imported from P4

/*
 * 
 *           Copyright (c) Digital Equipment Corporation, 1995
 * 
 *                          All Rights Reserved
 * 
 * Permission to use, copy, modify, and distribute  this software and its
 * documentation for any  purpose   and without fee  is  hereby  granted,
 * provided that the above copyright notice appear in all copies and that
 * both  that  copyright  notice  and  this  permission notice appear  in
 * supporting documentation, and that the name of Digital  not be used in
 * advertising or publicity  pertaining to distribution  of the  software
 * without specific, written prior permission.
 * 
 * DIGITAL DISCLAIMS   ALL  WARRANTIES WITH   REGARD   TO  THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT   SHALL  DIGITAL  BE   LIABLE  FOR  ANY SPECIAL,   INDIRECT   OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION  OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 * 
 */
/*
** $Header: //depot/main/gfx/samples/xglinfo/xglinfo.c#1 $
*/
/*
 * HISTORY
 */
/*****************************************************************************/
/******************************** Documentation ******************************/
/*****************************************************************************/

/*
 * See man page for full documentation.
 *
 * Written by John Dennis, Digital Equipment Corporation.
 * jdennis@mlo.dec.com
 *
 * With thanks and credit to Jim Fulton who wrote the original version of
 * xdpyinfo while at MIT which served as a starting point for this code.
 */

/*****************************************************************************/
/******************************* Include Files *******************************/
/*****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glu.h>
#include "global.h"


/*****************************************************************************/
/****************************** Internal Defines *****************************/
/*****************************************************************************/

#define GL_GET_CONFIG(_config, _pValue)                                      \
{                                                                            \
  switch (result = glXGetConfig(dpy, visual, _config, (_pValue))) {          \
  case Success:                                                              \
    break;                                                                   \
  case GLX_NO_EXTENSION:                                                     \
    printf("ERROR glXGetConfig %s return GLX_NO_EXTENSION, visuaID 0x%lx\n", \
          "_config", visual->visualid);                                      \
    break;                                                                   \
  case GLX_BAD_SCREEN:                                                       \
    printf("ERROR glXGetConfig %s return GLX_BAD_SCREEN, visuaID 0x%lx\n",   \
          "_config", visual->visualid);                                      \
    break;                                                                   \
  case GLX_BAD_ATTRIBUTE:                                                    \
    printf("ERROR glXGetConfig %s return GLX_BAD_ATTRIBUTE, visuaID 0x%lx\n",\
          "_config", visual->visualid);                                      \
    break;                                                                   \
  case GLX_BAD_VISUAL:                                                       \
    printf("ERROR glXGetConfig %s return GLX_BAD_VISUAL, visuaID 0x%lx\n",   \
          "_config", visual->visualid);                                      \
    break;                                                                   \
  default:                                                                   \
    printf("ERROR glXGetConfig %s return unknown error %d, visuaID 0x%lx\n", \
          "_config", result, visual->visualid);                              \
    break;                                                                   \
  }                                                                          \
}

/*****************************************************************************/
/************************** Internal Type Definitions ************************/
/*****************************************************************************/

typedef struct GLXVisualInfo {
  int useGL;			       /* support GLX rendering */
  int bufferSize;		       /* depth of the color buffer */
  int level;			       /* level in plane stacking */
  int rgba;			       /* true if RGBA mode */
  int doubleBuffer;		       /* double buffering supported */
  int stereo;			       /* stereo buffering supported */
  int auxBuffers;		       /* number of aux buffers */
  int redSize;			       /* number of red component bits */
  int greenSize;		       /* number of green component bits */
  int blueSize;			       /* number of blue component bits */
  int alphaSize;		       /* number of alpha component bits */
  int depthSize;		       /* number of depth bits */
  int stencilSize;		       /* number of stencil bits */
  int accumRedSize;		       /* number of red accum bits */
  int accumGreenSize;		       /* number of green accum bits */
  int accumBlueSize;		       /* number of blue accum bits */
  int accumAlphaSize;		       /* number of alpha accum bits */
  int xVisualType;
  int transparentPixel;		       /* None or Pixel */
  int transparentIndex;		       /* transparent index value */
  int transparentRedValue;	       /* transparent color value */
  int transparentGreenValue;
  int transparentBlueValue;
  int transparentAlphaValue;
  int visualCaveats;		       /* None or Slow */
} GLXVisualInfo;

typedef enum 
{
  VID_NONE = 0,
  VID_RGB  = 1,
  VID_RGBA = 2,
  VID_CI   = 4,
  VID_ALL  = 7
} VidTypes;

/*****************************************************************************/
/**********************  External Function Declarations  *********************/
/*****************************************************************************/

/*****************************************************************************/
/**********************  Internal Function Declarations  *********************/
/*****************************************************************************/

static void
Usage(
  void
);

static void
ProcessArgs(
	     int argc   ,
	     char       *argv[]
);

void
PrintEventMask (
    int indent,				/* amount by which to indent */
    unsigned long mask				/* event mask */
);

void
PrintExtensionInfo(
  Display    *dpy,
  int         fieldNameLen,
  int	      indent
);

void
PrintPixmapFormats(
  Display    *dpy,
  int         fieldNameLen,
  int	      indent
);

void
PrintWindowFocus(
  Display    *dpy,
  int         fieldNameLen
);

void
PrintDisplayInfo(
  Display    *dpy,
  int         fieldNameLen
);

int
GetGLVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    GLXVisualInfo *glVisual
);

void
PrintCookedVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    int indent
);

void
PrintRawVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    int indent
);

int
PrintVisualIDs (
    Display    *dpy,
    XVisualInfo *visual
);

void
PrintScreenInfo(
  Display    *dpy,
  int         scr,
  int         fieldNameLen,
  int	      indent
);

void
PrintScreenVisualInfo(
  Display    *dpy,
  int         scr,
  int         fieldNameLen,
  int	      indent
);

static void
PrintIndentedStringWithBlanks(
  const char	* head,
  const char	* string,
  int	        fieldNameLen,
  int		indent
);

static int
ProcessScreen(
  Display *dpy,
  int screenNum,
  int fieldNameLen,
  int indent
);

/*****************************************************************************/
/*************************  External Global Variables  ***********************/
/*****************************************************************************/

char       *ProgramName;

/*****************************************************************************/
/*************************  Internal Global Variables  ***********************/
/*****************************************************************************/

static char       *displayname = NULL;	/* server to contact */
static int         printDisplayInfo = GL_TRUE;
static int         printScreenInfo = GL_TRUE;
static int         printVisualInfo = GL_TRUE;
static int         printCookedVisualInfo = GL_TRUE;
static int         printRawVisualInfo = GL_FALSE;
static int         printSpecficScreen = GL_FALSE;
static int         specficScreenNum = 0;
static VidTypes    printVids = VID_NONE;

static int         pageWidth = 80;
static int         glErrorBase, glEventBase;
static int         glXMajorVersion, glXMinorVersion;
static const char  *glXExtensionString = "";
static int         glXVisRating = GL_FALSE;
static int         glXVisInfo = GL_FALSE;

static Bool        dpyHasGL = GL_FALSE;

/*****************************************************************************/
/***************************  Internal Functions  ****************************/
/*****************************************************************************/

static void
Usage(
  void
)
{
  fprintf(stderr, "usage:  %s [-help] [-display displayname] [-vid rgb | rgba | ci | all ] [-screen n]\n\n",
	  ProgramName);
  fprintf(stderr, "  the following options take a '+' or '-' switch\n");
  fprintf(stderr, "  a '+' turns the option on, a '-' turns the option off\n\n");
  fprintf(stderr, "  [+-printDisplayInfo] [+-printScreenInfo] [+-printVisualInfo]\n");
  fprintf(stderr, "  [+-printCookedVisualInfo]");
  fprintf(stderr, "\n");
  exit(1);
}

static void
ProcessArgs(
	     int argc   ,
	     char       *argv[]
)
{
  int         i;
    char       *arg;
  char        switchChar;

  ProgramName = argv[0];

  for (i = 1; i < argc; i++) {
    arg = argv[i];
    switchChar = arg[0];

    if (switchChar == '-' || switchChar == '+') {
      arg++;
      if (strcmp(arg, "display") == 0) {
	if (switchChar == '-') {
	  if (++i >= argc) goto missing;
	  displayname = argv[i];
	}
	else goto unknown;
      }
      else if (strcmp(arg, "screen") == 0) {
	if (switchChar == '-') {
	  if (++i >= argc) goto missing;
	  if (sscanf(argv[i], "%d", &specficScreenNum) != 1) goto unknown;
          printSpecficScreen = GL_TRUE;
	}
	else goto unknown;
      }
      else if (strcmp(arg, "printDisplayInfo") == 0
	    || strcmp(arg, "printdisplayinfo") == 0) {
	if (switchChar == '+')
	  printDisplayInfo = GL_TRUE;
	else
	  printDisplayInfo = GL_FALSE;
      }
      else if (strcmp(arg, "printScreenInfo") == 0
	    || strcmp(arg, "printscreeninfo") == 0) {
	if (switchChar == '+')
	  printScreenInfo = GL_TRUE;
	else
	  printScreenInfo = GL_FALSE;
      }
      else if (strcmp(arg, "printVisualInfo") == 0
	    || strcmp(arg, "printvisualinfo") == 0) {
	if (switchChar == '+')
	  printVisualInfo = GL_TRUE;
	else
	  printVisualInfo = GL_FALSE;
      }
      else if (strcmp(arg, "printCookedVisualInfo") == 0
	    || strcmp(arg, "printcookedvisualinfo") == 0) {
	if (switchChar == '+')
	  printCookedVisualInfo = GL_TRUE;
	else
	  printCookedVisualInfo = GL_FALSE;
      }
      else if (strcmp(arg, "vid") == 0) {
	if (switchChar == '-') {
	  if (++i >= argc) goto missing;
          if (strcmp(argv[i], "rgb") == 0 || strcmp(argv[i], "RGB") == 0) {
            printVids = VID_RGB;
          }
          else if (strcmp(argv[i], "rgba") == 0 || strcmp(argv[i], "RGBA") == 0) {
            printVids = VID_RGBA;
          }
          else if (strcmp(argv[i], "ci") == 0 || strcmp(argv[i], "CI") == 0) {
            printVids = VID_CI;
          }
          else if (strcmp(argv[i], "all") == 0 || strcmp(argv[i], "ALL") == 0) {
            printVids = VID_ALL;
          }
          else {
            goto unknown;
          }
          printDisplayInfo = GL_FALSE;
          printScreenInfo = GL_FALSE;
          printVisualInfo = GL_TRUE;
          printCookedVisualInfo = GL_FALSE;
        }
	else
          goto unknown;
      }
      else if (strcmp(arg, "help") == 0
        || strcmp(arg, "?") == 0) {
        Usage();
      }
      else goto unknown;
    }
    else {
      goto unknown;
    }
  }
  return;

  unknown:
      fprintf(stderr, "unknown arg: %s\n", argv[i]);
      Usage();
    
  missing:
      fprintf(stderr, "missing arg for: %s\n", argv[i]);
      Usage();
}

void
PrintEventMask (
    int indent,				/* amount by which to indent */
    unsigned long mask				/* event mask */
)
{
  char buf[1024];
    int i, pad;
    int nameWidth = 21;
    unsigned long bit;
    int len = indent;
    int nameLen;
    int bitsfound = 0;
    char *name;

    for (i = 0; i < indent; i++) buf[i] = ' ';

    for (bit = 1; mask; bit <<= 1) {
      if (bit & mask) {
	mask ^= bit;		       /* clear bit from mask */
	name = EventMaskName((long)bit);
	nameLen = strlen(name);
	if (nameLen >= nameWidth) nameLen = nameWidth - 1; /* -1 for pad */
	pad = nameWidth - nameLen;
	if (len + nameLen > pageWidth) {
	  puts (buf);
	  len = indent;
	}
	strncpy(buf+len, name, nameLen);
	len += nameLen;
	if (len + pad > pageWidth) {
	  buf[len] = 0;
	  puts (buf);
	  len = indent;
	}
	else {
	  for (i = 0; i < pad; i++) buf[len++] = ' ';
	}
	buf[len] = 0;
	bitsfound++;
      }
    }

    if (bitsfound) puts (buf);
}

void
PrintExtensionInfo(
  Display    *dpy,
  int         fieldNameLen,
  int	      indent
)
{
  int         n = 0;
  int         len, lineLen;
  char      **extlist = XListExtensions(dpy, &n);


  printf("%*s%d total\n",
	 fieldNameLen, "Server Extensions:",
	 n);
  if (extlist) {
    register int i;

    printf("%*s", indent, "");
    lineLen = indent;
    for (i = 0; i < n; i++) {
      len = strlen(extlist[i]);
      len += 2;			       /* for ", " */
      if ((lineLen + len) >= pageWidth) {
	printf("\n%*s", indent, "");
	lineLen = indent;
      }
      printf("%s, ", extlist[i]);
      lineLen += len;
    }
    if (lineLen > indent) printf("\n");
    XFreeExtensionList(extlist);
  }
}

void
PrintPixmapFormats(
  Display    *dpy,
  int         fieldNameLen,
  int	      indent
)
{
  int i, n;
  XPixmapFormatValues *pmf;

  pmf = XListPixmapFormats(dpy, &n);
  printf("%*s%d total\n",
	 fieldNameLen, "pixmap formats:",
	 n);
  if (pmf) {
    for (i = 0; i < n; i++) {
      printf("%*sdepth %2d, bits_per_pixel %2d, scanline_pad %2d\n",
	     indent, "",
	     pmf[i].depth, pmf[i].bits_per_pixel, pmf[i].scanline_pad);
    }
    XFree((char *) pmf);
  }
}

void
PrintWindowFocus(
  Display    *dpy,
  int         fieldNameLen
)
{
  Window      focusWin;
  int         focusRevert;

  XGetInputFocus(dpy, &focusWin, &focusRevert);
  switch (focusWin) {
  case PointerRoot:
  case None:
    printf("%*s%s\n",
	   fieldNameLen, "focus:",
	   WindowFocusName(focusWin));
    break;
  default:
    printf("%*s0x%lx, revert to %s\n",
	   fieldNameLen, "focus window:",
	   focusWin, WindowFocusRevertName(focusRevert));
    break;
  }
}

void
PrintDisplayInfo(
  Display    *dpy,
  int         fieldNameLen
)
{
  char       *cp;
  const char *ccp;
  int         minkeycode, maxkeycode;
  char        title[256];
  int         i;
  int         titleLen, fillLen;
  int	      indent;

  if (fieldNameLen < 0) indent = -fieldNameLen;
  else indent = fieldNameLen;
  
  sprintf(title, " Display %s ", DisplayString(dpy));
  titleLen = strlen(title);
  fillLen = (pageWidth - titleLen) / 2;
  for (i = 0; i < fillLen; i++) printf("%c", '=');
  printf("%s", title);
  for (i = 0; i < fillLen; i++) printf("%c", '=');
  printf("\n");  

  printf("%*s%s\n",
	 fieldNameLen, "name of display:",
	 DisplayString(dpy));
  printf("%*s%d.%d\n",
	 fieldNameLen, "version number:",
	 ProtocolVersion(dpy), ProtocolRevision(dpy));
  printf("%*s%s\n",
	 fieldNameLen, "vendor string:",
	 ServerVendor(dpy));
  printf("%*s%d\n",
	 fieldNameLen, "vendor release:",
	 VendorRelease(dpy));
  printf("%*s%ld bytes\n",
	 fieldNameLen, "max request size:",
	 XMaxRequestSize(dpy) * 4);
  printf("%*s%d\n",
	 fieldNameLen, "motion buffer size:",
	 XDisplayMotionBufferSize(dpy));

  cp = ByteOrderName(BitmapBitOrder(dpy));
  printf("%*sunit = %d, bit order = %s, padding = %d\n",
	 fieldNameLen, "bitmap:",
	 BitmapUnit(dpy), cp, BitmapPad(dpy));

  cp = ByteOrderName(ImageByteOrder(dpy));
  printf("%*s%s\n",
	 fieldNameLen, "image byte order:",
	 cp);

  XDisplayKeycodes(dpy, &minkeycode, &maxkeycode);
  printf("%*sminimum %d, maximum %d\n",
	 fieldNameLen, "keycode range:",
	 minkeycode, maxkeycode);

  PrintWindowFocus(dpy, fieldNameLen);

  printf("%*s%d\n",
	 fieldNameLen, "default screen num:",
	 DefaultScreen(dpy));
  printf("%*s%d\n",
	 fieldNameLen, "number of screens:",
	 ScreenCount(dpy));


  PrintPixmapFormats(dpy, fieldNameLen, indent);
  PrintExtensionInfo(dpy, fieldNameLen, indent);

  printf("%*s",
	 fieldNameLen, "GLX Extension:");
  if (dpyHasGL) {
    printf("error base = %d, event base = %d, ",
	   glErrorBase, glEventBase);
    if (glXQueryVersion(dpy, &glXMajorVersion, &glXMinorVersion)) {
      printf("Version %d.%d\n",
	     glXMajorVersion, glXMinorVersion);
    }
    else {
      printf("glXQueryVersion returned error\n");
      exit(1);
    }
  }
  else {
    printf("NONE\n");
  }
#if defined(GLX_VERSION_1_1)
  ccp = glXGetClientString (dpy, GLX_VENDOR);
  if (ccp) {
    printf ("%*sVendor = %s\n", fieldNameLen, "GLX Library:", ccp);
  }
  else {
    printf ("%*sNo Vendor string\n", fieldNameLen, "GLX Library:");
  }
  ccp = glXGetClientString (dpy, GLX_VERSION);
  if (ccp) {
    printf ("%*sVersion = %s\n", indent, "", ccp);
  }
  else {
    printf ("%*sNo Version string\n", indent, "");
  }
  ccp = glXGetClientString (dpy, GLX_EXTENSIONS);
  PrintIndentedStringWithBlanks ("Extensions = ", ccp,
	fieldNameLen, 2);
#endif
#if defined (GLU_VERSION_1_1)
  ccp = (const char *) gluGetString (GLU_VERSION);
  if (ccp) {
    printf ("%*sVersion = %s\n", fieldNameLen, "GLU Library:", ccp);
  }
  else {
    printf ("%*sNo Version string\n", fieldNameLen, "GLU Library:");
  }
  ccp = (const char *) gluGetString (GLU_EXTENSIONS);
  PrintIndentedStringWithBlanks ("Extensions = ", ccp,
	fieldNameLen, 2);
#endif
}

static int 
QueryExtension(
    char *extName
)
{
    /*
    ** Search for extName in the extensions string.  Use of strstr()
    ** is not sufficient because extension names can be prefixes of
    ** other extension names.  Could use strtok() but the constant
    ** string returned by glXGetString can be in read-only memory.
    */
    char *p = (char *)glXExtensionString;
    char *end;
    int extNameLen;

    extNameLen = strlen(extName);

    end = p + strlen(p);

    while (p < end) {
        int n = strcspn(p, " ");
        if ((extNameLen == n) && (strncmp(extName, p, n) == 0)) {
            return GL_TRUE;
        }
        p += (n + 1);
    }
    return GL_FALSE;
}

int
GetGLVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    GLXVisualInfo *glVisual
)
{
  int result;

  if (!dpyHasGL) {
    glVisual->useGL = GL_FALSE;
    return(0);
  }

  GL_GET_CONFIG(GLX_USE_GL, &glVisual->useGL);

  if (!glVisual->useGL) return(0);

  GL_GET_CONFIG(GLX_BUFFER_SIZE, &glVisual->bufferSize);
  GL_GET_CONFIG(GLX_LEVEL, &glVisual->level);
  GL_GET_CONFIG(GLX_RGBA, &glVisual->rgba);
  GL_GET_CONFIG(GLX_DOUBLEBUFFER, &glVisual->doubleBuffer);
  GL_GET_CONFIG(GLX_STEREO, &glVisual->stereo);
  GL_GET_CONFIG(GLX_AUX_BUFFERS, &glVisual->auxBuffers);
  GL_GET_CONFIG(GLX_RED_SIZE, &glVisual->redSize);
  GL_GET_CONFIG(GLX_GREEN_SIZE, &glVisual->greenSize);
  GL_GET_CONFIG(GLX_BLUE_SIZE, &glVisual->blueSize);
  GL_GET_CONFIG(GLX_ALPHA_SIZE, &glVisual->alphaSize);
  GL_GET_CONFIG(GLX_DEPTH_SIZE, &glVisual->depthSize);
  GL_GET_CONFIG(GLX_STENCIL_SIZE, &glVisual->stencilSize);
  GL_GET_CONFIG(GLX_ACCUM_RED_SIZE, &glVisual->accumRedSize);
  GL_GET_CONFIG(GLX_ACCUM_GREEN_SIZE, &glVisual->accumGreenSize);
  GL_GET_CONFIG(GLX_ACCUM_BLUE_SIZE, &glVisual->accumBlueSize);
  GL_GET_CONFIG(GLX_ACCUM_ALPHA_SIZE, &glVisual->accumAlphaSize);

#ifdef GLX_VERSION_1_1
    if (glXMinorVersion > 0 || glXMajorVersion > 1)
      glXExtensionString = glXQueryExtensionsString(dpy, visual->screen);

#ifdef GLX_EXT_visual_rating
  if ( QueryExtension("GLX_EXT_visual_rating") ) {
      GL_GET_CONFIG(GLX_VISUAL_CAVEAT_EXT, &glVisual->visualCaveats);
      glXVisRating = GL_TRUE;
  }
#endif

#ifdef GLX_EXT_visual_info
  if ( QueryExtension("GLX_EXT_visual_info") ) {
      GL_GET_CONFIG(GLX_X_VISUAL_TYPE_EXT, &glVisual->xVisualType);
      GL_GET_CONFIG(GLX_TRANSPARENT_TYPE_EXT, &glVisual->transparentPixel);
      GL_GET_CONFIG(GLX_TRANSPARENT_INDEX_VALUE_EXT, &glVisual->transparentIndex);
      GL_GET_CONFIG(GLX_TRANSPARENT_RED_VALUE_EXT, &glVisual->transparentRedValue);
      GL_GET_CONFIG(GLX_TRANSPARENT_GREEN_VALUE_EXT, &glVisual->transparentGreenValue);
      GL_GET_CONFIG(GLX_TRANSPARENT_BLUE_VALUE_EXT, &glVisual->transparentBlueValue);
      GL_GET_CONFIG(GLX_TRANSPARENT_ALPHA_VALUE_EXT, &glVisual->transparentAlphaValue);
      glXVisInfo = GL_TRUE;
  }
#endif
#endif

  return(1);
}


void
PrintCookedVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    int indent
)
{
  int result;
  int hasRGB, hasAlpha, hasDepth, hasStencil, hasAccum, hasAuxBuffers;
  GLXVisualInfo glVisualInfo;
  GLXVisualInfo *gl = &glVisualInfo;
  int listEmpty;

  printf ("%s visual: ID = 0x%lx (hex) %d (decimal) screen = %d\n",
	  VisualClassName(visual->class) , visual->visualid, visual->visualid,
	  visual->screen);

  if (result = GetGLVisualInfo(dpy, visual, gl)) {

    hasRGB = ((gl->redSize != 0)   ||
	      (gl->greenSize != 0) ||
	      (gl->blueSize != 0));
    hasAlpha = (gl->alphaSize != 0);
    hasDepth = (gl->depthSize != 0);
    hasStencil = (gl->stencilSize != 0);
    hasAccum = ((gl->accumRedSize != 0)   ||
		(gl->accumGreenSize != 0) ||
		(gl->accumBlueSize != 0)  ||
		(gl->accumAlphaSize != 0));
    hasAuxBuffers = (gl->auxBuffers != 0);


    printf("%*s", indent, "");
    if (gl->level < 0) {
      printf("UNDERLAY(%d) ", -gl->level);
    }
    if (gl->level > 0) {
      printf("OVERLAY(%d) ", gl->level);
    }
    if (gl->doubleBuffer)
      printf("DOUBLE buffered ");
    else
      printf("SINGLE buffered ");

    if (gl->stereo)
      printf("STEREO ");
    else
      printf("MONO ");

    /*
     * RGBA visual
     */
    if (gl->rgba) {		       /* rgba visual */
      printf("RGB visual ");

      listEmpty = GL_TRUE;
      if (hasAlpha || hasDepth || hasStencil || hasAccum || hasAuxBuffers) {
	printf("with (");
	if (hasAlpha) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Alpha");
	}
	if (hasDepth) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Z");
	}
	if (hasStencil) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Stencil");
	}
	if (hasAccum) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Accum");
	}
	if (hasAuxBuffers) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("%d Aux Buffers", gl->auxBuffers);
	}
	printf(")\n");
      }

      printf("%*s", indent, "");
      printf("GL Sizes: RGBA=(%d,%d,%d,%d), ",
	     gl->redSize, gl->greenSize, gl->blueSize, gl->alphaSize);
      if (hasDepth)
	printf("Z=%d, ", gl->depthSize);
      if (hasStencil)
	printf("Stencil=%d, ", gl->stencilSize);
      if (hasAccum)
	printf("Accum=(%d,%d,%d,%d)",
	       gl->accumRedSize, gl->accumGreenSize, gl->accumBlueSize,
	       gl->accumAlphaSize);
      printf("\n");

      /*
       * Do some simple sanity checks on rgba visual.
       */
      if (!hasRGB)
	printf("WARNING: RGBA visual, but RGB have zero size\n");
      if (hasAlpha && hasAccum && gl->accumAlphaSize == 0)
	printf("WARNING: RGBA visual with Alpha and Accum, but Accum Alpha size is zero\n");
      if (!hasAlpha && hasAccum && gl->accumAlphaSize != 0)
	printf("WARNING: RGBA visual without Alpha and with Accum, but Accum Alpha size is not zero\n");
    }				       /* end rgba visual */
    /*
     * COLOR INDEX visual
     */
    else {			       /* color index visual */
      printf("COLOR INDEX visual ");

      listEmpty = GL_TRUE;
      if (hasDepth || hasStencil || hasAuxBuffers) {
	printf("with (");
	if (hasDepth) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Z");
	}
	if (hasStencil) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("Stencil");
	}
	if (hasAuxBuffers) {
	  if (listEmpty) listEmpty = GL_FALSE; else printf(" ");
	  printf("%d Aux Buffers");
	}
	printf(")\n");
      }

      printf("%*s", indent, "");
      printf("GL Sizes: ColorIndex=%d, ", gl->bufferSize);
      if (hasDepth)
	printf("Z=%d, ", gl->depthSize);
      if (hasStencil)
	printf("Stencil=%d", gl->stencilSize);
      printf("\n");

      /*
       * Do some simple sanity checks on color index visual.
       */
      if (hasRGB)
	printf("WARNING: CI visual, but RGB has non-zero sizes (%d,%d,%d)\n",
	       gl->redSize, gl->greenSize, gl->blueSize);
      if (hasAlpha)
	printf("WARNING: CI visual, but Alpha has non-zero size = %d\n",
	       gl->alphaSize);
      if (hasAccum)
	printf("WARNING: CI visual, but Accum has non-zero sizes (%d,%d,%d,%d)\n",
	       gl->accumRedSize, gl->accumGreenSize,
	       gl->accumBlueSize, gl->accumAlphaSize);
    }				       /* end color index visual */

    if (glXVisRating || glXVisInfo) {
      printf("%*s", indent, "");
      printf("Extensions: ");
    }
#ifdef GLX_EXT_visual_rating
    if (glXVisRating) {
      if (gl->visualCaveats == GLX_NONE_EXT)
        printf("Caveats=None");
      else if (gl->visualCaveats == GLX_SLOW_VISUAL_EXT)
        printf("Caveats=Slow");
      else
        printf("\nERROR: Unrecognized token for GLX_VISUAL_CAVEATS attribute\n");
    }
#endif

#ifdef GLX_EXT_visual_info
    if (glXVisInfo) {
      if (glXVisRating) printf(", ");
      if (gl->transparentPixel == GLX_NONE_EXT) {
        printf("OPAQUE ");
      }
      else if (gl->transparentPixel == GLX_TRANSPARENT_RGB_EXT) {
        printf("TRANSPARENT PIXEL, ");
        printf("color value=(%d,%d,%d,%d)", gl->transparentRedValue,
	       gl->transparentGreenValue, gl->transparentBlueValue, 
	       gl->transparentAlphaValue);
      }
      else if (gl->transparentPixel == GLX_TRANSPARENT_INDEX_EXT) {
        printf("TRANSPARENT PIXEL, ");
        printf("index value=%d", gl->transparentIndex);
      }
      else
        printf("\nERROR: Unrecognized token for GLX_TRANSPARENT_PIXEL attribute\n");
    }
#endif
    if (glXVisRating || glXVisInfo)
      printf("\n");
    }
  else {
    printf("%*s", indent, "");
    printf("GL NOT SUPPORTED\n");
  }

  printf("%*sCore X: ", indent, "");
  printf ("depth=%d, ", visual->depth);
  printf ("colormapSize=%d ", visual->colormap_size);

  if ((visual->class == TrueColor) || (visual->class == DirectColor)) {
    printf ("RGB: masks=(0x%lx,0x%lx,0x%lx) ",
	    visual->red_mask, visual->green_mask, visual->blue_mask);
    printf ("bits=%d",
	      visual->bits_per_rgb);
  }
  printf("\n");
}

void
PrintRawVisualInfo (
    Display    *dpy,
    XVisualInfo *visual,
    int indent
)
{
  int result;
  GLXVisualInfo glVisualInfo;
  GLXVisualInfo *gl = &glVisualInfo;

  printf ("%s visual: ID = 0x%lx (hex) %d (decimal) screen = %d\n",
	  VisualClassName(visual->class) , visual->visualid, visual->visualid,
	  visual->screen);
  
  if (result = GetGLVisualInfo(dpy, visual, gl)) {

    printf("%*s", indent, "");
    printf("useGL=%d, level=%d, doubleBuffer=%d, rgba=%d, stereo=%d\n",
	   gl->useGL, gl->level, gl->doubleBuffer, gl->rgba, gl->stereo);

    printf("%*s", indent, "");
    printf("bufferSize=%d, number aux buffers=%d\n",
	   gl->bufferSize, gl->auxBuffers);

    printf("%*s", indent, "");
    printf("sizes: RGBA=(%d,%d,%d,%d), Z=%d, STENCIL=%d, ACCUM=(%d,%d,%d,%d)\n",
	   gl->redSize, gl->greenSize, gl->blueSize, gl->alphaSize,
	   gl->depthSize, gl->stencilSize, 
	   gl->accumRedSize, gl->accumGreenSize,
	   gl->accumBlueSize, gl->accumAlphaSize);


    printf("%*s", indent, "");
    printf("Extensions: ");
#ifdef GLX_EXT_visual_rating
    if (glXVisRating) {
      if (gl->visualCaveats == GLX_NONE_EXT)
        printf("visualCaveats=NONE, ");
      else if (gl->visualCaveats == GLX_SLOW_VISUAL_EXT)
        printf("visualCaveats=SLOW_VISUAL, ");
      else
        printf("\nERROR: Unrecognized token for GLX_VISUAL_CAVEATS attribute\n");
    } 
    else
        printf("EXT_visual_rating not supported, ");
#else
    printf("EXT_visual_rating not supported, ");
#endif

#ifdef GLX_EXT_visual_info
    if (glXVisInfo) {
      if (glXVisRating) printf(", ");
      if (gl->transparentPixel == GLX_NONE_EXT) {
        printf("transparentPixel=NONE");
      }
      else if (gl->transparentPixel == GLX_TRANSPARENT_RGB_EXT) {
        printf("transparentPixel=PIXEL, ");
        printf("color value=(%d,%d,%d,%d)", gl->transparentRedValue,
               gl->transparentGreenValue, gl->transparentBlueValue, 
               gl->transparentAlphaValue);
      }
      else if (gl->transparentPixel == GLX_TRANSPARENT_INDEX_EXT) {
        printf("transparentPixel=PIXEL, ");
        printf("index value=%d", gl->transparentIndex);
      }
      else
        printf("\nERROR: Unrecognized token for GLX_TRANSPARENT_PIXEL attribute\n");
    }
    else
        printf("EXT_visual_info not supported ");
#else
    printf("EXT_visual_info not supported ");
#endif
    printf("\n");

  }
  else {
    printf("%*s", indent, "");
    printf("GL NOT SUPPORTED\n");
  }

  printf("%*sCore X: ", indent, "");
  printf ("depth=%d, ", visual->depth);
  printf ("colormapSize=%d ", visual->colormap_size);
  printf ("RGB: masks=(0x%lx,0x%lx,0x%lx) ",
	  visual->red_mask, visual->green_mask, visual->blue_mask);
  printf ("bits=%d",
	  visual->bits_per_rgb);
  printf("\n");
}

int
PrintVisualIDs (
    Display    *dpy,
    XVisualInfo *visual
)
{
  GLXVisualInfo glVisualInfo;
  GLXVisualInfo *gl = &glVisualInfo;

  if (!GetGLVisualInfo(dpy, visual, gl)) return(0);
  switch(printVids) {
  case VID_NONE:
    return(0);
  case VID_RGB:
    if (!gl->rgba || gl->alphaSize != 0) return(0);
    break;
  case VID_RGBA:
    if (!gl->rgba || gl->alphaSize == 0) return(0);
    break;
  case VID_CI:
    if (gl->rgba) return(0);
    break;
  case VID_ALL:
    break;
  default:
    return(0);
  }
  
  printf ("%d\n", visual->visualid);
  return(0);
}

static void PrintIndentedStringWithBlanks(
    const char	* head,
    const char	* string,
    int	        fieldNameLen,
    int		indent
)
{
    int			indentPos;
    const char		*cp;
    const char		*ncp;
    int			leftOnLine;
    
    if (fieldNameLen < 0) indentPos = -fieldNameLen;
    else indentPos = fieldNameLen;
    leftOnLine = pageWidth - indentPos - strlen (head);

    printf ("%*s%s", fieldNameLen, "", head);	/* first line */
    
    indentPos += indent;

    cp = string;
    
    if (cp == NULL)
    {
	printf ("(no string)\n");
	return;
    }
    if (*cp == 0)
    {
	printf ("(none)\n");
	return;
    }

    while (1)
    {
	if (strlen(cp) <= leftOnLine)
	{
	    printf ("%s\n", cp);
	    return;	    /* all done */
	}

	/* we must find a space at which to break the line */
	ncp = cp + leftOnLine;    /* last possible char */
	while (ncp > cp && *ncp != ' ') ncp--;
	if (ncp == cp)
	{
	    /* very long extension name; print it on one line */
	    ncp = cp + leftOnLine;
	    while (*ncp != 0 && *ncp != ' ') ncp++;
	}

	/* print from cp to ncp */
	printf ("%.*s\n", ncp - cp, cp);
	cp = ncp;

	/* skip to next non-blank */
	while (*cp == ' ') cp++;

	if (*cp == 0) return; /* all done */

	printf ("%*s", indentPos, "");
	leftOnLine = pageWidth - indentPos;
    }

}
void
PrintScreenInfo(
  Display    *dpy,
  int         scr,
  int         fieldNameLen,
  int	      indent
)
{
  Screen     *s = ScreenOfDisplay(dpy, scr);	/* opaque structure */
  int         i;		/* temp variable: iterator */
  static char *yes = "YES", *no = "NO", *when = "WHEN MAPPED";
  double      xres, yres;
  int         ndepths = 0, *depths = NULL;
  char        title[256];
  int         titleLen, fillLen;
  XVisualInfo	* vi;
  GLXContext	ctx;
  int		attrib_list[] = {0};
  Window	w;
  XSetWindowAttributes	wattribs;
  char	      *cp;
  const char	      *ccp;

  sprintf(title, " Screen %d ", scr);
  titleLen = strlen(title);
  fillLen = (pageWidth - titleLen) / 2;
  for (i = 0; i < fillLen; i++) printf("%c", '=');
  printf("%s", title);
  for (i = 0; i < fillLen; i++) printf("%c", '=');
  printf("\n");  

  /*
   * there are 2.54 centimeters to an inch; so there are 25.4 millimeters.
   * 
   * dpi = N pixels / (M millimeters / (25.4 millimeters / 1 inch)) = N pixels /
   * (M inch / 25.4) = N * 25.4 pixels / M inch
   */

  xres = ((((double) DisplayWidth(dpy, scr)) * 25.4) /
	  ((double) DisplayWidthMM(dpy, scr)));
  yres = ((((double) DisplayHeight(dpy, scr)) * 25.4) /
	  ((double) DisplayHeightMM(dpy, scr)));

  printf("%*s%d\n",
	 fieldNameLen, "screen:",
	 scr);
  printf("%*s%dx%d pixels (%dx%d millimeters)\n",
         fieldNameLen, "dimensions:",
	 DisplayWidth(dpy, scr), DisplayHeight(dpy, scr),
	 DisplayWidthMM(dpy, scr), DisplayHeightMM(dpy, scr));

  printf("%*s%dx%d dots per inch\n",
	 fieldNameLen, "resolution:",
	 (int) (xres + 0.5), (int) (yres + 0.5));
  depths = XListDepths(dpy, scr, &ndepths);
  if (!depths)
    ndepths = 0;
  printf("%*s(%d total):       ",
	 fieldNameLen, "depths:", ndepths);
  for (i = 0; i < ndepths; i++) {
    printf("%d", depths[i]);
    if (i < ndepths - 1) {
      putchar(',');
      putchar(' ');
    }
  }
  putchar('\n');
  if (depths)
    XFree((char *) depths);
  printf("%*s0x%lx\n",
	 fieldNameLen, "root window id:", RootWindow(dpy, scr));
  printf("%*s%d plane%s\n",
	 fieldNameLen, "depth of root window:",
	 DisplayPlanes(dpy, scr),
	 DisplayPlanes(dpy, scr) == 1 ? "" : "s");
  printf("%*s0x%lx\n",
	 fieldNameLen, "default visual id:",
	 XVisualIDFromVisual (DefaultVisual (dpy, scr)));
  printf("%*sminimum %d, maximum %d\n",
	 fieldNameLen, "number colormaps:",
	 MinCmapsOfScreen(s), MaxCmapsOfScreen(s));
  printf("%*s0x%lx, number colormap cells %d\n",
	 fieldNameLen, "default colormap:",
	 DefaultColormap(dpy, scr), DisplayCells(dpy, scr));
  printf("%*sblack 0x%lx, white 0x%lx\n",
	 fieldNameLen, "preallocated pixels:",  
	 BlackPixel(dpy, scr), WhitePixel(dpy, scr));
  printf("%*sbacking-store %s, save-unders %s\n",
	 fieldNameLen, "options:",
	 (DoesBackingStore(s) == NotUseful) ? no :
	 ((DoesBackingStore(s) == Always) ? yes : when),
	 DoesSaveUnders(s) ? yes : no);
  printf("%*s0x%lx\n",
	 fieldNameLen, "input event mask:", EventMaskOfScreen(s));
  PrintEventMask(fieldNameLen > 0 ? fieldNameLen : -fieldNameLen,
		 EventMaskOfScreen(s));

    if (dpyHasGL)
    {
	vi = glXChooseVisual (dpy, scr, attrib_list);
	if (vi == NULL)
	{
	    int attrib_list_again[] = {GLX_DOUBLEBUFFER, None};
	    vi = glXChooseVisual (dpy, scr, attrib_list_again);
	    if (vi == NULL)
	    {
		printf ("Error: could not find visual for OpenGL\n");
		return;	    
	    }
	}
	ctx = glXCreateContext (dpy, vi, NULL, False);
	wattribs.colormap = XCreateColormap (dpy, 
		RootWindow(dpy, scr), vi->visual, AllocNone);

#if defined(GLX_VERSION_1_1)
        ccp = glXQueryServerString (dpy, scr, GLX_VENDOR);
        if (ccp == NULL) ccp = "NOT AVAILABLE";
        printf ("%*sVendor = %s\n", fieldNameLen, "GLX Server:", ccp);
        ccp = glXQueryServerString (dpy, scr, GLX_VERSION);
        if (ccp == NULL) ccp = "NOT AVAILABLE";
        printf ("%*sVersion = %s\n", fieldNameLen, "", ccp);
        ccp = glXQueryServerString (dpy, scr, GLX_EXTENSIONS);
        if (ccp == NULL) ccp = "NOT AVAILABLE";
        PrintIndentedStringWithBlanks ("Extensions = ", ccp, fieldNameLen,
                                       indent);
        ccp = glXQueryExtensionsString (dpy, scr);
        PrintIndentedStringWithBlanks ("Useable Extensions = ", ccp, fieldNameLen,
                                       indent);
#endif

	w = XCreateWindow (dpy, RootWindow(dpy, scr),
	    0, 0, 1, 1, 0, vi->depth,
	    InputOutput, vi->visual, 
	    CWBackPixel | CWBorderPixel | CWColormap, 
	    &wattribs);
	glXMakeCurrent (dpy, w, ctx);
	cp = (char *) glGetString (GL_VENDOR);
	printf ("%*sVendor = %s\n", fieldNameLen, "GL Extension:", cp);
	cp = (char *) glGetString (GL_RENDERER);
	printf ("%*sRenderer = %s\n", fieldNameLen, "", cp);
	cp = (char *) glGetString (GL_VERSION);
	printf ("%*sVersion = %s\n", fieldNameLen, "", cp);
	cp = (char *) glGetString (GL_EXTENSIONS);
	PrintIndentedStringWithBlanks ("Extensions = ", cp, fieldNameLen,
		indent);
    }

  return;
}

void
PrintScreenVisualInfo(
  Display    *dpy,
  int         scr,
  int         fieldNameLen,
  int	      indent
)
{
  XVisualInfo visualTemplate;		/* fill in for getting info */
  XVisualInfo *visuals;		/* retured info */
  int         nVisuals;		/* number of elements returned */
  int         i;
  char        title[256];
  int         titleLen, fillLen;

  nVisuals = 0;
  visualTemplate.screen = scr;
  visuals = XGetVisualInfo(dpy, VisualScreenMask, &visualTemplate, &nVisuals);

  if (printVids == VID_NONE) {
    sprintf(title, " %d Visuals for Screen %d (default = 0x%lx) ",
            nVisuals, scr, XVisualIDFromVisual(DefaultVisual(dpy, scr)));
    titleLen = strlen(title);
    fillLen = (pageWidth - titleLen) / 2;
    for (i = 0; i < fillLen; i++) printf("%c", '=');
    printf("%s", title);
    for (i = 0; i < fillLen; i++) printf("%c", '=');
    printf("\n");  
  }

  for (i = 0; i < nVisuals; i++) {
    if (printVids != VID_NONE) {
      PrintVisualIDs (dpy, &visuals[i]);
    }
    else {
      if (printCookedVisualInfo)
        PrintCookedVisualInfo (dpy, &visuals[i], indent);
      else
        PrintRawVisualInfo (dpy, &visuals[i], indent);
      printf("\n");
    }
  }
  
  if (visuals)
    XFree((char *) visuals);

}

int
ProcessScreen(
  Display *dpy,
  int screenNum,
  int fieldNameLen,
  int indent
)
{
  if (screenNum >= ScreenCount(dpy)) {
    fprintf(stderr, "%s: screen %d does not exist on display \"%s\".\nscreen count = %d\n",
	    ProgramName, screenNum, XDisplayName(displayname),
            ScreenCount(dpy));
    exit(1);
  }
  
  if (printScreenInfo)
    PrintScreenInfo(dpy, screenNum, fieldNameLen, indent);
  if (printVisualInfo)
    PrintScreenVisualInfo(dpy, screenNum, fieldNameLen, indent);
  return(0);
}

/*****************************************************************************/
/****************************  Exported Functions  ***************************/
/*****************************************************************************/

int
main(
      int argc,
      char *argv[]
)
{
  Display    *dpy;		/* X connection */
  int         screenNum;
  int         fieldNameLen = -24;
  int         indent = 2;

  ProcessArgs(argc, argv);

  dpy = XOpenDisplay(displayname);
  if (!dpy) {
    fprintf(stderr, "%s:  unable to open display \"%s\".\n",
	    ProgramName, XDisplayName(displayname));
    exit(1);
  }

  dpyHasGL = glXQueryExtension(dpy, &glErrorBase, &glEventBase);


  if (printSpecficScreen) {
    if (specficScreenNum >= ScreenCount(dpy)) {
      fprintf(stderr, "%s: screen %d does not exist on display \"%s\".\nscreen count = %d\n",
              ProgramName, specficScreenNum, XDisplayName(displayname),
              ScreenCount(dpy));
      exit(1);
    }
  
    if (printDisplayInfo) PrintDisplayInfo(dpy, fieldNameLen);
    ProcessScreen(dpy, specficScreenNum, fieldNameLen, indent);
  }
  else {
    if (printDisplayInfo) PrintDisplayInfo(dpy, fieldNameLen);
    for (screenNum = 0; screenNum < ScreenCount(dpy); screenNum++) {
      ProcessScreen(dpy, screenNum, fieldNameLen, indent);
    }
  }
  
  return(XCloseDisplay(dpy));
}