Merge branch 'master' into multi-monitor
This commit is contained in:
Коммит
ff09d3a343
|
@ -400,14 +400,19 @@ extern "C" {
|
||||||
/* The following constants are used with both glfwGetWindowParam
|
/* The following constants are used with both glfwGetWindowParam
|
||||||
* and glfwWindowHint
|
* and glfwWindowHint
|
||||||
*/
|
*/
|
||||||
#define GLFW_OPENGL_VERSION_MAJOR 0x00022000
|
#define GLFW_CLIENT_API 0x00022000
|
||||||
#define GLFW_OPENGL_VERSION_MINOR 0x00022001
|
#define GLFW_OPENGL_VERSION_MAJOR 0x00022001
|
||||||
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022002
|
#define GLFW_OPENGL_VERSION_MINOR 0x00022002
|
||||||
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022003
|
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022003
|
||||||
#define GLFW_OPENGL_PROFILE 0x00022004
|
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022004
|
||||||
#define GLFW_OPENGL_ROBUSTNESS 0x00022005
|
#define GLFW_OPENGL_PROFILE 0x00022005
|
||||||
#define GLFW_RESIZABLE 0x00022006
|
#define GLFW_OPENGL_ROBUSTNESS 0x00022006
|
||||||
#define GLFW_VISIBLE 0x00022007
|
#define GLFW_RESIZABLE 0x00022007
|
||||||
|
#define GLFW_VISIBLE 0x00022008
|
||||||
|
|
||||||
|
/* GLFW_CLIENT_API tokens */
|
||||||
|
#define GLFW_OPENGL_API 0x00000001
|
||||||
|
#define GLFW_OPENGL_ES_API 0x00000002
|
||||||
|
|
||||||
/* GLFW_OPENGL_ROBUSTNESS mode tokens */
|
/* GLFW_OPENGL_ROBUSTNESS mode tokens */
|
||||||
#define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000
|
#define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000
|
||||||
|
@ -418,7 +423,6 @@ extern "C" {
|
||||||
#define GLFW_OPENGL_NO_PROFILE 0x00000000
|
#define GLFW_OPENGL_NO_PROFILE 0x00000000
|
||||||
#define GLFW_OPENGL_CORE_PROFILE 0x00000001
|
#define GLFW_OPENGL_CORE_PROFILE 0x00000001
|
||||||
#define GLFW_OPENGL_COMPAT_PROFILE 0x00000002
|
#define GLFW_OPENGL_COMPAT_PROFILE 0x00000002
|
||||||
#define GLFW_OPENGL_ES2_PROFILE 0x00000004
|
|
||||||
|
|
||||||
/* glfwGetInputMode/glfwSetInputMode tokens */
|
/* glfwGetInputMode/glfwSetInputMode tokens */
|
||||||
#define GLFW_CURSOR_MODE 0x00030001
|
#define GLFW_CURSOR_MODE 0x00030001
|
||||||
|
|
|
@ -279,7 +279,7 @@ version of GLFW.</p>
|
||||||
<li>Added <code>glfwGetClipboardString</code> and <code>glfwSetClipboardString</code> functions for interacting with the system clipboard</li>
|
<li>Added <code>glfwGetClipboardString</code> and <code>glfwSetClipboardString</code> functions for interacting with the system clipboard</li>
|
||||||
<li>Added <code>glfwGetCurrentContext</code> function for retrieving the window whose OpenGL context is current</li>
|
<li>Added <code>glfwGetCurrentContext</code> function for retrieving the window whose OpenGL context is current</li>
|
||||||
<li>Added <code>glfwCopyContext</code> function for copying OpenGL state categories between contexts</li>
|
<li>Added <code>glfwCopyContext</code> function for copying OpenGL state categories between contexts</li>
|
||||||
<li>Added <code>GLFW_OPENGL_ES2_PROFILE</code> profile for creating OpenGL ES 2.0 contexts using the <code>GLX_EXT_create_context_es2_profile</code> and <code>WGL_EXT_create_context_es2_profile</code> extensions</li>
|
<li>Added <code>GLFW_CLIENT_API</code>, <code>GLFW_OPENGL_API</code> and <code>GLFW_OPENGL_ES_API</code> for selecting client API</li>
|
||||||
<li>Added <code>GLFW_OPENGL_ROBUSTNESS</code> window hint and associated strategy tokens for <code>GL_ARB_robustness</code> support</li>
|
<li>Added <code>GLFW_OPENGL_ROBUSTNESS</code> window hint and associated strategy tokens for <code>GL_ARB_robustness</code> support</li>
|
||||||
<li>Added <code>GLFW_OPENGL_REVISION</code> window parameter to make up for removal of <code>glfwGetGLVersion</code></li>
|
<li>Added <code>GLFW_OPENGL_REVISION</code> window parameter to make up for removal of <code>glfwGetGLVersion</code></li>
|
||||||
<li>Added <code>GLFW_INCLUDE_GLCOREARB</code> macro for including <code>glcorearb.h</code> instead of <code>gl.h</code></li>
|
<li>Added <code>GLFW_INCLUDE_GLCOREARB</code> macro for including <code>glcorearb.h</code> instead of <code>gl.h</code></li>
|
||||||
|
|
|
@ -729,6 +729,13 @@ static GLboolean createContext(_GLFWwindow* window,
|
||||||
else if (colorBits < 15)
|
else if (colorBits < 15)
|
||||||
colorBits = 15;
|
colorBits = 15;
|
||||||
|
|
||||||
|
if (wndconfig->clientAPI != GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"Cocoa/NSOpenGL: NSOpenGL does not support OpenGL ES");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
|
||||||
// Fail if any OpenGL version above 2.1 other than 3.2 was requested
|
// Fail if any OpenGL version above 2.1 other than 3.2 was requested
|
||||||
if (wndconfig->glMajor > 3 ||
|
if (wndconfig->glMajor > 3 ||
|
||||||
|
|
|
@ -101,6 +101,7 @@ struct _GLFWhints
|
||||||
GLboolean resizable;
|
GLboolean resizable;
|
||||||
GLboolean visible;
|
GLboolean visible;
|
||||||
int samples;
|
int samples;
|
||||||
|
int clientAPI;
|
||||||
int glMajor;
|
int glMajor;
|
||||||
int glMinor;
|
int glMinor;
|
||||||
GLboolean glForward;
|
GLboolean glForward;
|
||||||
|
@ -122,6 +123,7 @@ struct _GLFWwndconfig
|
||||||
int refreshRate;
|
int refreshRate;
|
||||||
GLboolean resizable;
|
GLboolean resizable;
|
||||||
GLboolean visible;
|
GLboolean visible;
|
||||||
|
int clientAPI;
|
||||||
int glMajor;
|
int glMajor;
|
||||||
int glMinor;
|
int glMinor;
|
||||||
GLboolean glForward;
|
GLboolean glForward;
|
||||||
|
@ -190,6 +192,7 @@ struct _GLFWwindow
|
||||||
char key[GLFW_KEY_LAST + 1];
|
char key[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
// OpenGL extensions and context attributes
|
// OpenGL extensions and context attributes
|
||||||
|
int clientAPI;
|
||||||
int glMajor, glMinor, glRevision;
|
int glMajor, glMinor, glRevision;
|
||||||
GLboolean glForward, glDebug;
|
GLboolean glForward, glDebug;
|
||||||
int glProfile;
|
int glProfile;
|
||||||
|
|
178
src/opengl.c
178
src/opengl.c
|
@ -36,15 +36,17 @@
|
||||||
|
|
||||||
|
|
||||||
//========================================================================
|
//========================================================================
|
||||||
// Parses the OpenGL version string and extracts the version number
|
// Parses the client API version string and extracts the version number
|
||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
static GLboolean parseGLVersion(int* major, int* minor, int* rev)
|
static GLboolean parseGLVersion(int* api, int* major, int* minor, int* rev)
|
||||||
{
|
{
|
||||||
int i, _major, _minor = 0, _rev = 0;
|
int i, _api = GLFW_OPENGL_API, _major, _minor = 0, _rev = 0;
|
||||||
const char* version;
|
const char* version;
|
||||||
const char* prefixes[] =
|
const char* prefixes[] =
|
||||||
{
|
{
|
||||||
|
"OpenGL ES-CM ",
|
||||||
|
"OpenGL ES-CL ",
|
||||||
"OpenGL ES ",
|
"OpenGL ES ",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
@ -63,6 +65,7 @@ static GLboolean parseGLVersion(int* major, int* minor, int* rev)
|
||||||
if (strncmp(version, prefixes[i], length) == 0)
|
if (strncmp(version, prefixes[i], length) == 0)
|
||||||
{
|
{
|
||||||
version += length;
|
version += length;
|
||||||
|
_api = GLFW_OPENGL_ES_API;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,6 +76,7 @@ static GLboolean parseGLVersion(int* major, int* minor, int* rev)
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*api = _api;
|
||||||
*major = _major;
|
*major = _major;
|
||||||
*minor = _minor;
|
*minor = _minor;
|
||||||
*rev = _rev;
|
*rev = _rev;
|
||||||
|
@ -249,83 +253,119 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired,
|
||||||
|
|
||||||
GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig)
|
GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig)
|
||||||
{
|
{
|
||||||
if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0)
|
if (wndconfig->clientAPI != GLFW_OPENGL_API &&
|
||||||
|
wndconfig->clientAPI != GLFW_OPENGL_ES_API)
|
||||||
{
|
{
|
||||||
// OpenGL 1.0 is the smallest valid version
|
_glfwSetError(GLFW_INVALID_ENUM,
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
"glfwCreateWindow: Invalid client API requested");
|
||||||
"glfwCreateWindow: Invalid OpenGL version requested");
|
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
if (wndconfig->glMajor == 1 && wndconfig->glMinor > 5)
|
|
||||||
{
|
|
||||||
// OpenGL 1.x series ended with version 1.5
|
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
|
||||||
"glfwCreateWindow: Invalid OpenGL version requested");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
else if (wndconfig->glMajor == 2 && wndconfig->glMinor > 1)
|
|
||||||
{
|
|
||||||
// OpenGL 2.x series ended with version 2.1
|
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
|
||||||
"glfwCreateWindow: Invalid OpenGL version requested");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
else if (wndconfig->glMajor == 3 && wndconfig->glMinor > 3)
|
|
||||||
{
|
|
||||||
// OpenGL 3.x series ended with version 3.3
|
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
|
||||||
"glfwCreateWindow: Invalid OpenGL version requested");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For now, let everything else through
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE)
|
if (wndconfig->clientAPI == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
if (wndconfig->glMajor != 2 || wndconfig->glMinor < 0)
|
if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0)
|
||||||
{
|
{
|
||||||
// The OpenGL ES 2.0 profile is currently only defined for version
|
// OpenGL 1.0 is the smallest valid version
|
||||||
// 2.0 (see {WGL|GLX}_EXT_create_context_es2_profile), but for
|
|
||||||
// compatibility with future updates to OpenGL ES, we allow
|
|
||||||
// everything 2.x and let the driver report invalid 2.x versions
|
|
||||||
|
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
"glfwCreateWindow: Invalid OpenGL ES 2.x version requested");
|
"glfwCreateWindow: Invalid OpenGL version requested");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
if (wndconfig->glMajor == 1 && wndconfig->glMinor > 5)
|
||||||
else if (wndconfig->glProfile)
|
|
||||||
{
|
|
||||||
if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE &&
|
|
||||||
wndconfig->glProfile != GLFW_OPENGL_COMPAT_PROFILE)
|
|
||||||
{
|
{
|
||||||
_glfwSetError(GLFW_INVALID_ENUM,
|
// OpenGL 1.x series ended with version 1.5
|
||||||
"glfwCreateWindow: Invalid OpenGL profile requested");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wndconfig->glMajor < 3 ||
|
|
||||||
(wndconfig->glMajor == 3 && wndconfig->glMinor < 2))
|
|
||||||
{
|
|
||||||
// Desktop OpenGL context profiles are only defined for version 3.2
|
|
||||||
// and above
|
|
||||||
|
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
"glfwCreateWindow: Context profiles only exist for "
|
"glfwCreateWindow: Invalid OpenGL version requested");
|
||||||
"OpenGL version 3.2 and above");
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
else if (wndconfig->glMajor == 2 && wndconfig->glMinor > 1)
|
||||||
|
{
|
||||||
|
// OpenGL 2.x series ended with version 2.1
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Invalid OpenGL version requested");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
else if (wndconfig->glMajor == 3 && wndconfig->glMinor > 3)
|
||||||
|
{
|
||||||
|
// OpenGL 3.x series ended with version 3.3
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Invalid OpenGL version requested");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For now, let everything else through
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->glProfile)
|
||||||
|
{
|
||||||
|
if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE &&
|
||||||
|
wndconfig->glProfile != GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_INVALID_ENUM,
|
||||||
|
"glfwCreateWindow: Invalid OpenGL profile requested");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->glMajor < 3 ||
|
||||||
|
(wndconfig->glMajor == 3 && wndconfig->glMinor < 2))
|
||||||
|
{
|
||||||
|
// Desktop OpenGL context profiles are only defined for version 3.2
|
||||||
|
// and above
|
||||||
|
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Context profiles only exist for "
|
||||||
|
"OpenGL version 3.2 and above");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->glForward && wndconfig->glMajor < 3)
|
||||||
|
{
|
||||||
|
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Forward compatibility only exist "
|
||||||
|
"for OpenGL version 3.0 and above");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (wndconfig->clientAPI == GLFW_OPENGL_ES_API)
|
||||||
if (wndconfig->glForward && wndconfig->glMajor < 3)
|
|
||||||
{
|
{
|
||||||
// Forward-compatible contexts are only defined for OpenGL version 3.0 and above
|
if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0)
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
{
|
||||||
"glfwCreateWindow: Forward compatibility only exist for "
|
// OpenGL ES 1.0 is the smallest valid version
|
||||||
"OpenGL version 3.0 and above");
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
return GL_FALSE;
|
"glfwCreateWindow: Invalid OpenGL ES version requested");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
if (wndconfig->glMajor == 1 && wndconfig->glMinor > 1)
|
||||||
|
{
|
||||||
|
// OpenGL ES 1.x series ended with version 1.1
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Invalid OpenGL ES version requested");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// For now, let everything else through
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->glProfile)
|
||||||
|
{
|
||||||
|
// OpenGL ES does not support profiles
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Context profiles are not supported "
|
||||||
|
"by OpenGL ES");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wndconfig->glForward)
|
||||||
|
{
|
||||||
|
// OpenGL ES does not support forward-compatibility
|
||||||
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
|
"glfwCreateWindow: Forward compatibility is not "
|
||||||
|
"supported by OpenGL ES");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->glRobustness)
|
if (wndconfig->glRobustness)
|
||||||
|
@ -334,7 +374,8 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig)
|
||||||
wndconfig->glRobustness != GLFW_OPENGL_LOSE_CONTEXT_ON_RESET)
|
wndconfig->glRobustness != GLFW_OPENGL_LOSE_CONTEXT_ON_RESET)
|
||||||
{
|
{
|
||||||
_glfwSetError(GLFW_INVALID_VALUE,
|
_glfwSetError(GLFW_INVALID_VALUE,
|
||||||
"glfwCreateWindow: Invalid OpenGL robustness mode requested");
|
"glfwCreateWindow: Invalid OpenGL robustness mode "
|
||||||
|
"requested");
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +393,8 @@ GLboolean _glfwRefreshContextParams(void)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
_GLFWwindow* window = _glfwPlatformGetCurrentContext();
|
||||||
|
|
||||||
if (!parseGLVersion(&window->glMajor,
|
if (!parseGLVersion(&window->clientAPI,
|
||||||
|
&window->glMajor,
|
||||||
&window->glMinor,
|
&window->glMinor,
|
||||||
&window->glRevision))
|
&window->glRevision))
|
||||||
{
|
{
|
||||||
|
@ -378,7 +420,7 @@ GLboolean _glfwRefreshContextParams(void)
|
||||||
{
|
{
|
||||||
window->glForward = GL_FALSE;
|
window->glForward = GL_FALSE;
|
||||||
|
|
||||||
if (window->glMajor >= 3)
|
if (window->clientAPI == GLFW_OPENGL_API && window->glMajor >= 3)
|
||||||
{
|
{
|
||||||
GLint flags;
|
GLint flags;
|
||||||
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
|
|
|
@ -356,6 +356,21 @@ static GLboolean createContext(_GLFWwindow* window,
|
||||||
attribs[i++] = wndconfig->glMinor;
|
attribs[i++] = wndconfig->glMinor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wndconfig->clientAPI == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (!window->WGL.ARB_create_context_profile ||
|
||||||
|
!window->WGL.EXT_create_context_es2_profile)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"Win32/WGL: OpenGL ES 2.x requested but "
|
||||||
|
"WGL_EXT_create_context_es2_profile is unavailable");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||||
|
attribs[i++] = WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
||||||
|
}
|
||||||
|
|
||||||
if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness)
|
if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -385,21 +400,10 @@ static GLboolean createContext(_GLFWwindow* window,
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE &&
|
|
||||||
!window->WGL.EXT_create_context_es2_profile)
|
|
||||||
{
|
|
||||||
_glfwSetError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"WGL: OpenGL ES 2.x profile requested but "
|
|
||||||
"WGL_EXT_create_context_es2_profile is unavailable");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE)
|
if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
flags = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
flags = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE)
|
|
||||||
flags = WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
|
|
||||||
|
|
||||||
attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
|
attribs[i++] = WGL_CONTEXT_PROFILE_MASK_ARB;
|
||||||
attribs[i++] = flags;
|
attribs[i++] = flags;
|
||||||
|
|
20
src/window.c
20
src/window.c
|
@ -76,7 +76,8 @@ void _glfwSetDefaultWindowHints(void)
|
||||||
{
|
{
|
||||||
memset(&_glfwLibrary.hints, 0, sizeof(_glfwLibrary.hints));
|
memset(&_glfwLibrary.hints, 0, sizeof(_glfwLibrary.hints));
|
||||||
|
|
||||||
// The default minimum OpenGL version is 1.0
|
// The default is OpenGL with minimum version 1.0
|
||||||
|
_glfwLibrary.hints.clientAPI = GLFW_OPENGL_API;
|
||||||
_glfwLibrary.hints.glMajor = 1;
|
_glfwLibrary.hints.glMajor = 1;
|
||||||
_glfwLibrary.hints.glMinor = 0;
|
_glfwLibrary.hints.glMinor = 0;
|
||||||
|
|
||||||
|
@ -84,11 +85,12 @@ void _glfwSetDefaultWindowHints(void)
|
||||||
_glfwLibrary.hints.resizable = GL_TRUE;
|
_glfwLibrary.hints.resizable = GL_TRUE;
|
||||||
_glfwLibrary.hints.visible = GL_TRUE;
|
_glfwLibrary.hints.visible = GL_TRUE;
|
||||||
|
|
||||||
// The default is 24 bits of depth, 8 bits of color
|
// The default is 24 bits of color, 24 bits of depth and 8 bits of stencil
|
||||||
_glfwLibrary.hints.depthBits = 24;
|
_glfwLibrary.hints.redBits = 8;
|
||||||
_glfwLibrary.hints.redBits = 8;
|
_glfwLibrary.hints.greenBits = 8;
|
||||||
_glfwLibrary.hints.greenBits = 8;
|
_glfwLibrary.hints.blueBits = 8;
|
||||||
_glfwLibrary.hints.blueBits = 8;
|
_glfwLibrary.hints.depthBits = 24;
|
||||||
|
_glfwLibrary.hints.stencilBits = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,6 +264,7 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
|
||||||
wndconfig.refreshRate = Max(_glfwLibrary.hints.refreshRate, 0);
|
wndconfig.refreshRate = Max(_glfwLibrary.hints.refreshRate, 0);
|
||||||
wndconfig.resizable = _glfwLibrary.hints.resizable ? GL_TRUE : GL_FALSE;
|
wndconfig.resizable = _glfwLibrary.hints.resizable ? GL_TRUE : GL_FALSE;
|
||||||
wndconfig.visible = _glfwLibrary.hints.visible ? GL_TRUE : GL_FALSE;
|
wndconfig.visible = _glfwLibrary.hints.visible ? GL_TRUE : GL_FALSE;
|
||||||
|
wndconfig.clientAPI = _glfwLibrary.hints.clientAPI;
|
||||||
wndconfig.glMajor = _glfwLibrary.hints.glMajor;
|
wndconfig.glMajor = _glfwLibrary.hints.glMajor;
|
||||||
wndconfig.glMinor = _glfwLibrary.hints.glMinor;
|
wndconfig.glMinor = _glfwLibrary.hints.glMinor;
|
||||||
wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE;
|
wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE;
|
||||||
|
@ -430,6 +433,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
|
||||||
case GLFW_FSAA_SAMPLES:
|
case GLFW_FSAA_SAMPLES:
|
||||||
_glfwLibrary.hints.samples = hint;
|
_glfwLibrary.hints.samples = hint;
|
||||||
break;
|
break;
|
||||||
|
case GLFW_CLIENT_API:
|
||||||
|
_glfwLibrary.hints.clientAPI = hint;
|
||||||
|
break;
|
||||||
case GLFW_OPENGL_VERSION_MAJOR:
|
case GLFW_OPENGL_VERSION_MAJOR:
|
||||||
_glfwLibrary.hints.glMajor = hint;
|
_glfwLibrary.hints.glMajor = hint;
|
||||||
break;
|
break;
|
||||||
|
@ -734,6 +740,8 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param)
|
||||||
return window->resizable;
|
return window->resizable;
|
||||||
case GLFW_VISIBLE:
|
case GLFW_VISIBLE:
|
||||||
return window->visible;
|
return window->visible;
|
||||||
|
case GLFW_CLIENT_API:
|
||||||
|
return window->clientAPI;
|
||||||
case GLFW_OPENGL_VERSION_MAJOR:
|
case GLFW_OPENGL_VERSION_MAJOR:
|
||||||
return window->glMajor;
|
return window->glMajor;
|
||||||
case GLFW_OPENGL_VERSION_MINOR:
|
case GLFW_OPENGL_VERSION_MINOR:
|
||||||
|
|
|
@ -295,6 +295,22 @@ static int createContext(_GLFWwindow* window,
|
||||||
setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor);
|
setGLXattrib(attribs, index, GLX_CONTEXT_MINOR_VERSION_ARB, wndconfig->glMinor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wndconfig->clientAPI == GLFW_OPENGL_ES_API)
|
||||||
|
{
|
||||||
|
if (!_glfwLibrary.GLX.ARB_create_context_profile ||
|
||||||
|
!_glfwLibrary.GLX.EXT_create_context_es2_profile)
|
||||||
|
{
|
||||||
|
_glfwSetError(GLFW_VERSION_UNAVAILABLE,
|
||||||
|
"GLX: OpenGL ES 2.x requested but "
|
||||||
|
"GLX_EXT_create_context_es2_profile is unavailable");
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
setGLXattrib(attribs, index,
|
||||||
|
GLX_CONTEXT_PROFILE_MASK_ARB,
|
||||||
|
GLX_CONTEXT_ES2_PROFILE_BIT_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness)
|
if (wndconfig->glForward || wndconfig->glDebug || wndconfig->glRobustness)
|
||||||
{
|
{
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
|
@ -323,21 +339,10 @@ static int createContext(_GLFWwindow* window,
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE &&
|
|
||||||
!_glfwLibrary.GLX.EXT_create_context_es2_profile)
|
|
||||||
{
|
|
||||||
_glfwSetError(GLFW_VERSION_UNAVAILABLE,
|
|
||||||
"GLX: OpenGL ES 2.x profile requested but "
|
|
||||||
"GLX_EXT_create_context_es2_profile is unavailable");
|
|
||||||
return GL_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE)
|
if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE)
|
||||||
flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE)
|
else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE)
|
||||||
flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
flags = GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
else if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE)
|
|
||||||
flags = GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
|
|
||||||
|
|
||||||
setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags);
|
setGLXattrib(attribs, index, GLX_CONTEXT_PROFILE_MASK_ARB, flags);
|
||||||
}
|
}
|
||||||
|
|
135
tests/glfwinfo.c
135
tests/glfwinfo.c
|
@ -42,56 +42,57 @@
|
||||||
#define strcasecmp(x, y) _stricmp(x, y)
|
#define strcasecmp(x, y) _stricmp(x, y)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define API_OPENGL "gl"
|
||||||
|
#define API_OPENGL_ES "es"
|
||||||
|
|
||||||
#define PROFILE_NAME_CORE "core"
|
#define PROFILE_NAME_CORE "core"
|
||||||
#define PROFILE_NAME_COMPAT "compat"
|
#define PROFILE_NAME_COMPAT "compat"
|
||||||
#define PROFILE_NAME_ES2 "es2"
|
|
||||||
|
|
||||||
#define STRATEGY_NAME_NONE "none"
|
#define STRATEGY_NAME_NONE "none"
|
||||||
#define STRATEGY_NAME_LOSE "lose"
|
#define STRATEGY_NAME_LOSE "lose"
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: glfwinfo [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n");
|
printf("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\n");
|
||||||
printf("available profiles: " PROFILE_NAME_CORE " " PROFILE_NAME_COMPAT " " PROFILE_NAME_ES2 "\n");
|
printf("available APIs: " API_OPENGL " " API_OPENGL_ES "\n");
|
||||||
|
printf("available profiles: " PROFILE_NAME_CORE " " PROFILE_NAME_COMPAT "\n");
|
||||||
printf("available strategies: " STRATEGY_NAME_NONE " " STRATEGY_NAME_LOSE "\n");
|
printf("available strategies: " STRATEGY_NAME_NONE " " STRATEGY_NAME_LOSE "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void error_callback(int error, const char* description)
|
static void error_callback(int error, const char* description)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Error: %s in %s\n", glfwErrorString(error), description);
|
fprintf(stderr, "Error: %s\n", description);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* get_glfw_profile_name(int profile)
|
static const char* get_client_api_name(int api)
|
||||||
{
|
{
|
||||||
if (profile == GLFW_OPENGL_COMPAT_PROFILE)
|
if (api == GLFW_OPENGL_API)
|
||||||
return PROFILE_NAME_COMPAT;
|
return "OpenGL";
|
||||||
else if (profile == GLFW_OPENGL_CORE_PROFILE)
|
else if (api == GLFW_OPENGL_ES_API)
|
||||||
return PROFILE_NAME_CORE;
|
return "OpenGL ES";
|
||||||
else if (profile == GLFW_OPENGL_ES2_PROFILE)
|
|
||||||
return PROFILE_NAME_ES2;
|
|
||||||
|
|
||||||
return "unknown";
|
return "Unknown API";
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* get_profile_name(GLint mask)
|
static const char* get_profile_name(GLint mask)
|
||||||
{
|
{
|
||||||
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
|
||||||
return PROFILE_NAME_COMPAT;
|
return "compatibility";
|
||||||
if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
if (mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
||||||
return PROFILE_NAME_CORE;
|
return "core";
|
||||||
|
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_extensions(int major, int minor)
|
static void list_extensions(int api, int major, int minor)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
GLint count;
|
GLint count;
|
||||||
const GLubyte* extensions;
|
const GLubyte* extensions;
|
||||||
|
|
||||||
printf("OpenGL context supported extensions:\n");
|
printf("%s context supported extensions:\n", get_client_api_name(api));
|
||||||
|
|
||||||
if (major > 2)
|
if (api == GLFW_OPENGL_API && major > 2)
|
||||||
{
|
{
|
||||||
PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
|
PFNGLGETSTRINGIPROC glGetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi");
|
||||||
if (!glGetStringi)
|
if (!glGetStringi)
|
||||||
|
@ -147,7 +148,7 @@ static GLboolean valid_version(void)
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int ch, profile = 0, strategy = 0, major = 1, minor = 0, revision;
|
int ch, api = 0, profile = 0, strategy = 0, major = 1, minor = 0, revision;
|
||||||
GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE;
|
GLboolean debug = GL_FALSE, forward = GL_FALSE, list = GL_FALSE;
|
||||||
GLint flags, mask;
|
GLint flags, mask;
|
||||||
GLFWwindow window;
|
GLFWwindow window;
|
||||||
|
@ -155,10 +156,20 @@ int main(int argc, char** argv)
|
||||||
if (!valid_version())
|
if (!valid_version())
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "dfhlm:n:p:r:")) != -1)
|
while ((ch = getopt(argc, argv, "a:dfhlm:n:p:r:")) != -1)
|
||||||
{
|
{
|
||||||
switch (ch)
|
switch (ch)
|
||||||
{
|
{
|
||||||
|
case 'a':
|
||||||
|
if (strcasecmp(optarg, API_OPENGL) == 0)
|
||||||
|
api = GLFW_OPENGL_API;
|
||||||
|
else if (strcasecmp(optarg, API_OPENGL_ES) == 0)
|
||||||
|
api = GLFW_OPENGL_ES_API;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
case 'd':
|
case 'd':
|
||||||
debug = GL_TRUE;
|
debug = GL_TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -182,8 +193,6 @@ int main(int argc, char** argv)
|
||||||
profile = GLFW_OPENGL_CORE_PROFILE;
|
profile = GLFW_OPENGL_CORE_PROFILE;
|
||||||
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
|
else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0)
|
||||||
profile = GLFW_OPENGL_COMPAT_PROFILE;
|
profile = GLFW_OPENGL_COMPAT_PROFILE;
|
||||||
else if (strcasecmp(optarg, PROFILE_NAME_ES2) == 0)
|
|
||||||
profile = GLFW_OPENGL_ES2_PROFILE;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
usage();
|
usage();
|
||||||
|
@ -226,6 +235,9 @@ int main(int argc, char** argv)
|
||||||
glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, minor);
|
glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (api != 0)
|
||||||
|
glfwWindowHint(GLFW_CLIENT_API, api);
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||||
|
|
||||||
|
@ -249,62 +261,77 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
glfwMakeContextCurrent(window);
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
// Report OpenGL version
|
// Report client API version
|
||||||
|
|
||||||
printf("OpenGL context version string: \"%s\"\n", glGetString(GL_VERSION));
|
|
||||||
|
|
||||||
|
api = glfwGetWindowParam(window, GLFW_CLIENT_API);
|
||||||
major = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MAJOR);
|
major = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MAJOR);
|
||||||
minor = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MINOR);
|
minor = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MINOR);
|
||||||
revision = glfwGetWindowParam(window, GLFW_OPENGL_REVISION);
|
revision = glfwGetWindowParam(window, GLFW_OPENGL_REVISION);
|
||||||
|
|
||||||
printf("OpenGL context version parsed by GLFW: %u.%u.%u\n", major, minor, revision);
|
printf("%s context version string: \"%s\"\n",
|
||||||
|
get_client_api_name(api),
|
||||||
|
glGetString(GL_VERSION));
|
||||||
|
|
||||||
// Report OpenGL context properties
|
printf("%s context version parsed by GLFW: %u.%u.%u\n",
|
||||||
|
get_client_api_name(api),
|
||||||
|
major, minor, revision);
|
||||||
|
|
||||||
if (major >= 3)
|
// Report client API context properties
|
||||||
|
|
||||||
|
if (api == GLFW_OPENGL_API)
|
||||||
{
|
{
|
||||||
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
if (major >= 3)
|
||||||
printf("OpenGL context flags (0x%08x):", flags);
|
{
|
||||||
|
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
|
||||||
|
printf("%s context flags (0x%08x):", get_client_api_name(api), flags);
|
||||||
|
|
||||||
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)
|
||||||
printf(" forward-compatible");
|
printf(" forward-compatible");
|
||||||
if (flags & 0)
|
if (flags & 0)
|
||||||
printf(" debug");
|
printf(" debug");
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
|
||||||
printf("OpenGL context flags parsed by GLFW:");
|
printf("%s context flags parsed by GLFW:", get_client_api_name(api));
|
||||||
|
|
||||||
if (glfwGetWindowParam(window, GLFW_OPENGL_FORWARD_COMPAT))
|
if (glfwGetWindowParam(window, GLFW_OPENGL_FORWARD_COMPAT))
|
||||||
printf(" forward-compatible");
|
printf(" forward-compatible");
|
||||||
if (glfwGetWindowParam(window, GLFW_OPENGL_DEBUG_CONTEXT))
|
if (glfwGetWindowParam(window, GLFW_OPENGL_DEBUG_CONTEXT))
|
||||||
printf(" debug");
|
printf(" debug");
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (major > 3 || (major == 3 && minor >= 2))
|
||||||
|
{
|
||||||
|
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
||||||
|
printf("%s profile mask (0x%08x): %s\n",
|
||||||
|
get_client_api_name(api),
|
||||||
|
mask,
|
||||||
|
get_profile_name(mask));
|
||||||
|
|
||||||
|
printf("%s profile mask parsed by GLFW:\n", get_client_api_name(api));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (major > 3 || (major == 3 && minor >= 2))
|
printf("%s context renderer string: \"%s\"\n",
|
||||||
{
|
get_client_api_name(api),
|
||||||
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask);
|
glGetString(GL_RENDERER));
|
||||||
printf("OpenGL profile mask (0x%08x): %s\n", mask, get_profile_name(mask));
|
printf("%s context vendor string: \"%s\"\n",
|
||||||
|
get_client_api_name(api),
|
||||||
printf("OpenGL profile mask parsed by GLFW: %s\n",
|
glGetString(GL_VENDOR));
|
||||||
get_glfw_profile_name(glfwGetWindowParam(window, GLFW_OPENGL_PROFILE)));
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("OpenGL context debug flag saved by GLFW: %s\n",
|
printf("OpenGL context debug flag saved by GLFW: %s\n",
|
||||||
glfwGetWindowParam(window, GLFW_OPENGL_DEBUG_CONTEXT) ? "true" : "false");
|
glfwGetWindowParam(window, GLFW_OPENGL_DEBUG_CONTEXT) ? "true" : "false");
|
||||||
|
|
||||||
printf("OpenGL context renderer string: \"%s\"\n", glGetString(GL_RENDERER));
|
|
||||||
printf("OpenGL context vendor string: \"%s\"\n", glGetString(GL_VENDOR));
|
|
||||||
|
|
||||||
if (major > 1)
|
if (major > 1)
|
||||||
{
|
{
|
||||||
printf("OpenGL context shading language version: \"%s\"\n",
|
printf("%s context shading language version: \"%s\"\n",
|
||||||
|
get_client_api_name(api),
|
||||||
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report OpenGL extensions
|
// Report client API extensions
|
||||||
if (list)
|
if (list)
|
||||||
list_extensions(major, minor);
|
list_extensions(api, major, minor);
|
||||||
|
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче