blob: 931296ced2aa5d4acf924da79c4b74b760005ec9 [file] [log] [blame]
Camilla Berglund3249f812010-09-07 17:34:51 +02001//========================================================================
Camilla Berglund6e553c72011-03-06 01:46:39 +01002// GLFW - An OpenGL library
Camilla Berglund3249f812010-09-07 17:34:51 +02003// Platform: Any
Camilla Berglund38b0ccb2010-09-07 17:41:26 +02004// API version: 3.0
Camilla Berglund3249f812010-09-07 17:34:51 +02005// WWW: http://www.glfw.org/
6//------------------------------------------------------------------------
7// Copyright (c) 2002-2006 Marcus Geelnard
8// Copyright (c) 2006-2010 Camilla Berglund <elmindreda@elmindreda.org>
9//
10// This software is provided 'as-is', without any express or implied
11// warranty. In no event will the authors be held liable for any damages
12// arising from the use of this software.
13//
14// Permission is granted to anyone to use this software for any purpose,
15// including commercial applications, and to alter it and redistribute it
16// freely, subject to the following restrictions:
17//
18// 1. The origin of this software must not be misrepresented; you must not
19// claim that you wrote the original software. If you use this software
20// in a product, an acknowledgment in the product documentation would
21// be appreciated but is not required.
22//
23// 2. Altered source versions must be plainly marked as such, and must not
24// be misrepresented as being the original software.
25//
26// 3. This notice may not be removed or altered from any source
27// distribution.
28//
29//========================================================================
30
31#include "internal.h"
32
Camilla Berglund208377d2012-08-02 14:48:06 +020033#include <stdio.h>
Camilla Berglundcdfbbaf2010-09-08 17:01:39 +020034#include <string.h>
Camilla Berglund596f56f2011-03-07 13:56:28 +010035#include <limits.h>
Camilla Berglundcdfbbaf2010-09-08 17:01:39 +020036
Camilla Berglund3249f812010-09-07 17:34:51 +020037
Camilla Berglund19be24a2011-03-07 14:55:11 +010038//========================================================================
Camilla Berglund38cad9a2012-09-30 15:32:50 +020039// Parses the client API version string and extracts the version number
Camilla Berglund19be24a2011-03-07 14:55:11 +010040//========================================================================
41
Camilla Berglund38cad9a2012-09-30 15:32:50 +020042static GLboolean parseGLVersion(int* api, int* major, int* minor, int* rev)
Camilla Berglund19be24a2011-03-07 14:55:11 +010043{
Camilla Berglund38cad9a2012-09-30 15:32:50 +020044 int i, _api = GLFW_OPENGL_API, _major, _minor = 0, _rev = 0;
Camilla Berglund208377d2012-08-02 14:48:06 +020045 const char* version;
46 const char* prefixes[] =
47 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +020048 "OpenGL ES-CM ",
49 "OpenGL ES-CL ",
Camilla Berglund208377d2012-08-02 14:48:06 +020050 "OpenGL ES ",
51 NULL
52 };
Camilla Berglund19be24a2011-03-07 14:55:11 +010053
Camilla Berglund208377d2012-08-02 14:48:06 +020054 version = (const char*) glGetString(GL_VERSION);
Camilla Berglund19be24a2011-03-07 14:55:11 +010055 if (!version)
Camilla Berglund59896c32012-08-02 14:42:24 +020056 {
57 _glfwSetError(GLFW_PLATFORM_ERROR, "Failed to retrieve version string");
Camilla Berglund208377d2012-08-02 14:48:06 +020058 return GL_FALSE;
Camilla Berglund59896c32012-08-02 14:42:24 +020059 }
Camilla Berglund19be24a2011-03-07 14:55:11 +010060
Camilla Berglund208377d2012-08-02 14:48:06 +020061 for (i = 0; prefixes[i]; i++)
Camilla Berglund19be24a2011-03-07 14:55:11 +010062 {
Camilla Berglund208377d2012-08-02 14:48:06 +020063 const size_t length = strlen(prefixes[i]);
Camilla Berglund19be24a2011-03-07 14:55:11 +010064
Camilla Berglund208377d2012-08-02 14:48:06 +020065 if (strncmp(version, prefixes[i], length) == 0)
Camilla Berglund19be24a2011-03-07 14:55:11 +010066 {
Camilla Berglund208377d2012-08-02 14:48:06 +020067 version += length;
Camilla Berglund38cad9a2012-09-30 15:32:50 +020068 _api = GLFW_OPENGL_ES_API;
Camilla Berglund208377d2012-08-02 14:48:06 +020069 break;
Camilla Berglund19be24a2011-03-07 14:55:11 +010070 }
71 }
72
Camilla Berglund208377d2012-08-02 14:48:06 +020073 if (!sscanf(version, "%d.%d.%d", &_major, &_minor, &_rev))
74 {
75 _glfwSetError(GLFW_PLATFORM_ERROR, "No version found in version string");
76 return GL_FALSE;
77 }
78
Camilla Berglund38cad9a2012-09-30 15:32:50 +020079 *api = _api;
Camilla Berglund19be24a2011-03-07 14:55:11 +010080 *major = _major;
81 *minor = _minor;
82 *rev = _rev;
Camilla Berglund59896c32012-08-02 14:42:24 +020083
84 return GL_TRUE;
Camilla Berglund19be24a2011-03-07 14:55:11 +010085}
86
87
Camilla Berglund1723c4a2010-09-09 20:59:50 +020088//////////////////////////////////////////////////////////////////////////
89////// GLFW internal API //////
90//////////////////////////////////////////////////////////////////////////
91
Camilla Berglund3249f812010-09-07 17:34:51 +020092//========================================================================
Camilla Berglund596f56f2011-03-07 13:56:28 +010093// Return the available framebuffer config closest to the desired values
94// This is based on the manual GLX Visual selection from 2.6
95//========================================================================
96
97const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
98 const _GLFWfbconfig* alternatives,
99 unsigned int count)
100{
101 unsigned int i;
102 unsigned int missing, leastMissing = UINT_MAX;
103 unsigned int colorDiff, leastColorDiff = UINT_MAX;
104 unsigned int extraDiff, leastExtraDiff = UINT_MAX;
105 const _GLFWfbconfig* current;
106 const _GLFWfbconfig* closest = NULL;
107
108 for (i = 0; i < count; i++)
109 {
110 current = alternatives + i;
111
112 if (desired->stereo > 0 && current->stereo == 0)
113 {
114 // Stereo is a hard constraint
115 continue;
116 }
117
118 // Count number of missing buffers
119 {
120 missing = 0;
121
122 if (desired->alphaBits > 0 && current->alphaBits == 0)
123 missing++;
124
125 if (desired->depthBits > 0 && current->depthBits == 0)
126 missing++;
127
128 if (desired->stencilBits > 0 && current->stencilBits == 0)
129 missing++;
130
131 if (desired->auxBuffers > 0 && current->auxBuffers < desired->auxBuffers)
132 missing += desired->auxBuffers - current->auxBuffers;
133
134 if (desired->samples > 0 && current->samples == 0)
135 {
136 // Technically, several multisampling buffers could be
137 // involved, but that's a lower level implementation detail and
138 // not important to us here, so we count them as one
139 missing++;
140 }
141 }
142
143 // These polynomials make many small channel size differences matter
144 // less than one large channel size difference
145
146 // Calculate color channel size difference value
147 {
148 colorDiff = 0;
149
150 if (desired->redBits > 0)
151 {
152 colorDiff += (desired->redBits - current->redBits) *
153 (desired->redBits - current->redBits);
154 }
155
156 if (desired->greenBits > 0)
157 {
158 colorDiff += (desired->greenBits - current->greenBits) *
159 (desired->greenBits - current->greenBits);
160 }
161
162 if (desired->blueBits > 0)
163 {
164 colorDiff += (desired->blueBits - current->blueBits) *
165 (desired->blueBits - current->blueBits);
166 }
167 }
168
169 // Calculate non-color channel size difference value
170 {
171 extraDiff = 0;
172
173 if (desired->alphaBits > 0)
174 {
175 extraDiff += (desired->alphaBits - current->alphaBits) *
176 (desired->alphaBits - current->alphaBits);
177 }
178
179 if (desired->depthBits > 0)
180 {
181 extraDiff += (desired->depthBits - current->depthBits) *
182 (desired->depthBits - current->depthBits);
183 }
184
185 if (desired->stencilBits > 0)
186 {
187 extraDiff += (desired->stencilBits - current->stencilBits) *
188 (desired->stencilBits - current->stencilBits);
189 }
190
191 if (desired->accumRedBits > 0)
192 {
193 extraDiff += (desired->accumRedBits - current->accumRedBits) *
194 (desired->accumRedBits - current->accumRedBits);
195 }
196
197 if (desired->accumGreenBits > 0)
198 {
199 extraDiff += (desired->accumGreenBits - current->accumGreenBits) *
200 (desired->accumGreenBits - current->accumGreenBits);
201 }
202
203 if (desired->accumBlueBits > 0)
204 {
205 extraDiff += (desired->accumBlueBits - current->accumBlueBits) *
206 (desired->accumBlueBits - current->accumBlueBits);
207 }
208
209 if (desired->accumAlphaBits > 0)
210 {
211 extraDiff += (desired->accumAlphaBits - current->accumAlphaBits) *
212 (desired->accumAlphaBits - current->accumAlphaBits);
213 }
214
215 if (desired->samples > 0)
216 {
217 extraDiff += (desired->samples - current->samples) *
218 (desired->samples - current->samples);
219 }
Camilla Berglund69a90052012-12-02 16:10:00 +0100220
221 if (desired->sRGB)
222 {
223 if (!current->sRGB)
224 extraDiff++;
225 }
Camilla Berglund596f56f2011-03-07 13:56:28 +0100226 }
227
228 // Figure out if the current one is better than the best one found so far
229 // Least number of missing buffers is the most important heuristic,
230 // then color buffer size match and lastly size match for other buffers
231
232 if (missing < leastMissing)
233 closest = current;
234 else if (missing == leastMissing)
235 {
236 if ((colorDiff < leastColorDiff) ||
237 (colorDiff == leastColorDiff && extraDiff < leastExtraDiff))
238 {
239 closest = current;
240 }
241 }
242
243 if (current == closest)
244 {
245 leastMissing = missing;
246 leastColorDiff = colorDiff;
247 leastExtraDiff = extraDiff;
248 }
249 }
250
251 return closest;
252}
253
254
255//========================================================================
Camilla Berglund19be24a2011-03-07 14:55:11 +0100256// Checks whether the OpenGL part of the window config is sane
Camilla Berglundaff30d02012-08-06 17:56:41 +0200257// It blames glfwCreateWindow because that's the only caller
Camilla Berglund3249f812010-09-07 17:34:51 +0200258//========================================================================
259
Camilla Berglund19be24a2011-03-07 14:55:11 +0100260GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig)
Camilla Berglund3249f812010-09-07 17:34:51 +0200261{
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200262 if (wndconfig->clientAPI != GLFW_OPENGL_API &&
263 wndconfig->clientAPI != GLFW_OPENGL_ES_API)
Camilla Berglund88194052010-11-15 19:28:06 +0100264 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200265 _glfwSetError(GLFW_INVALID_ENUM,
266 "glfwCreateWindow: Invalid client API requested");
Camilla Berglund19be24a2011-03-07 14:55:11 +0100267 return GL_FALSE;
268 }
Camilla Berglund88194052010-11-15 19:28:06 +0100269
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200270 if (wndconfig->clientAPI == GLFW_OPENGL_API)
Camilla Berglund3249f812010-09-07 17:34:51 +0200271 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200272 if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0)
Camilla Berglund3249f812010-09-07 17:34:51 +0200273 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200274 // OpenGL 1.0 is the smallest valid version
Camilla Berglunde4027f12011-07-27 17:48:56 +0200275 _glfwSetError(GLFW_INVALID_VALUE,
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200276 "glfwCreateWindow: Invalid OpenGL version requested");
Camilla Berglund19be24a2011-03-07 14:55:11 +0100277 return GL_FALSE;
278 }
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200279 if (wndconfig->glMajor == 1 && wndconfig->glMinor > 5)
Camilla Berglund19be24a2011-03-07 14:55:11 +0100280 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200281 // OpenGL 1.x series ended with version 1.5
Camilla Berglunde4027f12011-07-27 17:48:56 +0200282 _glfwSetError(GLFW_INVALID_VALUE,
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200283 "glfwCreateWindow: Invalid OpenGL version requested");
284 return GL_FALSE;
285 }
286 else if (wndconfig->glMajor == 2 && wndconfig->glMinor > 1)
287 {
288 // OpenGL 2.x series ended with version 2.1
289 _glfwSetError(GLFW_INVALID_VALUE,
290 "glfwCreateWindow: Invalid OpenGL version requested");
291 return GL_FALSE;
292 }
293 else if (wndconfig->glMajor == 3 && wndconfig->glMinor > 3)
294 {
295 // OpenGL 3.x series ended with version 3.3
296 _glfwSetError(GLFW_INVALID_VALUE,
297 "glfwCreateWindow: Invalid OpenGL version requested");
298 return GL_FALSE;
299 }
300 else
301 {
302 // For now, let everything else through
303 }
304
305 if (wndconfig->glProfile)
306 {
307 if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE &&
308 wndconfig->glProfile != GLFW_OPENGL_COMPAT_PROFILE)
309 {
310 _glfwSetError(GLFW_INVALID_ENUM,
311 "glfwCreateWindow: Invalid OpenGL profile requested");
312 return GL_FALSE;
313 }
314
315 if (wndconfig->glMajor < 3 ||
316 (wndconfig->glMajor == 3 && wndconfig->glMinor < 2))
317 {
318 // Desktop OpenGL context profiles are only defined for version 3.2
319 // and above
320
321 _glfwSetError(GLFW_INVALID_VALUE,
322 "glfwCreateWindow: Context profiles only exist for "
323 "OpenGL version 3.2 and above");
324 return GL_FALSE;
325 }
326 }
327
328 if (wndconfig->glForward && wndconfig->glMajor < 3)
329 {
330 // Forward-compatible contexts are only defined for OpenGL version 3.0 and above
331 _glfwSetError(GLFW_INVALID_VALUE,
332 "glfwCreateWindow: Forward compatibility only exist "
333 "for OpenGL version 3.0 and above");
Camilla Berglund19be24a2011-03-07 14:55:11 +0100334 return GL_FALSE;
Camilla Berglund3249f812010-09-07 17:34:51 +0200335 }
336 }
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200337 else if (wndconfig->clientAPI == GLFW_OPENGL_ES_API)
Camilla Berglund19be24a2011-03-07 14:55:11 +0100338 {
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200339 if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0)
340 {
341 // OpenGL ES 1.0 is the smallest valid version
342 _glfwSetError(GLFW_INVALID_VALUE,
343 "glfwCreateWindow: Invalid OpenGL ES version requested");
344 return GL_FALSE;
345 }
346 if (wndconfig->glMajor == 1 && wndconfig->glMinor > 1)
347 {
348 // OpenGL ES 1.x series ended with version 1.1
349 _glfwSetError(GLFW_INVALID_VALUE,
350 "glfwCreateWindow: Invalid OpenGL ES version requested");
351 return GL_FALSE;
352 }
353 else
354 {
355 // For now, let everything else through
356 }
357
358 if (wndconfig->glProfile)
359 {
360 // OpenGL ES does not support profiles
361 _glfwSetError(GLFW_INVALID_VALUE,
362 "glfwCreateWindow: Context profiles are not supported "
363 "by OpenGL ES");
364 return GL_FALSE;
365 }
366
367 if (wndconfig->glForward)
368 {
369 // OpenGL ES does not support forward-compatibility
370 _glfwSetError(GLFW_INVALID_VALUE,
371 "glfwCreateWindow: Forward compatibility is not "
372 "supported by OpenGL ES");
373 return GL_FALSE;
374 }
Camilla Berglund19be24a2011-03-07 14:55:11 +0100375 }
376
Camilla Berglundd43e0b52011-03-07 20:51:34 +0100377 if (wndconfig->glRobustness)
378 {
379 if (wndconfig->glRobustness != GLFW_OPENGL_NO_RESET_NOTIFICATION &&
380 wndconfig->glRobustness != GLFW_OPENGL_LOSE_CONTEXT_ON_RESET)
381 {
Camilla Berglunde4027f12011-07-27 17:48:56 +0200382 _glfwSetError(GLFW_INVALID_VALUE,
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200383 "glfwCreateWindow: Invalid OpenGL robustness mode "
384 "requested");
Camilla Berglundd43e0b52011-03-07 20:51:34 +0100385 return GL_FALSE;
386 }
387 }
388
Camilla Berglund19be24a2011-03-07 14:55:11 +0100389 return GL_TRUE;
Camilla Berglund3249f812010-09-07 17:34:51 +0200390}
391
Camilla Berglund65f074d2011-10-08 23:57:03 +0200392
Camilla Berglund3249f812010-09-07 17:34:51 +0200393//========================================================================
Camilla Berglund053737e2012-08-02 01:18:35 +0200394// Reads back context properties
Camilla Berglundaff30d02012-08-06 17:56:41 +0200395// It blames glfwCreateWindow because that's the only caller
Camilla Berglund19be24a2011-03-07 14:55:11 +0100396//========================================================================
397
Camilla Berglund59896c32012-08-02 14:42:24 +0200398GLboolean _glfwRefreshContextParams(void)
Camilla Berglund19be24a2011-03-07 14:55:11 +0100399{
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200400 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
Camilla Berglund053737e2012-08-02 01:18:35 +0200401
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200402 if (!parseGLVersion(&window->clientAPI,
403 &window->glMajor,
Camilla Berglund59896c32012-08-02 14:42:24 +0200404 &window->glMinor,
405 &window->glRevision))
406 {
407 return GL_FALSE;
408 }
409
410 if (window->glMajor > 2)
411 {
412 // OpenGL 3.0+ uses a different function for extension string retrieval
413 // We cache it here instead of in glfwExtensionSupported mostly to alert
414 // users as early as possible that their build may be broken
415
416 window->GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
417 if (!window->GetStringi)
418 {
419 _glfwSetError(GLFW_PLATFORM_ERROR,
Camilla Berglundaff30d02012-08-06 17:56:41 +0200420 "glfwCreateWindow: Entry point retrieval is broken");
Camilla Berglund59896c32012-08-02 14:42:24 +0200421 return GL_FALSE;
422 }
423 }
Camilla Berglund19be24a2011-03-07 14:55:11 +0100424
Camilla Berglundc233e002011-07-27 18:20:15 +0200425 // Read back forward-compatibility flag
426 {
427 window->glForward = GL_FALSE;
428
Camilla Berglund38cad9a2012-09-30 15:32:50 +0200429 if (window->clientAPI == GLFW_OPENGL_API && window->glMajor >= 3)
Camilla Berglundc233e002011-07-27 18:20:15 +0200430 {
431 GLint flags;
432 glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
433
434 if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
435 window->glForward = GL_TRUE;
Camilla Berglund302037d2012-07-31 23:52:23 +0200436 if (flags & 0)
437 window->glDebug = GL_TRUE;
Camilla Berglundc233e002011-07-27 18:20:15 +0200438 }
439 }
440
441 // Read back OpenGL context profile
442 {
443 window->glProfile = 0;
444
445 if (window->glMajor > 3 || (window->glMajor == 3 && window->glMinor >= 2))
446 {
447 GLint mask;
448 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
449
450 if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
451 window->glProfile = GLFW_OPENGL_COMPAT_PROFILE;
452 else if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
453 window->glProfile = GLFW_OPENGL_CORE_PROFILE;
454 }
455 }
456
Camilla Berglund59896c32012-08-02 14:42:24 +0200457 return GL_TRUE;
Camilla Berglund053737e2012-08-02 01:18:35 +0200458}
459
460
461//========================================================================
Camilla Berglund59896c32012-08-02 14:42:24 +0200462// Checks whether the current context fulfils the specified requirements
Camilla Berglundaff30d02012-08-06 17:56:41 +0200463// It blames glfwCreateWindow because that's the only caller
Camilla Berglund053737e2012-08-02 01:18:35 +0200464//========================================================================
465
Camilla Berglund59896c32012-08-02 14:42:24 +0200466GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig)
Camilla Berglund053737e2012-08-02 01:18:35 +0200467{
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200468 _GLFWwindow* window = _glfwPlatformGetCurrentContext();
Camilla Berglund59896c32012-08-02 14:42:24 +0200469
Camilla Berglund19be24a2011-03-07 14:55:11 +0100470 if (window->glMajor < wndconfig->glMajor ||
471 (window->glMajor == wndconfig->glMajor &&
472 window->glMinor < wndconfig->glMinor))
473 {
474 // The desired OpenGL version is greater than the actual version
475 // This only happens if the machine lacks {GLX|WGL}_ARB_create_context
476 // /and/ the user has requested an OpenGL version greater than 1.0
477
478 // For API consistency, we emulate the behavior of the
479 // {GLX|WGL}_ARB_create_context extension and fail here
480
Camilla Berglunde4027f12011-07-27 17:48:56 +0200481 _glfwSetError(GLFW_VERSION_UNAVAILABLE,
Camilla Berglundaff30d02012-08-06 17:56:41 +0200482 "glfwCreateWindow: The requested OpenGL version is not available");
Camilla Berglund19be24a2011-03-07 14:55:11 +0100483 return GL_FALSE;
484 }
485
Camilla Berglund19be24a2011-03-07 14:55:11 +0100486 return GL_TRUE;
487}
488
489
490//========================================================================
Camilla Berglund1baf2332010-09-07 17:50:43 +0200491// Check if a string can be found in an OpenGL extension string
Camilla Berglund3249f812010-09-07 17:34:51 +0200492//========================================================================
493
Camilla Berglunda4d888c2010-09-08 15:58:43 +0200494int _glfwStringInExtensionString(const char* string,
495 const GLubyte* extensions)
Camilla Berglund3249f812010-09-07 17:34:51 +0200496{
Camilla Berglunda4d888c2010-09-08 15:58:43 +0200497 const GLubyte* start;
498 GLubyte* where;
499 GLubyte* terminator;
Camilla Berglund3249f812010-09-07 17:34:51 +0200500
501 // It takes a bit of care to be fool-proof about parsing the
502 // OpenGL extensions string. Don't be fooled by sub-strings,
503 // etc.
504 start = extensions;
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200505 for (;;)
Camilla Berglund3249f812010-09-07 17:34:51 +0200506 {
Camilla Berglunda4d888c2010-09-08 15:58:43 +0200507 where = (GLubyte*) strstr((const char*) start, string);
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200508 if (!where)
Camilla Berglund3249f812010-09-07 17:34:51 +0200509 return GL_FALSE;
Camilla Berglund105e9272010-09-08 01:57:24 +0200510
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200511 terminator = where + strlen(string);
512 if (where == start || *(where - 1) == ' ')
Camilla Berglund3249f812010-09-07 17:34:51 +0200513 {
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200514 if (*terminator == ' ' || *terminator == '\0')
Camilla Berglund3249f812010-09-07 17:34:51 +0200515 break;
Camilla Berglund3249f812010-09-07 17:34:51 +0200516 }
Camilla Berglund105e9272010-09-08 01:57:24 +0200517
Camilla Berglund3249f812010-09-07 17:34:51 +0200518 start = terminator;
519 }
520
521 return GL_TRUE;
522}
523
524
Camilla Berglund1723c4a2010-09-09 20:59:50 +0200525//////////////////////////////////////////////////////////////////////////
526////// GLFW public API //////
527//////////////////////////////////////////////////////////////////////////
Camilla Berglund3249f812010-09-07 17:34:51 +0200528
529//========================================================================
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200530// Make the OpenGL context associated with the specified window current
531//========================================================================
532
533GLFWAPI void glfwMakeContextCurrent(GLFWwindow handle)
534{
535 _GLFWwindow* window = (_GLFWwindow*) handle;
536
537 if (!_glfwInitialized)
538 {
539 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
540 return;
541 }
542
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200543 if (_glfwPlatformGetCurrentContext() == window)
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200544 return;
545
546 _glfwPlatformMakeContextCurrent(window);
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200547}
548
549
550//========================================================================
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200551// Return the window object whose context is current
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200552//========================================================================
553
554GLFWAPI GLFWwindow glfwGetCurrentContext(void)
555{
556 if (!_glfwInitialized)
557 {
558 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
Camilla Berglund96963212012-08-27 13:52:10 +0200559 return NULL;
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200560 }
561
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200562 return _glfwPlatformGetCurrentContext();
Camilla Berglundc1ab73b2011-07-27 16:01:27 +0200563}
564
565
566//========================================================================
Camilla Berglundaae89992011-03-04 14:25:12 +0100567// Swap buffers (double-buffering)
568//========================================================================
569
Camilla Berglund585a8402012-08-06 18:13:37 +0200570GLFWAPI void glfwSwapBuffers(GLFWwindow handle)
Camilla Berglundaae89992011-03-04 14:25:12 +0100571{
Camilla Berglund585a8402012-08-06 18:13:37 +0200572 _GLFWwindow* window = (_GLFWwindow*) handle;
573
Camilla Berglundaae89992011-03-04 14:25:12 +0100574 if (!_glfwInitialized)
575 {
576 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
577 return;
578 }
579
Camilla Berglund585a8402012-08-06 18:13:37 +0200580 _glfwPlatformSwapBuffers(window);
Camilla Berglundaae89992011-03-04 14:25:12 +0100581}
582
583
584//========================================================================
585// Set double buffering swap interval (0 = vsync off)
586//========================================================================
587
588GLFWAPI void glfwSwapInterval(int interval)
589{
590 if (!_glfwInitialized)
591 {
592 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
593 return;
594 }
595
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200596 if (!_glfwPlatformGetCurrentContext())
Camilla Berglundaae89992011-03-04 14:25:12 +0100597 {
Camilla Berglund957ecdc2012-08-02 15:36:15 +0200598 _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
Camilla Berglundaae89992011-03-04 14:25:12 +0100599 return;
600 }
601
602 _glfwPlatformSwapInterval(interval);
603}
604
605
606//========================================================================
Camilla Berglund3249f812010-09-07 17:34:51 +0200607// Check if an OpenGL extension is available at runtime
608//========================================================================
609
Camilla Berglunda4d888c2010-09-08 15:58:43 +0200610GLFWAPI int glfwExtensionSupported(const char* extension)
Camilla Berglund3249f812010-09-07 17:34:51 +0200611{
Camilla Berglunda4d888c2010-09-08 15:58:43 +0200612 const GLubyte* extensions;
Camilla Berglund973ff492010-09-14 00:17:00 +0200613 _GLFWwindow* window;
Camilla Berglund3249f812010-09-07 17:34:51 +0200614
Camilla Berglund922cd102010-09-09 21:34:42 +0200615 if (!_glfwInitialized)
616 {
Camilla Berglundf1e7d7c2010-11-23 17:45:23 +0100617 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
Camilla Berglund3249f812010-09-07 17:34:51 +0200618 return GL_FALSE;
Camilla Berglund922cd102010-09-09 21:34:42 +0200619 }
Camilla Berglund3249f812010-09-07 17:34:51 +0200620
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200621 window = _glfwPlatformGetCurrentContext();
Camilla Berglund973ff492010-09-14 00:17:00 +0200622 if (!window)
Camilla Berglund922cd102010-09-09 21:34:42 +0200623 {
Camilla Berglund957ecdc2012-08-02 15:36:15 +0200624 _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
Camilla Berglund922cd102010-09-09 21:34:42 +0200625 return GL_FALSE;
626 }
627
Camilla Berglundee3304c2012-08-02 15:29:13 +0200628 if (extension == NULL || *extension == '\0')
629 {
630 _glfwSetError(GLFW_INVALID_VALUE, NULL);
Camilla Berglund3249f812010-09-07 17:34:51 +0200631 return GL_FALSE;
Camilla Berglundee3304c2012-08-02 15:29:13 +0200632 }
Camilla Berglund3249f812010-09-07 17:34:51 +0200633
Camilla Berglund135194a2010-09-09 18:15:32 +0200634 if (window->glMajor < 3)
Camilla Berglund3249f812010-09-07 17:34:51 +0200635 {
636 // Check if extension is in the old style OpenGL extensions string
637
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200638 extensions = glGetString(GL_EXTENSIONS);
639 if (extensions != NULL)
Camilla Berglund3249f812010-09-07 17:34:51 +0200640 {
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200641 if (_glfwStringInExtensionString(extension, extensions))
Camilla Berglund3249f812010-09-07 17:34:51 +0200642 return GL_TRUE;
Camilla Berglund3249f812010-09-07 17:34:51 +0200643 }
644 }
645 else
646 {
Camilla Berglund1bad5732012-08-02 15:31:08 +0200647 int i;
648 GLint count;
649
Camilla Berglund3249f812010-09-07 17:34:51 +0200650 // Check if extension is in the modern OpenGL extensions string list
651
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200652 glGetIntegerv(GL_NUM_EXTENSIONS, &count);
Camilla Berglund3249f812010-09-07 17:34:51 +0200653
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200654 for (i = 0; i < count; i++)
Camilla Berglund3249f812010-09-07 17:34:51 +0200655 {
Camilla Berglund135194a2010-09-09 18:15:32 +0200656 if (strcmp((const char*) window->GetStringi(GL_EXTENSIONS, i),
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200657 extension) == 0)
Camilla Berglund3249f812010-09-07 17:34:51 +0200658 {
659 return GL_TRUE;
660 }
661 }
662 }
663
Camilla Berglunda9169972012-08-02 15:32:39 +0200664 // Check if extension is in the platform-specific string
665 return _glfwPlatformExtensionSupported(extension);
Camilla Berglund3249f812010-09-07 17:34:51 +0200666}
667
668
669//========================================================================
Camilla Berglund1baf2332010-09-07 17:50:43 +0200670// Get the function pointer to an OpenGL function.
Camilla Berglund3249f812010-09-07 17:34:51 +0200671// This function can be used to get access to extended OpenGL functions.
672//========================================================================
673
Camilla Berglundbf42c3c2012-06-05 00:16:40 +0200674GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
Camilla Berglund3249f812010-09-07 17:34:51 +0200675{
Camilla Berglund922cd102010-09-09 21:34:42 +0200676 if (!_glfwInitialized)
677 {
Camilla Berglundf1e7d7c2010-11-23 17:45:23 +0100678 _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
Camilla Berglund3249f812010-09-07 17:34:51 +0200679 return NULL;
Camilla Berglund922cd102010-09-09 21:34:42 +0200680 }
681
Camilla Berglund9e4bc362012-08-12 14:13:18 +0200682 if (!_glfwPlatformGetCurrentContext())
Camilla Berglund922cd102010-09-09 21:34:42 +0200683 {
Camilla Berglund957ecdc2012-08-02 15:36:15 +0200684 _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
Camilla Berglund922cd102010-09-09 21:34:42 +0200685 return NULL;
686 }
Camilla Berglund3249f812010-09-07 17:34:51 +0200687
Camilla Berglund9e4137c2010-09-08 14:45:52 +0200688 return _glfwPlatformGetProcAddress(procname);
Camilla Berglund3249f812010-09-07 17:34:51 +0200689}
690