summaryrefslogtreecommitdiff
path: root/src/SFML/Window/EglContext.cpp
diff options
context:
space:
mode:
authorJames Cowgill <james410@cowgill.org.uk>2014-12-09 20:21:40 +0000
committerJames Cowgill <james410@cowgill.org.uk>2014-12-09 20:21:40 +0000
commitfa21c65d0c764705cfc377bf0d0de08fac26874e (patch)
treedbc9e87bbd8684d15e79fc0c8b7a8985389c3b35 /src/SFML/Window/EglContext.cpp
parentdd835931261c340acd5f0409341d13fa2670423e (diff)
Imported Upstream version 2.2.0+dfsg
Diffstat (limited to 'src/SFML/Window/EglContext.cpp')
-rw-r--r--src/SFML/Window/EglContext.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp
new file mode 100644
index 0000000..b4182dd
--- /dev/null
+++ b/src/SFML/Window/EglContext.cpp
@@ -0,0 +1,307 @@
+////////////////////////////////////////////////////////////
+//
+// SFML - Simple and Fast Multimedia Library
+// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@gmail.com)
+//
+// 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.
+//
+////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#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>
+#include <SFML/System/Lock.hpp>
+#ifdef SFML_SYSTEM_ANDROID
+ #include <SFML/System/Android/Activity.hpp>
+#endif
+#ifdef SFML_SYSTEM_LINUX
+ #include <X11/Xlib.h>
+#endif
+
+namespace
+{
+ EGLDisplay getInitializedDisplay()
+ {
+#if defined(SFML_SYSTEM_LINUX)
+
+ static EGLDisplay display = EGL_NO_DISPLAY;
+
+ if (display == EGL_NO_DISPLAY)
+ {
+ display = eglCheck(eglGetDisplay(EGL_DEFAULT_DISPLAY));
+ eglCheck(eglInitialize(display, NULL, NULL));
+ }
+
+ return display;
+
+#elif defined(SFML_SYSTEM_ANDROID)
+
+ // On Android, its native activity handles this for us
+ sf::priv::ActivityStates* states = sf::priv::getActivity(NULL);
+ sf::Lock lock(states->mutex);
+
+ return states->display;
+
+#endif
+ }
+}
+
+
+namespace sf
+{
+namespace priv
+{
+////////////////////////////////////////////////////////////
+EglContext::EglContext(EglContext* shared) :
+m_display (EGL_NO_DISPLAY),
+m_context (EGL_NO_CONTEXT),
+m_surface (EGL_NO_SURFACE),
+m_config (NULL)
+{
+ // Get the initialized EGL display
+ m_display = getInitializedDisplay();
+
+ // Get the best EGL config matching the default video settings
+ m_config = getBestConfig(m_display, VideoMode::getDesktopMode().bitsPerPixel, ContextSettings());
+
+ // Note: The EGL specs say that attrib_list can be NULL when passed to eglCreatePbufferSurface,
+ // but this is resulting in a segfault. Bug in Android?
+ EGLint attrib_list[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT,1,
+ EGL_NONE
+ };
+
+ m_surface = eglCheck(eglCreatePbufferSurface(m_display, m_config, attrib_list));
+
+ // Create EGL context
+ createContext(shared);
+}
+
+
+////////////////////////////////////////////////////////////
+EglContext::EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) :
+m_display (EGL_NO_DISPLAY),
+m_context (EGL_NO_CONTEXT),
+m_surface (EGL_NO_SURFACE),
+m_config (NULL)
+{
+#ifdef SFML_SYSTEM_ANDROID
+
+ // On Android, we must save the created context
+ ActivityStates* states = getActivity(NULL);
+ Lock lock(states->mutex);
+
+ states->context = this;
+
+#endif
+
+ // Get the initialized EGL display
+ m_display = getInitializedDisplay();
+
+ // Get the best EGL config matching the requested video settings
+ m_config = getBestConfig(m_display, bitsPerPixel, settings);
+
+ // Create EGL context
+ createContext(shared);
+
+#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());
+#endif
+}
+
+
+////////////////////////////////////////////////////////////
+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)
+{
+}
+
+
+////////////////////////////////////////////////////////////
+EglContext::~EglContext()
+{
+ // Deactivate the current context
+ EGLContext currentContext = eglCheck(eglGetCurrentContext());
+
+ if (currentContext == m_context)
+ {
+ eglCheck(eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+ }
+
+ // Destroy context
+ if (m_context != EGL_NO_CONTEXT)
+ {
+ eglCheck(eglDestroyContext(m_display, m_context));
+ }
+
+ // Destroy surface
+ if (m_surface != EGL_NO_SURFACE)
+ {
+ eglCheck(eglDestroySurface(m_display, m_surface));
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+bool EglContext::makeCurrent()
+{
+ return m_surface != EGL_NO_SURFACE && eglCheck(eglMakeCurrent(m_display, m_surface, m_surface, m_context));
+}
+
+
+////////////////////////////////////////////////////////////
+void EglContext::display()
+{
+ if (m_surface != EGL_NO_SURFACE)
+ eglCheck(eglSwapBuffers(m_display, m_surface));
+}
+
+
+////////////////////////////////////////////////////////////
+void EglContext::setVerticalSyncEnabled(bool enabled)
+{
+ eglCheck(eglSwapInterval(m_display, enabled ? 1 : 0));
+}
+
+
+////////////////////////////////////////////////////////////
+void EglContext::createContext(EglContext* shared)
+{
+ const EGLint contextVersion[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 1,
+ EGL_NONE
+ };
+
+ EGLContext toShared;
+
+ if (shared)
+ toShared = shared->m_context;
+ else
+ toShared = EGL_NO_CONTEXT;
+
+ // Create EGL context
+ m_context = eglCheck(eglCreateContext(m_display, m_config, toShared, contextVersion));
+}
+
+
+////////////////////////////////////////////////////////////
+void EglContext::createSurface(EGLNativeWindowType window)
+{
+ m_surface = eglCheck(eglCreateWindowSurface(m_display, m_config, window, NULL));
+}
+
+
+////////////////////////////////////////////////////////////
+void EglContext::destroySurface()
+{
+ 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)
+{
+ // Set our video settings constraint
+ const EGLint attributes[] = {
+ EGL_BUFFER_SIZE, bitsPerPixel,
+ EGL_DEPTH_SIZE, settings.depthBits,
+ EGL_STENCIL_SIZE, settings.stencilBits,
+ EGL_SAMPLE_BUFFERS, settings.antialiasingLevel,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+ EGL_NONE
+ };
+
+ EGLint configCount;
+ EGLConfig configs[1];
+
+ // Ask EGL for the best config matching our video settings
+ eglCheck(eglChooseConfig(display, attributes, configs, 1, &configCount));
+
+ return configs[0];
+}
+
+
+#ifdef SFML_SYSTEM_LINUX
+////////////////////////////////////////////////////////////
+XVisualInfo EglContext::selectBestVisual(::Display* XDisplay, unsigned int bitsPerPixel, const ContextSettings& settings)
+{
+ // Get the initialized EGL display
+ EGLDisplay display = getInitializedDisplay();
+
+ // Get the best EGL config matching the default video settings
+ EGLConfig config = getBestConfig(display, bitsPerPixel, settings);
+
+ // Retrieve the visual id associated with this EGL config
+ EGLint nativeVisualId;
+
+ eglCheck(eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &nativeVisualId));
+
+ if (nativeVisualId == 0)
+ {
+ // Should never happen...
+ err() << "No EGL visual found. You should check your graphics driver" << std::endl;
+
+ return XVisualInfo();
+ }
+
+ XVisualInfo vTemplate;
+ vTemplate.visualid = static_cast<VisualID>(nativeVisualId);
+
+ // Get X11 visuals compatible with this EGL config
+ XVisualInfo *availableVisuals, bestVisual;
+ int visualCount = 0;
+
+ availableVisuals = XGetVisualInfo(XDisplay, VisualIDMask, &vTemplate, &visualCount);
+
+ if (visualCount == 0)
+ {
+ // Can't happen...
+ err() << "No X11 visual found. Bug in your EGL implementation ?" << std::endl;
+
+ return XVisualInfo();
+ }
+
+ // Pick up the best one
+ bestVisual = availableVisuals[0];
+ XFree(availableVisuals);
+
+ return bestVisual;
+}
+#endif
+
+} // namespace priv
+
+} // namespace sf