Clone of mesa.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. /*
  2. * Copyright (C) 1999-2006 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 GLX_GLXEXT_PROTOTYPES
  34. #include <X11/Xlib.h>
  35. #include <X11/Xutil.h>
  36. #include <GL/gl.h>
  37. #include <GL/glx.h>
  38. #include <stdio.h>
  39. #include <string.h>
  40. #include <stdlib.h>
  41. #ifndef GLX_NONE_EXT
  42. #define GLX_NONE_EXT 0x8000
  43. #endif
  44. #ifndef GLX_TRANSPARENT_RGB
  45. #define GLX_TRANSPARENT_RGB 0x8008
  46. #endif
  47. #ifndef GLX_RGBA_BIT
  48. #define GLX_RGBA_BIT 0x00000001
  49. #endif
  50. #ifndef GLX_COLOR_INDEX_BIT
  51. #define GLX_COLOR_INDEX_BIT 0x00000002
  52. #endif
  53. typedef enum
  54. {
  55. Normal,
  56. Wide,
  57. Verbose
  58. } InfoMode;
  59. struct visual_attribs
  60. {
  61. /* X visual attribs */
  62. int id;
  63. int klass;
  64. int depth;
  65. int redMask, greenMask, blueMask;
  66. int colormapSize;
  67. int bitsPerRGB;
  68. /* GL visual attribs */
  69. int supportsGL;
  70. int transparentType;
  71. int transparentRedValue;
  72. int transparentGreenValue;
  73. int transparentBlueValue;
  74. int transparentAlphaValue;
  75. int transparentIndexValue;
  76. int bufferSize;
  77. int level;
  78. int render_type;
  79. int doubleBuffer;
  80. int stereo;
  81. int auxBuffers;
  82. int redSize, greenSize, blueSize, alphaSize;
  83. int depthSize;
  84. int stencilSize;
  85. int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
  86. int numSamples, numMultisample;
  87. int visualCaveat;
  88. };
  89. /*
  90. * Print a list of extensions, with word-wrapping.
  91. */
  92. static void
  93. print_extension_list(const char *ext)
  94. {
  95. const char *indentString = " ";
  96. const int indent = 4;
  97. const int max = 79;
  98. int width, i, j;
  99. if (!ext || !ext[0])
  100. return;
  101. width = indent;
  102. printf(indentString);
  103. i = j = 0;
  104. while (1) {
  105. if (ext[j] == ' ' || ext[j] == 0) {
  106. /* found end of an extension name */
  107. const int len = j - i;
  108. if (width + len > max) {
  109. /* start a new line */
  110. printf("\n");
  111. width = indent;
  112. printf(indentString);
  113. }
  114. /* print the extension name between ext[i] and ext[j] */
  115. while (i < j) {
  116. printf("%c", ext[i]);
  117. i++;
  118. }
  119. /* either we're all done, or we'll continue with next extension */
  120. width += len + 1;
  121. if (ext[j] == 0) {
  122. break;
  123. }
  124. else {
  125. i++;
  126. j++;
  127. if (ext[j] == 0)
  128. break;
  129. printf(", ");
  130. width += 2;
  131. }
  132. }
  133. j++;
  134. }
  135. printf("\n");
  136. }
  137. static void
  138. print_display_info(Display *dpy)
  139. {
  140. printf("name of display: %s\n", DisplayString(dpy));
  141. }
  142. /**
  143. * Print interesting limits for vertex/fragment programs.
  144. */
  145. static void
  146. print_program_limits(GLenum target)
  147. {
  148. #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
  149. struct token_name {
  150. GLenum token;
  151. const char *name;
  152. };
  153. static const struct token_name limits[] = {
  154. { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" },
  155. { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" },
  156. { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" },
  157. { GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB" },
  158. { GL_MAX_PROGRAM_PARAMETERS_ARB, "GL_MAX_PROGRAM_PARAMETERS_ARB" },
  159. { GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB" },
  160. { GL_MAX_PROGRAM_ATTRIBS_ARB, "GL_MAX_PROGRAM_ATTRIBS_ARB" },
  161. { GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB" },
  162. { GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB" },
  163. { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" },
  164. { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" },
  165. { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" },
  166. { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" },
  167. { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" },
  168. { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" },
  169. { GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB" },
  170. { GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB" },
  171. { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" },
  172. { (GLenum) 0, NULL }
  173. };
  174. PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC)
  175. glXGetProcAddressARB((GLubyte *) "glGetProgramivARB");
  176. GLint max[1];
  177. int i;
  178. if (target == GL_VERTEX_PROGRAM_ARB) {
  179. printf(" GL_VERTEX_PROGRAM_ARB:\n");
  180. }
  181. else if (target == GL_FRAGMENT_PROGRAM_ARB) {
  182. printf(" GL_FRAGMENT_PROGRAM_ARB:\n");
  183. }
  184. else {
  185. return; /* something's wrong */
  186. }
  187. for (i = 0; limits[i].token; i++) {
  188. GetProgramivARB_func(target, limits[i].token, max);
  189. if (glGetError() == GL_NO_ERROR) {
  190. printf(" %s = %d\n", limits[i].name, max[0]);
  191. }
  192. }
  193. #endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */
  194. }
  195. /**
  196. * Print interesting limits for vertex/fragment shaders.
  197. */
  198. static void
  199. print_shader_limits(GLenum target)
  200. {
  201. struct token_name {
  202. GLenum token;
  203. const char *name;
  204. };
  205. #if defined(GL_ARB_vertex_shader)
  206. static const struct token_name vertex_limits[] = {
  207. { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB" },
  208. { GL_MAX_VARYING_FLOATS_ARB, "GL_MAX_VARYING_FLOATS_ARB" },
  209. { GL_MAX_VERTEX_ATTRIBS_ARB, "GL_MAX_VERTEX_ATTRIBS_ARB" },
  210. { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
  211. { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB" },
  212. { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB" },
  213. { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
  214. { (GLenum) 0, NULL }
  215. };
  216. #endif
  217. #if defined(GL_ARB_fragment_shader)
  218. static const struct token_name fragment_limits[] = {
  219. { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB" },
  220. { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
  221. { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
  222. { (GLenum) 0, NULL }
  223. };
  224. #endif
  225. GLint max[1];
  226. int i;
  227. #if defined(GL_ARB_vertex_shader)
  228. if (target == GL_VERTEX_SHADER_ARB) {
  229. printf(" GL_VERTEX_SHADER_ARB:\n");
  230. for (i = 0; vertex_limits[i].token; i++) {
  231. glGetIntegerv(vertex_limits[i].token, max);
  232. if (glGetError() == GL_NO_ERROR) {
  233. printf(" %s = %d\n", vertex_limits[i].name, max[0]);
  234. }
  235. }
  236. }
  237. #endif
  238. #if defined(GL_ARB_fragment_shader)
  239. if (target == GL_FRAGMENT_SHADER_ARB) {
  240. printf(" GL_FRAGMENT_SHADER_ARB:\n");
  241. for (i = 0; fragment_limits[i].token; i++) {
  242. glGetIntegerv(fragment_limits[i].token, max);
  243. if (glGetError() == GL_NO_ERROR) {
  244. printf(" %s = %d\n", fragment_limits[i].name, max[0]);
  245. }
  246. }
  247. }
  248. #endif
  249. }
  250. /**
  251. * Print interesting OpenGL implementation limits.
  252. */
  253. static void
  254. print_limits(const char *extensions)
  255. {
  256. struct token_name {
  257. GLuint count;
  258. GLenum token;
  259. const char *name;
  260. };
  261. static const struct token_name limits[] = {
  262. { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" },
  263. { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" },
  264. { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" },
  265. { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" },
  266. { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" },
  267. { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" },
  268. { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" },
  269. { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" },
  270. { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" },
  271. { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" },
  272. { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" },
  273. { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" },
  274. { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" },
  275. { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" },
  276. { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" },
  277. { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" },
  278. { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" },
  279. { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" },
  280. { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" },
  281. { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" },
  282. { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" },
  283. #if defined(GL_ARB_texture_cube_map)
  284. { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" },
  285. #endif
  286. #if defined(GLX_NV_texture_rectangle)
  287. { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" },
  288. #endif
  289. #if defined(GL_ARB_texture_compression)
  290. { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" },
  291. #endif
  292. #if defined(GL_ARB_multitexture)
  293. { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" },
  294. #endif
  295. #if defined(GL_EXT_texture_lod_bias)
  296. { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" },
  297. #endif
  298. #if defined(GL_EXT_texture_filter_anisotropic)
  299. { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" },
  300. #endif
  301. #if defined(GL_ARB_draw_buffers)
  302. { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB" },
  303. #endif
  304. { 0, (GLenum) 0, NULL }
  305. };
  306. GLint i, max[2];
  307. printf("OpenGL limits:\n");
  308. for (i = 0; limits[i].count; i++) {
  309. glGetIntegerv(limits[i].token, max);
  310. if (glGetError() == GL_NO_ERROR) {
  311. if (limits[i].count == 1)
  312. printf(" %s = %d\n", limits[i].name, max[0]);
  313. else /* XXX fix if we ever query something with more than 2 values */
  314. printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]);
  315. }
  316. }
  317. /* these don't fit into the above mechanism, unfortunately */
  318. glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max);
  319. glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1);
  320. if (glGetError() == GL_NONE) {
  321. printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]);
  322. }
  323. #if defined(GL_ARB_vertex_program)
  324. if (strstr(extensions, "GL_ARB_vertex_program")) {
  325. print_program_limits(GL_VERTEX_PROGRAM_ARB);
  326. }
  327. #endif
  328. #if defined(GL_ARB_fragment_program)
  329. if (strstr(extensions, "GL_ARB_fragment_program")) {
  330. print_program_limits(GL_FRAGMENT_PROGRAM_ARB);
  331. }
  332. #endif
  333. #if defined(GL_ARB_vertex_shader)
  334. if (strstr(extensions, "GL_ARB_vertex_shader")) {
  335. print_shader_limits(GL_VERTEX_SHADER_ARB);
  336. }
  337. #endif
  338. #if defined(GL_ARB_fragment_shader)
  339. if (strstr(extensions, "GL_ARB_fragment_shader")) {
  340. print_shader_limits(GL_FRAGMENT_SHADER_ARB);
  341. }
  342. #endif
  343. }
  344. static void
  345. print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits)
  346. {
  347. Window win;
  348. int attribSingle[] = {
  349. GLX_RGBA,
  350. GLX_RED_SIZE, 1,
  351. GLX_GREEN_SIZE, 1,
  352. GLX_BLUE_SIZE, 1,
  353. None };
  354. int attribDouble[] = {
  355. GLX_RGBA,
  356. GLX_RED_SIZE, 1,
  357. GLX_GREEN_SIZE, 1,
  358. GLX_BLUE_SIZE, 1,
  359. GLX_DOUBLEBUFFER,
  360. None };
  361. XSetWindowAttributes attr;
  362. unsigned long mask;
  363. Window root;
  364. GLXContext ctx = NULL;
  365. XVisualInfo *visinfo;
  366. int width = 100, height = 100;
  367. root = RootWindow(dpy, scrnum);
  368. visinfo = glXChooseVisual(dpy, scrnum, attribSingle);
  369. if (!visinfo)
  370. visinfo = glXChooseVisual(dpy, scrnum, attribDouble);
  371. if (visinfo)
  372. ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect );
  373. #ifdef GLX_VERSION_1_3
  374. {
  375. int fbAttribSingle[] = {
  376. GLX_RENDER_TYPE, GLX_RGBA_BIT,
  377. GLX_RED_SIZE, 1,
  378. GLX_GREEN_SIZE, 1,
  379. GLX_BLUE_SIZE, 1,
  380. GLX_DOUBLEBUFFER, GL_TRUE,
  381. None };
  382. int fbAttribDouble[] = {
  383. GLX_RENDER_TYPE, GLX_RGBA_BIT,
  384. GLX_RED_SIZE, 1,
  385. GLX_GREEN_SIZE, 1,
  386. GLX_BLUE_SIZE, 1,
  387. None };
  388. GLXFBConfig *configs = NULL;
  389. int nConfigs;
  390. if (!visinfo)
  391. configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs);
  392. if (!visinfo)
  393. configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs);
  394. if (configs) {
  395. visinfo = glXGetVisualFromFBConfig(dpy, configs[0]);
  396. ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect);
  397. XFree(configs);
  398. }
  399. }
  400. #endif
  401. if (!visinfo) {
  402. fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n");
  403. return;
  404. }
  405. if (!ctx) {
  406. fprintf(stderr, "Error: glXCreateContext failed\n");
  407. XFree(visinfo);
  408. return;
  409. }
  410. attr.background_pixel = 0;
  411. attr.border_pixel = 0;
  412. attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
  413. attr.event_mask = StructureNotifyMask | ExposureMask;
  414. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  415. win = XCreateWindow(dpy, root, 0, 0, width, height,
  416. 0, visinfo->depth, InputOutput,
  417. visinfo->visual, mask, &attr);
  418. if (glXMakeCurrent(dpy, win, ctx)) {
  419. const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR);
  420. const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION);
  421. const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS);
  422. const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR);
  423. const char *clientVersion = glXGetClientString(dpy, GLX_VERSION);
  424. const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS);
  425. const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum);
  426. const char *glVendor = (const char *) glGetString(GL_VENDOR);
  427. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  428. const char *glVersion = (const char *) glGetString(GL_VERSION);
  429. const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
  430. int glxVersionMajor;
  431. int glxVersionMinor;
  432. char *displayName = NULL;
  433. char *colon = NULL, *period = NULL;
  434. if (! glXQueryVersion( dpy, & glxVersionMajor, & glxVersionMinor )) {
  435. fprintf(stderr, "Error: glXQueryVersion failed\n");
  436. exit(1);
  437. }
  438. /* Strip the screen number from the display name, if present. */
  439. if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) {
  440. fprintf(stderr, "Error: malloc() failed\n");
  441. exit(1);
  442. }
  443. strcpy(displayName, DisplayString(dpy));
  444. colon = strrchr(displayName, ':');
  445. if (colon) {
  446. period = strchr(colon, '.');
  447. if (period)
  448. *period = '\0';
  449. }
  450. printf("display: %s screen: %d\n", displayName, scrnum);
  451. free(displayName);
  452. printf("direct rendering: ");
  453. if (glXIsDirect(dpy, ctx)) {
  454. printf("Yes\n");
  455. } else {
  456. if (!allowDirect) {
  457. printf("No (-i specified)\n");
  458. } else if (getenv("LIBGL_ALWAYS_INDIRECT")) {
  459. printf("No (LIBGL_ALWAYS_INDIRECT set)\n");
  460. } else {
  461. printf("No (If you want to find out why, try setting "
  462. "LIBGL_DEBUG=verbose)\n");
  463. }
  464. }
  465. printf("server glx vendor string: %s\n", serverVendor);
  466. printf("server glx version string: %s\n", serverVersion);
  467. printf("server glx extensions:\n");
  468. print_extension_list(serverExtensions);
  469. printf("client glx vendor string: %s\n", clientVendor);
  470. printf("client glx version string: %s\n", clientVersion);
  471. printf("client glx extensions:\n");
  472. print_extension_list(clientExtensions);
  473. printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor);
  474. printf("GLX extensions:\n");
  475. print_extension_list(glxExtensions);
  476. printf("OpenGL vendor string: %s\n", glVendor);
  477. printf("OpenGL renderer string: %s\n", glRenderer);
  478. printf("OpenGL version string: %s\n", glVersion);
  479. #ifdef GL_VERSION_2_0
  480. if (glVersion[0] >= '2' && glVersion[1] == '.') {
  481. char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
  482. printf("OpenGL shading language version string: %s\n", v);
  483. }
  484. #endif
  485. printf("OpenGL extensions:\n");
  486. print_extension_list(glExtensions);
  487. if (limits)
  488. print_limits(glExtensions);
  489. }
  490. else {
  491. fprintf(stderr, "Error: glXMakeCurrent failed\n");
  492. }
  493. glXDestroyContext(dpy, ctx);
  494. XFree(visinfo);
  495. XDestroyWindow(dpy, win);
  496. }
  497. static const char *
  498. visual_class_name(int cls)
  499. {
  500. switch (cls) {
  501. case StaticColor:
  502. return "StaticColor";
  503. case PseudoColor:
  504. return "PseudoColor";
  505. case StaticGray:
  506. return "StaticGray";
  507. case GrayScale:
  508. return "GrayScale";
  509. case TrueColor:
  510. return "TrueColor";
  511. case DirectColor:
  512. return "DirectColor";
  513. default:
  514. return "";
  515. }
  516. }
  517. static const char *
  518. visual_class_abbrev(int cls)
  519. {
  520. switch (cls) {
  521. case StaticColor:
  522. return "sc";
  523. case PseudoColor:
  524. return "pc";
  525. case StaticGray:
  526. return "sg";
  527. case GrayScale:
  528. return "gs";
  529. case TrueColor:
  530. return "tc";
  531. case DirectColor:
  532. return "dc";
  533. default:
  534. return "";
  535. }
  536. }
  537. static const char *
  538. visual_render_type_name(int type)
  539. {
  540. switch (type) {
  541. case GLX_RGBA_BIT:
  542. return "rgba";
  543. case GLX_COLOR_INDEX_BIT:
  544. return "ci";
  545. case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT:
  546. return "rgba|ci";
  547. default:
  548. return "";
  549. }
  550. }
  551. static GLboolean
  552. get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
  553. struct visual_attribs *attribs)
  554. {
  555. const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
  556. int rgba;
  557. memset(attribs, 0, sizeof(struct visual_attribs));
  558. attribs->id = vInfo->visualid;
  559. #if defined(__cplusplus) || defined(c_plusplus)
  560. attribs->klass = vInfo->c_class;
  561. #else
  562. attribs->klass = vInfo->class;
  563. #endif
  564. attribs->depth = vInfo->depth;
  565. attribs->redMask = vInfo->red_mask;
  566. attribs->greenMask = vInfo->green_mask;
  567. attribs->blueMask = vInfo->blue_mask;
  568. attribs->colormapSize = vInfo->colormap_size;
  569. attribs->bitsPerRGB = vInfo->bits_per_rgb;
  570. if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
  571. !attribs->supportsGL)
  572. return GL_FALSE;
  573. glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
  574. glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
  575. glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
  576. if (rgba)
  577. attribs->render_type = GLX_RGBA_BIT;
  578. else
  579. attribs->render_type = GLX_COLOR_INDEX_BIT;
  580. glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
  581. glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
  582. glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
  583. glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
  584. glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
  585. glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
  586. glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
  587. glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
  588. glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
  589. glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
  590. glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
  591. glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
  592. glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
  593. /* get transparent pixel stuff */
  594. glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
  595. if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
  596. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
  597. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
  598. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
  599. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
  600. }
  601. else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
  602. glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
  603. }
  604. /* multisample attribs */
  605. #ifdef GLX_ARB_multisample
  606. if (ext && strstr(ext, "GLX_ARB_multisample")) {
  607. glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
  608. glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
  609. }
  610. #endif
  611. else {
  612. attribs->numSamples = 0;
  613. attribs->numMultisample = 0;
  614. }
  615. #if defined(GLX_EXT_visual_rating)
  616. if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
  617. glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
  618. }
  619. else {
  620. attribs->visualCaveat = GLX_NONE_EXT;
  621. }
  622. #else
  623. attribs->visualCaveat = 0;
  624. #endif
  625. return GL_TRUE;
  626. }
  627. #ifdef GLX_VERSION_1_3
  628. static int
  629. glx_token_to_visual_class(int visual_type)
  630. {
  631. switch (visual_type) {
  632. case GLX_TRUE_COLOR:
  633. return TrueColor;
  634. case GLX_DIRECT_COLOR:
  635. return DirectColor;
  636. case GLX_PSEUDO_COLOR:
  637. return PseudoColor;
  638. case GLX_STATIC_COLOR:
  639. return StaticColor;
  640. case GLX_GRAY_SCALE:
  641. return GrayScale;
  642. case GLX_STATIC_GRAY:
  643. return StaticGray;
  644. case GLX_NONE:
  645. default:
  646. return None;
  647. }
  648. }
  649. static GLboolean
  650. get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
  651. struct visual_attribs *attribs)
  652. {
  653. int visual_type;
  654. memset(attribs, 0, sizeof(struct visual_attribs));
  655. glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id);
  656. #if 0
  657. attribs->depth = vInfo->depth;
  658. attribs->redMask = vInfo->red_mask;
  659. attribs->greenMask = vInfo->green_mask;
  660. attribs->blueMask = vInfo->blue_mask;
  661. attribs->colormapSize = vInfo->colormap_size;
  662. attribs->bitsPerRGB = vInfo->bits_per_rgb;
  663. #endif
  664. glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
  665. attribs->klass = glx_token_to_visual_class(visual_type);
  666. glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
  667. glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
  668. glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
  669. glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
  670. glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
  671. glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
  672. glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
  673. glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
  674. glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
  675. glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
  676. glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
  677. glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
  678. glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
  679. glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
  680. glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
  681. glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
  682. /* get transparent pixel stuff */
  683. glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
  684. if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
  685. glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
  686. glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
  687. glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
  688. glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
  689. }
  690. else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
  691. glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
  692. }
  693. glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
  694. glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
  695. glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
  696. return GL_TRUE;
  697. }
  698. #endif
  699. static void
  700. print_visual_attribs_verbose(const struct visual_attribs *attribs)
  701. {
  702. printf("Visual ID: %x depth=%d class=%s\n",
  703. attribs->id, attribs->depth, visual_class_name(attribs->klass));
  704. printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
  705. attribs->bufferSize, attribs->level,
  706. visual_render_type_name(attribs->render_type),
  707. attribs->doubleBuffer, attribs->stereo);
  708. printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  709. attribs->redSize, attribs->greenSize,
  710. attribs->blueSize, attribs->alphaSize);
  711. printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n",
  712. attribs->auxBuffers, attribs->depthSize, attribs->stencilSize);
  713. printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n",
  714. attribs->accumRedSize, attribs->accumGreenSize,
  715. attribs->accumBlueSize, attribs->accumAlphaSize);
  716. printf(" multiSample=%d multiSampleBuffers=%d\n",
  717. attribs->numSamples, attribs->numMultisample);
  718. #ifdef GLX_EXT_visual_rating
  719. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  720. printf(" visualCaveat=None\n");
  721. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  722. printf(" visualCaveat=Slow\n");
  723. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  724. printf(" visualCaveat=Nonconformant\n");
  725. #endif
  726. if (attribs->transparentType == GLX_NONE) {
  727. printf(" Opaque.\n");
  728. }
  729. else if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
  730. printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue);
  731. }
  732. else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
  733. printf(" Transparent index=%d\n",attribs->transparentIndexValue);
  734. }
  735. }
  736. static void
  737. print_visual_attribs_short_header(void)
  738. {
  739. printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
  740. 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");
  741. printf("----------------------------------------------------------------------\n");
  742. }
  743. static void
  744. print_visual_attribs_short(const struct visual_attribs *attribs)
  745. {
  746. char *caveat = NULL;
  747. #ifdef GLX_EXT_visual_rating
  748. if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0)
  749. caveat = "None";
  750. else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT)
  751. caveat = "Slow";
  752. else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT)
  753. caveat = "Ncon";
  754. else
  755. caveat = "None";
  756. #else
  757. caveat = "None";
  758. #endif
  759. printf("0x%02x %2d %2s %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d",
  760. attribs->id,
  761. attribs->depth,
  762. visual_class_abbrev(attribs->klass),
  763. attribs->transparentType != GLX_NONE,
  764. attribs->bufferSize,
  765. attribs->level,
  766. (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ',
  767. (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ',
  768. attribs->doubleBuffer ? 'y' : '.',
  769. attribs->stereo ? 'y' : '.',
  770. attribs->redSize, attribs->greenSize,
  771. attribs->blueSize, attribs->alphaSize,
  772. attribs->auxBuffers,
  773. attribs->depthSize,
  774. attribs->stencilSize
  775. );
  776. printf(" %2d %2d %2d %2d %2d %1d %s\n",
  777. attribs->accumRedSize, attribs->accumGreenSize,
  778. attribs->accumBlueSize, attribs->accumAlphaSize,
  779. attribs->numSamples, attribs->numMultisample,
  780. caveat
  781. );
  782. }
  783. static void
  784. print_visual_attribs_long_header(void)
  785. {
  786. printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
  787. printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
  788. printf("----------------------------------------------------------------------------------------------------\n");
  789. }
  790. static void
  791. print_visual_attribs_long(const struct visual_attribs *attribs)
  792. {
  793. printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
  794. attribs->id,
  795. attribs->depth,
  796. visual_class_name(attribs->klass),
  797. attribs->transparentType != GLX_NONE,
  798. attribs->bufferSize,
  799. attribs->level,
  800. visual_render_type_name(attribs->render_type),
  801. attribs->doubleBuffer,
  802. attribs->stereo,
  803. attribs->redSize, attribs->greenSize,
  804. attribs->blueSize, attribs->alphaSize
  805. );
  806. printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
  807. attribs->auxBuffers,
  808. attribs->depthSize,
  809. attribs->stencilSize,
  810. attribs->accumRedSize, attribs->accumGreenSize,
  811. attribs->accumBlueSize, attribs->accumAlphaSize,
  812. attribs->numSamples, attribs->numMultisample
  813. );
  814. }
  815. static void
  816. print_visual_info(Display *dpy, int scrnum, InfoMode mode)
  817. {
  818. XVisualInfo theTemplate;
  819. XVisualInfo *visuals;
  820. int numVisuals, numGlxVisuals;
  821. long mask;
  822. int i;
  823. struct visual_attribs attribs;
  824. /* get list of all visuals on this screen */
  825. theTemplate.screen = scrnum;
  826. mask = VisualScreenMask;
  827. visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
  828. numGlxVisuals = 0;
  829. for (i = 0; i < numVisuals; i++) {
  830. if (get_visual_attribs(dpy, &visuals[i], &attribs))
  831. numGlxVisuals++;
  832. }
  833. if (numGlxVisuals == 0)
  834. return;
  835. printf("%d GLX Visuals\n", numGlxVisuals);
  836. if (mode == Normal)
  837. print_visual_attribs_short_header();
  838. else if (mode == Wide)
  839. print_visual_attribs_long_header();
  840. for (i = 0; i < numVisuals; i++) {
  841. if (!get_visual_attribs(dpy, &visuals[i], &attribs))
  842. continue;
  843. if (mode == Verbose)
  844. print_visual_attribs_verbose(&attribs);
  845. else if (mode == Normal)
  846. print_visual_attribs_short(&attribs);
  847. else if (mode == Wide)
  848. print_visual_attribs_long(&attribs);
  849. }
  850. printf("\n");
  851. XFree(visuals);
  852. }
  853. #ifdef GLX_VERSION_1_3
  854. static void
  855. print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode)
  856. {
  857. int numFBConfigs;
  858. struct visual_attribs attribs;
  859. GLXFBConfig *fbconfigs;
  860. int i;
  861. /* get list of all fbconfigs on this screen */
  862. fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs);
  863. if (numFBConfigs == 0)
  864. return;
  865. printf("%d GLXFBConfigs:\n", numFBConfigs);
  866. if (mode == Normal)
  867. print_visual_attribs_short_header();
  868. else if (mode == Wide)
  869. print_visual_attribs_long_header();
  870. for (i = 0; i < numFBConfigs; i++) {
  871. get_fbconfig_attribs(dpy, fbconfigs[i], &attribs);
  872. if (mode == Verbose)
  873. print_visual_attribs_verbose(&attribs);
  874. else if (mode == Normal)
  875. print_visual_attribs_short(&attribs);
  876. else if (mode == Wide)
  877. print_visual_attribs_long(&attribs);
  878. }
  879. printf("\n");
  880. XFree(fbconfigs);
  881. }
  882. #endif
  883. /*
  884. * Stand-alone Mesa doesn't really implement the GLX protocol so it
  885. * doesn't really know the GLX attributes associated with an X visual.
  886. * The first time a visual is presented to Mesa's pseudo-GLX it
  887. * attaches ancilliary buffers to it (like depth and stencil).
  888. * But that usually only works if glXChooseVisual is used.
  889. * This function calls glXChooseVisual() to sort of "prime the pump"
  890. * for Mesa's GLX so that the visuals that get reported actually
  891. * reflect what applications will see.
  892. * This has no effect when using true GLX.
  893. */
  894. static void
  895. mesa_hack(Display *dpy, int scrnum)
  896. {
  897. static int attribs[] = {
  898. GLX_RGBA,
  899. GLX_RED_SIZE, 1,
  900. GLX_GREEN_SIZE, 1,
  901. GLX_BLUE_SIZE, 1,
  902. GLX_DEPTH_SIZE, 1,
  903. GLX_STENCIL_SIZE, 1,
  904. GLX_ACCUM_RED_SIZE, 1,
  905. GLX_ACCUM_GREEN_SIZE, 1,
  906. GLX_ACCUM_BLUE_SIZE, 1,
  907. GLX_ACCUM_ALPHA_SIZE, 1,
  908. GLX_DOUBLEBUFFER,
  909. None
  910. };
  911. XVisualInfo *visinfo;
  912. visinfo = glXChooseVisual(dpy, scrnum, attribs);
  913. if (visinfo)
  914. XFree(visinfo);
  915. }
  916. /*
  917. * Examine all visuals to find the so-called best one.
  918. * We prefer deepest RGBA buffer with depth, stencil and accum
  919. * that has no caveats.
  920. */
  921. static int
  922. find_best_visual(Display *dpy, int scrnum)
  923. {
  924. XVisualInfo theTemplate;
  925. XVisualInfo *visuals;
  926. int numVisuals;
  927. long mask;
  928. int i;
  929. struct visual_attribs bestVis;
  930. /* get list of all visuals on this screen */
  931. theTemplate.screen = scrnum;
  932. mask = VisualScreenMask;
  933. visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals);
  934. /* init bestVis with first visual info */
  935. get_visual_attribs(dpy, &visuals[0], &bestVis);
  936. /* try to find a "better" visual */
  937. for (i = 1; i < numVisuals; i++) {
  938. struct visual_attribs vis;
  939. get_visual_attribs(dpy, &visuals[i], &vis);
  940. /* always skip visuals with caveats */
  941. if (vis.visualCaveat != GLX_NONE_EXT)
  942. continue;
  943. /* see if this vis is better than bestVis */
  944. if ((!bestVis.supportsGL && vis.supportsGL) ||
  945. (bestVis.visualCaveat != GLX_NONE_EXT) ||
  946. (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) ||
  947. (!bestVis.doubleBuffer && vis.doubleBuffer) ||
  948. (bestVis.redSize < vis.redSize) ||
  949. (bestVis.greenSize < vis.greenSize) ||
  950. (bestVis.blueSize < vis.blueSize) ||
  951. (bestVis.alphaSize < vis.alphaSize) ||
  952. (bestVis.depthSize < vis.depthSize) ||
  953. (bestVis.stencilSize < vis.stencilSize) ||
  954. (bestVis.accumRedSize < vis.accumRedSize)) {
  955. /* found a better visual */
  956. bestVis = vis;
  957. }
  958. }
  959. XFree(visuals);
  960. return bestVis.id;
  961. }
  962. static void
  963. usage(void)
  964. {
  965. printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
  966. printf("\t-v: Print visuals info in verbose form.\n");
  967. printf("\t-t: Print verbose table.\n");
  968. printf("\t-display <dname>: Print GLX visuals on specified server.\n");
  969. printf("\t-h: This information.\n");
  970. printf("\t-i: Force an indirect rendering context.\n");
  971. printf("\t-b: Find the 'best' visual and print it's number.\n");
  972. printf("\t-l: Print interesting OpenGL limits.\n");
  973. }
  974. int
  975. main(int argc, char *argv[])
  976. {
  977. char *displayName = NULL;
  978. Display *dpy;
  979. int numScreens, scrnum;
  980. InfoMode mode = Normal;
  981. GLboolean findBest = GL_FALSE;
  982. GLboolean limits = GL_FALSE;
  983. Bool allowDirect = True;
  984. int i;
  985. for (i = 1; i < argc; i++) {
  986. if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) {
  987. displayName = argv[i + 1];
  988. i++;
  989. }
  990. else if (strcmp(argv[i], "-t") == 0) {
  991. mode = Wide;
  992. }
  993. else if (strcmp(argv[i], "-v") == 0) {
  994. mode = Verbose;
  995. }
  996. else if (strcmp(argv[i], "-b") == 0) {
  997. findBest = GL_TRUE;
  998. }
  999. else if (strcmp(argv[i], "-i") == 0) {
  1000. allowDirect = False;
  1001. }
  1002. else if (strcmp(argv[i], "-l") == 0) {
  1003. limits = GL_TRUE;
  1004. }
  1005. else if (strcmp(argv[i], "-h") == 0) {
  1006. usage();
  1007. return 0;
  1008. }
  1009. else {
  1010. printf("Unknown option `%s'\n", argv[i]);
  1011. usage();
  1012. return 0;
  1013. }
  1014. }
  1015. dpy = XOpenDisplay(displayName);
  1016. if (!dpy) {
  1017. fprintf(stderr, "Error: unable to open display %s\n", XDisplayName(displayName));
  1018. return -1;
  1019. }
  1020. if (findBest) {
  1021. int b;
  1022. mesa_hack(dpy, 0);
  1023. b = find_best_visual(dpy, 0);
  1024. printf("%d\n", b);
  1025. }
  1026. else {
  1027. numScreens = ScreenCount(dpy);
  1028. print_display_info(dpy);
  1029. for (scrnum = 0; scrnum < numScreens; scrnum++) {
  1030. mesa_hack(dpy, scrnum);
  1031. print_screen_info(dpy, scrnum, allowDirect, limits);
  1032. printf("\n");
  1033. print_visual_info(dpy, scrnum, mode);
  1034. #ifdef GLX_VERSION_1_3
  1035. print_fbconfig_info(dpy, scrnum, mode);
  1036. #endif
  1037. if (scrnum + 1 < numScreens)
  1038. printf("\n\n");
  1039. }
  1040. }
  1041. XCloseDisplay(dpy);
  1042. return 0;
  1043. }