glfwinfo.c 31 KB

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