mirror of
https://github.com/SFML/SFML.git
synced 2024-11-25 04:41:05 +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
|
||||
////////////////////////////////////////////////////////////
|
||||
#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);
|
||||
|
@ -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?
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
@ -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 :
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
|
Loading…
Reference in New Issue
Block a user