glfwinfo.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  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 "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_layers(void)
  183. {
  184. uint32_t i, lp_count = 0;
  185. VkLayerProperties* lp;
  186. printf("Vulkan instance layers:\n");
  187. if (vkEnumerateInstanceLayerProperties(&lp_count, NULL) != VK_SUCCESS)
  188. return;
  189. lp = calloc(lp_count, sizeof(VkLayerProperties));
  190. if (vkEnumerateInstanceLayerProperties(&lp_count, lp) != VK_SUCCESS)
  191. {
  192. free(lp);
  193. return;
  194. }
  195. for (i = 0; i < lp_count; i++)
  196. {
  197. printf(" %s (v%u) \"%s\"\n",
  198. lp[i].layerName,
  199. lp[i].specVersion >> 22,
  200. lp[i].description);
  201. }
  202. free(lp);
  203. }
  204. static void list_vulkan_device_layers(VkInstance instance, VkPhysicalDevice device)
  205. {
  206. uint32_t i, lp_count;
  207. VkLayerProperties* lp;
  208. printf("Vulkan device layers:\n");
  209. if (vkEnumerateDeviceLayerProperties(device, &lp_count, NULL) != VK_SUCCESS)
  210. return;
  211. lp = calloc(lp_count, sizeof(VkLayerProperties));
  212. if (vkEnumerateDeviceLayerProperties(device, &lp_count, lp) != VK_SUCCESS)
  213. {
  214. free(lp);
  215. return;
  216. }
  217. for (i = 0; i < lp_count; i++)
  218. {
  219. printf(" %s (v%u) \"%s\"\n",
  220. lp[i].layerName,
  221. lp[i].specVersion >> 22,
  222. lp[i].description);
  223. }
  224. free(lp);
  225. }
  226. static int valid_version(void)
  227. {
  228. int major, minor, revision;
  229. glfwGetVersion(&major, &minor, &revision);
  230. if (major != GLFW_VERSION_MAJOR)
  231. {
  232. printf("*** ERROR: GLFW major version mismatch! ***\n");
  233. return GLFW_FALSE;
  234. }
  235. if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION)
  236. printf("*** WARNING: GLFW version mismatch! ***\n");
  237. return GLFW_TRUE;
  238. }
  239. static void print_version(void)
  240. {
  241. int major, minor, revision;
  242. glfwGetVersion(&major, &minor, &revision);
  243. printf("GLFW header version: %u.%u.%u\n",
  244. GLFW_VERSION_MAJOR,
  245. GLFW_VERSION_MINOR,
  246. GLFW_VERSION_REVISION);
  247. printf("GLFW library version: %u.%u.%u\n", major, minor, revision);
  248. printf("GLFW library version string: \"%s\"\n", glfwGetVersionString());
  249. }
  250. int main(int argc, char** argv)
  251. {
  252. int ch, client, major, minor, revision, profile;
  253. GLint redbits, greenbits, bluebits, alphabits, depthbits, stencilbits;
  254. int list_extensions = GLFW_FALSE, list_layers = GLFW_FALSE;
  255. GLenum error;
  256. GLFWwindow* window;
  257. enum { CLIENT, CONTEXT, BEHAVIOR, DEBUG_CONTEXT, FORWARD, HELP,
  258. EXTENSIONS, LAYERS,
  259. MAJOR, MINOR, PROFILE, ROBUSTNESS, VERSION,
  260. REDBITS, GREENBITS, BLUEBITS, ALPHABITS, DEPTHBITS, STENCILBITS,
  261. ACCUMREDBITS, ACCUMGREENBITS, ACCUMBLUEBITS, ACCUMALPHABITS,
  262. AUXBUFFERS, SAMPLES, STEREO, SRGB, SINGLEBUFFER, NOERROR_SRSLY,
  263. GRAPHICS_SWITCHING };
  264. const struct option options[] =
  265. {
  266. { "behavior", 1, NULL, BEHAVIOR },
  267. { "client-api", 1, NULL, CLIENT },
  268. { "context-api", 1, NULL, CONTEXT },
  269. { "debug", 0, NULL, DEBUG_CONTEXT },
  270. { "forward", 0, NULL, FORWARD },
  271. { "help", 0, NULL, HELP },
  272. { "list-extensions", 0, NULL, EXTENSIONS },
  273. { "list-layers", 0, NULL, LAYERS },
  274. { "major", 1, NULL, MAJOR },
  275. { "minor", 1, NULL, MINOR },
  276. { "profile", 1, NULL, PROFILE },
  277. { "robustness", 1, NULL, ROBUSTNESS },
  278. { "version", 0, NULL, VERSION },
  279. { "red-bits", 1, NULL, REDBITS },
  280. { "green-bits", 1, NULL, GREENBITS },
  281. { "blue-bits", 1, NULL, BLUEBITS },
  282. { "alpha-bits", 1, NULL, ALPHABITS },
  283. { "depth-bits", 1, NULL, DEPTHBITS },
  284. { "stencil-bits", 1, NULL, STENCILBITS },
  285. { "accum-red-bits", 1, NULL, ACCUMREDBITS },
  286. { "accum-green-bits", 1, NULL, ACCUMGREENBITS },
  287. { "accum-blue-bits", 1, NULL, ACCUMBLUEBITS },
  288. { "accum-alpha-bits", 1, NULL, ACCUMALPHABITS },
  289. { "aux-buffers", 1, NULL, AUXBUFFERS },
  290. { "samples", 1, NULL, SAMPLES },
  291. { "stereo", 0, NULL, STEREO },
  292. { "srgb", 0, NULL, SRGB },
  293. { "singlebuffer", 0, NULL, SINGLEBUFFER },
  294. { "no-error", 0, NULL, NOERROR_SRSLY },
  295. { "graphics-switching", 0, NULL, GRAPHICS_SWITCHING },
  296. { NULL, 0, NULL, 0 }
  297. };
  298. // Initialize GLFW and create window
  299. if (!valid_version())
  300. exit(EXIT_FAILURE);
  301. glfwSetErrorCallback(error_callback);
  302. glfwInitHint(GLFW_COCOA_MENUBAR, GLFW_FALSE);
  303. if (!glfwInit())
  304. exit(EXIT_FAILURE);
  305. while ((ch = getopt_long(argc, argv, "a:b:c:dfhlm:n:p:s:v", options, NULL)) != -1)
  306. {
  307. switch (ch)
  308. {
  309. case 'a':
  310. case CLIENT:
  311. if (strcasecmp(optarg, API_NAME_OPENGL) == 0)
  312. glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
  313. else if (strcasecmp(optarg, API_NAME_OPENGL_ES) == 0)
  314. glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
  315. else
  316. {
  317. usage();
  318. exit(EXIT_FAILURE);
  319. }
  320. break;
  321. case 'b':
  322. case BEHAVIOR:
  323. if (strcasecmp(optarg, BEHAVIOR_NAME_NONE) == 0)
  324. {
  325. glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
  326. GLFW_RELEASE_BEHAVIOR_NONE);
  327. }
  328. else if (strcasecmp(optarg, BEHAVIOR_NAME_FLUSH) == 0)
  329. {
  330. glfwWindowHint(GLFW_CONTEXT_RELEASE_BEHAVIOR,
  331. GLFW_RELEASE_BEHAVIOR_FLUSH);
  332. }
  333. else
  334. {
  335. usage();
  336. exit(EXIT_FAILURE);
  337. }
  338. break;
  339. case 'c':
  340. case CONTEXT:
  341. if (strcasecmp(optarg, API_NAME_NATIVE) == 0)
  342. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_NATIVE_CONTEXT_API);
  343. else if (strcasecmp(optarg, API_NAME_EGL) == 0)
  344. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
  345. else if (strcasecmp(optarg, API_NAME_OSMESA) == 0)
  346. glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_OSMESA_CONTEXT_API);
  347. else
  348. {
  349. usage();
  350. exit(EXIT_FAILURE);
  351. }
  352. break;
  353. case 'd':
  354. case DEBUG_CONTEXT:
  355. glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
  356. break;
  357. case 'f':
  358. case FORWARD:
  359. glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
  360. break;
  361. case 'h':
  362. case HELP:
  363. usage();
  364. exit(EXIT_SUCCESS);
  365. case 'l':
  366. case EXTENSIONS:
  367. list_extensions = GLFW_TRUE;
  368. break;
  369. case LAYERS:
  370. list_layers = GLFW_TRUE;
  371. break;
  372. case 'm':
  373. case MAJOR:
  374. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, atoi(optarg));
  375. break;
  376. case 'n':
  377. case MINOR:
  378. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, atoi(optarg));
  379. break;
  380. case 'p':
  381. case PROFILE:
  382. if (strcasecmp(optarg, PROFILE_NAME_CORE) == 0)
  383. {
  384. glfwWindowHint(GLFW_OPENGL_PROFILE,
  385. GLFW_OPENGL_CORE_PROFILE);
  386. }
  387. else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
  388. {
  389. glfwWindowHint(GLFW_OPENGL_PROFILE,
  390. GLFW_OPENGL_COMPAT_PROFILE);
  391. }
  392. else
  393. {
  394. usage();
  395. exit(EXIT_FAILURE);
  396. }
  397. break;
  398. case 's':
  399. case ROBUSTNESS:
  400. if (strcasecmp(optarg, STRATEGY_NAME_NONE) == 0)
  401. {
  402. glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
  403. GLFW_NO_RESET_NOTIFICATION);
  404. }
  405. else if (strcasecmp(optarg, STRATEGY_NAME_LOSE) == 0)
  406. {
  407. glfwWindowHint(GLFW_CONTEXT_ROBUSTNESS,
  408. GLFW_LOSE_CONTEXT_ON_RESET);
  409. }
  410. else
  411. {
  412. usage();
  413. exit(EXIT_FAILURE);
  414. }
  415. break;
  416. case 'v':
  417. case VERSION:
  418. print_version();
  419. exit(EXIT_SUCCESS);
  420. case REDBITS:
  421. if (strcmp(optarg, "-") == 0)
  422. glfwWindowHint(GLFW_RED_BITS, GLFW_DONT_CARE);
  423. else
  424. glfwWindowHint(GLFW_RED_BITS, atoi(optarg));
  425. break;
  426. case GREENBITS:
  427. if (strcmp(optarg, "-") == 0)
  428. glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
  429. else
  430. glfwWindowHint(GLFW_GREEN_BITS, atoi(optarg));
  431. break;
  432. case BLUEBITS:
  433. if (strcmp(optarg, "-") == 0)
  434. glfwWindowHint(GLFW_BLUE_BITS, GLFW_DONT_CARE);
  435. else
  436. glfwWindowHint(GLFW_BLUE_BITS, atoi(optarg));
  437. break;
  438. case ALPHABITS:
  439. if (strcmp(optarg, "-") == 0)
  440. glfwWindowHint(GLFW_ALPHA_BITS, GLFW_DONT_CARE);
  441. else
  442. glfwWindowHint(GLFW_ALPHA_BITS, atoi(optarg));
  443. break;
  444. case DEPTHBITS:
  445. if (strcmp(optarg, "-") == 0)
  446. glfwWindowHint(GLFW_DEPTH_BITS, GLFW_DONT_CARE);
  447. else
  448. glfwWindowHint(GLFW_DEPTH_BITS, atoi(optarg));
  449. break;
  450. case STENCILBITS:
  451. if (strcmp(optarg, "-") == 0)
  452. glfwWindowHint(GLFW_STENCIL_BITS, GLFW_DONT_CARE);
  453. else
  454. glfwWindowHint(GLFW_STENCIL_BITS, atoi(optarg));
  455. break;
  456. case ACCUMREDBITS:
  457. if (strcmp(optarg, "-") == 0)
  458. glfwWindowHint(GLFW_ACCUM_RED_BITS, GLFW_DONT_CARE);
  459. else
  460. glfwWindowHint(GLFW_ACCUM_RED_BITS, atoi(optarg));
  461. break;
  462. case ACCUMGREENBITS:
  463. if (strcmp(optarg, "-") == 0)
  464. glfwWindowHint(GLFW_ACCUM_GREEN_BITS, GLFW_DONT_CARE);
  465. else
  466. glfwWindowHint(GLFW_ACCUM_GREEN_BITS, atoi(optarg));
  467. break;
  468. case ACCUMBLUEBITS:
  469. if (strcmp(optarg, "-") == 0)
  470. glfwWindowHint(GLFW_ACCUM_BLUE_BITS, GLFW_DONT_CARE);
  471. else
  472. glfwWindowHint(GLFW_ACCUM_BLUE_BITS, atoi(optarg));
  473. break;
  474. case ACCUMALPHABITS:
  475. if (strcmp(optarg, "-") == 0)
  476. glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, GLFW_DONT_CARE);
  477. else
  478. glfwWindowHint(GLFW_ACCUM_ALPHA_BITS, atoi(optarg));
  479. break;
  480. case AUXBUFFERS:
  481. if (strcmp(optarg, "-") == 0)
  482. glfwWindowHint(GLFW_AUX_BUFFERS, GLFW_DONT_CARE);
  483. else
  484. glfwWindowHint(GLFW_AUX_BUFFERS, atoi(optarg));
  485. break;
  486. case SAMPLES:
  487. if (strcmp(optarg, "-") == 0)
  488. glfwWindowHint(GLFW_SAMPLES, GLFW_DONT_CARE);
  489. else
  490. glfwWindowHint(GLFW_SAMPLES, atoi(optarg));
  491. break;
  492. case STEREO:
  493. glfwWindowHint(GLFW_STEREO, GLFW_TRUE);
  494. break;
  495. case SRGB:
  496. glfwWindowHint(GLFW_SRGB_CAPABLE, GLFW_TRUE);
  497. break;
  498. case SINGLEBUFFER:
  499. glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_FALSE);
  500. break;
  501. case NOERROR_SRSLY:
  502. glfwWindowHint(GLFW_CONTEXT_NO_ERROR, GLFW_TRUE);
  503. break;
  504. case GRAPHICS_SWITCHING:
  505. glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE);
  506. break;
  507. default:
  508. usage();
  509. exit(EXIT_FAILURE);
  510. }
  511. }
  512. print_version();
  513. glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
  514. window = glfwCreateWindow(200, 200, "Version", NULL, NULL);
  515. if (!window)
  516. {
  517. glfwTerminate();
  518. exit(EXIT_FAILURE);
  519. }
  520. glfwMakeContextCurrent(window);
  521. gladLoadGL(glfwGetProcAddress);
  522. error = glGetError();
  523. if (error != GL_NO_ERROR)
  524. printf("*** OpenGL error after make current: 0x%08x ***\n", error);
  525. // Report client API version
  526. client = glfwGetWindowAttrib(window, GLFW_CLIENT_API);
  527. major = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MAJOR);
  528. minor = glfwGetWindowAttrib(window, GLFW_CONTEXT_VERSION_MINOR);
  529. revision = glfwGetWindowAttrib(window, GLFW_CONTEXT_REVISION);
  530. profile = glfwGetWindowAttrib(window, GLFW_OPENGL_PROFILE);
  531. printf("%s context version string: \"%s\"\n",
  532. get_api_name(client),
  533. glGetString(GL_VERSION));
  534. printf("%s context version parsed by GLFW: %u.%u.%u\n",
  535. get_api_name(client),
  536. major, minor, revision);
  537. // Report client API context properties
  538. if (client == GLFW_OPENGL_API)
  539. {
  540. if (major >= 3)
  541. {
  542. GLint flags;
  543. glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
  544. printf("%s context flags (0x%08x):", get_api_name(client), flags);
  545. if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
  546. printf(" forward-compatible");
  547. if (flags & 2/*GL_CONTEXT_FLAG_DEBUG_BIT*/)
  548. printf(" debug");
  549. if (flags & GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT_ARB)
  550. printf(" robustness");
  551. if (flags & 8/*GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR*/)
  552. printf(" no-error");
  553. putchar('\n');
  554. printf("%s context flags parsed by GLFW:", get_api_name(client));
  555. if (glfwGetWindowAttrib(window, GLFW_OPENGL_FORWARD_COMPAT))
  556. printf(" forward-compatible");
  557. if (glfwGetWindowAttrib(window, GLFW_OPENGL_DEBUG_CONTEXT))
  558. printf(" debug");
  559. if (glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS) == GLFW_LOSE_CONTEXT_ON_RESET)
  560. printf(" robustness");
  561. if (glfwGetWindowAttrib(window, GLFW_CONTEXT_NO_ERROR))
  562. printf(" no-error");
  563. putchar('\n');
  564. }
  565. if (major >= 4 || (major == 3 && minor >= 2))
  566. {
  567. GLint mask;
  568. glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
  569. printf("%s profile mask (0x%08x): %s\n",
  570. get_api_name(client),
  571. mask,
  572. get_profile_name_gl(mask));
  573. printf("%s profile mask parsed by GLFW: %s\n",
  574. get_api_name(client),
  575. get_profile_name_glfw(profile));
  576. }
  577. if (GLAD_GL_ARB_robustness)
  578. {
  579. const int robustness = glfwGetWindowAttrib(window, GLFW_CONTEXT_ROBUSTNESS);
  580. GLint strategy;
  581. glGetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB, &strategy);
  582. printf("%s robustness strategy (0x%08x): %s\n",
  583. get_api_name(client),
  584. strategy,
  585. get_strategy_name_gl(strategy));
  586. printf("%s robustness strategy parsed by GLFW: %s\n",
  587. get_api_name(client),
  588. get_strategy_name_glfw(robustness));
  589. }
  590. }
  591. printf("%s context renderer string: \"%s\"\n",
  592. get_api_name(client),
  593. glGetString(GL_RENDERER));
  594. printf("%s context vendor string: \"%s\"\n",
  595. get_api_name(client),
  596. glGetString(GL_VENDOR));
  597. if (major >= 2)
  598. {
  599. printf("%s context shading language version: \"%s\"\n",
  600. get_api_name(client),
  601. glGetString(GL_SHADING_LANGUAGE_VERSION));
  602. }
  603. printf("%s framebuffer:\n", get_api_name(client));
  604. if (client == GLFW_OPENGL_API && profile == GLFW_OPENGL_CORE_PROFILE)
  605. {
  606. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  607. GL_BACK_LEFT,
  608. GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
  609. &redbits);
  610. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  611. GL_BACK_LEFT,
  612. GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
  613. &greenbits);
  614. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  615. GL_BACK_LEFT,
  616. GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
  617. &bluebits);
  618. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  619. GL_BACK_LEFT,
  620. GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
  621. &alphabits);
  622. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  623. GL_DEPTH,
  624. GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
  625. &depthbits);
  626. glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
  627. GL_STENCIL,
  628. GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
  629. &stencilbits);
  630. }
  631. else
  632. {
  633. glGetIntegerv(GL_RED_BITS, &redbits);
  634. glGetIntegerv(GL_GREEN_BITS, &greenbits);
  635. glGetIntegerv(GL_BLUE_BITS, &bluebits);
  636. glGetIntegerv(GL_ALPHA_BITS, &alphabits);
  637. glGetIntegerv(GL_DEPTH_BITS, &depthbits);
  638. glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
  639. }
  640. printf(" red: %u green: %u blue: %u alpha: %u depth: %u stencil: %u\n",
  641. redbits, greenbits, bluebits, alphabits, depthbits, stencilbits);
  642. if (client == GLFW_OPENGL_ES_API ||
  643. GLAD_GL_ARB_multisample ||
  644. major > 1 || minor >= 3)
  645. {
  646. GLint samples, samplebuffers;
  647. glGetIntegerv(GL_SAMPLES, &samples);
  648. glGetIntegerv(GL_SAMPLE_BUFFERS, &samplebuffers);
  649. printf(" samples: %u sample buffers: %u\n", samples, samplebuffers);
  650. }
  651. if (client == GLFW_OPENGL_API && profile != GLFW_OPENGL_CORE_PROFILE)
  652. {
  653. GLint accumredbits, accumgreenbits, accumbluebits, accumalphabits;
  654. GLint auxbuffers;
  655. glGetIntegerv(GL_ACCUM_RED_BITS, &accumredbits);
  656. glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumgreenbits);
  657. glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbluebits);
  658. glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumalphabits);
  659. glGetIntegerv(GL_AUX_BUFFERS, &auxbuffers);
  660. printf(" accum red: %u accum green: %u accum blue: %u accum alpha: %u aux buffers: %u\n",
  661. accumredbits, accumgreenbits, accumbluebits, accumalphabits, auxbuffers);
  662. }
  663. if (list_extensions)
  664. list_context_extensions(client, major, minor);
  665. printf("Vulkan loader: %s\n",
  666. glfwVulkanSupported() ? "available" : "missing");
  667. if (glfwVulkanSupported())
  668. {
  669. uint32_t loader_version = VK_API_VERSION_1_0;
  670. int portability_enumeration = GLFW_FALSE;
  671. uint32_t i, j, glfw_re_count, re_count, pd_count, ep_count;
  672. const char** glfw_re;
  673. const char** re;
  674. VkApplicationInfo ai = {0};
  675. VkInstanceCreateInfo ici = {0};
  676. VkInstance instance;
  677. VkPhysicalDevice* pd;
  678. gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, NULL);
  679. if (vkEnumerateInstanceVersion)
  680. {
  681. uint32_t version;
  682. if (vkEnumerateInstanceVersion(&version) == VK_SUCCESS)
  683. loader_version = version;
  684. }
  685. printf("Vulkan loader API version: %i.%i\n",
  686. VK_VERSION_MAJOR(loader_version),
  687. VK_VERSION_MINOR(loader_version));
  688. glfw_re = glfwGetRequiredInstanceExtensions(&glfw_re_count);
  689. re_count = glfw_re_count;
  690. re = calloc(glfw_re_count, sizeof(char*));
  691. printf("Vulkan window surface required instance extensions:\n");
  692. if (glfw_re)
  693. {
  694. for (i = 0; i < glfw_re_count; i++)
  695. {
  696. printf(" %s\n", glfw_re[i]);
  697. re[i] = glfw_re[i];
  698. }
  699. }
  700. else
  701. printf(" missing\n");
  702. vkEnumerateInstanceExtensionProperties(NULL, &ep_count, NULL);
  703. VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
  704. vkEnumerateInstanceExtensionProperties(NULL, &ep_count, ep);
  705. if (list_extensions)
  706. {
  707. printf("Vulkan instance extensions:\n");
  708. for (i = 0; i < ep_count; i++)
  709. printf(" %s (spec version %u)\n", ep[i].extensionName, ep[i].specVersion);
  710. }
  711. for (i = 0; i < ep_count; i++)
  712. {
  713. if (strcmp(ep[i].extensionName, "VK_KHR_portability_enumeration") != 0)
  714. continue;
  715. re_count++;
  716. re = realloc((void*) re, sizeof(char*) * re_count);
  717. re[re_count - 1] = "VK_KHR_portability_enumeration";
  718. portability_enumeration = GLFW_TRUE;
  719. }
  720. free(ep);
  721. if (list_layers)
  722. list_vulkan_instance_layers();
  723. ai.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  724. ai.pApplicationName = "glfwinfo";
  725. ai.applicationVersion = VK_MAKE_VERSION(GLFW_VERSION_MAJOR,
  726. GLFW_VERSION_MINOR,
  727. GLFW_VERSION_REVISION);
  728. if (loader_version >= VK_API_VERSION_1_1)
  729. ai.apiVersion = VK_API_VERSION_1_1;
  730. else
  731. ai.apiVersion = VK_API_VERSION_1_0;
  732. ici.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  733. ici.pApplicationInfo = &ai;
  734. ici.enabledExtensionCount = re_count;
  735. ici.ppEnabledExtensionNames = re;
  736. if (portability_enumeration)
  737. ici.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
  738. if (vkCreateInstance(&ici, NULL, &instance) != VK_SUCCESS)
  739. {
  740. glfwTerminate();
  741. exit(EXIT_FAILURE);
  742. }
  743. free((void*) re);
  744. gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc) glfwGetInstanceProcAddress, instance);
  745. vkEnumeratePhysicalDevices(instance, &pd_count, NULL);
  746. pd = calloc(pd_count, sizeof(VkPhysicalDevice));
  747. vkEnumeratePhysicalDevices(instance, &pd_count, pd);
  748. for (i = 0; i < pd_count; i++)
  749. {
  750. VkPhysicalDeviceProperties pdp;
  751. uint32_t qfp_count, ep_count;
  752. vkGetPhysicalDeviceProperties(pd[i], &pdp);
  753. printf("Vulkan %s device: \"%s\" API version %i.%i\n",
  754. get_device_type_name(pdp.deviceType),
  755. pdp.deviceName,
  756. VK_VERSION_MAJOR(pdp.apiVersion),
  757. VK_VERSION_MINOR(pdp.apiVersion));
  758. vkGetPhysicalDeviceQueueFamilyProperties(pd[i], &qfp_count, NULL);
  759. vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, NULL);
  760. VkExtensionProperties* ep = calloc(ep_count, sizeof(VkExtensionProperties));
  761. vkEnumerateDeviceExtensionProperties(pd[i], NULL, &ep_count, ep);
  762. if (portability_enumeration)
  763. {
  764. int conformant = GLFW_TRUE;
  765. for (j = 0; j < ep_count; j++)
  766. {
  767. if (strcmp(ep[j].extensionName, "VK_KHR_portability_subset") == 0)
  768. {
  769. conformant = GLFW_FALSE;
  770. break;
  771. }
  772. }
  773. printf("Vulkan %s %s device: \"%s\" (API version %i.%i)\n",
  774. conformant ? "conformant" : "non-conformant",
  775. get_device_type_name(pdp.deviceType),
  776. pdp.deviceName,
  777. VK_VERSION_MAJOR(pdp.apiVersion),
  778. VK_VERSION_MINOR(pdp.apiVersion));
  779. }
  780. else
  781. {
  782. printf("Vulkan %s device: \"%s\" (API version %i.%i)\n",
  783. get_device_type_name(pdp.deviceType),
  784. pdp.deviceName,
  785. VK_VERSION_MAJOR(pdp.apiVersion),
  786. VK_VERSION_MINOR(pdp.apiVersion));
  787. }
  788. if (glfw_re_count)
  789. {
  790. printf("Vulkan device queue family presentation support:\n");
  791. for (j = 0; j < qfp_count; j++)
  792. {
  793. printf(" %u: ", j);
  794. if (glfwGetPhysicalDevicePresentationSupport(instance, pd[i], j))
  795. printf("supported\n");
  796. else
  797. printf("no\n");
  798. }
  799. }
  800. if (list_extensions)
  801. {
  802. printf("Vulkan device extensions:\n");
  803. for (j = 0; j < ep_count; j++)
  804. printf(" %s (spec version %u)\n", ep[j].extensionName, ep[j].specVersion);
  805. }
  806. free(ep);
  807. if (list_layers)
  808. list_vulkan_device_layers(instance, pd[i]);
  809. }
  810. free(pd);
  811. vkDestroyInstance(instance, NULL);
  812. }
  813. glfwTerminate();
  814. exit(EXIT_SUCCESS);
  815. }