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();