Fixed ContextSettings ignored on Linux when creating a window (#35)
This commit is contained in:
parent
6b50691551
commit
68748d2de1
@ -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<unsigned int>(depth);
|
||||
m_settings.stencilBits = static_cast<unsigned int>(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
|
||||
|
@ -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 :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -27,6 +27,7 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
|
||||
#include <SFML/Window/Linux/WindowImplX11.hpp>
|
||||
#include <SFML/Window/Linux/GlxContext.hpp>
|
||||
#include <SFML/Window/Linux/Display.hpp>
|
||||
#include <SFML/System/Utf.hpp>
|
||||
#include <SFML/System/Err.hpp>
|
||||
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <SFML/Window/JoystickImpl.hpp>
|
||||
#include <SFML/Window/VideoMode.hpp>
|
||||
#include <SFML/Window/WindowHandle.hpp>
|
||||
#include <SFML/Window/ContextSettings.hpp>
|
||||
#include <queue>
|
||||
#include <set>
|
||||
|
||||
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user