Clone of mesa.
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /*
  2. * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included
  12. * in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  15. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  18. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. */
  21. /*
  22. * This program is a work-alike of the IRIX glxinfo program.
  23. * Command line options:
  24. * -t print wide table
  25. * -v print verbose information
  26. * -display DisplayName specify the X display to interogate
  27. * -b only print ID of "best" visual on screen 0
  28. * -i use indirect rendering connection only
  29. * -l print interesting OpenGL limits (added 5 Sep 2002)
  30. *
  31. * Brian Paul 26 January 2000
  32. */
  33. #define DO_GLU /* may want to remove this for easier XFree86 building? */
  34. #include <X11/Xlib.h>
  35. #include <X11/Xutil.h>
  36. #include <GL/gl.h>
  37. #ifdef DO_GLU
  38. #include <GL/glu.h>
  39. #endif
  40. #include <GL/glx.h>
  41. #include <stdio.h>
  42. #include <string.h>
  43. #include <stdlib.h>
  44. #ifndef GLX_NONE_EXT
  45. #define GLX_NONE_EXT 0x8000
  46. #endif
  47. #ifndef GLX_TRANSPARENT_RGB
  48. #define GLX_TRANSPARENT_RGB 0x8008
  49. #endif
  50. typedef enum
  51. {
  52. Normal,
  53. Wide,
  54. Verbose
  55. } InfoMode;
  56. struct visual_attribs
  57. {
  58. /* X visual attribs */
  59. int id;
  60. int klass;
  61. int depth;
  62. int redMask, greenMask, blueMask;
  63. int colormapSize;
  64. int bitsPerRGB;
  65. /* GL visual attribs */
  66. int supportsGL;
  67. int transparentType;
  68. int transparentRedValue;
  69. int transparentGreenValue;
  70. int transparentBlueValue;
  71. int transparentAlphaValue;
  72. int transparentIndexValue;
  73. int bufferSize;
  74. int level;
  75. int rgba;
  76. int doubleBuffer;
  77. int stereo;
  78. int auxBuffers;
  79. int redSize, greenSize, blueSize, alphaSize;
  80. int depthSize;
  81. int stencilSize;
  82. int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
  83. int numSamples, numMultisample;
  84. int visualCaveat;
  85. };
  86. /*
  87. * Print a list of extensions, with word-wrapping.
  88. */
  89. static void
  90. print_extension_list(const char *ext)
  91. {
  92. const char *indentString = " ";
  93. const int indent = 4;
  94. const int max = 79;
  95. int width, i, j;
  96. if (!ext || !ext[0])
  97. return;
  98. width = indent;
  99. printf(indentString);
  100. i = j = 0;
  101. while (1) {
  102. if (ext[j] == ' ' || ext[j] == 0) {
  103. /* found end of an extension name */
  104. const int len = j - i;
  105. if (width + len > max) {
  106. /* start a new line */
  107. printf("\n");
  108. width = indent;
  109. printf(indentString);
  110. }
  111. /* print the extension name between ext[i] and ext[j] */
  112. while (i < j) {
  113. printf("%c", ext[i]);
  114. i++;
  115. }
  116. /* either we're all done, or we'll continue with next extension */
  117. width += len + 1;
  118. if (ext[j] == 0) {
  119. break;
  120. }
  121. else {
  122. i++;
  123. j++;
  124. if (ext[j] == 0)
  125. break;
  126. printf(", ");
  127. width += 2;
  128. }
  129. }
  130. j++;
  131. }
  132. printf("\n");
  133. }
  134. static void
  135. print_display_info(Display *dpy)
  136. {
  137. printf("name of display: %s\n", DisplayString(dpy));
  138. }
  139. static void
  140. print_limits(void)
  141. {
  142. struct token_name {
  143. GLuint count;
  144. GLenum token;
  145. const char *name;
  146. };
  147. static const struct token_name limits[] = {
  148. { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" },
  149. { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" },
  150. { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" },
  151. { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" },
  152. { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" },
  153. { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" },
  154. { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" },
  155. { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" },
  156. { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" },
  157. { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" },
  158. { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" },
  159. { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" },
  160. { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" },
  161. { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" },
  162. { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" },
  163. { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" },
  164. { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" },
  165. { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" },
  166. { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" },
  167. { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" },
  168. { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" },
  169. { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" },
  170. { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" },
  171. { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" },
  172. { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" },
  173. { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" },
  174. { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" },
  175. { 0, (GLenum) 0, NULL }
  176. };
  177. GLint i, max[2];
  178. printf("OpenGL limits:\n");
  179. for (i = 0; limits[i].count; i++) {
  180. glGetIntegerv(limits[i].token, max);
  181. if (glGetError() == GL_NONE) {
  182. if (limits[i].count == 1)
  183. printf(" %s = %d\n", limits[i].name, max[0]);
  184. else /* XXX fix if we ever query something with more than 2 values */
  185. printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]);
  186. }
  187. }
  188. }
  189. static void
  190. print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
  191. {
  192. Window win;
  193. int attribSingle[] = {
  194. GLX_RGBA,
  195. GLX_RED_SIZE, 1,
  196. GLX_GREEN_SIZE, 1,
  197. GLX_BLUE_SIZE, 1,
  198. None };
  199. int attribDouble[] = {
  200. GLX_RGBA,
  201. GLX_RED_SIZE, 1,
  202. GLX_GREEN_SIZE, 1,
  203. GLX_BLUE_SIZE, 1,
  204. GLX_DOUBLEBUFFER,
  205. None };
  206. XSetWindowAttributes attr;
  207. unsigned long mask;
  208. Window root;
  209. GLXContext ctx;
  210. XVisualInfo *visinfo;
  211. int width = 100, height = 100;
  212. root = RootWindow(dpy, scrnum);
  213. visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
  214. if (!visinfo) {
  215. visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
  216. if (!visinfo) {
  217. fprintf(stderr, "Error: couldn't find RGB GLX visual\n");
  218. return;
  219. }
  220. }
  221. attr.background_pixel = 0;
  222. attr.border_pixel = 0;
  223. attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
  224. attr.event_mask = StructureNotifyMask | ExposureMask;
  225. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  226. win = XCreateWindow(dpy, root, 0, 0, width, height,
  227. 0, visinfo->depth, InputOutput,
  228. visinfo->visual, mask, &attr);
  229. ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
  230. if (!ctx) {
  231. fprintf(stderr, "Error: glXCreateContext failed\n");
  232. XDestroyWindow(dpy, win);
  233. return;
  234. }
  235. if (glXMakeCurrent(dpy, win, ctx)) {
  236. const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
  237. const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
  238. const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
  239. const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
  240. const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
  241. const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
  242. const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
  243. const char *glVendor = (const char *) glGetString(GL_VENDOR);
  244. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  245. const char *glVersion = (const char *) glGetString(GL_VERSION);
  246. const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
  247. char *displayName = NULL;
  248. char *colon = NULL, *period = NULL;
  249. #ifdef DO_GLU
  250. const char *gluVersion = (const char *) gluGetString(GLU_VERSION);
  251. const char *gluExtensions = (const char *) gluGetString(GLU_EXTENSIONS);
  252. #endif
  253. /* Strip the screen number from the display name, if present. */
  254. if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
  255. fprintf(stderr, "Error: malloc() failed\n");
  256. exit(1);
  257. }
  258. strcpy(displayName, DisplayString(dpy));
  259. colon = strrchr(displayName, ':');
  260. if (colon) {
  261. period = strchr(colon, '.');
  262. if (period)
  263. *period = '\0';
  264. }
  265. printf("display: %s screen: %d\n", displayName, scrnum);
  266. free(displayName);
  267. printf("direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
  268. printf("server glx vendor string: %s\n", serverVendor);
  269. printf("server glx version string: %s\n", serverVersion);
  270. printf("server glx extensions:\n");
  271. print_extension_list(serverExtensions);
  272. printf("client glx vendor string: %s\n", clientVendor);
  273. printf("client glx version string: %s\n", clientVersion);
  274. printf("client glx extensions:\n");
  275. print_extension_list(clientExtensions);
  276. printf("GLX extensions:\n");
  277. print_extension_list(glxExtensions);
  278. printf("OpenGL vendor string: %s\n", glVendor);
  279. printf("OpenGL renderer string: %s\n", glRenderer);
  280. printf("OpenGL version string: %s\n", glVersion);
  281. printf("OpenGL extensions:\n");
  282. print_extension_list(glExtensions);
  283. if (limits)
  284. print_limits();
  285. #ifdef DO_GLU
  286. printf("glu version: %s\n", gluVersion);
  287. printf("glu extensions:\n");
  288. print_extension_list(gluExtensions);
  289. #endif
  290. }
  291. else {
  292. fprintf(stderr, "Error: glXMakeCurrent failed\n");
  293. }
  294. glXDestroyContext(dpy, ctx);
  295. XDestroyWindow(dpy, win);
  296. }
  297. static const char *
  298. visual_class_name(int cls)
  299. {
  300. switch (cls) {
  301. case StaticColor:
  302. return "StaticColor";
  303. case PseudoColor:
  304. return "PseudoColor";
  305. case StaticGray:
  306. return "StaticGray";
  307. case GrayScale:
  308. return "GrayScale";
  309. case TrueColor:
  310. return "TrueColor";
  311. case DirectColor:
  312. return "DirectColor";
  313. default:
  314. return "";
  315. }
  316. }
  317. static const char *
  318. visual_class_abbrev(int cls)
  319. {
  320. switch (cls) {
  321. case StaticColor:
  322. return "sc";
  323. case PseudoColor:
  324. return "pc";
  325. case StaticGray:
  326. return "sg";
  327. case GrayScale:
  328. return "gs";
  329. case TrueColor:
  330. return "tc";
  331. case DirectColor:
  332. return "dc";
  333. default:
  334. return "";
  335. }
  336. }
  337. static void
  338. get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
  339. struct visual_attribs *attribs)
  340. {
  341. const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
  342. memset(attribs, 0, sizeof(struct visual_attribs));
  343. attribs->id = vInfo->visualid;
  344. #if defined(__cplusplus) || defined(c_plusplus)
  345. attribs->klass = vInfo->c_class;
  346. #else
  347. attribs->klass = vInfo->class;
  348. #endif
  349. attribs->depth = vInfo->depth;
  350. attribs->redMask = vInfo->red_mask;
  351. attribs->greenMask = vInfo->green_mask;
  352. attribs->blueMask = vInfo->blue_mask;
  353. attribs->colormapSize = vInfo->colormap_size;
  354. attribs->bitsPerRGB = vInfo->bits_per_rgb;
  355. if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0)
  356. return;
  357. glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
  358. glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
  359. glXGetConfig(dpy, vInfo, GLX_RGBA, &attribs->rgba);
  360. glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
  361. glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
  362. glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
  363. glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
  364. glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
  365. glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
  366. glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
  367. glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
  368. glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
  369. glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
  370. glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
  371. glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
  372. glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
  373. /* get transparent pixel stuff */
  374. glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
  375. if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
  376. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
  377. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
  378. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
  379. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
  380. }
  381. else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
  382. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
  383. }
  384. /* multisample attribs */
  385. #ifdef GLX_ARB_multisample
  386. if (strstr("GLX_ARB_multisample", ext) == 0) {
  387. glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
  388. glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
  389. }
  390. #endif
  391. else {
  392. attribs->numSamples = 0;
  393. attribs->numMultisample = 0;
  394. }
  395. #if defined(GLX_EXT_visual_rating)
  396. if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
  397. glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
  398. }
  399. else {
  400. attribs->visualCaveat = GLX_NONE_EXT;
  401. }
  402. #else
  403. attribs->visualCaveat = 0;
  404. #endif
  405. }
  406. static void
  407. print_visual_attribs_verbose(const struct visual_attribs *attribs)
  408. {
  409. printf("Visual ID: %x depth=%d class=%s\n",
  410. attribs->id, attribs->depth, visual_class_name(attribs->klass));
  411. printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
  412. attribs->bufferSize, attribs->level, attribs->rgba ? "rgba" : "ci",
  413. attribs->doubleBuffer, attribs->stereo);
  414. printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  415. attribs->redSize, attribs->greenSize,
  416. attribs->blueSize, attribs->alphaSize);
  417. printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
  418. attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
  419. printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  420. attribs->accumRedSize, attribs->accumGreenSize,
  421. attribs->accumBlueSize, attribs->accumAlphaSize);
  422. printf(" multiSample=%d multiSampleBuffers=%d\n",
  423. attribs->numSamples, attribs->numMultisample);
  424. #ifdef GLX_EXT_visual_rating
  425. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  426. printf(" visualCaveat=None\n");
  427. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  428. printf(" visualCaveat=Slow\n");
  429. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  430. printf(" visualCaveat=Nonconformant\n");
  431. #endif
  432. if (attribs->transparentType == GLX_NONE) {
  433. printf(" Opaque.\n");
  434. }
  435. else if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
  436. printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue);
  437. }
  438. else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
  439. printf(" Transparent index=%d\n",attribs->transparentIndexValue);
  440. }
  441. }
  442. static void
  443. print_visual_attribs_short_header(void)
  444. {
  445. printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
  446. 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");
  447. printf("----------------------------------------------------------------------\n");
  448. }
  449. static void
  450. print_visual_attribs_short(const struct visual_attribs *attribs)
  451. {
  452. char *caveat = NULL;
  453. #ifdef GLX_EXT_visual_rating
  454. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  455. caveat = "None";
  456. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  457. caveat = "Slow";
  458. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  459. caveat = "Ncon";
  460. else
  461. caveat = "None";
  462. #else
  463. caveat = "None";
  464. #endif
  465. printf("0x%2x %2d %2s %2d %2d %2d %1s %2s %2s %2d %2d %2d %2d %2d %2d %2d",
  466. attribs->id,
  467. attribs->depth,
  468. visual_class_abbrev(attribs->klass),
  469. attribs->transparentType != GLX_NONE,
  470. attribs->bufferSize,
  471. attribs->level,
  472. attribs->rgba ? "r" : "c",
  473. attribs->doubleBuffer ? "y" : ".",
  474. attribs->stereo ? "y" : ".",
  475. attribs->redSize, attribs->greenSize,
  476. attribs->blueSize, attribs->alphaSize,
  477. attribs->auxBuffers,
  478. attribs->depthSize,
  479. attribs->stencilSize
  480. );
  481. printf(" %2d %2d %2d %2d %2d %1d %s\n",
  482. attribs->accumRedSize, attribs->accumGreenSize,
  483. attribs->accumBlueSize, attribs->accumAlphaSize,
  484. attribs->numSamples, attribs->numMultisample,
  485. caveat
  486. );
  487. }
  488. static void
  489. print_visual_attribs_long_header(void)
  490. {
  491. printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
  492. printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
  493. printf("----------------------------------------------------------------------------------------------------\n");
  494. }
  495. static void
  496. print_visual_attribs_long(const struct visual_attribs *attribs)
  497. {
  498. printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
  499. attribs->id,
  500. attribs->depth,
  501. visual_class_name(attribs->klass),
  502. attribs->transparentType != GLX_NONE,
  503. attribs->bufferSize,
  504. attribs->level,
  505. attribs->rgba ? "rgba" : "ci ",
  506. attribs->doubleBuffer,
  507. attribs->stereo,
  508. attribs->redSize, attribs->greenSize,
  509. attribs->blueSize, attribs->alphaSize
  510. );
  511. printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
  512. attribs->auxBuffers,
  513. attribs->depthSize,
  514. attribs->stencilSize,
  515. attribs->accumRedSize, attribs->accumGreenSize,
  516. attribs->accumBlueSize, attribs->accumAlphaSize,
  517. attribs->numSamples, attribs->numMultisample
  518. );
  519. }
  520. static void
  521. print_visual_info(Display *dpy, int scrnum, InfoMode mode)
  522. {
  523. XVisualInfo theTemplate;
  524. XVisualInfo *visuals;
  525. int numVisuals;
  526. long mask;
  527. int i;
  528. /* get list of all visuals on this screen */
  529. theTemplate.screen = scrnum;
  530. mask = VisualScreenMask;
  531. visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
  532. if (mode == Verbose) {
  533. for (i = 0; i < numVisuals; i++) {
  534. struct visual_attribs attribs;
  535. get_visual_attribs(dpy, &visuals[i], &attribs);
  536. print_visual_attribs_verbose(&attribs);
  537. }
  538. }
  539. else if (mode == Normal) {
  540. print_visual_attribs_short_header();
  541. for (i = 0; i < numVisuals; i++) {
  542. struct visual_attribs attribs;
  543. get_visual_attribs(dpy, &visuals[i], &attribs);
  544. print_visual_attribs_short(&attribs);
  545. }
  546. }
  547. else if (mode == Wide) {
  548. print_visual_attribs_long_header();
  549. for (i = 0; i < numVisuals; i++) {
  550. struct visual_attribs attribs;
  551. get_visual_attribs(dpy, &visuals[i], &attribs);
  552. print_visual_attribs_long(&attribs);
  553. }
  554. }
  555. XFree(visuals);
  556. }
  557. /*
  558. * Stand-alone Mesa doesn't really implement the GLX protocol so it
  559. * doesn't really know the GLX attributes associated with an X visual.
  560. * The first time a visual is presented to Mesa's pseudo-GLX it
  561. * attaches ancilliary buffers to it (like depth and stencil).
  562. * But that usually only works if glXChooseVisual is used.
  563. * This function calls glXChooseVisual() to sort of "prime the pump"
  564. * for Mesa's GLX so that the visuals that get reported actually
  565. * reflect what applications will see.
  566. * This has no effect when using true GLX.
  567. */
  568. static void
  569. mesa_hack(Display *dpy, int scrnum)
  570. {
  571. static int attribs[] = {
  572. GLX_RGBA,
  573. GLX_RED_SIZE, 1,
  574. GLX_GREEN_SIZE, 1,
  575. GLX_BLUE_SIZE, 1,
  576. GLX_DEPTH_SIZE, 1,
  577. GLX_STENCIL_SIZE, 1,
  578. GLX_ACCUM_RED_SIZE, 1,
  579. GLX_ACCUM_GREEN_SIZE, 1,
  580. GLX_ACCUM_BLUE_SIZE, 1,
  581. GLX_ACCUM_ALPHA_SIZE, 1,
  582. GLX_DOUBLEBUFFER,
  583. None
  584. };
  585. XVisualInfo *visinfo;
  586. visinfo = glXChooseVisual(dpy, scrnum, attribs);
  587. if (visinfo)
  588. XFree(visinfo);
  589. }
  590. /*
  591. * Examine all visuals to find the so-called best one.
  592. * We prefer deepest RGBA buffer with depth, stencil and accum
  593. * that has no caveats.
  594. */
  595. static int
  596. find_best_visual(Display *dpy, int scrnum)
  597. {
  598. XVisualInfo theTemplate;
  599. XVisualInfo *visuals;
  600. int numVisuals;
  601. long mask;
  602. int i;
  603. struct visual_attribs bestVis;
  604. /* get list of all visuals on this screen */
  605. theTemplate.screen = scrnum;
  606. mask = VisualScreenMask;
  607. visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
  608. /* init bestVis with first visual info */
  609. get_visual_attribs(dpy, &visuals[0], &bestVis);
  610. /* try to find a "better" visual */
  611. for (i = 1; i < numVisuals; i++) {
  612. struct visual_attribs vis;
  613. get_visual_attribs(dpy, &visuals[i], &vis);
  614. /* always skip visuals with caveats */
  615. if (vis.visualCaveat != GLX_NONE_EXT)
  616. continue;
  617. /* see if this vis is better than bestVis */
  618. if ((!bestVis.supportsGL && vis.supportsGL) ||
  619. (bestVis.visualCaveat != GLX_NONE_EXT) ||
  620. (!bestVis.rgba && vis.rgba) ||
  621. (!bestVis.doubleBuffer && vis.doubleBuffer) ||
  622. (bestVis.redSize < vis.redSize) ||
  623. (bestVis.greenSize < vis.greenSize) ||
  624. (bestVis.blueSize < vis.blueSize) ||
  625. (bestVis.alphaSize < vis.alphaSize) ||
  626. (bestVis.depthSize < vis.depthSize) ||
  627. (bestVis.stencilSize < vis.stencilSize) ||
  628. (bestVis.accumRedSize < vis.accumRedSize)) {
  629. /* found a better visual */
  630. bestVis = vis;
  631. }
  632. }
  633. XFree(visuals);
  634. return bestVis.id;
  635. }
  636. static void
  637. usage(void)
  638. {
  639. printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
  640. printf("\t-v: Print visuals info in verbose form.\n");
  641. printf("\t-t: Print verbose table.\n");
  642. printf("\t-display <dname>: Print GLX visuals on specified server.\n");
  643. printf("\t-h: This information.\n");
  644. printf("\t-i: Force an indirect rendering context.\n");
  645. printf("\t-b: Find the 'best' visual and print it's number.\n");
  646. printf("\t-l: Print interesting OpenGL limits.\n");
  647. }
  648. int
  649. main(int argc, char *argv[])
  650. {
  651. char *displayName = NULL;
  652. Display *dpy;
  653. int numScreens, scrnum;
  654. InfoMode mode = Normal;
  655. GLboolean findBest = GL_FALSE;
  656. GLboolean limits = GL_FALSE;
  657. Bool allowDirect = True;
  658. int i;
  659. for (i = 1; i < argc; i++) {
  660. if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
  661. displayName = argv[i + 1];
  662. i++;
  663. }
  664. else if (strcmp(argv[i], "-t") == 0) {
  665. mode = Wide;
  666. }
  667. else if (strcmp(argv[i], "-v") == 0) {
  668. mode = Verbose;
  669. }
  670. else if (strcmp(argv[i], "-b") == 0) {
  671. findBest = GL_TRUE;
  672. }
  673. else if (strcmp(argv[i], "-i") == 0) {
  674. allowDirect = False;
  675. }
  676. else if (strcmp(argv[i], "-l") == 0) {
  677. limits = GL_TRUE;
  678. }
  679. else if (strcmp(argv[i], "-h") == 0) {
  680. usage();
  681. return 0;
  682. }
  683. else {
  684. printf("Unknown option `%s'\n", argv[i]);
  685. usage();
  686. return 0;
  687. }
  688. }
  689. dpy = XOpenDisplay(displayName);
  690. if (!dpy) {
  691. fprintf(stderr, "Error: unable to open display %s\n", displayName);
  692. return -1;
  693. }
  694. if (findBest) {
  695. int b;
  696. mesa_hack(dpy, 0);
  697. b = find_best_visual(dpy, 0);
  698. printf("%d\n", b);
  699. }
  700. else {
  701. numScreens = ScreenCount(dpy);
  702. print_display_info(dpy);
  703. for (scrnum = 0; scrnum < numScreens; scrnum++) {
  704. mesa_hack(dpy, scrnum);
  705. print_screen_info(dpy, scrnum, allowDirect, limits);
  706. printf("\n");
  707. print_visual_info(dpy, scrnum, mode);
  708. if (scrnum + 1 < numScreens)
  709. printf("\n\n");
  710. }
  711. }
  712. XCloseDisplay(dpy);
  713. return 0;
  714. }