diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 4a12955d..01fef48b 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -338,6 +338,7 @@ extern "C" { /* GLFW_OPENGL_PROFILE tokens */ #define GLFW_OPENGL_CORE_PROFILE 0x00050001 #define GLFW_OPENGL_COMPAT_PROFILE 0x00050002 +#define GLFW_OPENGL_ES2_PROFILE 0x00050004 /* glfwEnable/glfwDisable tokens */ #define GLFW_MOUSE_CURSOR 0x00030001 diff --git a/readme.html b/readme.html index 24f6d203..7ac687ad 100644 --- a/readme.html +++ b/readme.html @@ -271,6 +271,7 @@ version of GLFW.

  • Added glfwSetWindowFocusCallback function and GLFWwindowfocusfun type for receiving window focus events
  • Added glfwSetWindowIconifyCallback function and GLFWwindowiconifyfun type for receiving window iconification events
  • Added glfwGetCurrentWindow function for retrieving the window whose OpenGL context is current
  • +
  • Added GLFW_OPENGL_ES2_PROFILE profile for creating OpenGL ES 2.0 contexts
  • Added windows simple multi-window test program
  • Added sharing simple OpenGL object sharing test program
  • Added a parameter to glfwOpenWindow for specifying a context the new window's context will share objects with
  • diff --git a/src/glext.c b/src/glext.c index f8f7fe03..ff6f607c 100644 --- a/src/glext.c +++ b/src/glext.c @@ -51,12 +51,21 @@ void _glfwParseGLVersion(int* major, int* minor, int* rev) GLuint _major, _minor = 0, _rev = 0; const GLubyte* version; const GLubyte* ptr; + const char* glesPrefix = "OpenGL ES "; // Get OpenGL version string version = glGetString(GL_VERSION); if (!version) return; + if (strncmp(version, glesPrefix, strlen(glesPrefix)) == 0) + { + // The version string on OpenGL ES has a prefix before the version + // number, so we skip past it and then continue as normal + + version += strlen(glesPrefix); + } + // Parse string ptr = version; for (_major = 0; *ptr >= '0' && *ptr <= '9'; ptr++) diff --git a/src/win32/platform.h b/src/win32/platform.h index fe75c2c8..144ff75a 100644 --- a/src/win32/platform.h +++ b/src/win32/platform.h @@ -241,6 +241,8 @@ typedef struct _GLFWcontextWGL GLboolean has_WGL_ARB_multisample; GLboolean has_WGL_ARB_pixel_format; GLboolean has_WGL_ARB_create_context; + GLboolean has_WGL_ARB_create_context_profile; + GLboolean has_WGL_EXT_create_context_es2_profile; } _GLFWcontextWGL; diff --git a/src/win32/win32_window.c b/src/win32/win32_window.c index 07ae49d1..99c0cc49 100644 --- a/src/win32/win32_window.c +++ b/src/win32/win32_window.c @@ -316,7 +316,7 @@ static GLboolean createContext(_GLFWwindow* window, int pixelFormat) { PIXELFORMATDESCRIPTOR pfd; - int flags, i = 0, attribs[7]; + int i = 0, attribs[7]; HGLRC share = NULL; if (wndconfig->share) @@ -350,7 +350,7 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glForward || wndconfig->glDebug) { - flags = 0; + int flags = 0; if (wndconfig->glForward) flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; @@ -364,10 +364,27 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glProfile) { + int flags = 0; + + if (!window->WGL.has_WGL_ARB_create_context_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE); + return GL_FALSE; + } + + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !window->WGL.has_WGL_EXT_create_context_es2_profile) + { + _glfwSetError(GLFW_VERSION_UNAVAILABLE); + return GL_FALSE; + } + if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) flags = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - else + 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; @@ -1008,6 +1025,7 @@ static void initWGLExtensions(_GLFWwindow* window) window->WGL.has_WGL_ARB_pixel_format = GL_FALSE; window->WGL.has_WGL_ARB_multisample = GL_FALSE; window->WGL.has_WGL_ARB_create_context = GL_FALSE; + window->WGL.has_WGL_ARB_create_context_profile = GL_FALSE; window->WGL.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) wglGetProcAddress("wglGetExtensionsStringEXT"); @@ -1031,6 +1049,19 @@ static void initWGLExtensions(_GLFWwindow* window) window->WGL.has_WGL_ARB_create_context = GL_TRUE; } + if (window->WGL.has_WGL_ARB_create_context) + { + if (_glfwPlatformExtensionSupported("WGL_ARB_create_context_profile")) + window->WGL.has_WGL_ARB_create_context_profile = GL_TRUE; + } + + if (window->WGL.has_WGL_ARB_create_context && + window->WGL.has_WGL_ARB_create_context_profile) + { + if (_glfwPlatformExtensionSupported("WGL_EXT_create_context_es2_profile")) + window->WGL.has_WGL_EXT_create_context_es2_profile = GL_TRUE; + } + if (_glfwPlatformExtensionSupported("WGL_EXT_swap_control")) { window->WGL.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) diff --git a/src/window.c b/src/window.c index 8b4a7903..e9135b50 100644 --- a/src/window.c +++ b/src/window.c @@ -490,13 +490,30 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, // For now, let everything else through } - if (wndconfig.glProfile && - (wndconfig.glMajor < 3 || (wndconfig.glMajor == 3 && wndconfig.glMinor < 2))) + if (wndconfig.glProfile == GLFW_OPENGL_ES2_PROFILE) { - // Context profiles are only defined for OpenGL version 3.2 and above - glfwCloseWindow(window); - _glfwSetError(GLFW_INVALID_VALUE); - return GL_FALSE; + if (wndconfig.glMajor != 2 || wndconfig.glMinor < 0) + { + // The OpenGL ES 2.0 profile is currently only defined for version + // 2.0, but for compatibility with future updates to OpenGL ES, we + // allow everything 2.x and let the driver report invalid versions + + glfwCloseWindow(window); + _glfwSetError(GLFW_INVALID_VALUE); + return GL_FALSE; + } + } + else if (wndconfig.glProfile) + { + if (wndconfig.glMajor < 3 || (wndconfig.glMajor == 3 && wndconfig.glMinor < 2)) + { + // Desktop OpenGL context profiles are only defined for version 3.2 + // and above + + glfwCloseWindow(window); + _glfwSetError(GLFW_INVALID_VALUE); + return GL_FALSE; + } } if (wndconfig.glForward && wndconfig.glMajor < 3) diff --git a/src/x11/platform.h b/src/x11/platform.h index a3a6e428..57b10447 100644 --- a/src/x11/platform.h +++ b/src/x11/platform.h @@ -110,6 +110,7 @@ typedef struct _GLFWcontextGLX GLboolean has_GLX_ARB_multisample; GLboolean has_GLX_ARB_create_context; GLboolean has_GLX_ARB_create_context_profile; + GLboolean has_GLX_EXT_create_context_es2_profile; } _GLFWcontextGLX; diff --git a/src/x11/x11_window.c b/src/x11/x11_window.c index 7728eb49..e716129d 100644 --- a/src/x11/x11_window.c +++ b/src/x11/x11_window.c @@ -490,7 +490,7 @@ static int createContext(_GLFWwindow* window, GLXFBConfigID fbconfigID) { int attribs[40]; - int flags, dummy, index; + int dummy, index; GLXFBConfig* fbconfig; GLXContext share = NULL; @@ -562,7 +562,7 @@ static int createContext(_GLFWwindow* window, if (wndconfig->glForward || wndconfig->glDebug) { - flags = 0; + int flags = 0; if (wndconfig->glForward) flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; @@ -575,6 +575,8 @@ static int createContext(_GLFWwindow* window, if (wndconfig->glProfile) { + int flags = 0; + if (!window->GLX.has_GLX_ARB_create_context_profile) { fprintf(stderr, "OpenGL profile requested but GLX_ARB_create_context_profile " @@ -583,10 +585,21 @@ static int createContext(_GLFWwindow* window, return GL_FALSE; } + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !window->GLX.has_GLX_EXT_create_context_es2_profile) + { + fprintf(stderr, "OpenGL ES2 profile requested but " + "GLX_EXT_create_context_es2_profile is unavailable\n"); + _glfwSetError(GLFW_VERSION_UNAVAILABLE); + return GL_FALSE; + } + if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) flags = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - else + 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); } @@ -695,8 +708,18 @@ static void initGLXExtensions(_GLFWwindow* window) window->GLX.has_GLX_ARB_create_context = GL_TRUE; } - if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) - window->GLX.has_GLX_ARB_create_context_profile = GL_TRUE; + if (window->GLX.has_GLX_ARB_create_context) + { + if (_glfwPlatformExtensionSupported("GLX_ARB_create_context_profile")) + window->GLX.has_GLX_ARB_create_context_profile = GL_TRUE; + } + + if (window->GLX.has_GLX_ARB_create_context && + window->GLX.has_GLX_ARB_create_context_profile) + { + if (_glfwPlatformExtensionSupported("GLX_EXT_create_context_es2_profile")) + window->GLX.has_GLX_EXT_create_context_es2_profile = GL_TRUE; + } } diff --git a/tests/version.c b/tests/version.c index 0b0dc7e9..5ed9ae05 100644 --- a/tests/version.c +++ b/tests/version.c @@ -45,7 +45,7 @@ static void usage(void) { printf("Usage: version [-h] [-m MAJOR] [-n MINOR] [-d] [-l] [-f] [-p PROFILE]\n"); - printf("available profiles: core compat\n"); + printf("available profiles: core compat es2\n"); } static const char* get_glfw_profile_name(int profile) @@ -54,6 +54,8 @@ static const char* get_glfw_profile_name(int profile) return "compatibility"; else if (profile == GLFW_OPENGL_CORE_PROFILE) return "core"; + else if (profile == GLFW_OPENGL_ES2_PROFILE) + return "es2"; return "unknown"; } @@ -141,6 +143,8 @@ int main(int argc, char** argv) profile = GLFW_OPENGL_CORE_PROFILE; else if (strcasecmp(optarg, "compat") == 0) profile = GLFW_OPENGL_COMPAT_PROFILE; + else if (strcasecmp(optarg, "es2") == 0) + profile = GLFW_OPENGL_ES2_PROFILE; else { usage();