Platformer in OpenGL
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

899 regels
31 KiB

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