Better handling of X display in OpenGL contexts, which solves some multithreading issues (on Linux)

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1191 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-07-24 13:41:28 +00:00
parent 42a3027d7c
commit d3125eecd7
4 changed files with 66 additions and 36 deletions

View File

@ -26,7 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Linux/ContextGLX.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/Window/Linux/WindowImplX11.hpp>
#include <SFML/OpenGL.hpp>
#include <SFML/Window/glext/glxext.h>
#include <iostream>
@ -43,17 +43,20 @@ ContextGLX::ContextGLX(ContextGLX* shared) :
myWindow (0),
myContext (NULL),
myOwnsWindow(true)
{
{
// Open a connection with the X server
myDisplay = XOpenDisplay(NULL);
// Create a dummy window (disabled and hidden)
int screen = DefaultScreen(myDisplay.GetDisplay());
myWindow = XCreateWindow(myDisplay.GetDisplay(),
RootWindow(myDisplay.GetDisplay(), screen),
int screen = DefaultScreen(myDisplay);
myWindow = XCreateWindow(myDisplay,
RootWindow(myDisplay, screen),
0, 0,
1, 1,
0,
DefaultDepth(myDisplay.GetDisplay(), screen),
DefaultDepth(myDisplay, screen),
InputOutput,
DefaultVisual(myDisplay.GetDisplay(), screen),
DefaultVisual(myDisplay, screen),
0, NULL);
// Create the context
@ -72,7 +75,10 @@ ContextGLX::ContextGLX(ContextGLX* shared, const WindowImpl* owner, unsigned int
myWindow (0),
myContext (NULL),
myOwnsWindow(false)
{
{
// Use the same context as the owner window (important!)
myDisplay = static_cast<const WindowImplX11*>(owner)->GetDisplay();
// Get the owner window and its device context
myWindow = static_cast<Window>(owner->GetHandle());
@ -95,15 +101,21 @@ ContextGLX::~ContextGLX()
if (myContext)
{
if (glXGetCurrentContext() == myContext)
glXMakeCurrent(myDisplay.GetDisplay(), None, NULL);
glXDestroyContext(myDisplay.GetDisplay(), myContext);
glXMakeCurrent(myDisplay, None, NULL);
glXDestroyContext(myDisplay, myContext);
}
// Destroy the window if we own it
if (myWindow && myOwnsWindow)
{
XDestroyWindow(myDisplay.GetDisplay(), myWindow);
XFlush(myDisplay.GetDisplay());
XDestroyWindow(myDisplay, myWindow);
XFlush(myDisplay);
}
// Close the connection with the X server
if (myOwnsWindow)
{
XCloseDisplay(myDisplay);
}
}
@ -118,7 +130,7 @@ bool ContextGLX::MakeCurrent(bool active)
if (myContext)
{
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay.GetDisplay(), myWindow, myContext) != 0;
return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
else
return true;
}
@ -130,7 +142,7 @@ bool ContextGLX::MakeCurrent(bool active)
else
{
if (glXGetCurrentContext() == myContext)
return glXMakeCurrent(myDisplay.GetDisplay(), None, NULL) != 0;
return glXMakeCurrent(myDisplay, None, NULL) != 0;
else
return true;
}
@ -143,7 +155,7 @@ bool ContextGLX::MakeCurrent(bool active)
void ContextGLX::Display()
{
if (myWindow)
glXSwapBuffers(myDisplay.GetDisplay(), myWindow);
glXSwapBuffers(myDisplay, myWindow);
}
@ -178,7 +190,7 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
// Get the attributes of the target window
XWindowAttributes windowAttributes;
if (XGetWindowAttributes(myDisplay.GetDisplay(), myWindow, &windowAttributes) == 0)
if (XGetWindowAttributes(myDisplay, myWindow, &windowAttributes) == 0)
{
std::cerr << "Failed to get the window attributes" << std::endl;
return;
@ -188,11 +200,11 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
XVisualInfo tpl;
tpl.depth = windowAttributes.depth;
tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
tpl.screen = DefaultScreen(myDisplay.GetDisplay());
tpl.screen = DefaultScreen(myDisplay);
// Get all the visuals matching the template
int nbVisuals = 0;
XVisualInfo* visuals = XGetVisualInfo(myDisplay.GetDisplay(), VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
XVisualInfo* visuals = XGetVisualInfo(myDisplay, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
if (!visuals || (nbVisuals == 0))
{
if (visuals)
@ -210,16 +222,16 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
{
// Get the current visual attributes
int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples;
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_RGBA, &RGBA);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_RED_SIZE, &red);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_GREEN_SIZE, &green);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_BLUE_SIZE, &blue);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_ALPHA_SIZE, &alpha);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_STENCIL_SIZE, &stencil);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetConfig(myDisplay.GetDisplay(), &visuals[i], GLX_SAMPLES_ARB, &samples);
glXGetConfig(myDisplay, &visuals[i], GLX_RGBA, &RGBA);
glXGetConfig(myDisplay, &visuals[i], GLX_DOUBLEBUFFER, &doubleBuffer);
glXGetConfig(myDisplay, &visuals[i], GLX_RED_SIZE, &red);
glXGetConfig(myDisplay, &visuals[i], GLX_GREEN_SIZE, &green);
glXGetConfig(myDisplay, &visuals[i], GLX_BLUE_SIZE, &blue);
glXGetConfig(myDisplay, &visuals[i], GLX_ALPHA_SIZE, &alpha);
glXGetConfig(myDisplay, &visuals[i], GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay, &visuals[i], GLX_STENCIL_SIZE, &stencil);
glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);
glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLES_ARB, &samples);
// First check the mandatory parameters
if ((RGBA == 0) || (doubleBuffer == 0))
@ -263,7 +275,7 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
GLXContext toShare = shared ? shared->myContext : NULL;
// Create the context
myContext = glXCreateContext(myDisplay.GetDisplay(), bestVisual, toShare, true);
myContext = glXCreateContext(myDisplay, bestVisual, toShare, true);
if (!myContext)
{
std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
@ -272,15 +284,15 @@ void ContextGLX::CreateContext(ContextGLX* shared, unsigned int bitsPerPixel, co
// Update the creation settings from the chosen format
int depth, stencil;
glXGetConfig(myDisplay.GetDisplay(), bestVisual, GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay.GetDisplay(), bestVisual, GLX_STENCIL_SIZE, &stencil);
glXGetConfig(myDisplay, bestVisual, GLX_DEPTH_SIZE, &depth);
glXGetConfig(myDisplay, bestVisual, GLX_STENCIL_SIZE, &stencil);
mySettings.DepthBits = static_cast<unsigned int>(depth);
mySettings.StencilBits = static_cast<unsigned int>(stencil);
// Change the target window's colormap so that it matches the context's one
::Window root = RootWindow(myDisplay.GetDisplay(), DefaultScreen(myDisplay.GetDisplay()));
Colormap colorMap = XCreateColormap(myDisplay.GetDisplay(), root, bestVisual->visual, AllocNone);
XSetWindowColormap(myDisplay.GetDisplay(), myWindow, colorMap);
::Window root = RootWindow(myDisplay, DefaultScreen(myDisplay));
Colormap colorMap = XCreateColormap(myDisplay, root, bestVisual->visual, AllocNone);
XSetWindowColormap(myDisplay, myWindow, colorMap);
// Free the temporary visuals array
XFree(visuals);

View File

@ -29,7 +29,6 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/ContextGL.hpp>
#include <SFML/Window/Linux/DisplayRef.hpp>
#include <X11/Xlib.h>
#include <GL/glx.h>
@ -111,7 +110,7 @@ private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
DisplayRef myDisplay; ///< Connection to the X server
::Display* myDisplay; ///< Connection to the X server
::Window myWindow; ///< Window to which the context is attached
GLXContext myContext; ///< OpenGL context
bool myOwnsWindow; ///< Do we own the window associated to the context?

View File

@ -262,6 +262,16 @@ WindowImplX11::~WindowImplX11()
XFlush(myDisplay);
}
}
////////////////////////////////////////////////////////////
/// Get the display used by the window.
/// This functions is meant to be used internally by ContextGLX.
////////////////////////////////////////////////////////////
::Display* WindowImplX11::GetDisplay() const
{
return myDisplay;
}
////////////////////////////////////////////////////////////

View File

@ -71,6 +71,15 @@ public :
////////////////////////////////////////////////////////////
~WindowImplX11();
////////////////////////////////////////////////////////////
/// Get the display used by the window.
/// This functions is meant to be used internally by ContextGLX.
///
/// \return Pointer to the X display of the window
///
////////////////////////////////////////////////////////////
::Display* GetDisplay() const;
private :
////////////////////////////////////////////////////////////