static void makeContextCurrentEGL(_GLFWwindow* window) { if (window) { if (!eglMakeCurrent(_glfw.egl.display, window->context.egl.surface, window->context.egl.surface, window->context.egl.handle)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to make context current: %s", getEGLErrorString(eglGetError())); return; } } else { if (!eglMakeCurrent(_glfw.egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: Failed to clear current context: %s", getEGLErrorString(eglGetError())); return; } } _glfwPlatformSetCurrentContext(window); }
static void logEGLError(const char *msg) { EGLint error = eglGetError(); const char *errorStr = getEGLErrorString(error); ERROR( "%s: %s (%x)", msg, errorStr, error ); }
// 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 (!chooseEGLConfig(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", getEGLErrorString(eglGetError())); return GLFW_FALSE; } } else { if (!eglBindAPI(EGL_OPENGL_API)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to bind OpenGL: %s", getEGLErrorString(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", getEGLErrorString(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); } 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", getEGLErrorString(eglGetError())); return GLFW_FALSE; } 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 = makeContextCurrentEGL; window->context.swapBuffers = swapBuffersEGL; window->context.swapInterval = swapIntervalEGL; window->context.extensionSupported = extensionSupportedEGL; window->context.getProcAddress = getProcAddressEGL; window->context.destroy = destroyContextEGL; return GLFW_TRUE; }
// Initialize EGL // GLFWbool _glfwInitEGL(void) { int i; const char* sonames[] = { #if defined(_GLFW_WIN32) "libEGL.dll", "EGL.dll", #elif defined(_GLFW_COCOA) "libEGL.dylib", #else "libEGL.so.1", #endif NULL }; for (i = 0; sonames[i]; i++) { _glfw.egl.handle = _glfw_dlopen(sonames[i]); if (_glfw.egl.handle) break; } if (!_glfw.egl.handle) return GLFW_FALSE; _glfw.egl.GetConfigAttrib = (PFNEGLGETCONFIGATTRIBPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); _glfw.egl.GetConfigs = (PFNEGLGETCONFIGSPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); _glfw.egl.GetDisplay = (PFNEGLGETDISPLAYPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); _glfw.egl.GetError = (PFNEGLGETERRORPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetError"); _glfw.egl.Initialize = (PFNEGLINITIALIZEPROC) _glfw_dlsym(_glfw.egl.handle, "eglInitialize"); _glfw.egl.Terminate = (PFNEGLTERMINATEPROC) _glfw_dlsym(_glfw.egl.handle, "eglTerminate"); _glfw.egl.BindAPI = (PFNEGLBINDAPIPROC) _glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); _glfw.egl.CreateContext = (PFNEGLCREATECONTEXTPROC) _glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); _glfw.egl.DestroySurface = (PFNEGLDESTROYSURFACEPROC) _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface"); _glfw.egl.DestroyContext = (PFNEGLDESTROYCONTEXTPROC) _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); _glfw.egl.CreateWindowSurface = (PFNEGLCREATEWINDOWSURFACEPROC) _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); _glfw.egl.MakeCurrent = (PFNEGLMAKECURRENTPROC) _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); _glfw.egl.SwapBuffers = (PFNEGLSWAPBUFFERSPROC) _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers"); _glfw.egl.SwapInterval = (PFNEGLSWAPINTERVALPROC) _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval"); _glfw.egl.QueryString = (PFNEGLQUERYSTRINGPROC) _glfw_dlsym(_glfw.egl.handle, "eglQueryString"); _glfw.egl.GetProcAddress = (PFNEGLGETPROCADDRESSPROC) _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress"); _glfw.egl.display = eglGetDisplay(_GLFW_EGL_NATIVE_DISPLAY); if (_glfw.egl.display == EGL_NO_DISPLAY) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to get EGL display: %s", getEGLErrorString(eglGetError())); _glfwTerminateEGL(); return GLFW_FALSE; } if (!eglInitialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) { _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Failed to initialize EGL: %s", getEGLErrorString(eglGetError())); _glfwTerminateEGL(); return GLFW_FALSE; } _glfw.egl.KHR_create_context = extensionSupportedEGL("EGL_KHR_create_context"); _glfw.egl.KHR_create_context_no_error = extensionSupportedEGL("EGL_KHR_create_context_no_error"); _glfw.egl.KHR_gl_colorspace = extensionSupportedEGL("EGL_KHR_gl_colorspace"); return GLFW_TRUE; }