/* * Client application for querying drivers' configuration information * Copyright (C) 2003 Felix Kuehling * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #define GLX_GLXEXT_PROTOTYPES #include <GL/glx.h> #include <GL/glxext.h> #include <X11/Xlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> typedef const char * glXGetScreenDriver_t (Display *dpy, int scrNum); typedef const char * glXGetDriverConfig_t (const char *driverName); static glXGetScreenDriver_t *GetScreenDriver; static glXGetDriverConfig_t *GetDriverConfig; enum INFO_FUNC { LIST, NSCREENS, DRIVER, OPTIONS }; void printUsage (void); void printUsage (void) { fprintf (stderr, "Usage: xdriinfo [-display <dpy>] [-version] [command]\n" "Commands:\n" " nscreens print the number of screens on display\n" " driver screen print the DRI driver name of screen\n" " options screen|driver print configuration information about screen or driver\n" "If no command is given then the DRI drivers for all screens are listed.\n"); } int main (int argc, char *argv[]) { Display *dpy; int nScreens, screenNum, i; enum INFO_FUNC func = LIST; char *funcArg = NULL; char *dpyName = NULL; GetScreenDriver = (glXGetScreenDriver_t *)glXGetProcAddressARB ((const GLubyte *)"glXGetScreenDriver"); GetDriverConfig = (glXGetDriverConfig_t *)glXGetProcAddressARB ((const GLubyte *)"glXGetDriverConfig"); if (!GetScreenDriver || !GetDriverConfig) { fprintf (stderr, "libGL is too old.\n"); return 1; } /* parse the command line */ for (i = 1; i < argc; ++i) { char **argPtr = NULL; if (!strcmp (argv[i], "-display")) argPtr = &dpyName; else if (!strcmp (argv[i], "nscreens")) func = NSCREENS; else if (!strcmp (argv[i], "driver")) { func = DRIVER; argPtr = &funcArg; } else if (!strcmp (argv[i], "options")) { func = OPTIONS; argPtr = &funcArg; } else if (!strcmp (argv[i], "-version")) { puts(PACKAGE_STRING); return 0; } else { fprintf (stderr, "%s: unrecognized argument '%s'\n", argv[0], argv[i]); printUsage (); return 1; } if (argPtr) { if (++i == argc) { fprintf (stderr, "%s: '%s' requires an argument\n", argv[0], argv[i-1]); printUsage (); return 1; } *argPtr = argv[i]; } } /* parse screen number argument */ if (func == DRIVER || func == OPTIONS) { if (sscanf (funcArg, "%i", &screenNum) != 1) screenNum = -1; else if (screenNum < 0) { fprintf (stderr, "Negative screen number \"%s\".\n", funcArg); return 1; } } /* driver command needs a valid screen number */ if (func == DRIVER && screenNum == -1) { fprintf (stderr, "Invalid screen number \"%s\".\n", funcArg); return 1; } /* open display and count the number of screens */ if (!(dpy = XOpenDisplay (dpyName))) { fprintf (stderr, "Error: Couldn't open display\n"); return 1; } nScreens = ScreenCount (dpy); /* final check on the screen number argument (if any)*/ if ((func == DRIVER || func == OPTIONS) && screenNum >= nScreens) { fprintf (stderr, "Screen number \"%d\" out of range.\n", screenNum); return 1; } /* Call glXGetClientString to load vendor libs on glvnd enabled systems */ glXGetClientString (dpy, GLX_EXTENSIONS); switch (func) { case NSCREENS: printf ("%d", nScreens); if (isatty (STDOUT_FILENO)) printf ("\n"); break; case DRIVER: { const char *name = (*GetScreenDriver) (dpy, screenNum); if (!name) { fprintf (stderr, "Screen \"%d\" is not direct rendering capable.\n", screenNum); return 1; } printf ("%s", name); if (isatty (STDOUT_FILENO)) printf ("\n"); break; } case OPTIONS: { const char *name, *options; if (screenNum == -1) { name = funcArg; } else { name = (*GetScreenDriver) (dpy, screenNum); } if (!name) { fprintf (stderr, "Screen \"%d\" is not direct rendering capable.\n", screenNum); return 1; } options = (*GetDriverConfig) (name); if (!options) { fprintf (stderr, "Driver \"%s\" is not installed or does not support configuration.\n", name); return 1; } printf ("%s", options); if (isatty (STDOUT_FILENO)) printf ("\n"); break; } case LIST: for (i = 0; i < nScreens; ++i) { const char *name = (*GetScreenDriver) (dpy, i); if (name) printf ("Screen %d: %s\n", i, name); else printf ("Screen %d: not direct rendering capable.\n", i); } } return 0; }