diff options
Diffstat (limited to 'src/SFML/Window/EglContext.cpp')
-rw-r--r-- | src/SFML/Window/EglContext.cpp | 169 |
1 files changed, 122 insertions, 47 deletions
diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp index fb91cda..a43a211 100644 --- a/src/SFML/Window/EglContext.cpp +++ b/src/SFML/Window/EglContext.cpp @@ -28,7 +28,6 @@ //////////////////////////////////////////////////////////// #include <SFML/Window/EglContext.hpp> #include <SFML/Window/WindowImpl.hpp> -#include <SFML/OpenGL.hpp> #include <SFML/System/Err.hpp> #include <SFML/System/Sleep.hpp> #include <SFML/System/Mutex.hpp> @@ -36,35 +35,63 @@ #ifdef SFML_SYSTEM_ANDROID #include <SFML/System/Android/Activity.hpp> #endif -#ifdef SFML_SYSTEM_LINUX +#if defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM) #include <X11/Xlib.h> #endif +// We check for this definition in order to avoid multiple definitions of GLAD +// entities during unity builds of SFML. +#ifndef SF_GLAD_EGL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_EGL_IMPLEMENTATION_INCLUDED +#define SF_GLAD_EGL_IMPLEMENTATION +#include <glad/egl.h> +#endif + namespace { - EGLDisplay getInitializedDisplay() + // A nested named namespace is used here to allow unity builds of SFML. + namespace EglContextImpl { -#if defined(SFML_SYSTEM_LINUX) + EGLDisplay getInitializedDisplay() + { +#if defined(SFML_SYSTEM_ANDROID) - static EGLDisplay display = EGL_NO_DISPLAY; + // On Android, its native activity handles this for us + sf::priv::ActivityStates& states = sf::priv::getActivity(); + sf::Lock lock(states.mutex); - if (display == EGL_NO_DISPLAY) - { - display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY)); - eglCheck(eglInitialize(display, NULL, NULL)); - } + return states.display; - return display; +#endif -#elif defined(SFML_SYSTEM_ANDROID) + static EGLDisplay display = EGL_NO_DISPLAY; - // On Android, its native activity handles this for us - sf::priv::ActivityStates* states = sf::priv::getActivity(NULL); - sf::Lock lock(states->mutex); + if (display == EGL_NO_DISPLAY) + { + eglCheck(display = eglGetDisplay(EGL_DEFAULT_DISPLAY)); + eglCheck(eglInitialize(display, NULL, NULL)); + } - return states->display; + return display; + } -#endif + + //////////////////////////////////////////////////////////// + void ensureInit() + { + static bool initialized = false; + if (!initialized) + { + initialized = true; + + // We don't check the return value since the extension + // flags are cleared even if loading fails + gladLoaderLoadEGL(EGL_NO_DISPLAY); + + // Continue loading with a display + gladLoaderLoadEGL(getInitializedDisplay()); + } + } } } @@ -80,8 +107,10 @@ m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { + EglContextImpl::ensureInit(); + // Get the initialized EGL display - m_display = getInitializedDisplay(); + m_display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the default video settings m_config = getBestConfig(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings()); @@ -95,7 +124,7 @@ m_config (NULL) EGL_NONE }; - m_surface = eglCheck(eglCreatePbufferSurface(m_display, m_config, attrib_list)); + eglCheck(m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list)); // Create EGL context createContext(shared); @@ -109,18 +138,20 @@ m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { + EglContextImpl::ensureInit(); + #ifdef SFML_SYSTEM_ANDROID // On Android, we must save the created context - ActivityStates* states = getActivity(NULL); - Lock lock(states->mutex); + ActivityStates& states = getActivity(); + Lock lock(states.mutex); - states->context = this; + states.context = this; #endif // Get the initialized EGL display - m_display = getInitializedDisplay(); + m_display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the requested video settings m_config = getBestConfig(m_display, bitsPerPixel, settings); @@ -132,18 +163,23 @@ m_config (NULL) #if !defined(SFML_SYSTEM_ANDROID) // Create EGL surface (except on Android because the window is created // asynchronously, its activity manager will call it for us) - createSurface((EGLNativeWindowType)owner->getSystemHandle()); + createSurface(owner->getSystemHandle()); +#else + (void) owner; #endif } //////////////////////////////////////////////////////////// -EglContext::EglContext(EglContext* shared, const ContextSettings& settings, unsigned int width, unsigned int height) : +EglContext::EglContext(EglContext* /*shared*/, const ContextSettings& /*settings*/, unsigned int /*width*/, unsigned int /*height*/) : m_display (EGL_NO_DISPLAY), m_context (EGL_NO_CONTEXT), m_surface (EGL_NO_SURFACE), m_config (NULL) { + EglContextImpl::ensureInit(); + + sf::err() << "Warning: context has not been initialized. The constructor EglContext(shared, settings, width, height) is currently not implemented." << std::endl; } @@ -154,7 +190,8 @@ EglContext::~EglContext() cleanupUnsharedResources(); // Deactivate the current context - EGLContext currentContext = eglCheck(eglGetCurrentContext()); + EGLContext currentContext = EGL_NO_CONTEXT; + eglCheck(currentContext = eglGetCurrentContext()); if (currentContext == m_context) { @@ -176,12 +213,32 @@ EglContext::~EglContext() //////////////////////////////////////////////////////////// +GlFunctionPointer EglContext::getFunction(const char* name) +{ + EglContextImpl::ensureInit(); + + return eglGetProcAddress(name); +} + + +//////////////////////////////////////////////////////////// bool EglContext::makeCurrent(bool current) { + if (m_surface == EGL_NO_SURFACE) + return false; + + EGLBoolean result = EGL_FALSE; + if (current) - return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context)); + { + eglCheck(result = eglMakeCurrent(m_display, m_surface, m_surface, m_context)); + } + else + { + eglCheck(result = eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + } - return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + return (result != EGL_FALSE); } @@ -219,37 +276,40 @@ void EglContext::createContext(EglContext* shared) eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); // Create EGL context - m_context = eglCheck(eglCreateContext(m_display, m_config, toShared, contextVersion)); + eglCheck(m_context = eglCreateContext(m_display, m_config, toShared, contextVersion)); } //////////////////////////////////////////////////////////// void EglContext::createSurface(EGLNativeWindowType window) { - m_surface = eglCheck(eglCreateWindowSurface(m_display, m_config, window, NULL)); + eglCheck(m_surface = eglCreateWindowSurface(m_display, m_config, window, NULL)); } //////////////////////////////////////////////////////////// void EglContext::destroySurface() { + // Ensure that this context is no longer active since our surface is going to be destroyed + setActive(false); + eglCheck(eglDestroySurface(m_display, m_surface)); m_surface = EGL_NO_SURFACE; - - // Ensure that this context is no longer active since our surface is now destroyed - setActive(false); } //////////////////////////////////////////////////////////// EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixel, const ContextSettings& settings) { + EglContextImpl::ensureInit(); + // Set our video settings constraint const EGLint attributes[] = { EGL_BUFFER_SIZE, static_cast<EGLint>(bitsPerPixel), EGL_DEPTH_SIZE, static_cast<EGLint>(settings.depthBits), EGL_STENCIL_SIZE, static_cast<EGLint>(settings.stencilBits), - EGL_SAMPLE_BUFFERS, static_cast<EGLint>(settings.antialiasingLevel), + EGL_SAMPLE_BUFFERS, settings.antialiasingLevel ? 1 : 0, + EGL_SAMPLES, static_cast<EGLint>(settings.antialiasingLevel), EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_NONE @@ -270,30 +330,45 @@ EGLConfig EglContext::getBestConfig(EGLDisplay display, unsigned int bitsPerPixe //////////////////////////////////////////////////////////// void EglContext::updateSettings() { - EGLint tmp; - + EGLBoolean result = EGL_FALSE; + EGLint tmp = 0; + // Update the internal context settings with the current config - eglCheck(eglGetConfigAttrib(m_display, m_config, EGL_DEPTH_SIZE, &tmp)); - m_settings.depthBits = tmp; - - eglCheck(eglGetConfigAttrib(m_display, m_config, EGL_STENCIL_SIZE, &tmp)); - m_settings.stencilBits = tmp; - - eglCheck(eglGetConfigAttrib(m_display, m_config, EGL_SAMPLES, &tmp)); - m_settings.antialiasingLevel = tmp; - + eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_DEPTH_SIZE, &tmp)); + + if (result == EGL_FALSE) + err() << "Failed to retrieve EGL_DEPTH_SIZE" << std::endl; + + m_settings.depthBits = static_cast<unsigned int>(tmp); + + eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_STENCIL_SIZE, &tmp)); + + if (result == EGL_FALSE) + err() << "Failed to retrieve EGL_STENCIL_SIZE" << std::endl; + + m_settings.stencilBits = static_cast<unsigned int>(tmp); + + eglCheck(result = eglGetConfigAttrib(m_display, m_config, EGL_SAMPLES, &tmp)); + + if (result == EGL_FALSE) + err() << "Failed to retrieve EGL_SAMPLES" << std::endl; + + m_settings.antialiasingLevel = static_cast<unsigned int>(tmp); + m_settings.majorVersion = 1; m_settings.minorVersion = 1; m_settings.attributeFlags = ContextSettings::Default; } -#ifdef SFML_SYSTEM_LINUX +#if defined(SFML_SYSTEM_LINUX) && !defined(SFML_USE_DRM) //////////////////////////////////////////////////////////// XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsPerPixel, const ContextSettings& settings) { + EglContextImpl::ensureInit(); + // Get the initialized EGL display - EGLDisplay display = getInitializedDisplay(); + EGLDisplay display = EglContextImpl::getInitializedDisplay(); // Get the best EGL config matching the default video settings EGLConfig config = getBestConfig(display, bitsPerPixel, settings); |