Clone of mesa.
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. /*
  2. * Copyright (C) 2009 VMware, Inc.
  3. * Copyright (C) 1999-2006 Brian Paul
  4. * All Rights Reserved.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a
  7. * copy of this software and associated documentation files (the "Software"),
  8. * to deal in the Software without restriction, including without limitation
  9. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10. * and/or sell copies of the Software, and to permit persons to whom the
  11. * Software is furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included
  14. * in all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  20. * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. /*
  24. * This program is a work-alike of the GLX glxinfo program.
  25. * Command line options:
  26. * -t print wide table
  27. * -v print verbose information
  28. * -b only print ID of "best" visual on screen 0
  29. * -l print interesting OpenGL limits (added 5 Sep 2002)
  30. */
  31. #include <windows.h>
  32. #include <GL/gl.h>
  33. #include <GL/glext.h>
  34. #include <GL/wglext.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <stdlib.h>
  38. typedef enum
  39. {
  40. Normal,
  41. Wide,
  42. Verbose
  43. } InfoMode;
  44. /*
  45. * Print a list of extensions, with word-wrapping.
  46. */
  47. static void
  48. print_extension_list(const char *ext)
  49. {
  50. const char *indentString = " ";
  51. const int indent = 4;
  52. const int max = 79;
  53. int width, i, j;
  54. if (!ext || !ext[0])
  55. return;
  56. width = indent;
  57. printf(indentString);
  58. i = j = 0;
  59. while (1) {
  60. if (ext[j] == ' ' || ext[j] == 0) {
  61. /* found end of an extension name */
  62. const int len = j - i;
  63. if (width + len > max) {
  64. /* start a new line */
  65. printf("\n");
  66. width = indent;
  67. printf(indentString);
  68. }
  69. /* print the extension name between ext[i] and ext[j] */
  70. while (i < j) {
  71. printf("%c", ext[i]);
  72. i++;
  73. }
  74. /* either we're all done, or we'll continue with next extension */
  75. width += len + 1;
  76. if (ext[j] == 0) {
  77. break;
  78. }
  79. else {
  80. i++;
  81. j++;
  82. if (ext[j] == 0)
  83. break;
  84. printf(", ");
  85. width += 2;
  86. }
  87. }
  88. j++;
  89. }
  90. printf("\n");
  91. }
  92. /**
  93. * Print interesting limits for vertex/fragment programs.
  94. */
  95. static void
  96. print_program_limits(GLenum target)
  97. {
  98. #if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
  99. struct token_name {
  100. GLenum token;
  101. const char *name;
  102. };
  103. static const struct token_name limits[] = {
  104. { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" },
  105. { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" },
  106. { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" },
  107. { GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB" },
  108. { GL_MAX_PROGRAM_PARAMETERS_ARB, "GL_MAX_PROGRAM_PARAMETERS_ARB" },
  109. { GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB" },
  110. { GL_MAX_PROGRAM_ATTRIBS_ARB, "GL_MAX_PROGRAM_ATTRIBS_ARB" },
  111. { GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB" },
  112. { GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB" },
  113. { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" },
  114. { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" },
  115. { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" },
  116. { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" },
  117. { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" },
  118. { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" },
  119. { GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB" },
  120. { GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB" },
  121. { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" },
  122. { (GLenum) 0, NULL }
  123. };
  124. PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC)
  125. wglGetProcAddress("glGetProgramivARB");
  126. GLint max[1];
  127. int i;
  128. if (target == GL_VERTEX_PROGRAM_ARB) {
  129. printf(" GL_VERTEX_PROGRAM_ARB:\n");
  130. }
  131. else if (target == GL_FRAGMENT_PROGRAM_ARB) {
  132. printf(" GL_FRAGMENT_PROGRAM_ARB:\n");
  133. }
  134. else {
  135. return; /* something's wrong */
  136. }
  137. for (i = 0; limits[i].token; i++) {
  138. GetProgramivARB_func(target, limits[i].token, max);
  139. if (glGetError() == GL_NO_ERROR) {
  140. printf(" %s = %d\n", limits[i].name, max[0]);
  141. }
  142. }
  143. #endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */
  144. }
  145. /**
  146. * Print interesting limits for vertex/fragment shaders.
  147. */
  148. static void
  149. print_shader_limits(GLenum target)
  150. {
  151. struct token_name {
  152. GLenum token;
  153. const char *name;
  154. };
  155. #if defined(GL_ARB_vertex_shader)
  156. static const struct token_name vertex_limits[] = {
  157. { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB" },
  158. { GL_MAX_VARYING_FLOATS_ARB, "GL_MAX_VARYING_FLOATS_ARB" },
  159. { GL_MAX_VERTEX_ATTRIBS_ARB, "GL_MAX_VERTEX_ATTRIBS_ARB" },
  160. { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
  161. { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB" },
  162. { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB" },
  163. { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
  164. { (GLenum) 0, NULL }
  165. };
  166. #endif
  167. #if defined(GL_ARB_fragment_shader)
  168. static const struct token_name fragment_limits[] = {
  169. { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB" },
  170. { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" },
  171. { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" },
  172. { (GLenum) 0, NULL }
  173. };
  174. #endif
  175. GLint max[1];
  176. int i;
  177. #if defined(GL_ARB_vertex_shader)
  178. if (target == GL_VERTEX_SHADER_ARB) {
  179. printf(" GL_VERTEX_SHADER_ARB:\n");
  180. for (i = 0; vertex_limits[i].token; i++) {
  181. glGetIntegerv(vertex_limits[i].token, max);
  182. if (glGetError() == GL_NO_ERROR) {
  183. printf(" %s = %d\n", vertex_limits[i].name, max[0]);
  184. }
  185. }
  186. }
  187. #endif
  188. #if defined(GL_ARB_fragment_shader)
  189. if (target == GL_FRAGMENT_SHADER_ARB) {
  190. printf(" GL_FRAGMENT_SHADER_ARB:\n");
  191. for (i = 0; fragment_limits[i].token; i++) {
  192. glGetIntegerv(fragment_limits[i].token, max);
  193. if (glGetError() == GL_NO_ERROR) {
  194. printf(" %s = %d\n", fragment_limits[i].name, max[0]);
  195. }
  196. }
  197. }
  198. #endif
  199. }
  200. /**
  201. * Print interesting OpenGL implementation limits.
  202. */
  203. static void
  204. print_limits(const char *extensions)
  205. {
  206. struct token_name {
  207. GLuint count;
  208. GLenum token;
  209. const char *name;
  210. };
  211. static const struct token_name limits[] = {
  212. { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" },
  213. { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" },
  214. { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" },
  215. { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" },
  216. { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" },
  217. { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" },
  218. { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" },
  219. { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" },
  220. { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" },
  221. { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" },
  222. { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" },
  223. { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" },
  224. { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" },
  225. { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" },
  226. { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" },
  227. { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" },
  228. { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" },
  229. { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" },
  230. { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" },
  231. { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" },
  232. { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" },
  233. #if defined(GL_ARB_texture_cube_map)
  234. { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" },
  235. #endif
  236. #if defined(GLX_NV_texture_rectangle)
  237. { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" },
  238. #endif
  239. #if defined(GL_ARB_texture_compression)
  240. { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" },
  241. #endif
  242. #if defined(GL_ARB_multitexture)
  243. { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" },
  244. #endif
  245. #if defined(GL_EXT_texture_lod_bias)
  246. { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" },
  247. #endif
  248. #if defined(GL_EXT_texture_filter_anisotropic)
  249. { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" },
  250. #endif
  251. #if defined(GL_ARB_draw_buffers)
  252. { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB" },
  253. #endif
  254. { 0, (GLenum) 0, NULL }
  255. };
  256. GLint i, max[2];
  257. printf("OpenGL limits:\n");
  258. for (i = 0; limits[i].count; i++) {
  259. glGetIntegerv(limits[i].token, max);
  260. if (glGetError() == GL_NO_ERROR) {
  261. if (limits[i].count == 1)
  262. printf(" %s = %d\n", limits[i].name, max[0]);
  263. else /* XXX fix if we ever query something with more than 2 values */
  264. printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]);
  265. }
  266. }
  267. #if defined(GL_EXT_convolution)
  268. {
  269. PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC glGetConvolutionParameterivEXT_func =
  270. (PFNGLGETCONVOLUTIONPARAMETERIVEXTPROC)wglGetProcAddress("glGetConvolutionParameterivEXT");
  271. if(glGetConvolutionParameterivEXT_func) {
  272. /* these don't fit into the above mechanism, unfortunately */
  273. glGetConvolutionParameterivEXT_func(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max);
  274. glGetConvolutionParameterivEXT_func(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1);
  275. if (glGetError() == GL_NONE) {
  276. printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]);
  277. }
  278. }
  279. }
  280. #endif
  281. #if defined(GL_ARB_vertex_program)
  282. if (strstr(extensions, "GL_ARB_vertex_program")) {
  283. print_program_limits(GL_VERTEX_PROGRAM_ARB);
  284. }
  285. #endif
  286. #if defined(GL_ARB_fragment_program)
  287. if (strstr(extensions, "GL_ARB_fragment_program")) {
  288. print_program_limits(GL_FRAGMENT_PROGRAM_ARB);
  289. }
  290. #endif
  291. #if defined(GL_ARB_vertex_shader)
  292. if (strstr(extensions, "GL_ARB_vertex_shader")) {
  293. print_shader_limits(GL_VERTEX_SHADER_ARB);
  294. }
  295. #endif
  296. #if defined(GL_ARB_fragment_shader)
  297. if (strstr(extensions, "GL_ARB_fragment_shader")) {
  298. print_shader_limits(GL_FRAGMENT_SHADER_ARB);
  299. }
  300. #endif
  301. }
  302. static LRESULT CALLBACK
  303. WndProc(HWND hWnd,
  304. UINT uMsg,
  305. WPARAM wParam,
  306. LPARAM lParam )
  307. {
  308. switch (uMsg) {
  309. case WM_DESTROY:
  310. PostQuitMessage(0);
  311. break;
  312. default:
  313. return DefWindowProc(hWnd, uMsg, wParam, lParam);
  314. }
  315. return 0;
  316. }
  317. static void
  318. print_screen_info(HDC _hdc, GLboolean limits)
  319. {
  320. WNDCLASS wc;
  321. HWND win;
  322. HGLRC ctx;
  323. int visinfo;
  324. HDC hdc;
  325. PIXELFORMATDESCRIPTOR pfd;
  326. memset(&wc, 0, sizeof wc);
  327. wc.hbrBackground = (HBRUSH) (COLOR_BTNFACE + 1);
  328. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  329. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  330. wc.lpfnWndProc = WndProc;
  331. wc.lpszClassName = "wglinfo";
  332. wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
  333. RegisterClass(&wc);
  334. win = CreateWindowEx(0,
  335. wc.lpszClassName,
  336. "wglinfo",
  337. WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
  338. CW_USEDEFAULT,
  339. CW_USEDEFAULT,
  340. CW_USEDEFAULT,
  341. CW_USEDEFAULT,
  342. NULL,
  343. NULL,
  344. wc.hInstance,
  345. NULL);
  346. if (!win) {
  347. fprintf(stderr, "Couldn't create window");
  348. return;
  349. }
  350. hdc = GetDC(win);
  351. if (!hdc) {
  352. fprintf(stderr, "Couldn't obtain HDC");
  353. return;
  354. }
  355. pfd.cColorBits = 3;
  356. pfd.cRedBits = 1;
  357. pfd.cGreenBits = 1;
  358. pfd.cBlueBits = 1;
  359. pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
  360. pfd.iLayerType = PFD_MAIN_PLANE;
  361. pfd.iPixelType = PFD_TYPE_RGBA;
  362. pfd.nSize = sizeof(pfd);
  363. pfd.nVersion = 1;
  364. visinfo = ChoosePixelFormat(hdc, &pfd);
  365. if (!visinfo) {
  366. pfd.dwFlags |= PFD_DOUBLEBUFFER;
  367. visinfo = ChoosePixelFormat(hdc, &pfd);
  368. }
  369. if (!visinfo) {
  370. fprintf(stderr, "Error: couldn't find RGB WGL visual\n");
  371. return;
  372. }
  373. SetPixelFormat(hdc, visinfo, &pfd);
  374. ctx = wglCreateContext(hdc);
  375. if (!ctx) {
  376. fprintf(stderr, "Error: wglCreateContext failed\n");
  377. return;
  378. }
  379. if (wglMakeCurrent(hdc, ctx)) {
  380. #if defined(WGL_ARB_extensions_string)
  381. PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB_func =
  382. (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
  383. #endif
  384. const char *glVendor = (const char *) glGetString(GL_VENDOR);
  385. const char *glRenderer = (const char *) glGetString(GL_RENDERER);
  386. const char *glVersion = (const char *) glGetString(GL_VERSION);
  387. const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
  388. #if defined(WGL_ARB_extensions_string)
  389. if(wglGetExtensionsStringARB_func) {
  390. const char *wglExtensions = wglGetExtensionsStringARB_func(hdc);
  391. if(wglExtensions) {
  392. printf("WGL extensions:\n");
  393. print_extension_list(wglExtensions);
  394. }
  395. }
  396. #endif
  397. printf("OpenGL vendor string: %s\n", glVendor);
  398. printf("OpenGL renderer string: %s\n", glRenderer);
  399. printf("OpenGL version string: %s\n", glVersion);
  400. #ifdef GL_VERSION_2_0
  401. if (glVersion[0] >= '2' && glVersion[1] == '.') {
  402. char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
  403. printf("OpenGL shading language version string: %s\n", v);
  404. }
  405. #endif
  406. printf("OpenGL extensions:\n");
  407. print_extension_list(glExtensions);
  408. if (limits)
  409. print_limits(glExtensions);
  410. }
  411. else {
  412. fprintf(stderr, "Error: wglMakeCurrent failed\n");
  413. }
  414. DestroyWindow(win);
  415. }
  416. static const char *
  417. visual_render_type_name(BYTE iPixelType)
  418. {
  419. switch (iPixelType) {
  420. case PFD_TYPE_RGBA:
  421. return "rgba";
  422. case PFD_TYPE_COLORINDEX:
  423. return "ci";
  424. default:
  425. return "";
  426. }
  427. }
  428. static void
  429. print_visual_attribs_verbose(int iPixelFormat, LPPIXELFORMATDESCRIPTOR ppfd)
  430. {
  431. printf("Visual ID: %x generic=%d native=%d\n",
  432. iPixelFormat,
  433. ppfd->dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
  434. ppfd->dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0);
  435. printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n",
  436. 0 /* ppfd->bufferSize */, 0 /* ppfd->level */,
  437. visual_render_type_name(ppfd->iPixelType),
  438. ppfd->dwFlags & PFD_DOUBLEBUFFER ? 1 : 0,
  439. ppfd->dwFlags & PFD_STEREO ? 1 : 0);
  440. printf(" rgba: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d\n",
  441. ppfd->cRedBits, ppfd->cGreenBits,
  442. ppfd->cBlueBits, ppfd->cAlphaBits);
  443. printf(" cAuxBuffers=%d cDepthBits=%d cStencilBits=%d\n",
  444. ppfd->cAuxBuffers, ppfd->cDepthBits, ppfd->cStencilBits);
  445. printf(" accum: cRedBits=%d cGreenBits=%d cBlueBits=%d cAlphaBits=%d\n",
  446. ppfd->cAccumRedBits, ppfd->cAccumGreenBits,
  447. ppfd->cAccumBlueBits, ppfd->cAccumAlphaBits);
  448. printf(" multiSample=%d multiSampleBuffers=%d\n",
  449. 0 /* ppfd->numSamples */, 0 /* ppfd->numMultisample */);
  450. }
  451. static void
  452. print_visual_attribs_short_header(void)
  453. {
  454. printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n");
  455. printf(" id gen nat sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n");
  456. printf("-----------------------------------------------------------------------\n");
  457. }
  458. static void
  459. print_visual_attribs_short(int iPixelFormat, LPPIXELFORMATDESCRIPTOR ppfd)
  460. {
  461. char *caveat = "None";
  462. printf("0x%02x %2d %2d %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d",
  463. iPixelFormat,
  464. ppfd->dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
  465. ppfd->dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0,
  466. 0,
  467. 0 /* ppfd->bufferSize */,
  468. 0 /* ppfd->level */,
  469. ppfd->iPixelType == PFD_TYPE_RGBA ? 'r' : ' ',
  470. ppfd->iPixelType == PFD_TYPE_COLORINDEX ? 'c' : ' ',
  471. ppfd->dwFlags & PFD_DOUBLEBUFFER ? 'y' : '.',
  472. ppfd->dwFlags & PFD_STEREO ? 'y' : '.',
  473. ppfd->cRedBits, ppfd->cGreenBits,
  474. ppfd->cBlueBits, ppfd->cAlphaBits,
  475. ppfd->cAuxBuffers,
  476. ppfd->cDepthBits,
  477. ppfd->cStencilBits
  478. );
  479. printf(" %2d %2d %2d %2d %2d %1d %s\n",
  480. ppfd->cAccumRedBits, ppfd->cAccumGreenBits,
  481. ppfd->cAccumBlueBits, ppfd->cAccumAlphaBits,
  482. 0 /* ppfd->numSamples */, 0 /* ppfd->numMultisample */,
  483. caveat
  484. );
  485. }
  486. static void
  487. print_visual_attribs_long_header(void)
  488. {
  489. printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n");
  490. printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n");
  491. printf("----------------------------------------------------------------------------------------------------\n");
  492. }
  493. static void
  494. print_visual_attribs_long(int iPixelFormat, LPPIXELFORMATDESCRIPTOR ppfd)
  495. {
  496. printf("0x%2x %2d %11d %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d",
  497. iPixelFormat,
  498. ppfd->dwFlags & PFD_GENERIC_FORMAT ? 1 : 0,
  499. ppfd->dwFlags & PFD_DRAW_TO_WINDOW ? 1 : 0,
  500. 0,
  501. 0 /* ppfd->bufferSize */,
  502. 0 /* ppfd->level */,
  503. visual_render_type_name(ppfd->iPixelType),
  504. ppfd->dwFlags & PFD_DOUBLEBUFFER ? 1 : 0,
  505. ppfd->dwFlags & PFD_STEREO ? 1 : 0,
  506. ppfd->cRedBits, ppfd->cGreenBits,
  507. ppfd->cBlueBits, ppfd->cAlphaBits
  508. );
  509. printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n",
  510. ppfd->cAuxBuffers,
  511. ppfd->cDepthBits,
  512. ppfd->cStencilBits,
  513. ppfd->cAccumRedBits, ppfd->cAccumGreenBits,
  514. ppfd->cAccumBlueBits, ppfd->cAccumAlphaBits,
  515. 0 /* ppfd->numSamples */, 0 /* ppfd->numMultisample */
  516. );
  517. }
  518. static void
  519. print_visual_info(HDC hdc, InfoMode mode)
  520. {
  521. PIXELFORMATDESCRIPTOR pfd;
  522. int numVisuals, numWglVisuals;
  523. int i;
  524. numVisuals = DescribePixelFormat(hdc, 1, sizeof(PIXELFORMATDESCRIPTOR), NULL);
  525. if (numVisuals == 0)
  526. return;
  527. numWglVisuals = 0;
  528. for (i = 0; i < numVisuals; i++) {
  529. if(!DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
  530. continue;
  531. //if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
  532. // continue;
  533. ++numWglVisuals;
  534. }
  535. printf("%d WGL Visuals\n", numWglVisuals);
  536. if (mode == Normal)
  537. print_visual_attribs_short_header();
  538. else if (mode == Wide)
  539. print_visual_attribs_long_header();
  540. for (i = 0; i < numVisuals; i++) {
  541. if(!DescribePixelFormat(hdc, i, sizeof(PIXELFORMATDESCRIPTOR), &pfd))
  542. continue;
  543. //if(!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
  544. // continue;
  545. if (mode == Verbose)
  546. print_visual_attribs_verbose(i, &pfd);
  547. else if (mode == Normal)
  548. print_visual_attribs_short(i, &pfd);
  549. else if (mode == Wide)
  550. print_visual_attribs_long(i, &pfd);
  551. }
  552. printf("\n");
  553. }
  554. /*
  555. * Examine all visuals to find the so-called best one.
  556. * We prefer deepest RGBA buffer with depth, stencil and accum
  557. * that has no caveats.
  558. */
  559. static int
  560. find_best_visual(HDC hdc)
  561. {
  562. #if 0
  563. XVisualInfo theTemplate;
  564. XVisualInfo *visuals;
  565. int numVisuals;
  566. long mask;
  567. int i;
  568. struct visual_attribs bestVis;
  569. /* get list of all visuals on this screen */
  570. theTemplate.screen = scrnum;
  571. mask = VisualScreenMask;
  572. visuals = XGetVisualInfo(hdc, mask, &theTemplate, &numVisuals);
  573. /* init bestVis with first visual info */
  574. get_visual_attribs(hdc, &visuals[0], &bestVis);
  575. /* try to find a "better" visual */
  576. for (i = 1; i < numVisuals; i++) {
  577. struct visual_attribs vis;
  578. get_visual_attribs(hdc, &visuals[i], &vis);
  579. /* always skip visuals with caveats */
  580. if (vis.visualCaveat != GLX_NONE_EXT)
  581. continue;
  582. /* see if this vis is better than bestVis */
  583. if ((!bestVis.supportsGL && vis.supportsGL) ||
  584. (bestVis.visualCaveat != GLX_NONE_EXT) ||
  585. (bestVis.iPixelType != vis.iPixelType) ||
  586. (!bestVis.doubleBuffer && vis.doubleBuffer) ||
  587. (bestVis.cRedBits < vis.cRedBits) ||
  588. (bestVis.cGreenBits < vis.cGreenBits) ||
  589. (bestVis.cBlueBits < vis.cBlueBits) ||
  590. (bestVis.cAlphaBits < vis.cAlphaBits) ||
  591. (bestVis.cDepthBits < vis.cDepthBits) ||
  592. (bestVis.cStencilBits < vis.cStencilBits) ||
  593. (bestVis.cAccumRedBits < vis.cAccumRedBits)) {
  594. /* found a better visual */
  595. bestVis = vis;
  596. }
  597. }
  598. return bestVis.id;
  599. #else
  600. return 0;
  601. #endif
  602. }
  603. static void
  604. usage(void)
  605. {
  606. printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display <dname>]\n");
  607. printf("\t-v: Print visuals info in verbose form.\n");
  608. printf("\t-t: Print verbose table.\n");
  609. printf("\t-h: This information.\n");
  610. printf("\t-b: Find the 'best' visual and print it's number.\n");
  611. printf("\t-l: Print interesting OpenGL limits.\n");
  612. }
  613. int
  614. main(int argc, char *argv[])
  615. {
  616. HDC hdc;
  617. InfoMode mode = Normal;
  618. GLboolean findBest = GL_FALSE;
  619. GLboolean limits = GL_FALSE;
  620. int i;
  621. for (i = 1; i < argc; i++) {
  622. if (strcmp(argv[i], "-t") == 0) {
  623. mode = Wide;
  624. }
  625. else if (strcmp(argv[i], "-v") == 0) {
  626. mode = Verbose;
  627. }
  628. else if (strcmp(argv[i], "-b") == 0) {
  629. findBest = GL_TRUE;
  630. }
  631. else if (strcmp(argv[i], "-l") == 0) {
  632. limits = GL_TRUE;
  633. }
  634. else if (strcmp(argv[i], "-h") == 0) {
  635. usage();
  636. return 0;
  637. }
  638. else {
  639. printf("Unknown option `%s'\n", argv[i]);
  640. usage();
  641. return 0;
  642. }
  643. }
  644. hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);
  645. if (findBest) {
  646. int b;
  647. b = find_best_visual(hdc);
  648. printf("%d\n", b);
  649. }
  650. else {
  651. print_screen_info(hdc, limits);
  652. printf("\n");
  653. print_visual_info(hdc, mode);
  654. }
  655. return 0;
  656. }