diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 2ff67627..4ff8e857 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -413,12 +413,17 @@ extern "C" { #define GLFW_STEREO 0x0002100C #define GLFW_WINDOW_RESIZABLE 0x0002100D #define GLFW_FSAA_SAMPLES 0x0002100E -#define GLFW_OPENGL_VERSION_MAJOR 0x0002100F -#define GLFW_OPENGL_VERSION_MINOR 0x00021010 -#define GLFW_OPENGL_FORWARD_COMPAT 0x00021011 -#define GLFW_OPENGL_DEBUG_CONTEXT 0x00021012 -#define GLFW_OPENGL_PROFILE 0x00021013 -#define GLFW_OPENGL_ROBUSTNESS 0x00021014 +#define GLFW_CLIENT_API 0x0002100F +#define GLFW_OPENGL_VERSION_MAJOR 0x00021010 +#define GLFW_OPENGL_VERSION_MINOR 0x00021011 +#define GLFW_OPENGL_FORWARD_COMPAT 0x00021012 +#define GLFW_OPENGL_DEBUG_CONTEXT 0x00021013 +#define GLFW_OPENGL_PROFILE 0x00021014 +#define GLFW_OPENGL_ROBUSTNESS 0x00021015 + +/* GLFW_OPENGL_API mode tokens */ +#define GLFW_OPENGL_API 0x00000001 +#define GLFW_OPENGL_ES_API 0x00000002 /* GLFW_OPENGL_ROBUSTNESS mode tokens */ #define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000 @@ -429,7 +434,6 @@ extern "C" { #define GLFW_OPENGL_NO_PROFILE 0x00000000 #define GLFW_OPENGL_CORE_PROFILE 0x00000001 #define GLFW_OPENGL_COMPAT_PROFILE 0x00000002 -#define GLFW_OPENGL_ES2_PROFILE 0x00000004 /* glfwGetInputMode/glfwSetInputMode tokens */ #define GLFW_CURSOR_MODE 0x00030001 diff --git a/readme.html b/readme.html index cdbb9885..9873da27 100644 --- a/readme.html +++ b/readme.html @@ -280,7 +280,7 @@ version of GLFW.

  • Added glfwGetClipboardString and glfwSetClipboardString functions for interacting with the system clipboard
  • Added glfwGetCurrentContext function for retrieving the window whose OpenGL context is current
  • Added glfwCopyContext function for copying OpenGL state categories between contexts
  • -
  • Added GLFW_OPENGL_ES2_PROFILE profile for creating OpenGL ES 2.0 contexts using the GLX_EXT_create_context_es2_profile and WGL_EXT_create_context_es2_profile extensions
  • +
  • Added GLFW_CLIENT_API window hint for creating contexts for APIs other than desktop OpenGL
  • Added GLFW_OPENGL_ROBUSTNESS window hint and associated strategy tokens for GL_ARB_robustness support
  • Added GLFW_OPENGL_REVISION window parameter to make up for removal of glfwGetGLVersion
  • Added GLFW_INCLUDE_GL3 macro for telling the GLFW header to include gl3.h header instead of gl.h
  • diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 3523806a..8093c3c6 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -717,6 +717,13 @@ static GLboolean createContext(_GLFWwindow* window, else if (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 // Fail if any OpenGL version above 2.1 other than 3.2 was requested if (wndconfig->glMajor > 3 || diff --git a/src/internal.h b/src/internal.h index 4f34bd21..bda462a8 100644 --- a/src/internal.h +++ b/src/internal.h @@ -110,6 +110,7 @@ struct _GLFWhints GLboolean stereo; GLboolean resizable; int samples; + int clientAPI; int glMajor; int glMinor; GLboolean glForward; @@ -131,6 +132,7 @@ struct _GLFWwndconfig const char* title; int refreshRate; GLboolean resizable; + int clientAPI; int glMajor; int glMinor; GLboolean glForward; @@ -212,6 +214,7 @@ struct _GLFWwindow // OpenGL extensions and context attributes GLboolean accelerated; // GL_TRUE if OpenGL context is "accelerated" + int clientAPI; int glMajor, glMinor, glRevision; GLboolean glForward, glDebug; int glProfile; diff --git a/src/opengl.c b/src/opengl.c index 59097e1e..ff623ed3 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -36,7 +36,7 @@ //======================================================================== -// Parses the OpenGL version string and extracts the version number +// Parses the client API version string and extracts the version number //======================================================================== static void parseGLVersion(int* major, int* minor, int* rev) @@ -256,89 +256,125 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, //======================================================================== -// Checks whether the OpenGL part of the window config is sane +// Checks whether the client API part of the window config is sane // It blames glfwOpenWindow because that's the only caller //======================================================================== 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_VALUE, - "glfwOpenWindow: Invalid OpenGL version requested"); + _glfwSetError(GLFW_INVALID_ENUM, + "glfwOpenWindow: Invalid client API requested"); return GL_FALSE; } - if (wndconfig->glMajor == 1 && wndconfig->glMinor > 5) - { - // OpenGL 1.x series ended with version 1.5 - _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: 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, - "glfwOpenWindow: 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, - "glfwOpenWindow: 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 - // 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 - + // OpenGL 1.0 is the smallest valid version _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: Invalid OpenGL ES 2.x version requested"); + "glfwOpenWindow: Invalid OpenGL version requested"); return GL_FALSE; } - } - else if (wndconfig->glProfile) - { - if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE && - wndconfig->glProfile != GLFW_OPENGL_COMPAT_PROFILE) + if (wndconfig->glMajor == 1 && wndconfig->glMinor > 5) { - _glfwSetError(GLFW_INVALID_ENUM, - "glfwOpenWindow: 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 - + // OpenGL 1.x series ended with version 1.5 _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: Context profiles only exist for " - "OpenGL version 3.2 and above"); + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: Forward compatibility only exist for " + "OpenGL version 3.0 and above"); return GL_FALSE; } } - - if (wndconfig->glForward && wndconfig->glMajor < 3) + else if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { - // Forward-compatible contexts are only defined for OpenGL version 3.0 and above - _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: Forward compatibility only exist for " - "OpenGL version 3.0 and above"); - return GL_FALSE; + if (wndconfig->glMajor < 1 || wndconfig->glMinor < 0) + { + // OpenGL ES 1.0 is the smallest valid version + _glfwSetError(GLFW_INVALID_VALUE, + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: 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, + "glfwOpenWindow: Forward compatibility is not " + "supported by OpenGL ES"); + return GL_FALSE; + } } if (wndconfig->glRobustness) @@ -347,7 +383,8 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig) wndconfig->glRobustness != GLFW_OPENGL_LOSE_CONTEXT_ON_RESET) { _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: Invalid OpenGL robustness mode requested"); + "glfwOpenWindow: Invalid OpenGL robustness mode " + "requested"); return GL_FALSE; } } @@ -363,6 +400,8 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig) GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig) { + window->clientAPI = wndconfig->clientAPI; + parseGLVersion(&window->glMajor, &window->glMinor, &window->glRevision); // Read back forward-compatibility flag @@ -433,7 +472,7 @@ GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig) //======================================================================== -// Check if a string can be found in an OpenGL extension string +// Check if a string can be found in a client API extension string //======================================================================== int _glfwStringInExtensionString(const char* string, @@ -472,7 +511,7 @@ int _glfwStringInExtensionString(const char* string, ////////////////////////////////////////////////////////////////////////// //======================================================================== -// Make the OpenGL context associated with the specified window current +// Make the context associated with the specified window current //======================================================================== GLFWAPI void glfwMakeContextCurrent(GLFWwindow handle) @@ -494,7 +533,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow handle) //======================================================================== -// Returns the window whose OpenGL context is current +// Returns the window whose context is current //======================================================================== GLFWAPI GLFWwindow glfwGetCurrentContext(void) @@ -554,7 +593,7 @@ GLFWAPI void glfwSwapInterval(int interval) //======================================================================== -// Check if an OpenGL extension is available at runtime +// Check if a client API extension is available at runtime //======================================================================== GLFWAPI int glfwExtensionSupported(const char* extension) @@ -619,8 +658,8 @@ GLFWAPI int glfwExtensionSupported(const char* extension) //======================================================================== -// Get the function pointer to an OpenGL function. -// This function can be used to get access to extended OpenGL functions. +// Get the function pointer to a client API function +// This can be used to get access to client API extension functions //======================================================================== GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) @@ -642,7 +681,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) //======================================================================== -// Copies the specified OpenGL state categories from src to dst +// Copies the specified context state categories from src to dst //======================================================================== GLFWAPI void glfwCopyContext(GLFWwindow hsrc, GLFWwindow hdst, unsigned long mask) diff --git a/src/win32_window.c b/src/win32_window.c index 935767ce..c2870c4e 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -336,6 +336,21 @@ static GLboolean createContext(_GLFWwindow* window, 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) { int flags = 0; @@ -365,21 +380,10 @@ static GLboolean createContext(_GLFWwindow* window, return GL_FALSE; } - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !window->WGL.EXT_create_context_es2_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/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) flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) 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++] = flags; diff --git a/src/window.c b/src/window.c index f8939e37..41729a78 100644 --- a/src/window.c +++ b/src/window.c @@ -97,7 +97,8 @@ void _glfwSetDefaultWindowHints(void) { 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.glMinor = 0; @@ -251,6 +252,7 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, wndconfig.title = title; wndconfig.refreshRate = Max(_glfwLibrary.hints.refreshRate, 0); wndconfig.resizable = _glfwLibrary.hints.resizable ? GL_TRUE : GL_FALSE; + wndconfig.clientAPI = _glfwLibrary.hints.clientAPI; wndconfig.glMajor = _glfwLibrary.hints.glMajor; wndconfig.glMinor = _glfwLibrary.hints.glMinor; wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE; @@ -429,6 +431,9 @@ GLFWAPI void glfwOpenWindowHint(int target, int hint) case GLFW_FSAA_SAMPLES: _glfwLibrary.hints.samples = hint; break; + case GLFW_CLIENT_API: + _glfwLibrary.hints.clientAPI = hint; + break; case GLFW_OPENGL_VERSION_MAJOR: _glfwLibrary.hints.glMajor = hint; break; @@ -714,6 +719,8 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param) return window->resizable; case GLFW_FSAA_SAMPLES: return window->samples; + case GLFW_CLIENT_API: + return window->clientAPI; case GLFW_OPENGL_VERSION_MAJOR: return window->glMajor; case GLFW_OPENGL_VERSION_MINOR: diff --git a/src/x11_egl_opengl.c b/src/x11_egl_opengl.c index f52b962c..4db794ba 100644 --- a/src/x11_egl_opengl.c +++ b/src/x11_egl_opengl.c @@ -110,18 +110,23 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, continue; } - if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT) && - !(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) + if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { - // Only consider OpenGL ES context - continue; + if (wndconfig->glMajor == 1) + { + if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) + continue; + } + else + { + if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) + continue; + } } - - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) + else if (wndconfig->clientAPI == GLFW_OPENGL_API) { - // User requested only OpenGL ES 2.0 context - continue; + if (!(getConfigAttrib(configs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) + continue; } f->redBits = getConfigAttrib(configs[i], EGL_RED_SIZE); @@ -248,19 +253,17 @@ static int createContext(_GLFWwindow* window, } index = 0; - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) + + if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { - setEGLattrib(attribs, index, EGL_CONTEXT_CLIENT_VERSION, 2); + eglBindAPI(EGL_OPENGL_ES_API); + setEGLattrib(attribs, index, EGL_CONTEXT_CLIENT_VERSION, wndconfig->glMajor); } else - { - setEGLattrib(attribs, index, EGL_CONTEXT_CLIENT_VERSION, 1); - } + eglBindAPI(EGL_OPENGL_API); setEGLattrib(attribs, index, EGL_NONE, EGL_NONE); - eglBindAPI(EGL_OPENGL_ES_API); - window->EGL.context = eglCreateContext(_glfwLibrary.EGL.display, config, share, attribs); diff --git a/src/x11_glx_opengl.c b/src/x11_glx_opengl.c index edcd69b6..da06d65f 100644 --- a/src/x11_glx_opengl.c +++ b/src/x11_glx_opengl.c @@ -346,6 +346,22 @@ static int createContext(_GLFWwindow* window, 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, + "X11/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) { int flags = 0; @@ -374,21 +390,10 @@ static int createContext(_GLFWwindow* window, return GL_FALSE; } - if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && - !_glfwLibrary.GLX.EXT_create_context_es2_profile) - { - _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/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) flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) 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); } diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 45cb8616..28264179 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -42,17 +42,20 @@ #define strcasecmp(x, y) _stricmp(x, y) #endif +#define API_OPENGL "gl" +#define API_OPENGL_ES "es" + #define PROFILE_NAME_CORE "core" #define PROFILE_NAME_COMPAT "compat" -#define PROFILE_NAME_ES2 "es2" #define STRATEGY_NAME_NONE "none" #define STRATEGY_NAME_LOSE "lose" static void usage(void) { - printf("Usage: glfwinfo [-h] [-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("Usage: glfwinfo [-h] [-a API] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE] [-r STRATEGY]\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"); } @@ -61,14 +64,22 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s in %s\n", glfwErrorString(error), description); } +static const char* get_client_api_name(int api) +{ + if (api == GLFW_OPENGL_API) + return "OpenGL"; + else if (api == GLFW_OPENGL_ES_API) + return "OpenGL ES"; + + return "Unknown API"; +} + static const char* get_glfw_profile_name(int profile) { if (profile == GLFW_OPENGL_COMPAT_PROFILE) - return PROFILE_NAME_COMPAT; + return "compatibility"; else if (profile == GLFW_OPENGL_CORE_PROFILE) - return PROFILE_NAME_CORE; - else if (profile == GLFW_OPENGL_ES2_PROFILE) - return PROFILE_NAME_ES2; + return "core"; return "unknown"; } @@ -76,22 +87,22 @@ static const char* get_glfw_profile_name(int profile) static const char* get_profile_name(GLint mask) { if (mask & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) - return PROFILE_NAME_COMPAT; + return "compatibility"; if (mask & GL_CONTEXT_CORE_PROFILE_BIT) - return PROFILE_NAME_CORE; + return "core"; return "unknown"; } -static void list_extensions(int major, int minor) +static void list_extensions(int api, int major, int minor) { int i; GLint count; 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"); if (!glGetStringi) @@ -121,15 +132,25 @@ static void list_extensions(int major, int minor) 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; GLint flags, mask; GLFWwindow window; - while ((ch = getopt(argc, argv, "dfhlm:n:p:r:")) != -1) + while ((ch = getopt(argc, argv, "a:dfhlm:n:p:r:")) != -1) { 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': debug = GL_TRUE; break; @@ -153,8 +174,6 @@ int main(int argc, char** argv) profile = GLFW_OPENGL_CORE_PROFILE; else if (strcasecmp(optarg, PROFILE_NAME_COMPAT) == 0) profile = GLFW_OPENGL_COMPAT_PROFILE; - else if (strcasecmp(optarg, PROFILE_NAME_ES2) == 0) - profile = GLFW_OPENGL_ES2_PROFILE; else { usage(); @@ -195,6 +214,9 @@ int main(int argc, char** argv) glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, minor); } + if (api != 0) + glfwOpenWindowHint(GLFW_CLIENT_API, api); + if (debug) glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); @@ -234,53 +256,70 @@ int main(int argc, char** argv) printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); - // Report OpenGL version - - printf("OpenGL context version string: \"%s\"\n", glGetString(GL_VERSION)); + // Report client API version + api = glfwGetWindowParam(window, GLFW_CLIENT_API); major = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MAJOR); minor = glfwGetWindowParam(window, GLFW_OPENGL_VERSION_MINOR); 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); - printf("OpenGL context flags:"); + if (major >= 3) + { + glGetIntegerv(GL_CONTEXT_FLAGS, &flags); + printf("%s context flags:", get_client_api_name(api)); - if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) - puts(" forward-compatible"); - else - puts(" none"); + if (flags & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT) + puts(" forward-compatible"); + else + puts(" none"); - printf("OpenGL forward-compatible flag parsed by GLFW: %s\n", - glfwGetWindowParam(window, GLFW_OPENGL_FORWARD_COMPAT) ? "true" : "false"); + printf("%s forward-compatible flag parsed by GLFW: %s\n", + get_client_api_name(api), + glfwGetWindowParam(window, GLFW_OPENGL_FORWARD_COMPAT) ? "true" : "false"); + } + + if (major > 3 || (major == 3 && minor >= 2)) + { + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); + printf("%s profile mask: %s (0x%08x)\n", + get_client_api_name(api), + get_profile_name(mask), mask); + + printf("%s profile parsed by GLFW: %s\n", + get_client_api_name(api), + get_glfw_profile_name(glfwGetWindowParam(window, GLFW_OPENGL_PROFILE))); + } } - if (major > 3 || (major == 3 && minor >= 2)) - { - glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &mask); - printf("OpenGL profile mask: %s (0x%08x)\n", get_profile_name(mask), mask); - - printf("OpenGL profile parsed by GLFW: %s\n", - get_glfw_profile_name(glfwGetWindowParam(window, GLFW_OPENGL_PROFILE))); - } - - printf("OpenGL context renderer string: \"%s\"\n", glGetString(GL_RENDERER)); - printf("OpenGL context vendor string: \"%s\"\n", glGetString(GL_VENDOR)); + printf("%s context renderer string: \"%s\"\n", + get_client_api_name(api), + glGetString(GL_RENDERER)); + printf("%s context vendor string: \"%s\"\n", + get_client_api_name(api), + glGetString(GL_VENDOR)); 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)); } - // Report OpenGL extensions + // Report client API extensions if (list) - list_extensions(major, minor); + list_extensions(api, major, minor); glfwTerminate(); exit(EXIT_SUCCESS);