mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
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:
parent
42a3027d7c
commit
d3125eecd7
@ -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>
|
||||||
@ -43,17 +43,20 @@ ContextGLX::ContextGLX(ContextGLX* shared) :
|
|||||||
myWindow (0),
|
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
|
||||||
@ -72,7 +75,10 @@ ContextGLX::ContextGLX(ContextGLX* shared, const WindowImpl* owner, unsigned int
|
|||||||
myWindow (0),
|
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);
|
||||||
|
@ -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?
|
||||||
|
@ -262,6 +262,16 @@ WindowImplX11::~WindowImplX11()
|
|||||||
XFlush(myDisplay);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
@ -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 :
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user