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

View File

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

View File

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

View File

@ -71,6 +71,15 @@ public :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
~WindowImplX11(); ~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 : private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////