diff --git a/CMake/modules/FindEGL.cmake b/CMake/modules/FindEGL.cmake new file mode 100644 index 00000000..0d5765ed --- /dev/null +++ b/CMake/modules/FindEGL.cmake @@ -0,0 +1,15 @@ +# Find EGL +# +# EGL_INCLUDE_DIR +# EGL_LIBRARY +# EGL_FOUND + +FIND_PATH(EGL_INCLUDE_DIR NAMES EGL/egl.h) + +SET(EGL_NAMES ${EGL_NAMES} egl EGL) +FIND_LIBRARY(EGL_LIBRARY NAMES ${EGL_NAMES}) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR) + +MARK_AS_ADVANCED(EGL_INCLUDE_DIR EGL_LIBRARY) diff --git a/CMakeLists.txt b/CMakeLists.txt index 44dcb4d4..8680aec2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,14 @@ set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON) option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON) option(BUILD_SHARED_LIBS "Build shared libraries" OFF) +option(GLFW_USE_EGL "Build for EGL and OpenGL ES platform (Currently only X11)" OFF) -find_package(OpenGL REQUIRED) +if (GLFW_USE_EGL) + SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake/modules) + find_package(EGL REQUIRED) +else() + find_package(OpenGL REQUIRED) +endif() #-------------------------------------------------------------------- # Enable all warnings on GCC, regardless of OS @@ -39,8 +45,17 @@ elseif (UNIX AND APPLE) set(_GLFW_COCOA_NSGL 1) message(STATUS "Building GLFW for Cocoa and NSOpenGL on Mac OS X") elseif (UNIX AND NOT APPLE) - set(_GLFW_X11_GLX 1) - message(STATUS "Building GLFW for X11 and GLX on a Unix-like system") + set(_GLFW_X11 1) + if (GLFW_USE_EGL) + set(_GLFW_X11_EGL 1) + set(GLFW_BUILD_EXAMPLES 0) + set(GLFW_BUILD_TESTS 0) + message(STATUS "Building GLFW for X11 and EGL on a Unix-like system") + message(STATUS "NOTE: Examples and tests are disabled for EGL") + else() + set(_GLFW_X11_GLX 1) + message(STATUS "Building GLFW for X11 and GLX on a Unix-like system") + endif() else() message(FATAL_ERROR "No supported platform was detected") endif() @@ -62,20 +77,18 @@ if (_GLFW_WIN32_WGL) endif() #-------------------------------------------------------------------- -# Set up GLFW for Xlib and GLX on Unix-like systems with X Windows +# Set up GLFW for Xlib and GLX or EGL on Unix-like systems with X Windows #-------------------------------------------------------------------- -if (_GLFW_X11_GLX) +if (_GLFW_X11) find_package(X11 REQUIRED) - # Set up library and include paths - list(APPEND glfw_INCLUDE_DIRS ${X11_X11_INCLUDE_PATH} ${OPENGL_INCLUDE_DIR}) - list(APPEND glfw_LIBRARIES ${X11_X11_LIB} ${OPENGL_gl_LIBRARY}) - - set(GLFW_PKG_DEPS "gl x11") set(GLFW_PKG_LIBS "") + set(GLFW_PKG_DEPS "x11") - include(CheckFunctionExists) + # Set up library and include paths + list(APPEND glfw_INCLUDE_DIRS ${X11_X11_INCLUDE_PATH}) + list(APPEND glfw_LIBRARIES ${X11_X11_LIB}) # Check for XRandR (modern resolution switching extension) if (X11_Xrandr_FOUND) @@ -121,6 +134,25 @@ if (_GLFW_X11_GLX) set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -lm") endif() + if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + set(_GLFW_USE_LINUX_JOYSTICKS 1) + endif() + +endif() + +#-------------------------------------------------------------------- +# GLX Context +#-------------------------------------------------------------------- +if (_GLFW_X11_GLX) + + # Set up library and include paths + list(APPEND glfw_INCLUDE_DIRS${OPENGL_INCLUDE_DIR}) + list(APPEND glfw_LIBRARIES ${OPENGL_gl_LIBRARY}) + + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} gl") + + include(CheckFunctionExists) + set(CMAKE_REQUIRED_LIBRARIES ${OPENGL_gl_LIBRARY}) check_function_exists(glXGetProcAddress _GLFW_HAS_GLXGETPROCADDRESS) @@ -160,9 +192,50 @@ if (_GLFW_X11_GLX) endif() endif() - if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - set(_GLFW_USE_LINUX_JOYSTICKS 1) +endif() + +#-------------------------------------------------------------------- +# EGL Context +#-------------------------------------------------------------------- +if (_GLFW_X11_EGL) + + # Set up library and include paths + list(APPEND glfw_INCLUDE_DIRS${EGL_INCLUDE_DIR}) + list(APPEND glfw_LIBRARIES ${EGL_LIBRARY}) + + set(GLFW_PKG_DEPS "${GLFW_PKG_DEPS} egl") + + include(CheckFunctionExists) + + set(CMAKE_REQUIRED_LIBRARIES ${EGL_LIBRARY}) + + check_function_exists(eglGetProcAddress _GLFW_HAS_EGLGETPROCADDRESS) + + if (NOT _GLFW_HAS_EGLGETPROCADDRESS) + message(WARNING "No eglGetProcAddress found") + + # Check for dlopen support as a fallback + + find_library(DL_LIBRARY dl) + mark_as_advanced(DL_LIBRARY) + if (DL_LIBRARY) + set(CMAKE_REQUIRED_LIBRARIES ${DL_LIBRARY}) + else() + set(CMAKE_REQUIRED_LIBRARIES "") + endif() + + check_function_exists(dlopen _GLFW_HAS_DLOPEN) + + if (NOT _GLFW_HAS_DLOPEN) + message(FATAL_ERROR "No entry point retrieval mechanism found") + endif() + + if (DL_LIBRARY) + list(APPEND glfw_LIBRARIES ${DL_LIBRARY}) + set(GLFW_PKG_LIBS "${GLFW_PKG_LIBS} -ldl") + endif() endif() + endif() #-------------------------------------------------------------------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index add05982..3ba760f9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,6 +25,11 @@ elseif (_GLFW_X11_GLX) set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c x11_gamma.c x11_init.c x11_input.c x11_joystick.c x11_keysym2unicode.c x11_opengl.c x11_time.c x11_window.c) +elseif (_GLFW_X11_EGL) + set(glfw_HEADERS ${common_HEADERS} x11_egl_platform.h) + set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c + x11_gamma.c x11_init.c x11_input.c x11_joystick.c + x11_keysym2unicode.c x11_egl_opengl.c x11_time.c x11_window.c) endif() add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS}) diff --git a/src/config.h.in b/src/config.h.in index 01d541a2..ceb7e5a2 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -37,6 +37,8 @@ // Define this to 1 if building GLFW for X11/GLX #cmakedefine _GLFW_X11_GLX +// Define this to 1 if building GLFW for X11/EGL +#cmakedefine _GLFW_X11_EGL // Define this to 1 if building GLFW for Win32/WGL #cmakedefine _GLFW_WIN32_WGL // Define this to 1 if building GLFW for Cocoa/NSOpenGL @@ -63,6 +65,9 @@ // Define this to 1 if glXGetProcAddressEXT is available #cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT +// Define this to 1 if eglGetProcAddress is available +#cmakedefine _GLFW_HAS_EGLGETPROCADDRESS 1 + // Define this to 1 if the Linux joystick API is available #cmakedefine _GLFW_USE_LINUX_JOYSTICKS diff --git a/src/internal.h b/src/internal.h index 700b6c06..386d5858 100644 --- a/src/internal.h +++ b/src/internal.h @@ -82,6 +82,8 @@ typedef struct _GLFWlibrary _GLFWlibrary; #include "win32_platform.h" #elif defined(_GLFW_X11_GLX) #include "x11_platform.h" +#elif defined(_GLFW_X11_EGL) + #include "x11_egl_platform.h" #else #error "No supported platform selected" #endif diff --git a/src/opengl.c b/src/opengl.c index 67b5e728..59097e1e 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -32,6 +32,7 @@ #include #include +#include //======================================================================== @@ -42,13 +43,16 @@ static void parseGLVersion(int* major, int* minor, int* rev) { GLuint _major, _minor = 0, _rev = 0; const GLubyte* version; - const GLubyte* ptr; - const char* glesPrefix = "OpenGL ES "; version = glGetString(GL_VERSION); if (!version) return; +#if 0 + // Old version detection code. This doesn't work very well + const GLubyte* ptr; + const char* glesPrefix = "OpenGL ES "; + if (strncmp((const char*) version, glesPrefix, strlen(glesPrefix)) == 0) { // The version string on OpenGL ES has a prefix before the version @@ -76,6 +80,12 @@ static void parseGLVersion(int* major, int* minor, int* rev) _rev = 10 * _rev + (*ptr - '0'); } } +#endif + + // Find version from OpenGL string + for (; version && + !sscanf((char*)version, "%d.%d.%d", &_major, &_minor, &_rev); + ++version); // Store result *major = _major; diff --git a/src/x11_egl_opengl.c b/src/x11_egl_opengl.c new file mode 100644 index 00000000..e1eed5cd --- /dev/null +++ b/src/x11_egl_opengl.c @@ -0,0 +1,536 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: X11/EGL/GLES +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#include "internal.h" + +#include +#include + +// Max number of EGL configuration we handle +#define _GLFW_EGL_CONFIG_IN 15 + +//======================================================================== +// Returns the specified attribute of the specified EGLConfig +//======================================================================== + +static int getFBConfigAttrib(EGLConfig fbconfig, int attrib) +{ + int value; + eglGetConfigAttrib(_glfwLibrary.EGL.display, fbconfig, attrib, &value); + return value; +} + + +//======================================================================== +// Return a list of available and usable framebuffer configs +//======================================================================== + +static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, unsigned int* found) +{ + EGLConfig fbconfigs[_GLFW_EGL_CONFIG_IN]; + _GLFWfbconfig* result; + int i, count = 0; + + *found = 0; + + + eglGetConfigs(_glfwLibrary.EGL.display, fbconfigs, + _GLFW_EGL_CONFIG_IN, &count); + if (!count) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/EGL: No EGLConfigs returned"); + return NULL; + } + + result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); + if (!result) + { + _glfwSetError(GLFW_OUT_OF_MEMORY, + "X11/EGL: Failed to allocate _GLFWfbconfig array"); + return NULL; + } + + for (i = 0; i < count; i++) + { + if (!getFBConfigAttrib(fbconfigs[i], EGL_NATIVE_VISUAL_ID)) + { + // Only consider EGLConfigs with associated visuals + continue; + } + + if (!(getFBConfigAttrib(fbconfigs[i], + EGL_COLOR_BUFFER_TYPE) & EGL_RGB_BUFFER)) + { + // Only consider RGB(A) EGLConfigs + continue; + } + + if (!(getFBConfigAttrib(fbconfigs[i], EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) + { + // Only consider window EGLConfigs + continue; + } + + if (!(getFBConfigAttrib(fbconfigs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT) && + !(getFBConfigAttrib(fbconfigs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) + { + // Only consider OpenGL ES context + continue; + } + + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE && + !(getFBConfigAttrib(fbconfigs[i], EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) + { + // User requested only OpenGL ES 2.0 context + continue; + } + + result[*found].redBits = getFBConfigAttrib(fbconfigs[i], EGL_RED_SIZE); + result[*found].greenBits = getFBConfigAttrib(fbconfigs[i], EGL_GREEN_SIZE); + result[*found].blueBits = getFBConfigAttrib(fbconfigs[i], EGL_BLUE_SIZE); + + result[*found].alphaBits = getFBConfigAttrib(fbconfigs[i], EGL_ALPHA_SIZE); + result[*found].depthBits = getFBConfigAttrib(fbconfigs[i], EGL_DEPTH_SIZE); + result[*found].stencilBits = getFBConfigAttrib(fbconfigs[i], EGL_STENCIL_SIZE); + + result[*found].samples = getFBConfigAttrib(fbconfigs[i], EGL_SAMPLES); + + result[*found].platformID = (GLFWintptr) getFBConfigAttrib(fbconfigs[i], EGL_CONFIG_ID); + + (*found)++; + } + + return result; +} + +//======================================================================== +// Read back framebuffer parameters from the context +//======================================================================== + +static void refreshContextParams(_GLFWwindow* window, EGLint fbconfigID) +{ + EGLint dummy; + EGLConfig fbconfig[_GLFW_EGL_CONFIG_IN]; + + int attribs[] = { EGL_CONFIG_ID, fbconfigID, None }; + + eglChooseConfig(_glfwLibrary.EGL.display, + attribs, + fbconfig, + _GLFW_EGL_CONFIG_IN, + &dummy); + if (!dummy) + { + // This should never ever happen + // TODO: Flag this as an error and propagate up + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/EGL: Cannot find known " + "EGLConfig by ID. This cannot " + "happen. Have a nice day.\n"); + abort(); + } + + // There is no clear definition of an "accelerated" context on X11/EGL, and + // true sounds better than false, so we hardcode true here + window->accelerated = GL_TRUE; + + window->redBits = getFBConfigAttrib(*fbconfig, EGL_RED_SIZE); + window->greenBits = getFBConfigAttrib(*fbconfig, EGL_GREEN_SIZE); + window->blueBits = getFBConfigAttrib(*fbconfig, EGL_BLUE_SIZE); + + window->alphaBits = getFBConfigAttrib(*fbconfig, EGL_ALPHA_SIZE); + window->depthBits = getFBConfigAttrib(*fbconfig, EGL_DEPTH_SIZE); + window->stencilBits = getFBConfigAttrib(*fbconfig, EGL_STENCIL_SIZE); + + // Get FSAA buffer sample count + window->samples = getFBConfigAttrib(*fbconfig, EGL_SAMPLES); +} + + +//======================================================================== +// Create the actual OpenGL(|ES) context +//======================================================================== + +#define setEGLattrib(attribs, index, attribName, attribValue) \ + attribs[index++] = attribName; \ + attribs[index++] = attribValue; + +static int createContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + EGLint fbconfigID) +{ + int attribs[40], visMask; + EGLint dummy, index, vid = 0; + EGLint red_size, green_size, blue_size, alpha_size; + EGLConfig fbconfig[_GLFW_EGL_CONFIG_IN]; + EGLContext share = NULL; + XVisualInfo visTemplate; + + if (wndconfig->share) + share = wndconfig->share->EGL.context; + + // Retrieve the previously selected EGLConfig + { + index = 0; + + setEGLattrib(attribs, index, EGL_CONFIG_ID, fbconfigID); + setEGLattrib(attribs, index, EGL_NONE, EGL_NONE); + + eglChooseConfig(_glfwLibrary.EGL.display, + attribs, + fbconfig, + _GLFW_EGL_CONFIG_IN, + &dummy); + + if (!dummy) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/EGL: Failed to retrieve the selected EGLConfig"); + return GL_FALSE; + } + } + + // Retrieve the corresponding visual + // NOTE: This is the only non-portable code in this file. + // Maybe it would not hurt too much to add #ifdefs for different platforms? + eglGetConfigAttrib(_glfwLibrary.EGL.display, *fbconfig, EGL_NATIVE_VISUAL_ID, &vid); + + // Init visual template + visTemplate.screen = _glfwLibrary.X11.screen; + visMask = VisualScreenMask; + + if (vid != 0) + { + // The X window visual must match the EGL config + visTemplate.visualid = vid; + visMask |= VisualIDMask; + } + else + { + // some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID + // attribute, so attempt to find the closest match. + + eglGetConfigAttrib(_glfwLibrary.EGL.display, *fbconfig, + EGL_RED_SIZE, &red_size); + eglGetConfigAttrib (_glfwLibrary.EGL.display, *fbconfig, + EGL_GREEN_SIZE, &green_size); + eglGetConfigAttrib (_glfwLibrary.EGL.display, *fbconfig, + EGL_BLUE_SIZE, &blue_size); + eglGetConfigAttrib (_glfwLibrary.EGL.display, *fbconfig, + EGL_ALPHA_SIZE, &alpha_size); + + visTemplate.depth = red_size + green_size + blue_size + alpha_size; + visMask |= VisualDepthMask; + } + + // Get X Visual + window->EGL.visual = XGetVisualInfo(_glfwLibrary.X11.display, visMask, &visTemplate, &dummy); + if (window->EGL.visual == NULL) { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/GLX: Failed to retrieve visual for EGLConfig"); + return GL_FALSE; + } + + index = 0; + if (wndconfig->glProfile == GLFW_OPENGL_ES2_PROFILE) + { + setEGLattrib(attribs, index, EGL_CONTEXT_CLIENT_VERSION, 2); + } + else + { + setEGLattrib(attribs, index, EGL_CONTEXT_CLIENT_VERSION, 1); + } + + setEGLattrib(attribs, index, EGL_NONE, EGL_NONE); + + eglBindAPI(EGL_OPENGL_ES_API); + + window->EGL.context = eglCreateContext(_glfwLibrary.EGL.display, *fbconfig, share, attribs); + if (window->EGL.context == EGL_NO_CONTEXT) + { + // TODO: Handle all the various error codes here + + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/EGL: Failed to create OpenGL(|ES) context"); + return GL_FALSE; + } + + // store configuraion + window->EGL.config = *fbconfig; + + refreshContextParams(window, fbconfigID); + + return GL_TRUE; +} + +#undef setEGLattrib + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Initialize EGL +//======================================================================== + +int _glfwInitOpenGL(void) +{ +#ifdef _GLFW_DLOPEN_LIBGL + int i; + char* libEGL_names[ ] = + { + "libEGL.so", + "libEGL.so.1", + "/usr/lib/libEGL.so", + "/usr/lib/libEGL.so.1", + NULL + }; + + for (i = 0; libEGL_names[i] != NULL; i++) + { + _glfwLibrary.EGL.libEGL = dlopen(libEGL_names[i], RTLD_LAZY | RTLD_GLOBAL); + if (_glfwLibrary.EGL.libEGL) + break; + } + + if (!_glfwLibrary.EGL.libEGL) + { + _glfwSetError(GLFW_PLATFORM_ERROR, "X11/EGL: Failed to find libEGL"); + return GL_FALSE; + } +#endif + + _glfwLibrary.EGL.display = eglGetDisplay((EGLNativeDisplayType)_glfwLibrary.X11.display); + if (_glfwLibrary.EGL.display == EGL_NO_DISPLAY) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/EGL: Failed to get EGL display"); + return GL_FALSE; + } + + if (!eglInitialize(_glfwLibrary.EGL.display, + &_glfwLibrary.EGL.majorVersion, + &_glfwLibrary.EGL.minorVersion)) + { + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, + "X11/EGL: Failed to initialize EGL"); + return GL_FALSE; + } + + return GL_TRUE; +} + + +//======================================================================== +// Terminate EGL +//======================================================================== + +void _glfwTerminateOpenGL(void) +{ + // Unload libEGL.so if necessary +#ifdef _GLFW_DLOPEN_LIBGL + if (_glfwLibrary.EGL.libEGL != NULL) + { + dlclose(_glfwLibrary.EGL.libEGL); + _glfwLibrary.EGL.libEGL = NULL; + } +#endif + eglTerminate(_glfwLibrary.EGL.display); +} + + +//======================================================================== +// Prepare for creation of the OpenGL context +//======================================================================== + +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) +{ + _GLFWfbconfig closest; + + // Choose the best available fbconfig + { + unsigned int fbcount; + _GLFWfbconfig* fbconfigs; + const _GLFWfbconfig* result; + + fbconfigs = getFBConfigs(window, wndconfig, &fbcount); + if (!fbconfigs) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/EGL: No usable EGLFBConfigs found"); + return GL_FALSE; + } + + result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); + if (!result) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/EGL: No EGLFBConfig matched the criteria"); + + free(fbconfigs); + return GL_FALSE; + } + + closest = *result; + free(fbconfigs); + } + + return createContext(window, wndconfig, closest.platformID); +} + + +//======================================================================== +// Destroy the OpenGL context +//======================================================================== + +void _glfwDestroyContext(_GLFWwindow* window) +{ + if (window->EGL.visual) + { + XFree(window->EGL.visual); + window->EGL.visual = NULL; + } + + if (window->EGL.surface) + { + // Release and destroy the surface + eglDestroySurface(_glfwLibrary.EGL.display, window->EGL.surface); + window->EGL.surface = EGL_NO_SURFACE; + } + + if (window->EGL.context) + { + // Release and destroy the context + eglDestroyContext(_glfwLibrary.EGL.display, window->EGL.context); + window->EGL.context = EGL_NO_CONTEXT; + } +} + +//======================================================================== +// Return the X visual associated with the specified context +//======================================================================== + +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window) +{ + return window->EGL.visual; +} + +//======================================================================== +// Make the OpenGL context associated with the specified window current +//======================================================================== + +void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) +{ + if (window) + { + if (window->EGL.surface == EGL_NO_SURFACE) + { + window->EGL.surface = eglCreateWindowSurface(_glfwLibrary.EGL.display, + window->EGL.config, (EGLNativeWindowType)window->X11.handle, NULL); + if (window->EGL.surface == EGL_NO_SURFACE) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "X11/EGL: Failed to create window surface"); + } + } + eglMakeCurrent(_glfwLibrary.EGL.display, + window->EGL.surface, + window->EGL.surface, + window->EGL.context); + } + else + eglMakeCurrent(_glfwLibrary.EGL.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + + +//======================================================================== +// Swap OpenGL buffers +//======================================================================== + +void _glfwPlatformSwapBuffers(void) +{ + eglSwapBuffers(_glfwLibrary.EGL.display, + _glfwLibrary.currentWindow->EGL.surface); +} + + +//======================================================================== +// Set double buffering swap interval +//======================================================================== + +void _glfwPlatformSwapInterval(int interval) +{ + eglSwapInterval(_glfwLibrary.EGL.display, interval); +} + + +//======================================================================== +// Check if an OpenGL extension is available at runtime +//======================================================================== + +int _glfwPlatformExtensionSupported(const char* extension) +{ + const char* extensions; + + // Get list of GLX extensions + extensions = eglQueryString(_glfwLibrary.EGL.display, + EGL_EXTENSIONS); + if (extensions != NULL) + { + if (_glfwStringInExtensionString(extension, (unsigned char*)extensions)) + return GL_TRUE; + } + + return GL_FALSE; +} + + +//======================================================================== +// Get the function pointer to an OpenGL function +//======================================================================== + +GLFWglproc _glfwPlatformGetProcAddress(const char* procname) +{ + return _glfw_eglGetProcAddress(procname); +} + + +//======================================================================== +// Copies the specified OpenGL state categories from src to dst +//======================================================================== + +void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long mask) +{ + // AFAIK, EGL doesn't have this +} + diff --git a/src/x11_egl_platform.h b/src/x11_egl_platform.h new file mode 100644 index 00000000..9e0e21b4 --- /dev/null +++ b/src/x11_egl_platform.h @@ -0,0 +1,286 @@ +//======================================================================== +// GLFW - An OpenGL library +// Platform: X11/EGL +// API version: 3.0 +// WWW: http://www.glfw.org/ +//------------------------------------------------------------------------ +// Copyright (c) 2002-2006 Marcus Geelnard +// Copyright (c) 2006-2010 Camilla Berglund +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would +// be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, and must not +// be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source +// distribution. +// +//======================================================================== + +#ifndef _platform_h_ +#define _platform_h_ + +#include +#include +#include +#include +#include +#include +#include + +// Include EGL +#include + +// With XFree86, we can use the XF86VidMode extension +#if defined(_GLFW_HAS_XF86VIDMODE) + #include +#endif + +#if defined(_GLFW_HAS_XRANDR) + #include +#endif + +// Do we have support for dlopen/dlsym? +#if defined(_GLFW_HAS_DLOPEN) + #include +#endif + +// The Xkb extension provides improved keyboard support +#if defined(_GLFW_HAS_XKB) + #include +#endif + +// We support two different ways for getting addresses for EGL +// extension functions: eglGetProcAddress and dlsym +#if defined(_GLFW_HAS_EGLGETPROCADDRESS) + #define _glfw_eglGetProcAddress(x) eglGetProcAddress(x) +#elif defined(_GLFW_HAS_DLOPEN) + #define _glfw_eglGetProcAddress(x) dlsym(_glfwLibrary.EGL.libEGL, x) + #define _GLFW_DLOPEN_LIBEGL +#else + #error "No OpenGL entry point retrieval mechanism was enabled" +#endif + +#define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowX11 X11 +#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextEGL EGL +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 X11 +#define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryEGL EGL + +// Clipboard format atom indices +#define _GLFW_CLIPBOARD_FORMAT_UTF8 0 +#define _GLFW_CLIPBOARD_FORMAT_COMPOUND 1 +#define _GLFW_CLIPBOARD_FORMAT_STRING 2 +#define _GLFW_CLIPBOARD_FORMAT_COUNT 3 + +// Clipboard conversion status tokens +#define _GLFW_CONVERSION_INACTIVE 0 +#define _GLFW_CONVERSION_SUCCEEDED 1 +#define _GLFW_CONVERSION_FAILED 2 + + +//======================================================================== +// GLFW platform specific types +//======================================================================== + +//------------------------------------------------------------------------ +// Pointer length integer +//------------------------------------------------------------------------ +typedef intptr_t GLFWintptr; + + +//------------------------------------------------------------------------ +// Platform-specific OpenGL context structure +//------------------------------------------------------------------------ +typedef struct _GLFWcontextEGL +{ + EGLConfig config; + EGLContext context; + EGLSurface surface; + XVisualInfo* visual; +} _GLFWcontextEGL; + + +//------------------------------------------------------------------------ +// Platform-specific window structure +//------------------------------------------------------------------------ +typedef struct _GLFWwindowX11 +{ + // Platform specific window resources + Colormap colormap; // Window colormap + Window handle; // Window handle + + // Various platform specific internal variables + GLboolean overrideRedirect; // True if window is OverrideRedirect + GLboolean keyboardGrabbed; // True if keyboard is currently grabbed + GLboolean cursorGrabbed; // True if cursor is currently grabbed + GLboolean cursorHidden; // True if cursor is currently hidden + GLboolean cursorCentered; // True if cursor was moved since last poll + int cursorPosX, cursorPosY; + +} _GLFWwindowX11; + +//------------------------------------------------------------------------ +// Platform-specific library global data for X11 +//------------------------------------------------------------------------ +typedef struct _GLFWlibraryX11 +{ + Display* display; + int screen; + Window root; + Cursor cursor; // Invisible cursor for hidden cursor + + Atom wmDeleteWindow; // WM_DELETE_WINDOW atom + Atom wmName; // _NET_WM_NAME atom + Atom wmIconName; // _NET_WM_ICON_NAME atom + Atom wmPing; // _NET_WM_PING atom + Atom wmState; // _NET_WM_STATE atom + Atom wmStateFullscreen; // _NET_WM_STATE_FULLSCREEN atom + Atom wmActiveWindow; // _NET_ACTIVE_WINDOW atom + + // True if window manager supports EWMH + GLboolean hasEWMH; + + struct { + GLboolean available; + int eventBase; + int errorBase; + } VidMode; + + struct { + GLboolean available; + int eventBase; + int errorBase; + int majorVersion; + int minorVersion; + GLboolean gammaBroken; + } RandR; + + struct { + GLboolean available; + int majorOpcode; + int eventBase; + int errorBase; + int majorVersion; + int minorVersion; + } Xkb; + + // Key code LUT (mapping X11 key codes to GLFW key codes) + int keyCodeLUT[256]; + + // Screensaver data + struct { + GLboolean changed; + int timeout; + int interval; + int blanking; + int exposure; + } saver; + + // Fullscreen data + struct { + GLboolean modeChanged; +#if defined(_GLFW_HAS_XRANDR) + SizeID oldSizeID; + int oldWidth; + int oldHeight; + Rotation oldRotation; +#endif /*_GLFW_HAS_XRANDR*/ +#if defined(_GLFW_HAS_XF86VIDMODE) + XF86VidModeModeInfo oldMode; +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } FS; + + // Timer data + struct { + GLboolean monotonic; + double resolution; + uint64_t base; + } timer; + + // Selection data + struct { + Atom atom; + Atom formats[_GLFW_CLIPBOARD_FORMAT_COUNT]; + char* string; + Atom target; + Atom targets; + Atom property; + int status; + } selection; + +} _GLFWlibraryX11; + +//------------------------------------------------------------------------ +// Platform-specific library global data for EGL +//------------------------------------------------------------------------ +typedef struct _GLFWlibraryEGL +{ + EGLDisplay display; + EGLint majorVersion, minorVersion; + +#if defined(_GLFW_DLOPEN_LIBEGL) + void* libEGL; // dlopen handle for libEGL.so +#endif +} _GLFWlibraryEGL; + +//------------------------------------------------------------------------ +// Joystick information & state +//------------------------------------------------------------------------ +GLFWGLOBAL struct { + int Present; + int fd; + int NumAxes; + int NumButtons; + float* Axis; + unsigned char* Button; +} _glfwJoy[GLFW_JOYSTICK_LAST + 1]; + + +//======================================================================== +// Prototypes for platform specific internal functions +//======================================================================== + +// Time +void _glfwInitTimer(void); + +// OpenGL(|ES) support +int _glfwInitOpenGL(void); +void _glfwTerminateOpenGL(void); +int _glfwCreateContext(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig); +void _glfwDestroyContext(_GLFWwindow* window); +XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window); + +// Fullscreen support +int _glfwGetClosestVideoMode(int* width, int* height, int* rate); +void _glfwSetVideoModeMODE(int mode, int rate); +void _glfwSetVideoMode(int* width, int* height, int* rate); +void _glfwRestoreVideoMode(void); + +// Joystick input +void _glfwInitJoysticks(void); +void _glfwTerminateJoysticks(void); + +// Unicode support +long _glfwKeySym2Unicode(KeySym keysym); + +// Clipboard handling +GLboolean _glfwReadSelection(XSelectionEvent* request); +Atom _glfwWriteSelection(XSelectionRequestEvent* request); + +// Event processing +void _glfwProcessPendingEvents(void); + +#endif // _platform_h_ diff --git a/src/x11_fullscreen.c b/src/x11_fullscreen.c index 7ad11ec5..a17acde4 100644 --- a/src/x11_fullscreen.c +++ b/src/x11_fullscreen.c @@ -357,6 +357,8 @@ int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) rgbarray = (int*) malloc(sizeof(int) * viscount); rgbcount = 0; + // Temporary solution +#if !defined(_GLFW_X11_EGL) // Build RGB array for (k = 0; k < viscount; k++) { @@ -386,6 +388,7 @@ int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) } } } +#endif XFree(vislist); diff --git a/src/x11_platform.h b/src/x11_platform.h index 39593655..28e749fe 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -85,6 +85,7 @@ #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX GLX #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryX11 X11 #define _GLFW_PLATFORM_LIBRARY_OPENGL_STATE _GLFWlibraryGLX GLX +#define _GLFW_CTX GLX // Clipboard format atom indices #define _GLFW_CLIPBOARD_FORMAT_UTF8 0