glfwinfo.c 32 KB

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