glfwinfo.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. //========================================================================
  2. // Context creation and information tool
  3. // Copyright (c) Camilla Löwy <[email protected]>
  4. //
  5. // This software is provided 'as-is', without any express or implied
  6. // warranty. In no event will the authors be held liable for any damages
  7. // arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it
  11. // freely, subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented; you must not
  14. // claim that you wrote the original software. If you use this software
  15. // in a product, an acknowledgment in the product documentation would
  16. // be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such, and must not
  19. // be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source
  22. // distribution.
  23. //
  24. //========================================================================
  25. #include <glad/gl.h>
  26. #include <glad/vulkan.h>
  27. #define GLFW_INCLUDE_NONE
  28. #include <GLFW/glfw3.h>
  29. #include <stdio.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <stdbool.h>
  33. #include "getopt.h"
  34. #ifdef _MSC_VER
  35. #define strcasecmp(x, y) _stricmp(x, y)
  36. #endif
  37. #define API_NAME_OPENGL "gl"
  38. #define API_NAME_OPENGL_ES "es"
  39. #define API_NAME_NATIVE "native"
  40. #define API_NAME_EGL "egl"
  41. #define API_NAME_OSMESA "osmesa"
  42. #define PROFILE_NAME_CORE "core"
  43. #define PROFILE_NAME_COMPAT "compat"
  44. #define STRATEGY_NAME_NONE "none"
  45. #define STRATEGY_NAME_LOSE "lose"
  46. #define BEHAVIOR_NAME_NONE "none"
  47. #define BEHAVIOR_NAME_FLUSH "flush"
  48. static void usage(void)
  49. {
  50. printf("Usage: glfwinfo [OPTION]...\n");
  51. printf("Options:\n");
  52. printf(" -a, --client-api=API the client API to use ("
  53. API_NAME_OPENGL " or "
  54. API_NAME_OPENGL_ES ")\n");
  55. printf(" -b, --behavior=BEHAVIOR the release behavior to use ("
  56. BEHAVIOR_NAME_NONE " or "
  57. BEHAVIOR_NAME_FLUSH ")\n");
  58. printf(" -c, --context-api=API the context creation API to use ("
  59. API_NAME_NATIVE " or "
  60. API_NAME_EGL " or "
  61. API_NAME_OSMESA ")\n");
  62. printf(" -d, --debug request a debug context\n");
  63. printf(" -f, --forward require a forward-compatible context\n");
  64. printf(" -h, --help show this help\n");
  65. printf(" -l, --list-extensions list all Vulkan and client API extensions\n");
  66. printf(" --list-layers list all Vulkan layers\n");
  67. printf(" -m, --major=MAJOR the major number of the required "
  68. "client API version\n");
  69. printf(" -n, --minor=MINOR the minor number of the required "
  70. "client API version\n");
  71. printf(" -p, --profile=PROFILE the OpenGL profile to use ("
  72. PROFILE_NAME_CORE " or "
  73. PROFILE_NAME_COMPAT ")\n");
  74. printf(" -s, --robustness=STRATEGY the robustness strategy to use ("
  75. STRATEGY_NAME_NONE " or "
  76. STRATEGY_NAME_LOSE ")\n");
  77. printf(" -v, --version print version information\n");
  78. printf(" --red-bits=N the number of red bits to request\n");
  79. printf(" --green-bits=N the number of green bits to request\n");
  80. printf(" --blue-bits=N the number of blue bits to request\n");
  81. printf(" --alpha-bits=N the number of alpha bits to request\n");
  82. printf(" --depth-bits=N the number of depth bits to request\n");
  83. printf(" --stencil-bits=N the number of stencil bits to request\n");
  84. printf(" --accum-red-bits=N the number of red bits to request\n");
  85. printf(" --accum-green-bits=N the number of green bits to request\n");
  86. printf(" --accum-blue-bits=N the number of blue bits to request\n");
  87. printf(" --accum-alpha-bits=N the number of alpha bits to request\n");
  88. printf(" --aux-buffers=N the number of aux buffers to request\n");
  89. printf(" --samples=N the number of MSAA samples to request\n");
  90. printf(" --stereo request stereo rendering\n");
  91. printf(" --srgb request an sRGB capable framebuffer\n");
  92. printf(" --singlebuffer request single-buffering\n");
  93. printf(" --no-error request a context that does not emit errors\n");
  94. printf(" --graphics-switching request macOS graphics switching\n");
  95. }
  96. static void error_callback(int error, const char* description)
  97. {
  98. fprintf(stderr, "Error: %s\n", description);
  99. }
  100. static const char* get_device_type_name(VkPhysicalDeviceType type)
  101. {
  102. if (type == VK_PHYSICAL_DEVICE_TYPE_OTHER)
  103. return "other";
  104. else if (type == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
  105. return "integrated GPU";
  106. else if (type == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  107. return "discrete GPU";
  108. else if (type == VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU)
  109. return "virtual GPU";
  110. else if (type == VK_PHYSICAL_DEVICE_TYPE_CPU)
  111. return "CPU";
  112. return "unknown";
  113. }
  114. static const char* get_api_name(int api)
  115. {
  116. if (api == GLFW_OPENGL_API)
  117. return "OpenGL";
  118. else if (api == GLFW_OPENGL_ES_API)
  119. return "OpenGL ES";
  120. return "Unknown API";
  121. }
  122. static const char* get_profile_name_gl(GLint mask)
  123. {
  124. if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
  125. return PROFILE_NAME_COMPAT;
  126. if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
  127. return PROFILE_NAME_CORE;
  128. return "unknown";
  129. }
  130. static const char* get_profile_name_glfw(int profile)
  131. {
  132. if (profile == GLFW_OPENGL_COMPAT_PROFILE)
  133. return PROFILE_NAME_COMPAT;
  134. if (profile == GLFW_OPENGL_CORE_PROFILE)
  135. return PROFILE_NAME_CORE;
  136. return "unknown";
  137. }
  138. static const char* get_strategy_name_gl(GLint strategy)
  139. {
  140. if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
  141. return STRATEGY_NAME_LOSE;
  142. if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
  143. return STRATEGY_NAME_NONE;
  144. return "unknown";
  145. }
  146. static const char* get_strategy_name_glfw(int strategy)
  147. {
  148. if (strategy == GLFW_LOSE_CONTEXT_ON_RESET)
  149. return STRATEGY_NAME_LOSE;
  150. if (strategy == GLFW_NO_RESET_NOTIFICATION)
  151. return STRATEGY_NAME_NONE;
  152. return "unknown";
  153. }
  154. static void list_context_extensions(int client, int major, int minor)
  155. {
  156. printf("%s context extensions:\n", get_api_name(client));
  157. if (client == GLFW_OPENGL_API && major > 2)
  158. {
  159. GLint count;
  160. glGetIntegerv(GL_NUM_EXTENSIONS, &count);
  161. for (int i = 0; i < count; i++)
  162. printf(" %s\n", (const char*) glGetStringi(GL_EXTENSIONS, i));
  163. }
  164. else
  165. {
  166. const GLubyte* extensions = glGetString(GL_EXTENSIONS);
  167. while (*extensions != '\0')
  168. {
  169. putchar(' ');
  170. while (*extensions != '\0' && *extensions != ' ')
  171. {
  172. putchar(*extensions);
  173. extensions++;
  174. }
  175. while (*extensions == ' ')
  176. extensions++;
  177. putchar('\n');
  178. }
  179. }
  180. }
  181. static void list_vulkan_instance_extensions(void)
  182. {
  183. printf("Vulkan instance extensions:\n");
  184. uint32_t ep_count;
  185. vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
  186. VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
  187. vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
  188. for (uint32_t i = 0; i < ep_count; i++)
  189. printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
  190. free(ep);
  191. }
  192. static void list_vulkan_instance_layers(void)
  193. {
  194. printf("Vulkan instance layers:\n");
  195. uint32_t lp_count;
  196. vkEnumerateInstanceLayerProperties(&lp_count, NULL);
  197. VkLayerProperties* lp = calloc(lp_count, sizeof(VkLayerProperties));
  198. vkEnumerateInstanceLayerProperties(&lp_count, lp);
  199. for (uint32_t i = 0; i < lp_count; i++)
  200. {
  201. printf(" %s (spec version %u) \"%s\"\n",
  202. lp[i].layerName,
  203. lp[i].specVersion >> 22,
  204. lp[i].description);
  205. }
  206. free(lp);
  207. }
  208. static void list_vulkan_device_extensions(VkInstance instance, VkPhysicalDevice device)
  209. {
  210. printf("Vulkan device extensions:\n");
  211. uint32_t ep_count;
  212. vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, NULL);
  213. VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
  214. vkEnumerateDeviceExtensionProperties(device, NULL, &ep_count, ep);
  215. for (uint32_t i = 0; i < ep_count; i++)
  216. printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
  217. free(ep);
  218. }
  219. static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
  220. {
  221. printf("Vulkan device layers:\n");
  222. uint32_t lp_count;
  223. vkEnumerateDeviceLayerProperties(device, &lp_count, NULL);
  224. VkLayerProperties* lp = calloc(lp_count, sizeof(VkLayerProperties));
  225. vkEnumerateDeviceLayerProperties(device, &lp_count, lp);
  226. for (uint32_t i = 0; i < lp_count; i++)
  227. {
  228. printf(" %s (spec version %u) \"%s\"\n",
  229. lp[i].layerName,
  230. lp[i].specVersion >> 22,
  231. lp[i].description);
  232. }
  233. free(lp);
  234. }
  235. static int valid_version(void)
  236. {
  237. int major, minor, revision;
  238. glfwGetVersion(&major, &minor, &revision);
  239. if (major != GLFW_VERSION_MAJOR)
  240. {
  241. printf("*** ERROR: GLFW major version mismatch! ***\n");
  242. return GLFW_FALSE;
  243. }
  244. if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION)
  245. printf("*** WARNING: GLFW version mismatch! ***\n");
  246. return GLFW_TRUE;
  247. }
  248. static void print_version(void)
  249. {
  250. int major, minor, revision;
  251. glfwGetVersion(&major, &minor, &revision);
  252. printf("GLFW header version: %u.%u.%u\n",
  253. GLFW_VERSION_MAJOR,
  254. GLFW_VERSION_MINOR,
  255. GLFW_VERSION_REVISION);
  256. printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
  257. printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
  258. }
  259. static GLADapiproc glad_vulkan_callback(const char* name, void* user)
  260. {
  261. return glfwGetInstanceProcAddress((VkInstance) user, name);
  262. }
  263. int main(int argc, char** argv)
  264. {
  265. int ch;
  266. bool list_extensions = false, list_layers = false;
  267. enum { CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP,
  268. EXTENSIONS, LAYERS,
  269. MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
  270. REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
  271. ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
  272. AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER, NOERROR_SRSLY,
  273. GRAPHICS_SWITCHING };
  274. const struct option options[] =
  275. {
  276. { "behavior", 1, NULL, BEHAVIOR },
  277. { "client-api", 1, NULL, CLIENT },
  278. { "context-api", 1, NULL, CONTEXT },
  279. { "debug", 0, NULL, DEBUG_CONTEXT },
  280. { "forward", 0, NULL, FORWARD },
  281. { "help", 0, NULL, HELP },
  282. { "list-extensions", 0, NULL, EXTENSIONS },
  283. { "list-layers", 0, NULL, LAYERS },
  284. { "major", 1, NULL, MAJOR },
  285. { "minor", 1, NULL, MINOR },
  286. { "profile", 1, NULL, PROFILE },
  287. { "robustness", 1, NULL, ROBUSTNESS },
  288. { "version", 0, NULL, VERSION },
  289. { "red-bits", 1, NULL, REDBITS },
  290. { "green-bits", 1, NULL, GREENBITS },
  291. { "blue-bits", 1, NULL, BLUEBITS },
  292. { "alpha-bits", 1, NULL, ALPHABITS },
  293. { "depth-bits", 1, NULL, DEPTHBITS },
  294. { "stencil-bits", 1, NULL, STENCILBITS },
  295. { "accum-red-bits", 1, NULL, ACCUMREDBITS },
  296. { "accum-green-bits", 1, NULL, ACCUMGREENBITS },
  297. { "accum-blue-bits", 1, NULL, ACCUMBLUEBITS },
  298. { "accum-alpha-bits", 1, NULL, ACCUMALPHABITS },
  299. { "aux-buffers", 1, NULL, AUXBUFFERS },
  300. { "samples", 1, NULL, SAMPLES },
  301. { "stereo", 0, NULL, STEREO },
  302. { "srgb", 0, NULL, SRGB },
  303. { "singlebuffer", 0, NULL, SINGLEBUFFER },
  304. { "no-error", 0, NULL, NOERROR_SRSLY },
  305. { "graphics-switching", 0, NULL, GRAPHICS_SWITCHING },
  306. { NULL, 0, NULL, 0 }
  307. };
  308. // Initialize GLFW and create window
  309. if (!valid_version())
  310. exit(EXIT_FAILURE);
  311. glfwSetErrorCallback(error_callback);
  312. glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
  313. if (!glfwInit())
  314. exit(EXIT_FAILURE);
  315. while ((ch = getopt_long(argc, argv, "a:b:c:dfhlm:n:p:s:v", options, NULL)) != -1)
  316. {
  317. switch (ch)
  318. {
  319. case 'a':
  320. case CLIENT:
  321. if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
  322. glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
  323. else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
  324. glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
  325. else
  326. {
  327. usage();
  328. exit(EXIT_FAILURE);
  329. }
  330. break;
  331. case 'b':
  332. case BEHAVIOR:
  333. if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
  334. {
  335. glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
  336. GLFW_RELEASE_BEHAVIOR_NONE);
  337. }
  338. else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
  339. {
  340. glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
  341. GLFW_RELEASE_BEHAVIOR_FLUSH);
  342. }
  343. else
  344. {
  345. usage();
  346. exit(EXIT_FAILURE);
  347. }
  348. break;
  349. case 'c':
  350. case CONTEXT:
  351. if (strcasecmp(optarg, API_NAME_NATIVE) == 0)
  352. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
  353. else if (strcasecmp(optarg, API_NAME_EGL) == 0)
  354. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
  355. else if (strcasecmp(optarg, API_NAME_OSMESA) == 0)
  356. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_OSMESA_CONTEXT_API);
  357. else
  358. {
  359. usage();
  360. exit(EXIT_FAILURE);
  361. }
  362. break;
  363. case 'd':
  364. case DEBUG_CONTEXT:
  365. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
  366. break;
  367. case 'f':
  368. case FORWARD:
  369. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
  370. break;
  371. case 'h':
  372. case HELP:
  373. usage();
  374. exit(EXIT_SUCCESS);
  375. case 'l':
  376. case EXTENSIONS:
  377. list_extensions = GLFW_TRUE;
  378. break;
  379. case LAYERS:
  380. list_layers = GLFW_TRUE;
  381. break;
  382. case 'm':
  383. case MAJOR:
  384. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, atoi(optarg));
  385. break;
  386. case 'n':
  387. case MINOR:
  388. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, atoi(optarg));
  389. break;
  390. case 'p':
  391. case PROFILE:
  392. if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
  393. {
  394. glfwWindowHint(GLFW_OPENGL_PROFILE,
  395. GLFW_OPENGL_CORE_PROFILE);
  396. }
  397. else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
  398. {
  399. glfwWindowHint(GLFW_OPENGL_PROFILE,
  400. GLFW_OPENGL_COMPAT_PROFILE);
  401. }
  402. else
  403. {
  404. usage();
  405. exit(EXIT_FAILURE);
  406. }
  407. break;
  408. case 's':
  409. case ROBUSTNESS:
  410. if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
  411. {
  412. glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
  413. GLFW_NO_RESET_NOTIFICATION);
  414. }
  415. else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
  416. {
  417. glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
  418. GLFW_LOSE_CONTEXT_ON_RESET);
  419. }
  420. else
  421. {
  422. usage();
  423. exit(EXIT_FAILURE);
  424. }
  425. break;
  426. case 'v':
  427. case VERSION:
  428. print_version();
  429. exit(EXIT_SUCCESS);
  430. case REDBITS:
  431. if (strcmp(optarg, "-") == 0)
  432. glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
  433. else
  434. glfwWindowHint(GLFW_RED_BITS, atoi(optarg));
  435. break;
  436. case GREENBITS:
  437. if (strcmp(optarg, "-") == 0)
  438. glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
  439. else
  440. glfwWindowHint(GLFW_GREEN_BITS, atoi(optarg));
  441. break;
  442. case BLUEBITS:
  443. if (strcmp(optarg, "-") == 0)
  444. glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
  445. else
  446. glfwWindowHint(GLFW_BLUE_BITS, atoi(optarg));
  447. break;
  448. case ALPHABITS:
  449. if (strcmp(optarg, "-") == 0)
  450. glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
  451. else
  452. glfwWindowHint(GLFW_ALPHA_BITS, atoi(optarg));
  453. break;
  454. case DEPTHBITS:
  455. if (strcmp(optarg, "-") == 0)
  456. glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
  457. else
  458. glfwWindowHint(GLFW_DEPTH_BITS, atoi(optarg));
  459. break;
  460. case STENCILBITS:
  461. if (strcmp(optarg, "-") == 0)
  462. glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
  463. else
  464. glfwWindowHint(GLFW_STENCIL_BITS, atoi(optarg));
  465. break;
  466. case ACCUMREDBITS:
  467. if (strcmp(optarg, "-") == 0)
  468. glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
  469. else
  470. glfwWindowHint(GLFW_ACCUM_RED_BITS, atoi(optarg));
  471. break;
  472. case ACCUMGREENBITS:
  473. if (strcmp(optarg, "-") == 0)
  474. glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
  475. else
  476. glfwWindowHint(GLFW_ACCUM_GREEN_BITS, atoi(optarg));
  477. break;
  478. case ACCUMBLUEBITS:
  479. if (strcmp(optarg, "-") == 0)
  480. glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
  481. else
  482. glfwWindowHint(GLFW_ACCUM_BLUE_BITS, atoi(optarg));
  483. break;
  484. case ACCUMALPHABITS:
  485. if (strcmp(optarg, "-") == 0)
  486. glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
  487. else
  488. glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, atoi(optarg));
  489. break;
  490. case AUXBUFFERS:
  491. if (strcmp(optarg, "-") == 0)
  492. glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
  493. else
  494. glfwWindowHint(GLFW_AUX_BUFFERS, atoi(optarg));
  495. break;
  496. case SAMPLES:
  497. if (strcmp(optarg, "-") == 0)
  498. glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
  499. else
  500. glfwWindowHint(GLFW_SAMPLES, atoi(optarg));
  501. break;
  502. case STEREO:
  503. glfwWindowHint(GLFW_STEREO, GLFW_TRUE);
  504. break;
  505. case SRGB:
  506. glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
  507. break;
  508. case SINGLEBUFFER:
  509. glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_FALSE);
  510. break;
  511. case NOERROR_SRSLY:
  512. glfwWindowHint(GLFW_CONTEXT_NO_ERROR, GLFW_TRUE);
  513. break;
  514. case GRAPHICS_SWITCHING:
  515. glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE);
  516. break;
  517. default:
  518. usage();
  519. exit(EXIT_FAILURE);
  520. }
  521. }
  522. print_version();
  523. glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
  524. GLFWwindow* window = glfwCreateWindow(200, 200, "Version", NULL, NULL);
  525. if (!window)
  526. {
  527. glfwTerminate();
  528. exit(EXIT_FAILURE);
  529. }
  530. glfwMakeContextCurrent(window);
  531. gladLoadGL(glfwGetProcAddress);
  532. const GLenum error = glGetError();
  533. if (error != GL_NO_ERROR)
  534. printf("*** OpenGL error after make current: 0x%08x ***\n", error);
  535. // Report client API version
  536. const int client = glfwGetWindowAttrib(window, GLFW_CLIENT_API);
  537. const int major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
  538. const int minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
  539. const int revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
  540. const int profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
  541. printf("%s context version string: \"%s\"\n",
  542. get_api_name(client),
  543. glGetString(GL_VERSION));
  544. printf("%s context version parsed by GLFW: %u.%u.%u\n",
  545. get_api_name(client),
  546. major, minor, revision);
  547. // Report client API context properties
  548. if (client == GLFW_OPENGL_API)
  549. {
  550. if (major >= 3)
  551. {
  552. GLint flags;
  553. glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
  554. printf("%s context flags (0x%08x):", get_api_name(client), flags);
  555. if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
  556. printf(" forward-compatible");
  557. if (flags & 2/*GL_CONTEXT_FLAG_DEBUG_BIT*/)
  558. printf(" debug");
  559. if (flags & GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB)
  560. printf(" robustness");
  561. if (flags & 8/*GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR*/)
  562. printf(" no-error");
  563. putchar('\n');
  564. printf("%s context flags parsed by GLFW:", get_api_name(client));
  565. if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
  566. printf(" forward-compatible");
  567. if (glfwGetWindowAttrib(window, GLFW_OPENGL_DEBUG_CONTEXT))
  568. printf(" debug");
  569. if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
  570. printf(" robustness");
  571. if (glfwGetWindowAttrib(window, GLFW_CONTEXT_NO_ERROR))
  572. printf(" no-error");
  573. putchar('\n');
  574. }
  575. if (major >= 4 || (major == 3 && minor >= 2))
  576. {
  577. GLint mask;
  578. glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
  579. printf("%s profile mask (0x%08x): %s\n",
  580. get_api_name(client),
  581. mask,
  582. get_profile_name_gl(mask));
  583. printf("%s profile mask parsed by GLFW: %s\n",
  584. get_api_name(client),
  585. get_profile_name_glfw(profile));
  586. }
  587. if (GLAD_GL_ARB_robustness)
  588. {
  589. const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
  590. GLint strategy;
  591. glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
  592. printf("%s robustness strategy (0x%08x): %s\n",
  593. get_api_name(client),
  594. strategy,
  595. get_strategy_name_gl(strategy));
  596. printf("%s robustness strategy parsed by GLFW: %s\n",
  597. get_api_name(client),
  598. get_strategy_name_glfw(robustness));
  599. }
  600. }
  601. printf("%s context renderer string: \"%s\"\n",
  602. get_api_name(client),
  603. glGetString(GL_RENDERER));
  604. printf("%s context vendor string: \"%s\"\n",
  605. get_api_name(client),
  606. glGetString(GL_VENDOR));
  607. if (major >= 2)
  608. {
  609. printf("%s context shading language version: \"%s\"\n",
  610. get_api_name(client),
  611. glGetString(GL_SHADING_LANGUAGE_VERSION));
  612. }
  613. printf("%s framebuffer:\n", get_api_name(client));
  614. GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
  615. if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
  616. {
  617. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  618. GL_BACK_LEFT,
  619. GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
  620. &redbits);
  621. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  622. GL_BACK_LEFT,
  623. GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
  624. &greenbits);
  625. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  626. GL_BACK_LEFT,
  627. GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
  628. &bluebits);
  629. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  630. GL_BACK_LEFT,
  631. GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
  632. &alphabits);
  633. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  634. GL_DEPTH,
  635. GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
  636. &depthbits);
  637. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  638. GL_STENCIL,
  639. GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
  640. &stencilbits);
  641. }
  642. else
  643. {
  644. glGetIntegerv(GL_RED_BITS, &redbits);
  645. glGetIntegerv(GL_GREEN_BITS, &greenbits);
  646. glGetIntegerv(GL_BLUE_BITS, &bluebits);
  647. glGetIntegerv(GL_ALPHA_BITS, &alphabits);
  648. glGetIntegerv(GL_DEPTH_BITS, &depthbits);
  649. glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
  650. }
  651. printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
  652. redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
  653. if (client == GLFW_OPENGL_ES_API ||
  654. GLAD_GL_ARB_multisample ||
  655. major > 1 || minor >= 3)
  656. {
  657. GLint samples, samplebuffers;
  658. glGetIntegerv(GL_SAMPLES, &samples);
  659. glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
  660. printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
  661. }
  662. if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
  663. {
  664. GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
  665. GLint auxbuffers;
  666. glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
  667. glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
  668. glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
  669. glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
  670. glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
  671. printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
  672. accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
  673. }
  674. if (list_extensions)
  675. list_context_extensions(client, major, minor);
  676. printf("Vulkan loader: %s\n",
  677. glfwVulkanSupported() ? "available" : "missing");
  678. if (glfwVulkanSupported())
  679. {
  680. gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, NULL);
  681. uint32_t loader_version = VK_API_VERSION_1_0;
  682. if (vkEnumerateInstanceVersion)
  683. {
  684. uint32_t version;
  685. if (vkEnumerateInstanceVersion(&version) == VK_SUCCESS)
  686. loader_version = version;
  687. }
  688. printf("Vulkan loader API version: %i.%i\n",
  689. VK_VERSION_MAJOR(loader_version),
  690. VK_VERSION_MINOR(loader_version));
  691. uint32_t re_count;
  692. const char** re = glfwGetRequiredInstanceExtensions(&re_count);
  693. printf("Vulkan required instance extensions:");
  694. if (re)
  695. {
  696. for (uint32_t i = 0; i < re_count; i++)
  697. printf(" %s", re[i]);
  698. putchar('\n');
  699. }
  700. else
  701. printf(" missing\n");
  702. if (list_extensions)
  703. list_vulkan_instance_extensions();
  704. if (list_layers)
  705. list_vulkan_instance_layers();
  706. VkApplicationInfo ai = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
  707. ai.pApplicationName = "glfwinfo";
  708. ai.applicationVersion = VK_MAKE_VERSION(GLFW_VERSION_MAJOR,
  709. GLFW_VERSION_MINOR,
  710. GLFW_VERSION_REVISION);
  711. if (loader_version >= VK_API_VERSION_1_1)
  712. ai.apiVersion = VK_API_VERSION_1_1;
  713. else
  714. ai.apiVersion = VK_API_VERSION_1_0;
  715. VkInstanceCreateInfo ici = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
  716. ici.pApplicationInfo = &ai;
  717. ici.enabledExtensionCount = re_count;
  718. ici.ppEnabledExtensionNames = re;
  719. VkInstance instance = VK_NULL_HANDLE;
  720. if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
  721. {
  722. glfwTerminate();
  723. exit(EXIT_FAILURE);
  724. }
  725. gladLoadVulkanUserPtr(NULL, glad_vulkan_callback, instance);
  726. uint32_t pd_count;
  727. vkEnumeratePhysicalDevices(instance, &pd_count, NULL);
  728. VkPhysicalDevice* pd = calloc(pd_count, sizeof(VkPhysicalDevice));
  729. vkEnumeratePhysicalDevices(instance, &pd_count, pd);
  730. for (uint32_t i = 0; i < pd_count; i++)
  731. {
  732. VkPhysicalDeviceProperties pdp;
  733. vkGetPhysicalDeviceProperties(pd[i], &pdp);
  734. printf("Vulkan %s device: \"%s\" (API version %i.%i)\n",
  735. get_device_type_name(pdp.deviceType),
  736. pdp.deviceName,
  737. VK_VERSION_MAJOR(pdp.apiVersion),
  738. VK_VERSION_MINOR(pdp.apiVersion));
  739. if (list_extensions)
  740. list_vulkan_device_extensions(instance, pd[i]);
  741. if (list_layers)
  742. list_vulkan_device_layers(instance, pd[i]);
  743. }
  744. free(pd);
  745. vkDestroyInstance(instance, NULL);
  746. }
  747. glfwTerminate();
  748. exit(EXIT_SUCCESS);
  749. }