diff --git a/src/SFML/Window/Linux/GlxContext.cpp b/src/SFML/Window/Linux/GlxContext.cpp index e2783ef6..acf54d6b 100644 --- a/src/SFML/Window/Linux/GlxContext.cpp +++ b/src/SFML/Window/Linux/GlxContext.cpp @@ -158,12 +158,69 @@ void GlxContext::setVerticalSyncEnabled(bool enabled) //////////////////////////////////////////////////////////// -void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings) +XVisualInfo GlxContext::selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings) +{ + // Retrieve all the visuals + int count; + XVisualInfo* visuals = XGetVisualInfo(display, 0, NULL, &count); + if (visuals) + { + // Evaluate all the returned visuals, and pick the best one1 + int bestScore = 0xFFFF; + XVisualInfo bestVisual; + for (int i = 0; i < count; ++i) + { + // Check mandatory attributes + int doubleBuffer; + glXGetConfig(display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); + if (!doubleBuffer) + continue; + + // Extract the components of the current visual + int red, green, blue, alpha, depth, stencil, multiSampling, samples; + glXGetConfig(display, &visuals[i], GLX_RED_SIZE, &red); + glXGetConfig(display, &visuals[i], GLX_GREEN_SIZE, &green); + glXGetConfig(display, &visuals[i], GLX_BLUE_SIZE, &blue); + glXGetConfig(display, &visuals[i], GLX_ALPHA_SIZE, &alpha); + glXGetConfig(display, &visuals[i], GLX_DEPTH_SIZE, &depth); + glXGetConfig(display, &visuals[i], GLX_STENCIL_SIZE, &stencil); + glXGetConfig(display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(display, &visuals[i], GLX_SAMPLES_ARB, &samples); + + // Evaluate the visual + int color = red + green + blue + alpha; + int score = evaluateFormat(bitsPerPixel, settings, color, depth, stencil, multiSampling ? samples : 0); + + // If it's better than the current best, make it the new best + if (score < bestScore) + { + bestScore = score; + bestVisual = visuals[i]; + } + } + + // Free the array of visuals + XFree(visuals); + + return bestVisual; + } + else + { + // Should never happen... + err() << "No GLX visual found. You should check your graphics driver" << std::endl; + + return XVisualInfo(); + } +} + + +//////////////////////////////////////////////////////////// +void GlxContext::createContext(GlxContext* shared, unsigned int /*bitsPerPixel*/, const ContextSettings& settings) { // Save the creation settings m_settings = settings; - // Get the attributes of the target window + // Retrieve the attributes of the target window XWindowAttributes windowAttributes; if (XGetWindowAttributes(m_display, m_window, &windowAttributes) == 0) { @@ -171,63 +228,12 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co return; } - // Setup the visual infos to match + // Get its visual XVisualInfo tpl; - tpl.depth = windowAttributes.depth; - tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); tpl.screen = DefaultScreen(m_display); - - // Get all the visuals matching the template + tpl.visualid = XVisualIDFromVisual(windowAttributes.visual); int nbVisuals = 0; - XVisualInfo* visuals = XGetVisualInfo(m_display, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); - if (!visuals || (nbVisuals == 0)) - { - if (visuals) - XFree(visuals); - err() << "There is no valid visual for the selected screen" << std::endl; - return; - } - - // Find the best visual - int bestScore = 0xFFFF; - XVisualInfo* bestVisual = NULL; - for (int i = 0; i < nbVisuals; ++i) - { - // Get the current visual attributes - int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples; - glXGetConfig(m_display, &visuals[i], GLX_RGBA, &RGBA); - glXGetConfig(m_display, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer); - glXGetConfig(m_display, &visuals[i], GLX_RED_SIZE, &red); - glXGetConfig(m_display, &visuals[i], GLX_GREEN_SIZE, &green); - glXGetConfig(m_display, &visuals[i], GLX_BLUE_SIZE, &blue); - glXGetConfig(m_display, &visuals[i], GLX_ALPHA_SIZE, &alpha); - glXGetConfig(m_display, &visuals[i], GLX_DEPTH_SIZE, &depth); - glXGetConfig(m_display, &visuals[i], GLX_STENCIL_SIZE, &stencil); - glXGetConfig(m_display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling); - glXGetConfig(m_display, &visuals[i], GLX_SAMPLES_ARB, &samples); - - // First check the mandatory parameters - if ((RGBA == 0) || (doubleBuffer == 0)) - continue; - - // Evaluate the current configuration - int color = red + green + blue + alpha; - int score = evaluateFormat(bitsPerPixel, m_settings, color, depth, stencil, multiSampling ? samples : 0); - - // Keep it if it's better than the current best - if (score < bestScore) - { - bestScore = score; - bestVisual = &visuals[i]; - } - } - - // Make sure that we have found a visual - if (!bestVisual) - { - err() << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl; - return; - } + XVisualInfo* visualInfo = XGetVisualInfo(m_display, VisualIDMask | VisualScreenMask, &tpl, &nbVisuals); // Get the context to share display lists with GLXContext toShare = shared ? shared->m_context : NULL; @@ -283,7 +289,7 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co m_settings.majorVersion = 2; m_settings.minorVersion = 0; - m_context = glXCreateContext(m_display, bestVisual, toShare, true); + m_context = glXCreateContext(m_display, visualInfo, toShare, true); if (!m_context) { err() << "Failed to create an OpenGL context for this window" << std::endl; @@ -293,21 +299,16 @@ void GlxContext::createContext(GlxContext* shared, unsigned int bitsPerPixel, co // Update the creation settings from the chosen format int depth, stencil, multiSampling, samples; - glXGetConfig(m_display, bestVisual, GLX_DEPTH_SIZE, &depth); - glXGetConfig(m_display, bestVisual, GLX_STENCIL_SIZE, &stencil); - glXGetConfig(m_display, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); - glXGetConfig(m_display, bestVisual, GLX_SAMPLES_ARB, &samples); + glXGetConfig(m_display, visualInfo, GLX_DEPTH_SIZE, &depth); + glXGetConfig(m_display, visualInfo, GLX_STENCIL_SIZE, &stencil); + glXGetConfig(m_display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &multiSampling); + glXGetConfig(m_display, visualInfo, GLX_SAMPLES_ARB, &samples); m_settings.depthBits = static_cast(depth); m_settings.stencilBits = static_cast(stencil); m_settings.antialiasingLevel = multiSampling ? samples : 0; - // Change the target window's colormap so that it matches the context's one - ::Window root = RootWindow(m_display, DefaultScreen(m_display)); - Colormap colorMap = XCreateColormap(m_display, root, bestVisual->visual, AllocNone); - XSetWindowColormap(m_display, m_window, colorMap); - - // Free the temporary visuals array - XFree(visuals); + // Free the visual info + XFree(visualInfo); } } // namespace priv diff --git a/src/SFML/Window/Linux/GlxContext.hpp b/src/SFML/Window/Linux/GlxContext.hpp index ccff1cb3..493c8586 100644 --- a/src/SFML/Window/Linux/GlxContext.hpp +++ b/src/SFML/Window/Linux/GlxContext.hpp @@ -108,6 +108,18 @@ public : //////////////////////////////////////////////////////////// virtual void setVerticalSyncEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Select the best GLX visual for a given set of settings + /// + /// \param display X display + /// \param bitsPerPixel Pixel depth, in bits per pixel + /// \param settings Requested context settings + /// + /// \return The best visual + /// + //////////////////////////////////////////////////////////// + static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings); + private : //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/Linux/WindowImplX11.cpp b/src/SFML/Window/Linux/WindowImplX11.cpp index 1f1fa5df..e26627ff 100644 --- a/src/SFML/Window/Linux/WindowImplX11.cpp +++ b/src/SFML/Window/Linux/WindowImplX11.cpp @@ -27,6 +27,7 @@ //////////////////////////////////////////////////////////// #include // important to be included first (conflict with None) #include +#include #include #include #include @@ -96,7 +97,7 @@ m_previousSize(-1, -1) { // Open a connection with the X server m_display = OpenDisplay(); - m_screen = DefaultScreen(m_display); + m_screen = DefaultScreen(m_display); // Save the window handle m_window = handle; @@ -113,7 +114,7 @@ m_previousSize(-1, -1) //////////////////////////////////////////////////////////// -WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long style) : +WindowImplX11::WindowImplX11(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings) : m_window (0), m_inputMethod (NULL), m_inputContext(NULL), @@ -126,7 +127,8 @@ m_previousSize(-1, -1) { // Open a connection with the X server m_display = OpenDisplay(); - m_screen = DefaultScreen(m_display); + m_screen = DefaultScreen(m_display); + ::Window root = RootWindow(m_display, m_screen); // Compute position and size int left, top; @@ -148,21 +150,25 @@ m_previousSize(-1, -1) if (fullscreen) switchToFullscreen(mode); + // Choose the visual according to the context settings + XVisualInfo visualInfo = GlxContext::selectBestVisual(m_display, mode.bitsPerPixel, settings); + // Define the window attributes XSetWindowAttributes attributes; - attributes.event_mask = eventMask; attributes.override_redirect = fullscreen; + attributes.event_mask = eventMask; + attributes.colormap = XCreateColormap(m_display, root, visualInfo.visual, AllocNone); // Create the window m_window = XCreateWindow(m_display, - RootWindow(m_display, m_screen), + root, left, top, width, height, 0, - DefaultDepth(m_display, m_screen), + visualInfo.depth, InputOutput, - DefaultVisual(m_display, m_screen), - CWEventMask | CWOverrideRedirect, &attributes); + visualInfo.visual, + CWEventMask | CWOverrideRedirect | CWColormap, &attributes); if (!m_window) { err() << "Failed to create window" << std::endl; diff --git a/src/SFML/Window/Linux/WindowImplX11.hpp b/src/SFML/Window/Linux/WindowImplX11.hpp index 5c84fee4..613fa7bf 100644 --- a/src/SFML/Window/Linux/WindowImplX11.hpp +++ b/src/SFML/Window/Linux/WindowImplX11.hpp @@ -61,9 +61,10 @@ public : /// \param mode Video mode to use /// \param title Title of the window /// \param style Window style (resizable, fixed, or fullscren) + /// \param settings Additional settings for the underlying OpenGL context /// //////////////////////////////////////////////////////////// - WindowImplX11(VideoMode mode, const String& title, unsigned long style); + WindowImplX11(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings); //////////////////////////////////////////////////////////// /// \brief Destructor diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index 83c3594e..c0c29c35 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -78,9 +78,10 @@ public : /// \param mode Video mode to use /// \param title Title of the window /// \param style Window style (resizable, fixed, or fullscren) + /// \param settings Additional settings for the underlying OpenGL context /// //////////////////////////////////////////////////////////// - WindowImplCocoa(VideoMode mode, const String& title, unsigned long style); + WindowImplCocoa(VideoMode mode, const String& title, unsigned long style, const ContextSettings& settings); //////////////////////////////////////////////////////////// /// \brief Destructor diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index ca5c01bd..a3bea49d 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -81,9 +81,10 @@ WindowImplCocoa::WindowImplCocoa(WindowHandle handle) //////////////////////////////////////////////////////////// -WindowImplCocoa::WindowImplCocoa(VideoMode mode, - const String& title, - unsigned long style) +WindowImplCocoa::WindowImplCocoa(VideoMode mode, + const String& title, + unsigned long style, + const ContextSettings& /*settings*/) : m_showCursor(true) { // Transform the app process. diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 47003465..6f6d743b 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -86,7 +86,7 @@ m_surrogate (0) //////////////////////////////////////////////////////////// -WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style) : +WindowImplWin32::WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& /*settings*/) : m_handle (NULL), m_callback (0), m_cursor (NULL), diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index 746e72aa..b6ca9751 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -60,9 +60,10 @@ public : /// \param mode Video mode to use /// \param title Title of the window /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context /// //////////////////////////////////////////////////////////// - WindowImplWin32(VideoMode mode, const String& title, Uint32 style); + WindowImplWin32(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); //////////////////////////////////////////////////////////// /// \brief Destructor diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 71f71b2c..0970c986 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -114,7 +114,7 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con style |= Style::Titlebar; // Recreate the window implementation - m_impl = priv::WindowImpl::create(mode, title, style); + m_impl = priv::WindowImpl::create(mode, title, style, settings); // Recreate the context m_context = priv::GlContext::create(settings, m_impl, mode.bitsPerPixel); diff --git a/src/SFML/Window/WindowImpl.cpp b/src/SFML/Window/WindowImpl.cpp index d5091598..1b336c75 100644 --- a/src/SFML/Window/WindowImpl.cpp +++ b/src/SFML/Window/WindowImpl.cpp @@ -55,9 +55,9 @@ namespace sf namespace priv { //////////////////////////////////////////////////////////// -WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style) +WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) { - return new WindowImplType(mode, title, style); + return new WindowImplType(mode, title, style, settings); } diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 779afd5c..4d061a1e 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -59,11 +60,12 @@ public : /// \param mode Video mode to use /// \param title Title of the window /// \param style Window style + /// \param settings Additional settings for the underlying OpenGL context /// /// \return Pointer to the created window (don't forget to delete it) /// //////////////////////////////////////////////////////////// - static WindowImpl* create(VideoMode mode, const String& title, Uint32 style); + static WindowImpl* create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); //////////////////////////////////////////////////////////// /// \brief Create a new window depending on to the current OS