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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /* $Id: glxinfo.c,v 1.14 2001/04/24 20:57:36 brianp Exp $ */
  2. /*
  3. * Copyright (C) 1999-2001 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. * -b only print ID of "best" visual on screen 0
  29. *
  30. * Brian Paul 26 January 2000
  31. */
  32. #define DO_GLU /* may want to remove this for easier XFree86 building? */
  33. #include <X11/Xlib.h>
  34. #include <X11/Xutil.h>
  35. #include <GL/gl.h>
  36. #ifdef DO_GLU
  37. #include <GL/glu.h>
  38. #endif
  39. #include <GL/glx.h>
  40. #include <stdio.h>
  41. #include <string.h>
  42. #include <stdlib.h>
  43. #ifndef GLX_NONE_EXT
  44. #define GLX_NONE_EXT 0x8000
  45. #endif
  46. typedef enum
  47. {
  48. Normal,
  49. Wide,
  50. Verbose
  51. } InfoMode;
  52. struct visual_attribs
  53. {
  54. /* X visual attribs */
  55. int id;
  56. int klass;
  57. int depth;
  58. int redMask, greenMask, blueMask;
  59. int colormapSize;
  60. int bitsPerRGB;
  61. /* GL visual attribs */
  62. int supportsGL;
  63. int transparent;
  64. int bufferSize;
  65. int level;
  66. int rgba;
  67. int doubleBuffer;
  68. int stereo;
  69. int auxBuffers;
  70. int redSize, greenSize, blueSize, alphaSize;
  71. int depthSize;
  72. int stencilSize;
  73. int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
  74. int numSamples, numMultisample;
  75. int visualCaveat;
  76. };
  77. /*
  78. * Print a list of extensions, with word-wrapping.
  79. */
  80. static void
  81. print_extension_list(const char *ext)
  82. {
  83. const char *indentString = " ";
  84. const int indent = 4;
  85. const int max = 79;
  86. int width, i, j;
  87. if (!ext || !ext[0])
  88. return;
  89. width = indent;
  90. printf(indentString);
  91. i = j = 0;
  92. while (1) {
  93. if (ext[j] == ' ' || ext[j] == 0) {
  94. /* found end of an extension name */
  95. const int len = j - i;
  96. if (width + len > max) {
  97. /* start a new line */
  98. printf("\n");
  99. width = indent;
  100. printf(indentString);
  101. }
  102. /* print the extension name between ext[i] and ext[j] */
  103. while (i < j) {
  104. printf("%c", ext[i]);
  105. i++;
  106. }
  107. /* either we're all done, or we'll continue with next extension */
  108. width += len + 1;
  109. if (ext[j] == 0) {
  110. break;
  111. }
  112. else {
  113. i++;
  114. j++;
  115. if (ext[j] == 0)
  116. break;
  117. printf(", ");
  118. width += 2;
  119. }
  120. }
  121. j++;
  122. }
  123. printf("\n");
  124. }
  125. static void
  126. print_display_info(Display *dpy)
  127. {
  128. printf("name of display: %s\n", DisplayString(dpy));
  129. }
  130. static void
  131. print_screen_info(Display *dpy, int scrnum, Bool allowDirect)
  132. {
  133. Window win;
  134. int attribSingle[] = {
  135. GLX_RGBA,
  136. GLX_RED_SIZE, 1,
  137. GLX_GREEN_SIZE, 1,
  138. GLX_BLUE_SIZE, 1,
  139. None };
  140. int attribDouble[] = {
  141. GLX_RGBA,
  142. GLX_RED_SIZE, 1,
  143. GLX_GREEN_SIZE, 1,
  144. GLX_BLUE_SIZE, 1,
  145. GLX_DOUBLEBUFFER,
  146. None };
  147. XSetWindowAttributes attr;
  148. unsigned long mask;
  149. Window root;
  150. GLXContext ctx;
  151. XVisualInfo *visinfo;
  152. int width = 100, height = 100;
  153. root = RootWindow(dpy, scrnum);
  154. visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
  155. if (!visinfo) {
  156. visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
  157. if (!visinfo) {
  158. fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
  159. return;
  160. }
  161. }
  162. attr.background_pixel = 0;
  163. attr.border_pixel = 0;
  164. attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
  165. attr.event_mask = StructureNotifyMask | ExposureMask;
  166. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  167. win = XCreateWindow(dpy, root, 0, 0, width, height,
  168. 0, visinfo->depth, InputOutput,
  169. visinfo->visual, mask, &attr);
  170. ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
  171. if (!ctx) {
  172. fprintf(stderr, "Error: glXCreateContext failed\n");
  173. XDestroyWindow(dpy, win);
  174. return;
  175. }
  176. if (glXMakeCurrent(dpy, win, ctx)) {
  177. const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
  178. const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
  179. const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
  180. const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
  181. const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
  182. const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
  183. const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
  184. const char *glVendor = (const char *) glGetString(GL_VENDOR);
  185. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  186. const char *glVersion = (const char *) glGetString(GL_VERSION);
  187. const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
  188. char *displayName = NULL;
  189. char *colon = NULL, *period = NULL;
  190. #ifdef DO_GLU
  191. const char *gluVersion = (const char *) gluGetString(GLU_VERSION);
  192. const char *gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS);
  193. #endif
  194. /* Strip the screen number from the display name, if present. */
  195. if (!(displayName = malloc(strlen(DisplayString(dpy)) + 1))) {
  196. fprintf(stderr, "Error: malloc() failed\n");
  197. exit(1);
  198. }
  199. strcpy(displayName, DisplayString(dpy));
  200. colon = strrchr(displayName, ':');
  201. if (colon) {
  202. period = strchr(colon, '.');
  203. if (period)
  204. *period = '\0';
  205. }
  206. printf("display: %s screen: %d\n", displayName, scrnum);
  207. free(displayName);
  208. printf("direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
  209. printf("server glx vendor string: %s\n", serverVendor);
  210. printf("server glx version string: %s\n", serverVersion);
  211. printf("server glx extensions:\n");
  212. print_extension_list(serverExtensions);
  213. printf("client glx vendor string: %s\n", clientVendor);
  214. printf("client glx version string: %s\n", clientVersion);
  215. printf("client glx extensions:\n");
  216. print_extension_list(clientExtensions);
  217. printf("GLX extensions:\n");
  218. print_extension_list(glxExtensions);
  219. printf("OpenGL vendor string: %s\n", glVendor);
  220. printf("OpenGL renderer string: %s\n", glRenderer);
  221. printf("OpenGL version string: %s\n", glVersion);
  222. printf("OpenGL extensions:\n");
  223. print_extension_list(glExtensions);
  224. #ifdef DO_GLU
  225. printf("glu version: %s\n", gluVersion);
  226. printf("glu extensions:\n");
  227. print_extension_list(gluExtensions);
  228. #endif
  229. }
  230. else {
  231. fprintf(stderr, "Error: glXMakeCurrent failed\n");
  232. }
  233. glXDestroyContext(dpy, ctx);
  234. XDestroyWindow(dpy, win);
  235. }
  236. static const char *
  237. visual_class_name(int cls)
  238. {
  239. switch (cls) {
  240. case StaticColor:
  241. return "StaticColor";
  242. case PseudoColor:
  243. return "PseudoColor";
  244. case StaticGray:
  245. return "StaticGray";
  246. case GrayScale:
  247. return "GrayScale";
  248. case TrueColor:
  249. return "TrueColor";
  250. case DirectColor:
  251. return "DirectColor";
  252. default:
  253. return "";
  254. }
  255. }
  256. static const char *
  257. visual_class_abbrev(int cls)
  258. {
  259. switch (cls) {
  260. case StaticColor:
  261. return "sc";
  262. case PseudoColor:
  263. return "pc";
  264. case StaticGray:
  265. return "sg";
  266. case GrayScale:
  267. return "gs";
  268. case TrueColor:
  269. return "tc";
  270. case DirectColor:
  271. return "dc";
  272. default:
  273. return "";
  274. }
  275. }
  276. static void
  277. get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
  278. struct visual_attribs *attribs)
  279. {
  280. const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
  281. memset(attribs, 0, sizeof(struct visual_attribs));
  282. attribs->id = vInfo->visualid;
  283. #if defined(__cplusplus) || defined(c_plusplus)
  284. attribs->klass = vInfo->c_class;
  285. #else
  286. attribs->klass = vInfo->class;
  287. #endif
  288. attribs->depth = vInfo->depth;
  289. attribs->redMask = vInfo->red_mask;
  290. attribs->greenMask = vInfo->green_mask;
  291. attribs->blueMask = vInfo->blue_mask;
  292. attribs->colormapSize = vInfo->colormap_size;
  293. attribs->bitsPerRGB = vInfo->bits_per_rgb;
  294. if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
  295. return;
  296. glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
  297. glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
  298. glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
  299. glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
  300. glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
  301. glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
  302. glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
  303. glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
  304. glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
  305. glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
  306. glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
  307. glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
  308. glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
  309. glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
  310. glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
  311. glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
  312. /* transparent pixel value not implemented yet */
  313. attribs->transparent = 0;
  314. /* multisample tests not implemented yet */
  315. attribs->numSamples = 0;
  316. attribs->numMultisample = 0;
  317. #if defined(GLX_EXT_visual_rating)
  318. if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
  319. glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
  320. }
  321. else {
  322. attribs->visualCaveat = GLX_NONE_EXT;
  323. }
  324. #else
  325. attribs->visualCaveat = 0;
  326. #endif
  327. }
  328. static void
  329. print_visual_attribs_verbose(const struct visual_attribs *attribs)
  330. {
  331. printf("Visual ID: %x depth=%d class=%s\n",
  332. attribs->id, attribs->depth, visual_class_name(attribs->klass));
  333. printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
  334. attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci",
  335. attribs->doubleBuffer, attribs->stereo);
  336. printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  337. attribs->redSize, attribs->greenSize,
  338. attribs->blueSize, attribs->alphaSize);
  339. printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
  340. attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
  341. printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  342. attribs->accumRedSize, attribs->accumGreenSize,
  343. attribs->accumBlueSize, attribs->accumAlphaSize);
  344. printf(" multiSample=%d multiSampleBuffers=%d\n",
  345. attribs->numSamples, attribs->numMultisample);
  346. #ifdef GLX_EXT_visual_rating
  347. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  348. printf(" visualCaveat=None\n");
  349. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  350. printf(" visualCaveat=Slow\n");
  351. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  352. printf(" visualCaveat=Nonconformant\n");
  353. #endif
  354. printf(" %s\n", attribs->transparent ? "Transparent." : "Opaque.");
  355. }
  356. static void
  357. print_visual_attribs_short_header(void)
  358. {
  359. printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
  360. 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");
  361. printf("----------------------------------------------------------------------\n");
  362. }
  363. static void
  364. print_visual_attribs_short(const struct visual_attribs *attribs)
  365. {
  366. char *caveat;
  367. #ifdef GLX_EXT_visual_rating
  368. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  369. caveat = "None";
  370. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  371. caveat = "Slow";
  372. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  373. caveat = "Ncon";
  374. #else
  375. caveat = "None";
  376. #endif
  377. printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d",
  378. attribs->id,
  379. attribs->depth,
  380. visual_class_abbrev(attribs->klass),
  381. attribs->transparent,
  382. attribs->bufferSize,
  383. attribs->level,
  384. attribs->rgba ? "r" : "c",
  385. attribs->doubleBuffer ? "y" : ".",
  386. attribs->stereo ? "y" : ".",
  387. attribs->redSize, attribs->greenSize,
  388. attribs->blueSize, attribs->alphaSize,
  389. attribs->auxBuffers,
  390. attribs->depthSize,
  391. attribs->stencilSize
  392. );
  393. printf(" %2d %2d %2d %2d %2d %1d %s\n",
  394. attribs->accumRedSize, attribs->accumGreenSize,
  395. attribs->accumBlueSize, attribs->accumAlphaSize,
  396. attribs->numSamples, attribs->numMultisample,
  397. caveat
  398. );
  399. }
  400. static void
  401. print_visual_attribs_long_header(void)
  402. {
  403. printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
  404. printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
  405. printf("----------------------------------------------------------------------------------------------------\n");
  406. }
  407. static void
  408. print_visual_attribs_long(const struct visual_attribs *attribs)
  409. {
  410. printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
  411. attribs->id,
  412. attribs->depth,
  413. visual_class_name(attribs->klass),
  414. attribs->transparent,
  415. attribs->bufferSize,
  416. attribs->level,
  417. attribs->rgba ? "rgba" : "ci ",
  418. attribs->doubleBuffer,
  419. attribs->stereo,
  420. attribs->redSize, attribs->greenSize,
  421. attribs->blueSize, attribs->alphaSize
  422. );
  423. printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
  424. attribs->auxBuffers,
  425. attribs->depthSize,
  426. attribs->stencilSize,
  427. attribs->accumRedSize, attribs->accumGreenSize,
  428. attribs->accumBlueSize, attribs->accumAlphaSize,
  429. attribs->numSamples, attribs->numMultisample
  430. );
  431. }
  432. static void
  433. print_visual_info(Display *dpy, int scrnum, InfoMode mode)
  434. {
  435. XVisualInfo template;
  436. XVisualInfo *visuals;
  437. int numVisuals;
  438. long mask;
  439. int i;
  440. /* get list of all visuals on this screen */
  441. template.screen = scrnum;
  442. mask = VisualScreenMask;
  443. visuals = XGetVisualInfo(dpy, mask, &template, &numVisuals);
  444. if (mode == Verbose) {
  445. for (i = 0; i < numVisuals; i++) {
  446. struct visual_attribs attribs;
  447. get_visual_attribs(dpy, &visuals[i], &attribs);
  448. print_visual_attribs_verbose(&attribs);
  449. }
  450. }
  451. else if (mode == Normal) {
  452. print_visual_attribs_short_header();
  453. for (i = 0; i < numVisuals; i++) {
  454. struct visual_attribs attribs;
  455. get_visual_attribs(dpy, &visuals[i], &attribs);
  456. print_visual_attribs_short(&attribs);
  457. }
  458. }
  459. else if (mode == Wide) {
  460. print_visual_attribs_long_header();
  461. for (i = 0; i < numVisuals; i++) {
  462. struct visual_attribs attribs;
  463. get_visual_attribs(dpy, &visuals[i], &attribs);
  464. print_visual_attribs_long(&attribs);
  465. }
  466. }
  467. XFree(visuals);
  468. }
  469. /*
  470. * Stand-alone Mesa doesn't really implement the GLX protocol so it
  471. * doesn't really know the GLX attributes associated with an X visual.
  472. * The first time a visual is presented to Mesa's pseudo-GLX it
  473. * attaches ancilliary buffers to it (like depth and stencil).
  474. * But that usually only works if glXChooseVisual is used.
  475. * This function calls glXChooseVisual() to sort of "prime the pump"
  476. * for Mesa's GLX so that the visuals that get reported actually
  477. * reflect what applications will see.
  478. * This has no effect when using true GLX.
  479. */
  480. static void
  481. mesa_hack(Display *dpy, int scrnum)
  482. {
  483. static int attribs[] = {
  484. GLX_RGBA,
  485. GLX_RED_SIZE, 1,
  486. GLX_GREEN_SIZE, 1,
  487. GLX_BLUE_SIZE, 1,
  488. GLX_DEPTH_SIZE, 1,
  489. GLX_STENCIL_SIZE, 1,
  490. GLX_ACCUM_RED_SIZE, 1,
  491. GLX_ACCUM_GREEN_SIZE, 1,
  492. GLX_ACCUM_BLUE_SIZE, 1,
  493. GLX_ACCUM_ALPHA_SIZE, 1,
  494. GLX_DOUBLEBUFFER,
  495. None
  496. };
  497. XVisualInfo *visinfo;
  498. visinfo = glXChooseVisual(dpy, scrnum, attribs);
  499. if (visinfo)
  500. XFree(visinfo);
  501. }
  502. /*
  503. * Examine all visuals to find the so-called best one.
  504. * We prefer deepest RGBA buffer with depth, stencil and accum
  505. * that has no caveats.
  506. */
  507. static int
  508. find_best_visual(Display *dpy, int scrnum)
  509. {
  510. XVisualInfo template;
  511. XVisualInfo *visuals;
  512. int numVisuals;
  513. long mask;
  514. int i;
  515. struct visual_attribs bestVis;
  516. /* get list of all visuals on this screen */
  517. template.screen = scrnum;
  518. mask = VisualScreenMask;
  519. visuals = XGetVisualInfo(dpy, mask, &template, &numVisuals);
  520. /* init bestVis with first visual info */
  521. get_visual_attribs(dpy, &visuals[0], &bestVis);
  522. /* try to find a "better" visual */
  523. for (i = 1; i < numVisuals; i++) {
  524. struct visual_attribs vis;
  525. get_visual_attribs(dpy, &visuals[i], &vis);
  526. /* always skip visuals with caveats */
  527. if (vis.visualCaveat != GLX_NONE_EXT)
  528. continue;
  529. /* see if this vis is better than bestVis */
  530. if ((!bestVis.supportsGL && vis.supportsGL) ||
  531. (bestVis.visualCaveat != GLX_NONE_EXT) ||
  532. (!bestVis.rgba && vis.rgba) ||
  533. (!bestVis.doubleBuffer && vis.doubleBuffer) ||
  534. (bestVis.redSize < vis.redSize) ||
  535. (bestVis.greenSize < vis.greenSize) ||
  536. (bestVis.blueSize < vis.blueSize) ||
  537. (bestVis.alphaSize < vis.alphaSize) ||
  538. (bestVis.depthSize < vis.depthSize) ||
  539. (bestVis.stencilSize < vis.stencilSize) ||
  540. (bestVis.accumRedSize < vis.accumRedSize)) {
  541. /* found a better visual */
  542. bestVis = vis;
  543. }
  544. }
  545. XFree(visuals);
  546. return bestVis.id;
  547. }
  548. static void
  549. usage(void)
  550. {
  551. printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
  552. printf("\t-v: Print visuals info in verbose form.\n");
  553. printf("\t-t: Print verbose table.\n");
  554. printf("\t-display <dname>: Print GLX visuals on specified server.\n");
  555. printf("\t-h: This information.\n");
  556. printf("\t-i: Force an indirect rendering context.\n");
  557. printf("\t-b: Find the 'best' visual and print it's number.\n");
  558. }
  559. int
  560. main(int argc, char *argv[])
  561. {
  562. char *displayName = NULL;
  563. Display *dpy;
  564. int numScreens, scrnum;
  565. InfoMode mode = Normal;
  566. GLboolean findBest = GL_FALSE;
  567. Bool allowDirect = True;
  568. int i;
  569. for (i = 1; i < argc; i++) {
  570. if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
  571. displayName = argv[i + 1];
  572. i++;
  573. }
  574. else if (strcmp(argv[i], "-t") == 0) {
  575. mode = Wide;
  576. }
  577. else if (strcmp(argv[i], "-v") == 0) {
  578. mode = Verbose;
  579. }
  580. else if (strcmp(argv[i], "-b") == 0) {
  581. findBest = GL_TRUE;
  582. }
  583. else if (strcmp(argv[i], "-i") == 0) {
  584. allowDirect = False;
  585. }
  586. else if (strcmp(argv[i], "-h") == 0) {
  587. usage();
  588. return 0;
  589. }
  590. else {
  591. printf("Unknown option `%s'\n", argv[i]);
  592. usage();
  593. return 0;
  594. }
  595. }
  596. dpy = XOpenDisplay(displayName);
  597. if (!dpy) {
  598. fprintf(stderr, "Error: unable to open display %s\n", displayName);
  599. return -1;
  600. }
  601. if (findBest) {
  602. int b;
  603. mesa_hack(dpy, 0);
  604. b = find_best_visual(dpy, 0);
  605. printf("%d\n", b);
  606. }
  607. else {
  608. numScreens = ScreenCount(dpy);
  609. print_display_info(dpy);
  610. for (scrnum = 0; scrnum < numScreens; scrnum++) {
  611. mesa_hack(dpy, scrnum);
  612. print_screen_info(dpy, scrnum, allowDirect);
  613. printf("\n");
  614. print_visual_info(dpy, scrnum, mode);
  615. if (scrnum + 1 < numScreens)
  616. printf("\n\n");
  617. }
  618. }
  619. XCloseDisplay(dpy);
  620. return 0;
  621. }