1/* 2 * Client application for querying drivers' configuration information 3 * Copyright (C) 2003 Felix Kuehling 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 * 23 */ 24 25#ifdef HAVE_CONFIG_H 26# include "config.h" 27#endif 28 29#define GLX_GLXEXT_PROTOTYPES 30#include <GL/glx.h> 31#include <GL/glxext.h> 32#include <X11/Xlib.h> 33#include <stdio.h> 34#include <unistd.h> 35#include <string.h> 36 37typedef const char * glXGetScreenDriver_t (Display *dpy, int scrNum); 38typedef const char * glXGetDriverConfig_t (const char *driverName); 39 40static glXGetScreenDriver_t *GetScreenDriver; 41static glXGetDriverConfig_t *GetDriverConfig; 42 43enum INFO_FUNC { 44 LIST, NSCREENS, DRIVER, OPTIONS 45}; 46 47void printUsage (void); 48 49void printUsage (void) { 50 fprintf (stderr, 51"Usage: xdriinfo [-display <dpy>] [-version] [command]\n" 52"Commands:\n" 53" nscreens print the number of screens on display\n" 54" driver screen print the DRI driver name of screen\n" 55" options screen|driver print configuration information about screen or driver\n" 56"If no command is given then the DRI drivers for all screens are listed.\n"); 57} 58 59int main (int argc, char *argv[]) { 60 Display *dpy; 61 int nScreens, screenNum; 62 enum INFO_FUNC func = LIST; 63 char *funcArg = NULL; 64 char *dpyName = NULL; 65 66 GetScreenDriver = (glXGetScreenDriver_t *)glXGetProcAddressARB ((const GLubyte *)"glXGetScreenDriver"); 67 GetDriverConfig = (glXGetDriverConfig_t *)glXGetProcAddressARB ((const GLubyte *)"glXGetDriverConfig"); 68 if (!GetScreenDriver || !GetDriverConfig) { 69 fprintf (stderr, "libGL is too old.\n"); 70 return 1; 71 } 72 73 /* parse the command line */ 74 for (int i = 1; i < argc; ++i) { 75 char **argPtr = NULL; 76 if (!strcmp (argv[i], "-display")) 77 argPtr = &dpyName; 78 else if (!strcmp (argv[i], "nscreens")) 79 func = NSCREENS; 80 else if (!strcmp (argv[i], "driver")) { 81 func = DRIVER; 82 argPtr = &funcArg; 83 } else if (!strcmp (argv[i], "options")) { 84 func = OPTIONS; 85 argPtr = &funcArg; 86 } else if (!strcmp (argv[i], "-version")) { 87 puts(PACKAGE_STRING); 88 return 0; 89 } else { 90 fprintf (stderr, "%s: unrecognized argument '%s'\n", 91 argv[0], argv[i]); 92 printUsage (); 93 return 1; 94 } 95 if (argPtr) { 96 if (++i == argc) { 97 fprintf (stderr, "%s: '%s' requires an argument\n", 98 argv[0], argv[i-1]); 99 printUsage (); 100 return 1; 101 } 102 *argPtr = argv[i]; 103 } 104 } 105 106 /* parse screen number argument */ 107 if (func == DRIVER || func == OPTIONS) { 108 if (sscanf (funcArg, "%i", &screenNum) != 1) 109 screenNum = -1; 110 else if (screenNum < 0) { 111 fprintf (stderr, "Negative screen number \"%s\".\n", funcArg); 112 return 1; 113 } 114 } 115 else 116 screenNum = -1; 117 118 /* driver command needs a valid screen number */ 119 if (func == DRIVER && screenNum == -1) { 120 fprintf (stderr, "Invalid screen number \"%s\".\n", funcArg); 121 return 1; 122 } 123 124 /* open display and count the number of screens */ 125 if (!(dpy = XOpenDisplay (dpyName))) { 126 fprintf (stderr, "Error: Couldn't open display\n"); 127 return 1; 128 } 129 nScreens = ScreenCount (dpy); 130 131 /* final check on the screen number argument (if any)*/ 132 if ((func == DRIVER || func == OPTIONS) && screenNum >= nScreens) { 133 fprintf (stderr, "Screen number \"%d\" out of range.\n", screenNum); 134 return 1; 135 } 136 137 /* Call glXGetClientString to load vendor libs on glvnd enabled systems */ 138 glXGetClientString (dpy, GLX_EXTENSIONS); 139 140 switch (func) { 141 case NSCREENS: 142 printf ("%d", nScreens); 143 if (isatty (STDOUT_FILENO)) 144 printf ("\n"); 145 break; 146 case DRIVER: { 147 const char *name = (*GetScreenDriver) (dpy, screenNum); 148 if (!name) { 149 fprintf (stderr, "Screen \"%d\" is not direct rendering capable.\n", 150 screenNum); 151 return 1; 152 } 153 printf ("%s", name); 154 if (isatty (STDOUT_FILENO)) 155 printf ("\n"); 156 break; 157 } 158 case OPTIONS: { 159 const char *name, *options; 160 161 if (screenNum == -1) { 162 name = funcArg; 163 } else { 164 name = (*GetScreenDriver) (dpy, screenNum); 165 } 166 if (!name) { 167 fprintf (stderr, "Screen \"%d\" is not direct rendering capable.\n", 168 screenNum); 169 return 1; 170 } 171 options = (*GetDriverConfig) (name); 172 if (!options) { 173 fprintf (stderr, 174 "Driver \"%s\" is not installed or does not support configuration.\n", 175 name); 176 return 1; 177 } 178 printf ("%s", options); 179 if (isatty (STDOUT_FILENO)) 180 printf ("\n"); 181 break; 182 } 183 case LIST: 184 for (int i = 0; i < nScreens; ++i) { 185 const char *name = (*GetScreenDriver) (dpy, i); 186 if (name) 187 printf ("Screen %d: %s\n", i, name); 188 else 189 printf ("Screen %d: not direct rendering capable.\n", i); 190 } 191 } 192 193 return 0; 194} 195