Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

glxinfo.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /* $Id: glxinfo.c,v 1.10 2000/05/08 14:53:57 brianp Exp $ */
  2. /*
  3. * Copyright (C) 1999 Brian Paul All Rights Reserved.
  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. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  19. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  20. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  21. */
  22. /*
  23. * This program is a work-alike of the IRIX glxinfo program.
  24. * Command line options:
  25. * -t print wide table
  26. * -v print verbose information
  27. * -display DisplayName specify the X display to interogate
  28. *
  29. * Brian Paul 26 January 2000
  30. */
  31. #include <X11/Xlib.h>
  32. #include <X11/Xutil.h>
  33. #include <GL/gl.h>
  34. #include <GL/glu.h>
  35. #include <GL/glx.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38. typedef enum
  39. {
  40. Normal,
  41. Wide,
  42. Verbose
  43. } InfoMode;
  44. struct visual_attribs
  45. {
  46. /* X visual attribs */
  47. int id;
  48. int klass;
  49. int depth;
  50. int redMask, greenMask, blueMask;
  51. int colormapSize;
  52. int bitsPerRGB;
  53. /* GL visual attribs */
  54. int supportsGL;
  55. int transparent;
  56. int bufferSize;
  57. int level;
  58. int rgba;
  59. int doubleBuffer;
  60. int stereo;
  61. int auxBuffers;
  62. int redSize, greenSize, blueSize, alphaSize;
  63. int depthSize;
  64. int stencilSize;
  65. int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
  66. int numSamples, numMultisample;
  67. int visualCaveat;
  68. };
  69. /*
  70. * Print a list of extensions, with word-wrapping.
  71. */
  72. static void
  73. print_extension_list(const char *ext)
  74. {
  75. const char *indentString = " ";
  76. const int indent = 4;
  77. const int max = 79;
  78. int width, i, j;
  79. if (!ext || !ext[0])
  80. return;
  81. width = indent;
  82. printf(indentString);
  83. i = j = 0;
  84. while (1) {
  85. if (ext[j] == ' ' || ext[j] == 0) {
  86. /* found end of an extension name */
  87. const int len = j - i;
  88. if (width + len > max) {
  89. /* start a new line */
  90. printf("\n");
  91. width = indent;
  92. printf(indentString);
  93. }
  94. /* print the extension name between ext[i] and ext[j] */
  95. while (i < j) {
  96. printf("%c", ext[i]);
  97. i++;
  98. }
  99. /* either we're all done, or we'll continue with next extension */
  100. width += len + 1;
  101. if (ext[j] == 0) {
  102. break;
  103. }
  104. else {
  105. i++;
  106. j++;
  107. if (ext[j] == 0)
  108. break;
  109. printf(", ");
  110. width += 2;
  111. }
  112. }
  113. j++;
  114. }
  115. printf("\n");
  116. }
  117. static void
  118. print_screen_info(Display *dpy, int scrnum)
  119. {
  120. Window win;
  121. int attribSingle[] = {
  122. GLX_RGBA,
  123. GLX_RED_SIZE, 1,
  124. GLX_GREEN_SIZE, 1,
  125. GLX_BLUE_SIZE, 1,
  126. None };
  127. int attribDouble[] = {
  128. GLX_RGBA,
  129. GLX_RED_SIZE, 1,
  130. GLX_GREEN_SIZE, 1,
  131. GLX_BLUE_SIZE, 1,
  132. GLX_DOUBLEBUFFER,
  133. None };
  134. XSetWindowAttributes attr;
  135. unsigned long mask;
  136. Window root;
  137. GLXContext ctx;
  138. XVisualInfo *visinfo;
  139. int width = 100, height = 100;
  140. root = RootWindow(dpy, scrnum);
  141. visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
  142. if (!visinfo) {
  143. visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
  144. if (!visinfo) {
  145. fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
  146. return;
  147. }
  148. }
  149. attr.background_pixel = 0;
  150. attr.border_pixel = 0;
  151. attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
  152. attr.event_mask = StructureNotifyMask | ExposureMask;
  153. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  154. win = XCreateWindow(dpy, root, 0, 0, width, height,
  155. 0, visinfo->depth, InputOutput,
  156. visinfo->visual, mask, &attr);
  157. ctx = glXCreateContext( dpy, visinfo, NULL, True );
  158. if (!ctx) {
  159. fprintf(stderr, "Error: glXCreateContext failed\n");
  160. XDestroyWindow(dpy, win);
  161. return;
  162. }
  163. if (glXMakeCurrent(dpy, win, ctx)) {
  164. const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
  165. const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
  166. const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
  167. const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
  168. const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
  169. const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
  170. const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
  171. const char *glVendor = (const char *) glGetString(GL_VENDOR);
  172. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  173. const char *glVersion = (const char *) glGetString(GL_VERSION);
  174. const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
  175. const char *gluVersion = (const char *) gluGetString(GLU_VERSION);
  176. const char *gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS);
  177. printf("display: %s screen:%d\n", DisplayString(dpy), scrnum);
  178. printf("direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
  179. printf("server glx vendor string: %s\n", serverVendor);
  180. printf("server glx version string: %s\n", serverVersion);
  181. printf("server glx extensions:\n");
  182. print_extension_list(serverExtensions);
  183. printf("client glx vendor string: %s\n", clientVendor);
  184. printf("client glx version string: %s\n", clientVersion);
  185. printf("client glx extensions:\n");
  186. print_extension_list(clientExtensions);
  187. printf("GLX extensions:\n");
  188. print_extension_list(glxExtensions);
  189. printf("OpenGL vendor string: %s\n", glVendor);
  190. printf("OpenGL renderer string: %s\n", glRenderer);
  191. printf("OpenGL version string: %s\n", glVersion);
  192. printf("OpenGL extensions:\n");
  193. print_extension_list(glExtensions);
  194. printf("glu version: %s\n", gluVersion);
  195. printf("glu extensions:\n");
  196. print_extension_list(gluExtensions);
  197. }
  198. else {
  199. fprintf(stderr, "Error: glXMakeCurrent failed\n");
  200. }
  201. glXDestroyContext(dpy, ctx);
  202. XDestroyWindow(dpy, win);
  203. }
  204. static const char *
  205. visual_class_name(int cls)
  206. {
  207. switch (cls) {
  208. case StaticColor:
  209. return "StaticColor";
  210. case PseudoColor:
  211. return "PseudoColor";
  212. case StaticGray:
  213. return "StaticGray";
  214. case GrayScale:
  215. return "GrayScale";
  216. case TrueColor:
  217. return "TrueColor";
  218. case DirectColor:
  219. return "DirectColor";
  220. default:
  221. return "";
  222. }
  223. }
  224. static const char *
  225. visual_class_abbrev(int cls)
  226. {
  227. switch (cls) {
  228. case StaticColor:
  229. return "sc";
  230. case PseudoColor:
  231. return "pc";
  232. case StaticGray:
  233. return "sg";
  234. case GrayScale:
  235. return "gs";
  236. case TrueColor:
  237. return "tc";
  238. case DirectColor:
  239. return "dc";
  240. default:
  241. return "";
  242. }
  243. }
  244. static void
  245. get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
  246. struct visual_attribs *attribs)
  247. {
  248. const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
  249. memset(attribs, 0, sizeof(struct visual_attribs));
  250. attribs->id = vInfo->visualid;
  251. #if defined(__cplusplus) || defined(c_plusplus)
  252. attribs->klass = vInfo->c_class;
  253. #else
  254. attribs->klass = vInfo->class;
  255. #endif
  256. attribs->depth = vInfo->depth;
  257. attribs->redMask = vInfo->red_mask;
  258. attribs->greenMask = vInfo->green_mask;
  259. attribs->blueMask = vInfo->blue_mask;
  260. attribs->colormapSize = vInfo->colormap_size;
  261. attribs->bitsPerRGB = vInfo->bits_per_rgb;
  262. if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
  263. return;
  264. glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
  265. glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
  266. glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
  267. glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
  268. glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
  269. glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
  270. glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
  271. glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
  272. glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
  273. glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
  274. glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
  275. glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
  276. glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
  277. glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
  278. glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
  279. glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
  280. /* transparent pixel value not implemented yet */
  281. attribs->transparent = 0;
  282. /* multisample tests not implemented yet */
  283. attribs->numSamples = 0;
  284. attribs->numMultisample = 0;
  285. #if defined(GLX_EXT_visual_rating)
  286. if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
  287. glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
  288. }
  289. else {
  290. attribs->visualCaveat = GLX_NONE_EXT;
  291. }
  292. #else
  293. attribs->visualCaveat = 0;
  294. #endif
  295. }
  296. static void
  297. print_visual_attribs_verbose(const struct visual_attribs *attribs)
  298. {
  299. printf("Visual ID: %x depth=%d class=%s\n",
  300. attribs->id, attribs->depth, visual_class_name(attribs->klass));
  301. printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
  302. attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci",
  303. attribs->doubleBuffer, attribs->stereo);
  304. printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  305. attribs->redSize, attribs->greenSize,
  306. attribs->blueSize, attribs->alphaSize);
  307. printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
  308. attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
  309. printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  310. attribs->accumRedSize, attribs->accumGreenSize,
  311. attribs->accumBlueSize, attribs->accumAlphaSize);
  312. printf(" multiSample=%d multiSampleBuffers=%d\n",
  313. attribs->numSamples, attribs->numMultisample);
  314. #ifdef GLX_EXT_visual_rating
  315. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  316. printf(" visualCaveat=None\n");
  317. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  318. printf(" visualCaveat=Slow\n");
  319. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  320. printf(" visualCaveat=Nonconformant\n");
  321. #endif
  322. printf(" %s\n", attribs->transparent ? "Transparent." : "Opaque.");
  323. }
  324. static void
  325. print_visual_attribs_short_header(void)
  326. {
  327. printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
  328. printf(" id dep cl sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n");
  329. printf("----------------------------------------------------------------------\n");
  330. }
  331. static void
  332. print_visual_attribs_short(const struct visual_attribs *attribs)
  333. {
  334. char *caveat;
  335. #ifdef GLX_EXT_visual_rating
  336. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  337. caveat = "None";
  338. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  339. caveat = "Slow";
  340. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  341. caveat = "Ncon";
  342. #else
  343. caveat = "None";
  344. #endif
  345. printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d",
  346. attribs->id,
  347. attribs->depth,
  348. visual_class_abbrev(attribs->klass),
  349. attribs->transparent,
  350. attribs->bufferSize,
  351. attribs->level,
  352. attribs->rgba ? "r" : "c",
  353. attribs->doubleBuffer ? "y" : ".",
  354. attribs->stereo ? "y" : ".",
  355. attribs->redSize, attribs->greenSize,
  356. attribs->blueSize, attribs->alphaSize,
  357. attribs->auxBuffers,
  358. attribs->depthSize,
  359. attribs->stencilSize
  360. );
  361. printf(" %2d %2d %2d %2d %2d %1d %s\n",
  362. attribs->accumRedSize, attribs->accumGreenSize,
  363. attribs->accumBlueSize, attribs->accumAlphaSize,
  364. attribs->numSamples, attribs->numMultisample,
  365. caveat
  366. );
  367. }
  368. static void
  369. print_visual_attribs_long_header(void)
  370. {
  371. printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
  372. printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
  373. printf("----------------------------------------------------------------------------------------------------\n");
  374. }
  375. static void
  376. print_visual_attribs_long(const struct visual_attribs *attribs)
  377. {
  378. printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
  379. attribs->id,
  380. attribs->depth,
  381. visual_class_name(attribs->klass),
  382. attribs->transparent,
  383. attribs->bufferSize,
  384. attribs->level,
  385. attribs->rgba ? "rgba" : "ci ",
  386. attribs->doubleBuffer,
  387. attribs->stereo,
  388. attribs->redSize, attribs->greenSize,
  389. attribs->blueSize, attribs->alphaSize
  390. );
  391. printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
  392. attribs->auxBuffers,
  393. attribs->depthSize,
  394. attribs->stencilSize,
  395. attribs->accumRedSize, attribs->accumGreenSize,
  396. attribs->accumBlueSize, attribs->accumAlphaSize,
  397. attribs->numSamples, attribs->numMultisample
  398. );
  399. }
  400. static void
  401. print_visual_info(Display *dpy, int scrnum, InfoMode mode)
  402. {
  403. XVisualInfo template;
  404. XVisualInfo *visuals;
  405. int numVisuals;
  406. long mask;
  407. int i;
  408. /* get list of all visuals on this screen */
  409. template.screen = scrnum;
  410. mask = VisualScreenMask;
  411. visuals = XGetVisualInfo(dpy, mask, &template, &numVisuals);
  412. if (mode == Verbose) {
  413. for (i = 0; i < numVisuals; i++) {
  414. struct visual_attribs attribs;
  415. get_visual_attribs(dpy, &visuals[i], &attribs);
  416. print_visual_attribs_verbose(&attribs);
  417. }
  418. }
  419. else if (mode == Normal) {
  420. print_visual_attribs_short_header();
  421. for (i = 0; i < numVisuals; i++) {
  422. struct visual_attribs attribs;
  423. get_visual_attribs(dpy, &visuals[i], &attribs);
  424. print_visual_attribs_short(&attribs);
  425. }
  426. }
  427. else if (mode == Wide) {
  428. print_visual_attribs_long_header();
  429. for (i = 0; i < numVisuals; i++) {
  430. struct visual_attribs attribs;
  431. get_visual_attribs(dpy, &visuals[i], &attribs);
  432. print_visual_attribs_long(&attribs);
  433. }
  434. }
  435. XFree(visuals);
  436. }
  437. int
  438. main(int argc, char *argv[])
  439. {
  440. char *displayName = ":0";
  441. Display *dpy;
  442. int numScreens, scrnum;
  443. InfoMode mode = Normal;
  444. int i;
  445. for (i = 1; i < argc; i++) {
  446. if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
  447. displayName = argv[i + 1];
  448. i++;
  449. }
  450. else if (strcmp(argv[i], "-t") == 0) {
  451. mode = Wide;
  452. }
  453. else if (strcmp(argv[i], "-v") == 0) {
  454. mode = Verbose;
  455. }
  456. }
  457. dpy = XOpenDisplay(displayName);
  458. if (!dpy) {
  459. fprintf(stderr, "Error: unable to open display %s\n", displayName);
  460. return -1;
  461. }
  462. numScreens = ScreenCount(dpy);
  463. for (scrnum = 0; scrnum < numScreens; scrnum++) {
  464. print_screen_info(dpy, scrnum);
  465. printf("\n");
  466. print_visual_info(dpy, scrnum, mode);
  467. if (scrnum + 1 < numScreens)
  468. printf("\n\n");
  469. }
  470. XCloseDisplay(dpy);
  471. return 0;
  472. }