// Create the OpenGL or OpenGL ES context // int _glfwCreateContext(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { int attribs[40]; EGLConfig config; EGLContext share = NULL; if (ctxconfig->share) share = ctxconfig->share->egl.context; if (!chooseFBConfigs(ctxconfig, fbconfig, &config)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to find a suitable EGLConfig"); return GL_FALSE; } #if defined(_GLFW_X11) // Retrieve the visual corresponding to the chosen EGL config { EGLint count = 0; int mask; EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0; XVisualInfo info; eglGetConfigAttrib(_glfw.egl.display, config, EGL_NATIVE_VISUAL_ID, &visualID); info.screen = _glfw.x11.screen; mask = VisualScreenMask; if (visualID) { // The X window visual must match the EGL config info.visualid = visualID; mask |= VisualIDMask; } else { // some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID // attribute, so attempt to find the closest match. eglGetConfigAttrib(_glfw.egl.display, config, EGL_RED_SIZE, &redBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_GREEN_SIZE, &greenBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_BLUE_SIZE, &blueBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_ALPHA_SIZE, &alphaBits); info.depth = redBits + greenBits + blueBits + alphaBits; mask |= VisualDepthMask; } window->egl.visual = XGetVisualInfo(_glfw.x11.display, mask, &info, &count); if (!window->egl.visual) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to retrieve visual for EGLConfig"); return GL_FALSE; } } #endif // _GLFW_X11 if (ctxconfig->api == GLFW_OPENGL_ES_API) { if (!eglBindAPI(EGL_OPENGL_ES_API)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL ES: %s", getErrorString(eglGetError())); return GL_FALSE; } } else { if (!eglBindAPI(EGL_OPENGL_API)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL: %s", getErrorString(eglGetError())); return GL_FALSE; } } if (_glfw.egl.KHR_create_context) { int index = 0, mask = 0, flags = 0, strategy = 0; if (ctxconfig->api == GLFW_OPENGL_API) { if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; if (ctxconfig->forward) flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; } if (ctxconfig->debug) flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; if (ctxconfig->robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) strategy = EGL_NO_RESET_NOTIFICATION_KHR; else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) strategy = EGL_LOSE_CONTEXT_ON_RESET_KHR; flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; } if (ctxconfig->major != 1 || ctxconfig->minor != 0) { setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); } if (mask) setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); if (flags) setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags); if (strategy) setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, strategy); setEGLattrib(EGL_NONE, EGL_NONE); } else { int index = 0; if (ctxconfig->api == GLFW_OPENGL_ES_API) setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_NONE, EGL_NONE); } // Context release behaviors (GL_KHR_context_flush_control) are not yet // supported on EGL but are not a hard constraint, so ignore and continue window->egl.context = eglCreateContext(_glfw.egl.display, config, share, attribs); if (window->egl.context == EGL_NO_CONTEXT) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: Failed to create context: %s", getErrorString(eglGetError())); return GL_FALSE; } window->egl.config = config; return GL_TRUE; }
static int createContext(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, EGLint fbconfigID) { int attribs[40]; EGLint count; EGLConfig config; EGLContext share = NULL; if (wndconfig->share) share = wndconfig->share->egl.context; // Retrieve the previously selected EGLConfig { int index = 0; setEGLattrib(EGL_CONFIG_ID, fbconfigID); setEGLattrib(EGL_NONE, EGL_NONE); eglChooseConfig(_glfw.egl.display, attribs, &config, 1, &count); if (!count) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to retrieve the selected EGLConfig"); return GL_FALSE; } } #if defined(_GLFW_X11) // Retrieve the visual corresponding to the chosen EGL config { int mask; EGLint redBits, greenBits, blueBits, alphaBits, visualID = 0; XVisualInfo info; eglGetConfigAttrib(_glfw.egl.display, config, EGL_NATIVE_VISUAL_ID, &visualID); info.screen = _glfw.x11.screen; mask = VisualScreenMask; if (visualID) { // The X window visual must match the EGL config info.visualid = visualID; mask |= VisualIDMask; } else { // some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID // attribute, so attempt to find the closest match. eglGetConfigAttrib(_glfw.egl.display, config, EGL_RED_SIZE, &redBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_GREEN_SIZE, &greenBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_BLUE_SIZE, &blueBits); eglGetConfigAttrib(_glfw.egl.display, config, EGL_ALPHA_SIZE, &alphaBits); info.depth = redBits + greenBits + blueBits + alphaBits; mask |= VisualDepthMask; } window->egl.visual = XGetVisualInfo(_glfw.x11.display, mask, &info, &count); if (window->egl.visual == NULL) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to retrieve visual for EGLConfig"); return GL_FALSE; } } #endif // _GLFW_X11 if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) { if (!eglBindAPI(EGL_OPENGL_ES_API)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: OpenGL ES is not supported"); return GL_FALSE; } } else { if (!eglBindAPI(EGL_OPENGL_API)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: OpenGL is not supported"); return GL_FALSE; } } if (_glfw.egl.KHR_create_context) { int index = 0, mask = 0, flags = 0, strategy = 0; if (wndconfig->clientAPI == GLFW_OPENGL_API) { if (wndconfig->glProfile == GLFW_OPENGL_CORE_PROFILE) mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; else if (wndconfig->glProfile == GLFW_OPENGL_COMPAT_PROFILE) mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; if (wndconfig->glForward) flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; if (wndconfig->glDebug) flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; } if (wndconfig->glRobustness != GLFW_NO_ROBUSTNESS) { if (wndconfig->glRobustness == GLFW_NO_RESET_NOTIFICATION) strategy = EGL_NO_RESET_NOTIFICATION_KHR; else if (wndconfig->glRobustness == GLFW_LOSE_CONTEXT_ON_RESET) strategy = EGL_LOSE_CONTEXT_ON_RESET_KHR; flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; } if (wndconfig->glMajor != 1 || wndconfig->glMinor != 0) { setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, wndconfig->glMajor); setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, wndconfig->glMinor); } if (mask) setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); if (flags) setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags); if (strategy) setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, strategy); setEGLattrib(EGL_NONE, EGL_NONE); } else { int index = 0; if (wndconfig->clientAPI == GLFW_OPENGL_ES_API) setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, wndconfig->glMajor); setEGLattrib(EGL_NONE, EGL_NONE); } window->egl.context = eglCreateContext(_glfw.egl.display, config, share, attribs); if (window->egl.context == EGL_NO_CONTEXT) { // TODO: Handle all the various error codes here _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to create context"); return GL_FALSE; } window->egl.config = config; return GL_TRUE; }
// Create the OpenGL or OpenGL ES context // GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { EGLint attribs[40]; EGLConfig config; EGLContext share = NULL; if (!_glfw.egl.display) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available"); return GLFW_FALSE; } if (ctxconfig->share) share = ctxconfig->share->context.egl.handle; if (!chooseFBConfigs(ctxconfig, fbconfig, &config)) { _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Failed to find a suitable EGLConfig"); return GLFW_FALSE; } if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (!eglBindAPI(EGL_OPENGL_ES_API)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL ES: %s", getErrorString(eglGetError())); return GLFW_FALSE; } } else { if (!eglBindAPI(EGL_OPENGL_API)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL: %s", getErrorString(eglGetError())); return GLFW_FALSE; } } if (_glfw.egl.KHR_create_context) { int index = 0, mask = 0, flags = 0; if (ctxconfig->client == GLFW_OPENGL_API) { if (ctxconfig->forward) flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; if (_glfw.egl.KHR_create_context_no_error) { if (ctxconfig->noerror) flags |= EGL_CONTEXT_OPENGL_NO_ERROR_KHR; } } if (ctxconfig->debug) flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; if (ctxconfig->robustness) { if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION) { setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_NO_RESET_NOTIFICATION_KHR); } else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET) { setEGLattrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_LOSE_CONTEXT_ON_RESET_KHR); } flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; } if (ctxconfig->major != 1 || ctxconfig->minor != 0) { setEGLattrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); setEGLattrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); } if (mask) setEGLattrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); if (flags) setEGLattrib(EGL_CONTEXT_FLAGS_KHR, flags); setEGLattrib(EGL_NONE, EGL_NONE); } else { int index = 0; if (ctxconfig->client == GLFW_OPENGL_ES_API) setEGLattrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig->major); setEGLattrib(EGL_NONE, EGL_NONE); } // Context release behaviors (GL_KHR_context_flush_control) are not yet // supported on EGL but are not a hard constraint, so ignore and continue window->context.egl.handle = eglCreateContext(_glfw.egl.display, config, share, attribs); if (window->context.egl.handle == EGL_NO_CONTEXT) { _glfwInputError(GLFW_VERSION_UNAVAILABLE, "EGL: Failed to create context: %s", getErrorString(eglGetError())); return GLFW_FALSE; } // Set up attributes for surface creation { int index = 0; if (fbconfig->sRGB) { if (_glfw.egl.KHR_gl_colorspace) { setEGLattrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); } } setEGLattrib(EGL_NONE, EGL_NONE); } // The surface for EGLDevice backened is created in _glfwPlatformCreateWindow // #if !defined (_GLFW_EGLDEVICE) window->context.egl.surface = eglCreateWindowSurface(_glfw.egl.display, config, _GLFW_EGL_NATIVE_WINDOW, attribs); if (window->context.egl.surface == EGL_NO_SURFACE) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to create window surface: %s", getErrorString(eglGetError())); return GLFW_FALSE; } #endif window->context.egl.config = config; // Load the appropriate client library { int i; const char** sonames; const char* es1sonames[] = { #if defined(_GLFW_WIN32) "GLESv1_CM.dll", "libGLES_CM.dll", #elif defined(_GLFW_COCOA) "libGLESv1_CM.dylib", #else "libGLESv1_CM.so.1", "libGLES_CM.so.1", #endif NULL }; const char* es2sonames[] = { #if defined(_GLFW_WIN32) "GLESv2.dll", "libGLESv2.dll", #elif defined(_GLFW_COCOA) "libGLESv2.dylib", #else "libGLESv2.so.2", #endif NULL }; const char* glsonames[] = { #if defined(_GLFW_WIN32) #elif defined(_GLFW_COCOA) #else "libGL.so.1", #endif NULL }; if (ctxconfig->client == GLFW_OPENGL_ES_API) { if (ctxconfig->major == 1) sonames = es1sonames; else sonames = es2sonames; } else sonames = glsonames; for (i = 0; sonames[i]; i++) { window->context.egl.client = _glfw_dlopen(sonames[i]); if (window->context.egl.client) break; } if (!window->context.egl.client) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to load client library"); return GLFW_FALSE; } } window->context.makeCurrent = makeContextCurrent; window->context.swapBuffers = swapBuffers; window->context.swapInterval = swapInterval; window->context.extensionSupported = extensionSupported; window->context.getProcAddress = getProcAddress; window->context.destroy = destroyContext; return GLFW_TRUE; }