2
0

context.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. //========================================================================
  2. // GLFW 3.4 - www.glfw.org
  3. //------------------------------------------------------------------------
  4. // Copyright (c) 2002-2006 Marcus Geelnard
  5. // Copyright (c) 2006-2016 Camilla Löwy <[email protected]>
  6. //
  7. // This software is provided 'as-is', without any express or implied
  8. // warranty. In no event will the authors be held liable for any damages
  9. // arising from the use of this software.
  10. //
  11. // Permission is granted to anyone to use this software for any purpose,
  12. // including commercial applications, and to alter it and redistribute it
  13. // freely, subject to the following restrictions:
  14. //
  15. // 1. The origin of this software must not be misrepresented; you must not
  16. // claim that you wrote the original software. If you use this software
  17. // in a product, an acknowledgment in the product documentation would
  18. // be appreciated but is not required.
  19. //
  20. // 2. Altered source versions must be plainly marked as such, and must not
  21. // be misrepresented as being the original software.
  22. //
  23. // 3. This notice may not be removed or altered from any source
  24. // distribution.
  25. //
  26. //========================================================================
  27. // Please use C89 style variable declarations in this file because VS 2010
  28. //========================================================================
  29. #include "internal.h"
  30. #include <assert.h>
  31. #include <stdio.h>
  32. #include <string.h>
  33. #include <limits.h>
  34. #include <stdio.h>
  35. //////////////////////////////////////////////////////////////////////////
  36. ////// GLFW internal API //////
  37. //////////////////////////////////////////////////////////////////////////
  38. // Checks whether the desired context attributes are valid
  39. //
  40. // This function checks things like whether the specified client API version
  41. // exists and whether all relevant options have supported and non-conflicting
  42. // values
  43. //
  44. GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig)
  45. {
  46. if (ctxconfig->share)
  47. {
  48. if (ctxconfig->client == GLFW_NO_API ||
  49. ctxconfig->share->context.client == GLFW_NO_API)
  50. {
  51. _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
  52. return GLFW_FALSE;
  53. }
  54. }
  55. if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API &&
  56. ctxconfig->source != GLFW_EGL_CONTEXT_API &&
  57. ctxconfig->source != GLFW_OSMESA_CONTEXT_API)
  58. {
  59. _glfwInputError(GLFW_INVALID_ENUM,
  60. "Invalid context creation API 0x%08X",
  61. ctxconfig->source);
  62. return GLFW_FALSE;
  63. }
  64. if (ctxconfig->client != GLFW_NO_API &&
  65. ctxconfig->client != GLFW_OPENGL_API &&
  66. ctxconfig->client != GLFW_OPENGL_ES_API)
  67. {
  68. _glfwInputError(GLFW_INVALID_ENUM,
  69. "Invalid client API 0x%08X",
  70. ctxconfig->client);
  71. return GLFW_FALSE;
  72. }
  73. if (ctxconfig->client == GLFW_OPENGL_API)
  74. {
  75. if ((ctxconfig->major < 1 || ctxconfig->minor < 0) ||
  76. (ctxconfig->major == 1 && ctxconfig->minor > 5) ||
  77. (ctxconfig->major == 2 && ctxconfig->minor > 1) ||
  78. (ctxconfig->major == 3 && ctxconfig->minor > 3))
  79. {
  80. // OpenGL 1.0 is the smallest valid version
  81. // OpenGL 1.x series ended with version 1.5
  82. // OpenGL 2.x series ended with version 2.1
  83. // OpenGL 3.x series ended with version 3.3
  84. // For now, let everything else through
  85. _glfwInputError(GLFW_INVALID_VALUE,
  86. "Invalid OpenGL version %i.%i",
  87. ctxconfig->major, ctxconfig->minor);
  88. return GLFW_FALSE;
  89. }
  90. if (ctxconfig->profile)
  91. {
  92. if (ctxconfig->profile != GLFW_OPENGL_CORE_PROFILE &&
  93. ctxconfig->profile != GLFW_OPENGL_COMPAT_PROFILE)
  94. {
  95. _glfwInputError(GLFW_INVALID_ENUM,
  96. "Invalid OpenGL profile 0x%08X",
  97. ctxconfig->profile);
  98. return GLFW_FALSE;
  99. }
  100. if (ctxconfig->major <= 2 ||
  101. (ctxconfig->major == 3 && ctxconfig->minor < 2))
  102. {
  103. // Desktop OpenGL context profiles are only defined for version 3.2
  104. // and above
  105. _glfwInputError(GLFW_INVALID_VALUE,
  106. "Context profiles are only defined for OpenGL version 3.2 and above");
  107. return GLFW_FALSE;
  108. }
  109. }
  110. if (ctxconfig->forward && ctxconfig->major <= 2)
  111. {
  112. // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
  113. _glfwInputError(GLFW_INVALID_VALUE,
  114. "Forward-compatibility is only defined for OpenGL version 3.0 and above");
  115. return GLFW_FALSE;
  116. }
  117. }
  118. else if (ctxconfig->client == GLFW_OPENGL_ES_API)
  119. {
  120. if (ctxconfig->major < 1 || ctxconfig->minor < 0 ||
  121. (ctxconfig->major == 1 && ctxconfig->minor > 1) ||
  122. (ctxconfig->major == 2 && ctxconfig->minor > 0))
  123. {
  124. // OpenGL ES 1.0 is the smallest valid version
  125. // OpenGL ES 1.x series ended with version 1.1
  126. // OpenGL ES 2.x series ended with version 2.0
  127. // For now, let everything else through
  128. _glfwInputError(GLFW_INVALID_VALUE,
  129. "Invalid OpenGL ES version %i.%i",
  130. ctxconfig->major, ctxconfig->minor);
  131. return GLFW_FALSE;
  132. }
  133. }
  134. if (ctxconfig->robustness)
  135. {
  136. if (ctxconfig->robustness != GLFW_NO_RESET_NOTIFICATION &&
  137. ctxconfig->robustness != GLFW_LOSE_CONTEXT_ON_RESET)
  138. {
  139. _glfwInputError(GLFW_INVALID_ENUM,
  140. "Invalid context robustness mode 0x%08X",
  141. ctxconfig->robustness);
  142. return GLFW_FALSE;
  143. }
  144. }
  145. if (ctxconfig->release)
  146. {
  147. if (ctxconfig->release != GLFW_RELEASE_BEHAVIOR_NONE &&
  148. ctxconfig->release != GLFW_RELEASE_BEHAVIOR_FLUSH)
  149. {
  150. _glfwInputError(GLFW_INVALID_ENUM,
  151. "Invalid context release behavior 0x%08X",
  152. ctxconfig->release);
  153. return GLFW_FALSE;
  154. }
  155. }
  156. return GLFW_TRUE;
  157. }
  158. // Chooses the framebuffer config that best matches the desired one
  159. //
  160. const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
  161. const _GLFWfbconfig* alternatives,
  162. unsigned int count)
  163. {
  164. unsigned int i;
  165. unsigned int missing, leastMissing = UINT_MAX;
  166. unsigned int colorDiff, leastColorDiff = UINT_MAX;
  167. unsigned int extraDiff, leastExtraDiff = UINT_MAX;
  168. const _GLFWfbconfig* current;
  169. const _GLFWfbconfig* closest = NULL;
  170. for (i = 0; i < count; i++)
  171. {
  172. current = alternatives + i;
  173. if (desired->stereo > 0 && current->stereo == 0)
  174. {
  175. // Stereo is a hard constraint
  176. continue;
  177. }
  178. if (desired->doublebuffer != current->doublebuffer)
  179. {
  180. // Double buffering is a hard constraint
  181. continue;
  182. }
  183. // Count number of missing buffers
  184. {
  185. missing = 0;
  186. if (desired->alphaBits > 0 && current->alphaBits == 0)
  187. missing++;
  188. if (desired->depthBits > 0 && current->depthBits == 0)
  189. missing++;
  190. if (desired->stencilBits > 0 && current->stencilBits == 0)
  191. missing++;
  192. if (desired->auxBuffers > 0 &&
  193. current->auxBuffers < desired->auxBuffers)
  194. {
  195. missing += desired->auxBuffers - current->auxBuffers;
  196. }
  197. if (desired->samples > 0 && current->samples == 0)
  198. {
  199. // Technically, several multisampling buffers could be
  200. // involved, but that's a lower level implementation detail and
  201. // not important to us here, so we count them as one
  202. missing++;
  203. }
  204. if (desired->transparent != current->transparent)
  205. missing++;
  206. }
  207. // These polynomials make many small channel size differences matter
  208. // less than one large channel size difference
  209. // Calculate color channel size difference value
  210. {
  211. colorDiff = 0;
  212. if (desired->redBits != GLFW_DONT_CARE)
  213. {
  214. colorDiff += (desired->redBits - current->redBits) *
  215. (desired->redBits - current->redBits);
  216. }
  217. if (desired->greenBits != GLFW_DONT_CARE)
  218. {
  219. colorDiff += (desired->greenBits - current->greenBits) *
  220. (desired->greenBits - current->greenBits);
  221. }
  222. if (desired->blueBits != GLFW_DONT_CARE)
  223. {
  224. colorDiff += (desired->blueBits - current->blueBits) *
  225. (desired->blueBits - current->blueBits);
  226. }
  227. }
  228. // Calculate non-color channel size difference value
  229. {
  230. extraDiff = 0;
  231. if (desired->alphaBits != GLFW_DONT_CARE)
  232. {
  233. extraDiff += (desired->alphaBits - current->alphaBits) *
  234. (desired->alphaBits - current->alphaBits);
  235. }
  236. if (desired->depthBits != GLFW_DONT_CARE)
  237. {
  238. extraDiff += (desired->depthBits - current->depthBits) *
  239. (desired->depthBits - current->depthBits);
  240. }
  241. if (desired->stencilBits != GLFW_DONT_CARE)
  242. {
  243. extraDiff += (desired->stencilBits - current->stencilBits) *
  244. (desired->stencilBits - current->stencilBits);
  245. }
  246. if (desired->accumRedBits != GLFW_DONT_CARE)
  247. {
  248. extraDiff += (desired->accumRedBits - current->accumRedBits) *
  249. (desired->accumRedBits - current->accumRedBits);
  250. }
  251. if (desired->accumGreenBits != GLFW_DONT_CARE)
  252. {
  253. extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
  254. (desired->accumGreenBits - current->accumGreenBits);
  255. }
  256. if (desired->accumBlueBits != GLFW_DONT_CARE)
  257. {
  258. extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
  259. (desired->accumBlueBits - current->accumBlueBits);
  260. }
  261. if (desired->accumAlphaBits != GLFW_DONT_CARE)
  262. {
  263. extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
  264. (desired->accumAlphaBits - current->accumAlphaBits);
  265. }
  266. if (desired->samples != GLFW_DONT_CARE)
  267. {
  268. extraDiff += (desired->samples - current->samples) *
  269. (desired->samples - current->samples);
  270. }
  271. if (desired->sRGB && !current->sRGB)
  272. extraDiff++;
  273. }
  274. // Figure out if the current one is better than the best one found so far
  275. // Least number of missing buffers is the most important heuristic,
  276. // then color buffer size match and lastly size match for other buffers
  277. if (missing < leastMissing)
  278. closest = current;
  279. else if (missing == leastMissing)
  280. {
  281. if ((colorDiff < leastColorDiff) ||
  282. (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
  283. {
  284. closest = current;
  285. }
  286. }
  287. if (current == closest)
  288. {
  289. leastMissing = missing;
  290. leastColorDiff = colorDiff;
  291. leastExtraDiff = extraDiff;
  292. }
  293. }
  294. return closest;
  295. }
  296. // Retrieves the attributes of the current context
  297. //
  298. GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window,
  299. const _GLFWctxconfig* ctxconfig)
  300. {
  301. int i;
  302. _GLFWwindow* previous;
  303. const char* version;
  304. const char* prefixes[] =
  305. {
  306. "OpenGL ES-CM ",
  307. "OpenGL ES-CL ",
  308. "OpenGL ES ",
  309. NULL
  310. };
  311. window->context.source = ctxconfig->source;
  312. window->context.client = GLFW_OPENGL_API;
  313. previous = (_GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  314. glfwMakeContextCurrent((GLFWwindow*) window);
  315. window->context.GetIntegerv = (PFNGLGETINTEGERVPROC)
  316. window->context.getProcAddress("glGetIntegerv");
  317. window->context.GetString = (PFNGLGETSTRINGPROC)
  318. window->context.getProcAddress("glGetString");
  319. if (!window->context.GetIntegerv || !window->context.GetString)
  320. {
  321. _glfwInputError(GLFW_PLATFORM_ERROR, "Entry point retrieval is broken");
  322. glfwMakeContextCurrent((GLFWwindow*) previous);
  323. return GLFW_FALSE;
  324. }
  325. version = (const char*) window->context.GetString(GL_VERSION);
  326. if (!version)
  327. {
  328. if (ctxconfig->client == GLFW_OPENGL_API)
  329. {
  330. _glfwInputError(GLFW_PLATFORM_ERROR,
  331. "OpenGL version string retrieval is broken");
  332. }
  333. else
  334. {
  335. _glfwInputError(GLFW_PLATFORM_ERROR,
  336. "OpenGL ES version string retrieval is broken");
  337. }
  338. glfwMakeContextCurrent((GLFWwindow*) previous);
  339. return GLFW_FALSE;
  340. }
  341. for (i = 0; prefixes[i]; i++)
  342. {
  343. const size_t length = strlen(prefixes[i]);
  344. if (strncmp(version, prefixes[i], length) == 0)
  345. {
  346. version += length;
  347. window->context.client = GLFW_OPENGL_ES_API;
  348. break;
  349. }
  350. }
  351. if (!sscanf(version, "%d.%d.%d",
  352. &window->context.major,
  353. &window->context.minor,
  354. &window->context.revision))
  355. {
  356. if (window->context.client == GLFW_OPENGL_API)
  357. {
  358. _glfwInputError(GLFW_PLATFORM_ERROR,
  359. "No version found in OpenGL version string");
  360. }
  361. else
  362. {
  363. _glfwInputError(GLFW_PLATFORM_ERROR,
  364. "No version found in OpenGL ES version string");
  365. }
  366. glfwMakeContextCurrent((GLFWwindow*) previous);
  367. return GLFW_FALSE;
  368. }
  369. if (window->context.major < ctxconfig->major ||
  370. (window->context.major == ctxconfig->major &&
  371. window->context.minor < ctxconfig->minor))
  372. {
  373. // The desired OpenGL version is greater than the actual version
  374. // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
  375. // /and/ the user has requested an OpenGL version greater than 1.0
  376. // For API consistency, we emulate the behavior of the
  377. // {GLX|WGL}_ARB_create_context extension and fail here
  378. if (window->context.client == GLFW_OPENGL_API)
  379. {
  380. _glfwInputError(GLFW_VERSION_UNAVAILABLE,
  381. "Requested OpenGL version %i.%i, got version %i.%i",
  382. ctxconfig->major, ctxconfig->minor,
  383. window->context.major, window->context.minor);
  384. }
  385. else
  386. {
  387. _glfwInputError(GLFW_VERSION_UNAVAILABLE,
  388. "Requested OpenGL ES version %i.%i, got version %i.%i",
  389. ctxconfig->major, ctxconfig->minor,
  390. window->context.major, window->context.minor);
  391. }
  392. glfwMakeContextCurrent((GLFWwindow*) previous);
  393. return GLFW_FALSE;
  394. }
  395. if (window->context.major >= 3)
  396. {
  397. // OpenGL 3.0+ uses a different function for extension string retrieval
  398. // We cache it here instead of in glfwExtensionSupported mostly to alert
  399. // users as early as possible that their build may be broken
  400. window->context.GetStringi = (PFNGLGETSTRINGIPROC)
  401. window->context.getProcAddress("glGetStringi");
  402. if (!window->context.GetStringi)
  403. {
  404. _glfwInputError(GLFW_PLATFORM_ERROR,
  405. "Entry point retrieval is broken");
  406. glfwMakeContextCurrent((GLFWwindow*) previous);
  407. return GLFW_FALSE;
  408. }
  409. }
  410. if (window->context.client == GLFW_OPENGL_API)
  411. {
  412. // Read back context flags (OpenGL 3.0 and above)
  413. if (window->context.major >= 3)
  414. {
  415. GLint flags;
  416. window->context.GetIntegerv(GL_CONTEXT_FLAGS, &flags);
  417. if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
  418. window->context.forward = GLFW_TRUE;
  419. if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
  420. window->context.debug = GLFW_TRUE;
  421. else if (glfwExtensionSupported("GL_ARB_debug_output") &&
  422. ctxconfig->debug)
  423. {
  424. // HACK: This is a workaround for older drivers (pre KHR_debug)
  425. // not setting the debug bit in the context flags for
  426. // debug contexts
  427. window->context.debug = GLFW_TRUE;
  428. }
  429. if (flags & GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR)
  430. window->context.noerror = GLFW_TRUE;
  431. }
  432. // Read back OpenGL context profile (OpenGL 3.2 and above)
  433. if (window->context.major >= 4 ||
  434. (window->context.major == 3 && window->context.minor >= 2))
  435. {
  436. GLint mask;
  437. window->context.GetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
  438. if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
  439. window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
  440. else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
  441. window->context.profile = GLFW_OPENGL_CORE_PROFILE;
  442. else if (glfwExtensionSupported("GL_ARB_compatibility"))
  443. {
  444. // HACK: This is a workaround for the compatibility profile bit
  445. // not being set in the context flags if an OpenGL 3.2+
  446. // context was created without having requested a specific
  447. // version
  448. window->context.profile = GLFW_OPENGL_COMPAT_PROFILE;
  449. }
  450. }
  451. // Read back robustness strategy
  452. if (glfwExtensionSupported("GL_ARB_robustness"))
  453. {
  454. // NOTE: We avoid using the context flags for detection, as they are
  455. // only present from 3.0 while the extension applies from 1.1
  456. GLint strategy;
  457. window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
  458. &strategy);
  459. if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
  460. window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
  461. else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
  462. window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
  463. }
  464. }
  465. else
  466. {
  467. // Read back robustness strategy
  468. if (glfwExtensionSupported("GL_EXT_robustness"))
  469. {
  470. // NOTE: The values of these constants match those of the OpenGL ARB
  471. // one, so we can reuse them here
  472. GLint strategy;
  473. window->context.GetIntegerv(GL_RESET_NOTIFICATION_STRATEGY_ARB,
  474. &strategy);
  475. if (strategy == GL_LOSE_CONTEXT_ON_RESET_ARB)
  476. window->context.robustness = GLFW_LOSE_CONTEXT_ON_RESET;
  477. else if (strategy == GL_NO_RESET_NOTIFICATION_ARB)
  478. window->context.robustness = GLFW_NO_RESET_NOTIFICATION;
  479. }
  480. }
  481. if (glfwExtensionSupported("GL_KHR_context_flush_control"))
  482. {
  483. GLint behavior;
  484. window->context.GetIntegerv(GL_CONTEXT_RELEASE_BEHAVIOR, &behavior);
  485. if (behavior == GL_NONE)
  486. window->context.release = GLFW_RELEASE_BEHAVIOR_NONE;
  487. else if (behavior == GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH)
  488. window->context.release = GLFW_RELEASE_BEHAVIOR_FLUSH;
  489. }
  490. // Clearing the front buffer to black to avoid garbage pixels left over from
  491. // previous uses of our bit of VRAM
  492. {
  493. PFNGLCLEARPROC glClear = (PFNGLCLEARPROC)
  494. window->context.getProcAddress("glClear");
  495. glClear(GL_COLOR_BUFFER_BIT);
  496. window->context.swapBuffers(window);
  497. }
  498. glfwMakeContextCurrent((GLFWwindow*) previous);
  499. return GLFW_TRUE;
  500. }
  501. // Searches an extension string for the specified extension
  502. //
  503. GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions)
  504. {
  505. const char* start = extensions;
  506. for (;;)
  507. {
  508. const char* where;
  509. const char* terminator;
  510. where = strstr(start, string);
  511. if (!where)
  512. return GLFW_FALSE;
  513. terminator = where + strlen(string);
  514. if (where == start || *(where - 1) == ' ')
  515. {
  516. if (*terminator == ' ' || *terminator == '\0')
  517. break;
  518. }
  519. start = terminator;
  520. }
  521. return GLFW_TRUE;
  522. }
  523. //////////////////////////////////////////////////////////////////////////
  524. ////// GLFW public API //////
  525. //////////////////////////////////////////////////////////////////////////
  526. GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle)
  527. {
  528. _GLFWwindow* window = (_GLFWwindow*) handle;
  529. _GLFWwindow* previous = (_GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  530. _GLFW_REQUIRE_INIT();
  531. if (window && window->context.client == GLFW_NO_API)
  532. {
  533. _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
  534. "Cannot make current with a window that has no OpenGL or OpenGL ES context");
  535. return;
  536. }
  537. if (previous)
  538. {
  539. if (!window || window->context.source != previous->context.source)
  540. previous->context.makeCurrent(NULL);
  541. }
  542. if (window)
  543. window->context.makeCurrent(window);
  544. }
  545. GLFWAPI GLFWwindow* glfwGetCurrentContext(void)
  546. {
  547. _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
  548. return (GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  549. }
  550. GLFWAPI void glfwSwapBuffers(GLFWwindow* handle)
  551. {
  552. _GLFWwindow* window = (_GLFWwindow*) handle;
  553. assert(window != NULL);
  554. _GLFW_REQUIRE_INIT();
  555. if (window->context.client == GLFW_NO_API)
  556. {
  557. _glfwInputError(GLFW_NO_WINDOW_CONTEXT,
  558. "Cannot swap buffers of a window that has no OpenGL or OpenGL ES context");
  559. return;
  560. }
  561. window->context.swapBuffers(window);
  562. }
  563. GLFWAPI void glfwSwapInterval(int interval)
  564. {
  565. _GLFWwindow* window;
  566. _GLFW_REQUIRE_INIT();
  567. window = (_GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  568. if (!window)
  569. {
  570. _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
  571. "Cannot set swap interval without a current OpenGL or OpenGL ES context");
  572. return;
  573. }
  574. window->context.swapInterval(interval);
  575. }
  576. GLFWAPI int glfwExtensionSupported(const char* extension)
  577. {
  578. _GLFWwindow* window;
  579. assert(extension != NULL);
  580. _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
  581. window = (_GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  582. if (!window)
  583. {
  584. _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
  585. "Cannot query extension without a current OpenGL or OpenGL ES context");
  586. return GLFW_FALSE;
  587. }
  588. if (*extension == '\0')
  589. {
  590. _glfwInputError(GLFW_INVALID_VALUE, "Extension name cannot be an empty string");
  591. return GLFW_FALSE;
  592. }
  593. if (window->context.major >= 3)
  594. {
  595. int i;
  596. GLint count;
  597. // Check if extension is in the modern OpenGL extensions string list
  598. window->context.GetIntegerv(GL_NUM_EXTENSIONS, &count);
  599. for (i = 0; i < count; i++)
  600. {
  601. const char* en = (const char*)
  602. window->context.GetStringi(GL_EXTENSIONS, i);
  603. if (!en)
  604. {
  605. _glfwInputError(GLFW_PLATFORM_ERROR,
  606. "Extension string retrieval is broken");
  607. return GLFW_FALSE;
  608. }
  609. if (strcmp(en, extension) == 0)
  610. return GLFW_TRUE;
  611. }
  612. }
  613. else
  614. {
  615. // Check if extension is in the old style OpenGL extensions string
  616. const char* extensions = (const char*)
  617. window->context.GetString(GL_EXTENSIONS);
  618. if (!extensions)
  619. {
  620. _glfwInputError(GLFW_PLATFORM_ERROR,
  621. "Extension string retrieval is broken");
  622. return GLFW_FALSE;
  623. }
  624. if (_glfwStringInExtensionString(extension, extensions))
  625. return GLFW_TRUE;
  626. }
  627. // Check if extension is in the platform-specific string
  628. return window->context.extensionSupported(extension);
  629. }
  630. GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
  631. {
  632. _GLFWwindow* window;
  633. assert(procname != NULL);
  634. _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
  635. window = (_GLFWwindow*)_glfwPlatformGetTls(&_glfw.contextSlot);
  636. if (!window)
  637. {
  638. _glfwInputError(GLFW_NO_CURRENT_CONTEXT,
  639. "Cannot query entry point without a current OpenGL or OpenGL ES context");
  640. return NULL;
  641. }
  642. return window->context.getProcAddress(procname);
  643. }