Added Linux implementation of OpenGL context (work in progress)

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1066 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-03-28 18:04:18 +00:00
parent 9c370e38da
commit 19ae448f13
8 changed files with 738 additions and 473 deletions

View File

@ -0,0 +1,294 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Linux/ContextGLX.hpp>
#include <SFML/Window/WindowImpl.hpp>
#include <GL/gl.h>
#include <SFML/Window/glext/glxext.h>
#include <SFML/Window/glext/glext.h>
#include <iostream>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Create a new context, not associated to a window
////////////////////////////////////////////////////////////
ContextGLX::ContextGLX(ContextGLX* Shared) :
myWindow (NULL),
myContext (NULL)/*,
myOwnsWindow(true)*/
{
// Create the rendering context
XVisualInfo Visual;
CreateContext(Shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
// Create a new color map with the chosen visual
/*Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
// Define the window attributes
XSetWindowAttributes Attributes;
Attributes.colormap = ColMap;
// Create a dummy window (disabled and hidden)
myWindow = XCreateWindow(ourDisplay,
RootWindow(ourDisplay, ourScreen),
0, 0,
myWidth, myHeight,
0,
Visual.depth,
InputOutput,
Visual.visual,
CWColormap, &Attributes);*/
}
////////////////////////////////////////////////////////////
/// Create a new context attached to a window
////////////////////////////////////////////////////////////
ContextGLX::ContextGLX(ContextWGL* Shared, const WindowImpl* Owner, unsigned int BitsPerPixel, const ContextSettings& Settings) :
myWindow (NULL),
myContext (NULL),/*
myOwnsWindow(false)*/
{
// Get the owner window and its device context
myWindow = static_cast<Window>(Owner->GetHandle());
// Create the context
if (myWindow)
CreateContext(Shared, BitsPerPixel, Settings);
}
////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
ContextGLX::~ContextGLX()
{
// Destroy the OpenGL context
if (myContext)
{
if (glXGetCurrentContext() == myContext)
glXMakeCurrent(myDisplay.GetDisplay(), None, NULL);
glXDestroyContext(myContext);
}
// Destroy the window if we own it
/*if (myWindow && myOwnsWindow)
{
XDestroyWindow(myDisplay.GetDisplay(), myWindow);
XFlush(myDisplay.GetDisplay());
}*/
}
////////////////////////////////////////////////////////////
/// \see Context::MakeCurrent
////////////////////////////////////////////////////////////
bool ContextGLX::MakeCurrent(bool Active)
{
if (Active)
{
if (myWindow && myContext)
{
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay.GetDisplay(), myWindow, myContext) != 0;
else
return true;
}
else
{
return false;
}
}
else
{
if (glXGetCurrentContext() == myContext)
return wglMakeCurrent(myDisplay.GetDisplay(), None, NULL) != 0;
else
return true;
}
}
////////////////////////////////////////////////////////////
/// \see Context::Display
////////////////////////////////////////////////////////////
void ContextGLX::Display()
{
if (myWindow)
glXSwapBuffers(myDisplay.GetDisplay(), myWindow);
}
////////////////////////////////////////////////////////////
/// \see Context::UseVerticalSync
////////////////////////////////////////////////////////////
void ContextGLX::UseVerticalSync(bool Enabled)
{
const GLubyte* ProcAddress = reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI");
PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(ProcAddress));
if (glXSwapIntervalSGI)
glXSwapIntervalSGI(Enabled ? 1 : 0);
}
////////////////////////////////////////////////////////////
/// Check if a context is active on the current thread
////////////////////////////////////////////////////////////
bool ContextGLX::IsContextActive()
{
return glXGetCurrentContext() != NULL;
}
////////////////////////////////////////////////////////////
/// Create the context
////////////////////////////////////////////////////////////
void ContextGLX::CreateContext(ContextGLX* Shared, unsigned int BitsPerPixel, const ContextSettings& Settings)
{
XVisualInfo Template;
Template.screen = DefaultScreen(myDisplayRef.GetDisplay());
if (myWindow)
{
// Get the attributes of the target window
XWindowAttributes WindowAttributes;
if (XGetWindowAttributes(myDisplayRef.GetDisplay(), myWindow, &WindowAttributes) == 0)
{
std::cerr << "Failed to get the window attributes" << std::endl;
return;
}
// Setup the visual infos to match
Template.depth = WindowAttributes.depth;
Template.visualid = XVisualIDFromVisual(WindowAttributes.visual);
}
// Get all the visuals matching the template
int NbVisuals = 0;
XVisualInfo* Visuals = XGetVisualInfo(myDisplay.GetDisplay(), VisualDepthMask | VisualIDMask | VisualScreenMask, &Template, &NbVisuals);
if (!Visuals || (NbVisuals == 0))
{
if (Visuals)
XFree(Visuals);
std::cerr << "There is no valid visual for the selected screen" << std::endl;
return;
}
// Find the best visual
int BestScore = 0xFFFF;
XVisualInfo* BestVisual = NULL;
while (!BestVisual)
{
for (int i = 0; i < NbVisuals; ++i)
{
// Get the current visual attributes
int RGBA, DoubleBuffer, Red, Green, Blue, Alpha, Depth, Stencil, MultiSampling, Samples;
glXGetConfig(ourDisplay, &Visuals[i], GLX_RGBA, &RGBA);
glXGetConfig(ourDisplay, &Visuals[i], GLX_DOUBLEBUFFER, &DoubleBuffer);
glXGetConfig(ourDisplay, &Visuals[i], GLX_RED_SIZE, &Red);
glXGetConfig(ourDisplay, &Visuals[i], GLX_GREEN_SIZE, &Green);
glXGetConfig(ourDisplay, &Visuals[i], GLX_BLUE_SIZE, &Blue);
glXGetConfig(ourDisplay, &Visuals[i], GLX_ALPHA_SIZE, &Alpha);
glXGetConfig(ourDisplay, &Visuals[i], GLX_DEPTH_SIZE, &Depth);
glXGetConfig(ourDisplay, &Visuals[i], GLX_STENCIL_SIZE, &Stencil);
glXGetConfig(ourDisplay, &Visuals[i], GLX_SAMPLE_BUFFERS_ARB, &MultiSampling);
glXGetConfig(ourDisplay, &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, mySettings, Color, Depth, Stencil, MultiSampling ? Samples : 0);
// Keep it if it's better than the current best
if (Score < BestScore)
{
BestScore = Score;
BestVisual = &Visuals[i];
}
}
// If no visual has been found, try a lower level of antialiasing
if (!BestVisual)
{
if (Params.AntialiasingLevel > 2)
{
std::cerr << "Failed to find a pixel format supporting "
<< Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
Params.AntialiasingLevel = 2;
}
else if (Params.AntialiasingLevel > 0)
{
std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
Params.AntialiasingLevel = 0;
}
else
{
std::cerr << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl;
return;
}
}
}
// Get the context to share display lists with
GLXContext ToShare = Shared ? Shared->myContext : NULL;
// Create the context
myContext = glXCreateContext(myDisplay.GetDisplay(), BestVisual, ToShare, true);
if (!myContext)
{
std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
return;
}
// 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);
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
if (myWindow)
{
::Window Root = RootWindow(myDisplay.GetDisplay(), DefaultScreen(myDisplay.GetDisplay()))
Colormap ColMap = XCreateColormap(myDisplay.GetDisplay(), Root, BestVisual->visual, AllocNone);
XSetWindowColormap(myDisplay.GetDisplay(), myWindow, ColMap);
}
// Free the temporary visuals array
XFree(Visuals);
}
} // namespace priv
} // namespace sf

View File

@ -0,0 +1,138 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_CONTEXTGLX_HPP
#define SFML_CONTEXTGLX_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Context.hpp>
#include <SFML/Window/Linux/DisplayRef.hpp>
#include <X11/Xlib.h>
#include <GL/glx.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Linux (GLX) implementation of OpenGL contexts
////////////////////////////////////////////////////////////
class ContextGLX : public Context
{
public :
////////////////////////////////////////////////////////////
/// Create a new context, not associated to a window
///
/// \param Shared : Context to share the new one with (can be NULL)
///
////////////////////////////////////////////////////////////
ContextGLX(ContextGLX* Shared);
////////////////////////////////////////////////////////////
/// Create a new context attached to a window
///
/// \param Shared : Context to share the new one with (can be NULL)
/// \param Owner : Pointer to the owner window
/// \param BitsPerPixel : Pixel depth (in bits per pixel)
/// \param Settings : Creation parameters
///
////////////////////////////////////////////////////////////
ContextGLX(ContextGLX* Shared, const WindowImpl* Owner, unsigned int BitsPerPixel, const ContextSettings& Settings);
////////////////////////////////////////////////////////////
/// Destructor
///
////////////////////////////////////////////////////////////
~ContextGLX();
////////////////////////////////////////////////////////////
/// \see Context::MakeCurrent
///
////////////////////////////////////////////////////////////
virtual bool MakeCurrent(bool Active);
////////////////////////////////////////////////////////////
/// \see Context::Display
///
////////////////////////////////////////////////////////////
virtual void Display();
////////////////////////////////////////////////////////////
/// \see Context::UseVerticalSync
///
////////////////////////////////////////////////////////////
virtual void UseVerticalSync(bool Enabled);
////////////////////////////////////////////////////////////
/// Check if a context is active on the current thread
///
/// \return True if there's an active context, false otherwise
///
////////////////////////////////////////////////////////////
static bool IsContextActive();
private :
////////////////////////////////////////////////////////////
/// Create the context
///
/// \param Shared : Context to share the new one with (can be NULL)
/// \param BitsPerPixel : Pixel depth, in bits per pixel
/// \param Settings : Creation parameters
///
////////////////////////////////////////////////////////////
void CreateContext(ContextGLX* Shared, unsigned int BitsPerPixel, const ContextSettings& Settings);
////////////////////////////////////////////////////////////
/// Create the OpenGL rendering context
///
/// \param Mode : Video mode to use
/// \param ChosenVisual : Visual that has been chosen for creating the contexte
/// \param Params : Creation parameters
/// \param Template : Visual infos to match
/// \param Mask : Visual attributes to check in Template
///
/// \return True on success, false on error
///
////////////////////////////////////////////////////////////
//bool CreateContext(XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template = XVisualInfo(), unsigned long Mask = 0);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
DisplayRef myDisplay; ///< Connection to the X server
::Window myWindow; ///< Window to which the context is attached
GLXContext myContext; ///< OpenGL context
//bool myOwnsWindow; ///< Did we create the host window?
};
} // namespace priv
} // namespace sf
#endif // SFML_CONTEXTGLX_HPP

View File

@ -0,0 +1,122 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Linux/DisplayRef.hpp>
#include <iostream>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
::Display* TheDisplay = NULL;
XIM TheInputMethod = NULL;
int RefCount = 0;
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Default constructor
////////////////////////////////////////////////////////////
DisplayRef::DisplayRef()
{
// If the display hasn't been opened yet, open it
if (TheDisplay == NULL)
{
TheDisplay = XOpenDisplay(NULL);
if (TheDisplay)
{
// Create the input method object
TheInputMethod = XOpenIM(TheDisplay, NULL, NULL, NULL);
}
else
{
std::cerr << "Failed to open a connection with the X server" << std::endl;
}
}
// Increase the number of references
RefCount++;
}
////////////////////////////////////////////////////////////
/// Copy constructor
////////////////////////////////////////////////////////////
DisplayRef::DisplayRef(const DisplayRef& Copy)
{
// Increase the number of references
RefCount++;
}
////////////////////////////////////////////////////////////
/// Destructor
////////////////////////////////////////////////////////////
DisplayRef::~DisplayRef()
{
// Decrease the number of references
RefCount--;
// If all references have been destroyed, we can close the display
if (RefCount == 0)
{
// Destroy the input method object
if (TheInputMethod)
XCloseIM(TheInputMethod);
// Close the display
XCloseDisplay(TheDisplay);
}
}
////////////////////////////////////////////////////////////
/// Get the current display
////////////////////////////////////////////////////////////
::Display* DisplayRef::GetDisplay() const
{
return TheDisplay;
}
////////////////////////////////////////////////////////////
/// Get the input method associated to the display
////////////////////////////////////////////////////////////
XIM DisplayRef::GetInputMethod() const
{
return TheInputMethod;
}
} // namespace priv
} // namespace sf

View File

@ -0,0 +1,86 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_DISPLAYREF_HPP
#define SFML_DISPLAYREF_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <X11/Xlib.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Provides an access to the display (connection to the X server)
////////////////////////////////////////////////////////////
class DisplayRef
{
public :
////////////////////////////////////////////////////////////
/// Default constructor
///
////////////////////////////////////////////////////////////
DisplayRef();
////////////////////////////////////////////////////////////
/// Copy constructor
///
/// \param Copy : Instance to copy
///
////////////////////////////////////////////////////////////
DisplayRef(const DisplayRef& Copy);
////////////////////////////////////////////////////////////
/// Destructor
///
////////////////////////////////////////////////////////////
~DisplayRef();
////////////////////////////////////////////////////////////
/// Get the current display
///
/// \return Pointer to the current display
///
////////////////////////////////////////////////////////////
::Display* GetDisplay() const;
////////////////////////////////////////////////////////////
/// Get the input method associated to the display
///
/// \return Input method object
///
////////////////////////////////////////////////////////////
XIM GetInputMethod() const;
};
} // namespace priv
} // namespace sf
#endif // SFML_DISPLAYREF_HPP

View File

@ -26,7 +26,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Linux/VideoModeSupport.hpp> #include <SFML/Window/Linux/VideoModeSupport.hpp>
#include <SFML/Window/Linux/WindowImplX11.hpp> #include <SFML/Window/Linux/DisplayRef.hpp>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <algorithm> #include <algorithm>
@ -45,17 +45,15 @@ void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
// First, clear array to fill // First, clear array to fill
Modes.clear(); Modes.clear();
// Get the display and screen from sfWindowImplUnix // Get an access to the display
WindowImplX11::OpenDisplay(false); DisplayRef Disp;
Display* Disp = WindowImplX11::ourDisplay;
int Screen = WindowImplX11::ourScreen;
// Check if the XRandR extension is present // Check if the XRandR extension is present
int Version; int Version;
if (XQueryExtension(Disp, "RANDR", &Version, &Version, &Version)) if (XQueryExtension(Disp.GetDisplay(), "RANDR", &Version, &Version, &Version))
{ {
// Get the current configuration // Get the current configuration
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp, RootWindow(Disp, Screen)); XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), DefaultScreen(Disp.GetDisplay())));
if (Config) if (Config)
{ {
// Get the available screen sizes // Get the available screen sizes
@ -99,17 +97,15 @@ VideoMode VideoModeSupport::GetDesktopVideoMode()
{ {
VideoMode DesktopMode; VideoMode DesktopMode;
// Get the display and screen from sfWindowImplUnix // Get an access to the display
WindowImplX11::OpenDisplay(false); DisplayRef Disp;
Display* Disp = WindowImplX11::ourDisplay;
int Screen = WindowImplX11::ourScreen;
// Check if the XRandR extension is present // Check if the XRandR extension is present
int Version; int Version;
if (XQueryExtension(Disp, "RANDR", &Version, &Version, &Version)) if (XQueryExtension(Disp.GetDisplay(), "RANDR", &Version, &Version, &Version))
{ {
// Get the current configuration // Get the current configuration
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp, RootWindow(Disp, Screen)); XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), DefaultScreen(Disp.GetDisplay())));
if (Config) if (Config)
{ {
// Get the current video mode // Get the current video mode

View File

@ -27,8 +27,6 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None) #include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Linux/WindowImplX11.hpp> #include <SFML/Window/Linux/WindowImplX11.hpp>
#include <SFML/Window/glext/glxext.h>
#include <SFML/Window/glext/glext.h>
#include <SFML/System/Unicode.hpp> #include <SFML/System/Unicode.hpp>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
@ -37,89 +35,37 @@
#include <vector> #include <vector>
////////////////////////////////////////////////////////////
// Private data
////////////////////////////////////////////////////////////
namespace
{
WindowImplX11* FullscreenWindow = NULL;
unsigned long EventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask;
}
namespace sf namespace sf
{ {
namespace priv namespace priv
{ {
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
Display* WindowImplX11::ourDisplay = NULL;
int WindowImplX11::ourScreen = 0;
WindowImplX11* WindowImplX11::ourFullscreenWindow = NULL;
unsigned int WindowImplX11::ourWindowsCount = 0;
XIM WindowImplX11::ourInputMethod = NULL;
unsigned long WindowImplX11::ourEventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask;
////////////////////////////////////////////////////////////
/// Default constructor
/// (creates a dummy window to provide a valid OpenGL context)
////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11() :
myWindow (0),
myIsExternal (false),
myGLContext (NULL),
myAtomClose (0),
myOldVideoMode(-1),
myHiddenCursor(0),
myInputContext(NULL),
myKeyRepeat (true)
{
// Open the display at first call
if (!OpenDisplay())
return;
// Use small dimensions
myWidth = 1;
myHeight = 1;
// Create the rendering context
XVisualInfo Visual;
WindowSettings Params(0, 0, 0);
if (!CreateContext(VideoMode(myWidth, myHeight, 32), Visual, Params))
return;
// Create a new color map with the chosen visual
Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
// Define the window attributes
XSetWindowAttributes Attributes;
Attributes.colormap = ColMap;
// Create a dummy window (disabled and hidden)
myWindow = XCreateWindow(ourDisplay,
RootWindow(ourDisplay, ourScreen),
0, 0,
myWidth, myHeight,
0,
Visual.depth,
InputOutput,
Visual.visual,
CWColormap, &Attributes);
// Don't activate the dummy context by default
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the window implementation from an existing control /// Create the window implementation from an existing control
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(WindowHandle Handle, WindowSettings& Params) : WindowImplX11::WindowImplX11(WindowHandle Handle) :
myWindow (0), myWindow (0),
myIsExternal (true), myIsExternal (true),
myGLContext (NULL),
myAtomClose (0), myAtomClose (0),
myOldVideoMode(-1), myOldVideoMode(-1),
myHiddenCursor(0), myHiddenCursor(0),
myInputContext(NULL), myInputContext(NULL),
myKeyRepeat (true) myKeyRepeat (true)
{ {
// Open the display at first call // Get the display and screen
if (!OpenDisplay()) myDisplay = myDisplayRef.GetDisplay();
return; myScreen = DefaultScreen(myDisplay);
// Save the window handle // Save the window handle
myWindow = Handle; myWindow = Handle;
@ -128,7 +74,7 @@ myKeyRepeat (true)
{ {
// Get the window size // Get the window size
XWindowAttributes WindowAttributes; XWindowAttributes WindowAttributes;
if (XGetWindowAttributes(ourDisplay, 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;
@ -136,24 +82,8 @@ myKeyRepeat (true)
myWidth = WindowAttributes.width; myWidth = WindowAttributes.width;
myHeight = WindowAttributes.height; myHeight = WindowAttributes.height;
// Setup the visual infos to match
XVisualInfo Template;
Template.depth = WindowAttributes.depth;
Template.visualid = XVisualIDFromVisual(WindowAttributes.visual);
unsigned long Mask = VisualDepthMask | VisualIDMask;
// Create the rendering context
VideoMode Mode(myWidth, myHeight, VideoMode::GetDesktopMode().BitsPerPixel);
XVisualInfo Visual;
if (!CreateContext(Mode, Visual, Params, Template, Mask))
return;
// Create a new color map with the chosen visual
Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
XSetWindowColormap(ourDisplay, myWindow, ColMap);
// Make sure the window is listening to all the requiered events // Make sure the window is listening to all the requiered events
XSelectInput(ourDisplay, myWindow, ourEventMask & ~ButtonPressMask); XSelectInput(myDisplay, myWindow, EventMask & ~ButtonPressMask);
// Do some common initializations // Do some common initializations
Initialize(); Initialize();
@ -164,7 +94,7 @@ myKeyRepeat (true)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the window implementation /// Create the window implementation
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplX11::WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params) : WindowImplX11::WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle) :
myWindow (0), myWindow (0),
myIsExternal (false), myIsExternal (false),
myGLContext (NULL), myGLContext (NULL),
@ -174,17 +104,13 @@ myHiddenCursor(0),
myInputContext(NULL), myInputContext(NULL),
myKeyRepeat (true) myKeyRepeat (true)
{ {
// Open the display at first call
if (!OpenDisplay())
return;
// Compute position and size // Compute position and size
int Left, Top; int Left, Top;
bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0; bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0;
if (!Fullscreen) if (!Fullscreen)
{ {
Left = (DisplayWidth(ourDisplay, ourScreen) - Mode.Width) / 2; Left = (DisplayWidth(myDisplay, myScreen) - Mode.Width) / 2;
Top = (DisplayHeight(ourDisplay, ourScreen) - Mode.Height) / 2; Top = (DisplayHeight(myDisplay, myScreen) - Mode.Height) / 2;
} }
else else
{ {
@ -198,23 +124,14 @@ myKeyRepeat (true)
if (Fullscreen) if (Fullscreen)
SwitchToFullscreen(Mode); SwitchToFullscreen(Mode);
// Create the rendering context
XVisualInfo Visual;
if (!CreateContext(Mode, Visual, Params))
return;
// Create a new color map with the chosen visual
Colormap ColMap = XCreateColormap(ourDisplay, RootWindow(ourDisplay, ourScreen), Visual.visual, AllocNone);
// Define the window attributes // Define the window attributes
XSetWindowAttributes Attributes; XSetWindowAttributes Attributes;
Attributes.event_mask = ourEventMask; Attributes.event_mask = EventMask;
Attributes.colormap = ColMap;
Attributes.override_redirect = Fullscreen; Attributes.override_redirect = Fullscreen;
// Create the window // Create the window
myWindow = XCreateWindow(ourDisplay, myWindow = XCreateWindow(myDisplay,
RootWindow(ourDisplay, ourScreen), RootWindow(myDisplay, myScreen),
Left, Top, Left, Top,
Width, Height, Width, Height,
0, 0,
@ -229,12 +146,12 @@ myKeyRepeat (true)
} }
// Set the window's name // Set the window's name
XStoreName(ourDisplay, myWindow, Title.c_str()); XStoreName(myDisplay, myWindow, Title.c_str());
// Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style) // Set the window's style (tell the windows manager to change our window's decorations and functions according to the requested style)
if (!Fullscreen) if (!Fullscreen)
{ {
Atom WMHintsAtom = XInternAtom(ourDisplay, "_MOTIF_WM_HINTS", false); Atom WMHintsAtom = XInternAtom(myDisplay, "_MOTIF_WM_HINTS", false);
if (WMHintsAtom) if (WMHintsAtom)
{ {
static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0; static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0;
@ -286,7 +203,7 @@ myKeyRepeat (true)
} }
const unsigned char* HintsPtr = reinterpret_cast<const unsigned char*>(&Hints); const unsigned char* HintsPtr = reinterpret_cast<const unsigned char*>(&Hints);
XChangeProperty(ourDisplay, myWindow, WMHintsAtom, WMHintsAtom, 32, PropModeReplace, HintsPtr, 5); XChangeProperty(myDisplay, myWindow, WMHintsAtom, WMHintsAtom, 32, PropModeReplace, HintsPtr, 5);
} }
// This is a hack to force some windows managers to disable resizing // This is a hack to force some windows managers to disable resizing
@ -296,7 +213,7 @@ myKeyRepeat (true)
XSizeHints.flags = PMinSize | PMaxSize; XSizeHints.flags = PMinSize | PMaxSize;
XSizeHints.min_width = XSizeHints.max_width = Width; XSizeHints.min_width = XSizeHints.max_width = Width;
XSizeHints.min_height = XSizeHints.max_height = Height; XSizeHints.min_height = XSizeHints.max_height = Height;
XSetWMNormalHints(ourDisplay, myWindow, &XSizeHints); XSetWMNormalHints(myDisplay, myWindow, &XSizeHints);
} }
} }
@ -306,8 +223,8 @@ myKeyRepeat (true)
// In fullscreen mode, we must grab keyboard and mouse inputs // In fullscreen mode, we must grab keyboard and mouse inputs
if (Fullscreen) if (Fullscreen)
{ {
XGrabPointer(ourDisplay, myWindow, true, 0, GrabModeAsync, GrabModeAsync, myWindow, None, CurrentTime); XGrabPointer(myDisplay, myWindow, true, 0, GrabModeAsync, GrabModeAsync, myWindow, None, CurrentTime);
XGrabKeyboard(ourDisplay, myWindow, true, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabKeyboard(myDisplay, myWindow, true, GrabModeAsync, GrabModeAsync, CurrentTime);
} }
} }
@ -322,38 +239,14 @@ WindowImplX11::~WindowImplX11()
// Destroy the input context // Destroy the input context
if (myInputContext) if (myInputContext)
{
XDestroyIC(myInputContext); XDestroyIC(myInputContext);
}
// Destroy the window // Destroy the window
if (myWindow && !myIsExternal) if (myWindow && !myIsExternal)
{ {
XDestroyWindow(ourDisplay, myWindow); XDestroyWindow(myDisplay, myWindow);
XFlush(ourDisplay); XFlush(myDisplay);
} }
// Close the display
CloseDisplay();
}
////////////////////////////////////////////////////////////
/// Check if there's an active context on the current thread
////////////////////////////////////////////////////////////
bool WindowImplX11::IsContextActive()
{
return glXGetCurrentContext() != NULL;
}
////////////////////////////////////////////////////////////
/// /see WindowImpl::Display
////////////////////////////////////////////////////////////
void WindowImplX11::Display()
{
if (myWindow && myGLContext)
glXSwapBuffers(ourDisplay, myWindow);
} }
@ -364,21 +257,21 @@ void WindowImplX11::ProcessEvents()
{ {
// Process any event in the queue matching our window // Process any event in the queue matching our window
XEvent Event; XEvent Event;
while (XCheckIfEvent(ourDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow))) while (XCheckIfEvent(myDisplay, &Event, &WindowImplX11::CheckEvent, reinterpret_cast<XPointer>(myWindow)))
{ {
// Filter repeated key events // Filter repeated key events
if (Event.type == KeyRelease) if (Event.type == KeyRelease)
{ {
if (XPending(ourDisplay)) if (XPending(myDisplay))
{ {
XEvent NextEvent; XEvent NextEvent;
XPeekEvent(ourDisplay, &NextEvent); XPeekEvent(myDisplay, &NextEvent);
if ((NextEvent.type == KeyPress) && if ((NextEvent.type == KeyPress) &&
(NextEvent.xkey.keycode == Event.xkey.keycode) && (NextEvent.xkey.keycode == Event.xkey.keycode) &&
(NextEvent.xkey.time == Event.xkey.time)) (NextEvent.xkey.time == Event.xkey.time))
{ {
if (!myKeyRepeat) if (!myKeyRepeat)
XNextEvent(ourDisplay, &NextEvent); XNextEvent(myDisplay, &NextEvent);
continue; continue;
} }
} }
@ -389,43 +282,13 @@ void WindowImplX11::ProcessEvents()
} }
////////////////////////////////////////////////////////////
/// /see WindowImpl::SetActive
////////////////////////////////////////////////////////////
void WindowImplX11::SetActive(bool Active) const
{
if (Active)
{
if (myWindow && myGLContext && (glXGetCurrentContext() != myGLContext))
glXMakeCurrent(ourDisplay, myWindow, myGLContext);
}
else
{
if (glXGetCurrentContext() == myGLContext)
glXMakeCurrent(ourDisplay, None, NULL);
}
}
////////////////////////////////////////////////////////////
/// /see WindowImpl::UseVerticalSync
////////////////////////////////////////////////////////////
void WindowImplX11::UseVerticalSync(bool Enabled)
{
const GLubyte* ProcAddress = reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI");
PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(ProcAddress));
if (glXSwapIntervalSGI)
glXSwapIntervalSGI(Enabled ? 1 : 0);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see WindowImpl::ShowMouseCursor /// /see WindowImpl::ShowMouseCursor
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplX11::ShowMouseCursor(bool Show) void WindowImplX11::ShowMouseCursor(bool Show)
{ {
XDefineCursor(ourDisplay, myWindow, Show ? None : myHiddenCursor); XDefineCursor(myDisplay, myWindow, Show ? None : myHiddenCursor);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -434,8 +297,8 @@ void WindowImplX11::ShowMouseCursor(bool Show)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplX11::SetCursorPosition(unsigned int Left, unsigned int Top) void WindowImplX11::SetCursorPosition(unsigned int Left, unsigned int Top)
{ {
XWarpPointer(ourDisplay, None, myWindow, 0, 0, 0, 0, Left, Top); XWarpPointer(myDisplay, None, myWindow, 0, 0, 0, 0, Left, Top);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -444,8 +307,8 @@ void WindowImplX11::SetCursorPosition(unsigned int Left, unsigned int Top)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplX11::SetPosition(int Left, int Top) void WindowImplX11::SetPosition(int Left, int Top)
{ {
XMoveWindow(ourDisplay, myWindow, Left, Top); XMoveWindow(myDisplay, myWindow, Left, Top);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -454,8 +317,8 @@ void WindowImplX11::SetPosition(int Left, int Top)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplX11::SetSize(unsigned int Width, unsigned int Height) void WindowImplX11::SetSize(unsigned int Width, unsigned int Height)
{ {
XResizeWindow(ourDisplay, myWindow, Width, Height); XResizeWindow(myDisplay, myWindow, Width, Height);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -465,11 +328,11 @@ void WindowImplX11::SetSize(unsigned int Width, unsigned int Height)
void WindowImplX11::Show(bool State) void WindowImplX11::Show(bool State)
{ {
if (State) if (State)
XMapWindow(ourDisplay, myWindow); XMapWindow(myDisplay, myWindow);
else else
XUnmapWindow(ourDisplay, myWindow); XUnmapWindow(myDisplay, myWindow);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -499,19 +362,19 @@ void WindowImplX11::SetIcon(unsigned int Width, unsigned int Height, const Uint8
} }
// Create the icon pixmap // Create the icon pixmap
Visual* DefVisual = DefaultVisual(ourDisplay, ourScreen); Visual* DefVisual = DefaultVisual(myDisplay, myScreen);
unsigned int DefDepth = DefaultDepth(ourDisplay, ourScreen); unsigned int DefDepth = DefaultDepth(myDisplay, myScreen);
XImage* IconImage = XCreateImage(ourDisplay, DefVisual, DefDepth, ZPixmap, 0, (char*)IconPixels, Width, Height, 32, 0); XImage* IconImage = XCreateImage(myDisplay, DefVisual, DefDepth, ZPixmap, 0, (char*)IconPixels, Width, Height, 32, 0);
if (!IconImage) if (!IconImage)
{ {
std::cerr << "Failed to set the window's icon" << std::endl; std::cerr << "Failed to set the window's icon" << std::endl;
return; return;
} }
Pixmap IconPixmap = XCreatePixmap(ourDisplay, RootWindow(ourDisplay, ourScreen), Width, Height, DefDepth); Pixmap IconPixmap = XCreatePixmap(myDisplay, RootWindow(myDisplay, myScreen), Width, Height, DefDepth);
XGCValues Values; XGCValues Values;
GC IconGC = XCreateGC(ourDisplay, IconPixmap, 0, &Values); GC IconGC = XCreateGC(myDisplay, IconPixmap, 0, &Values);
XPutImage(ourDisplay, IconPixmap, IconGC, IconImage, 0, 0, 0, 0, Width, Height); XPutImage(myDisplay, IconPixmap, IconGC, IconImage, 0, 0, 0, 0, Width, Height);
XFreeGC(ourDisplay, IconGC); XFreeGC(myDisplay, IconGC);
XDestroyImage(IconImage); XDestroyImage(IconImage);
// Create the mask pixmap (must have 1 bit depth) // Create the mask pixmap (must have 1 bit depth)
@ -531,17 +394,17 @@ void WindowImplX11::SetIcon(unsigned int Width, unsigned int Height, const Uint8
} }
} }
} }
Pixmap MaskPixmap = XCreatePixmapFromBitmapData(ourDisplay, myWindow, (char*)&MaskPixels[0], Width, Height, 1, 0, 1); Pixmap MaskPixmap = XCreatePixmapFromBitmapData(myDisplay, myWindow, (char*)&MaskPixels[0], Width, Height, 1, 0, 1);
// Send our new icon to the window through the WMHints // Send our new icon to the window through the WMHints
XWMHints* Hints = XAllocWMHints(); XWMHints* Hints = XAllocWMHints();
Hints->flags = IconPixmapHint | IconMaskHint; Hints->flags = IconPixmapHint | IconMaskHint;
Hints->icon_pixmap = IconPixmap; Hints->icon_pixmap = IconPixmap;
Hints->icon_mask = MaskPixmap; Hints->icon_mask = MaskPixmap;
XSetWMHints(ourDisplay, myWindow, Hints); XSetWMHints(myDisplay, myWindow, Hints);
XFree(Hints); XFree(Hints);
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -552,10 +415,10 @@ void WindowImplX11::SwitchToFullscreen(const VideoMode& Mode)
{ {
// Check if the XRandR extension is present // Check if the XRandR extension is present
int Version; int Version;
if (XQueryExtension(ourDisplay, "RANDR", &Version, &Version, &Version)) if (XQueryExtension(myDisplay, "RANDR", &Version, &Version, &Version))
{ {
// Get the current configuration // Get the current configuration
XRRScreenConfiguration* Config = XRRGetScreenInfo(ourDisplay, RootWindow(ourDisplay, ourScreen)); XRRScreenConfiguration* Config = XRRGetScreenInfo(myDisplay, RootWindow(myDisplay, myScreen));
if (Config) if (Config)
{ {
// Get the current rotation // Get the current rotation
@ -573,10 +436,10 @@ void WindowImplX11::SwitchToFullscreen(const VideoMode& Mode)
if ((Sizes[i].width == static_cast<int>(Mode.Width)) && (Sizes[i].height == static_cast<int>(Mode.Height))) if ((Sizes[i].width == static_cast<int>(Mode.Width)) && (Sizes[i].height == static_cast<int>(Mode.Height)))
{ {
// Switch to fullscreen mode // Switch to fullscreen mode
XRRSetScreenConfig(ourDisplay, Config, RootWindow(ourDisplay, ourScreen), i, CurrentRotation, CurrentTime); XRRSetScreenConfig(myDisplay, Config, RootWindow(myDisplay, myScreen), i, CurrentRotation, CurrentTime);
// Set "this" as the current fullscreen window // Set "this" as the current fullscreen window
ourFullscreenWindow = this; FullscreenWindow = this;
break; break;
} }
} }
@ -599,124 +462,20 @@ void WindowImplX11::SwitchToFullscreen(const VideoMode& Mode)
} }
////////////////////////////////////////////////////////////
/// Create the OpenGL rendering context
////////////////////////////////////////////////////////////
bool WindowImplX11::CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template, unsigned long Mask)
{
// Get all the visuals matching the template
Template.screen = ourScreen;
int NbVisuals = 0;
XVisualInfo* Visuals = XGetVisualInfo(ourDisplay, Mask | VisualScreenMask, &Template, &NbVisuals);
if (!Visuals || (NbVisuals == 0))
{
if (Visuals)
XFree(Visuals);
std::cerr << "There is no valid visual for the selected screen" << std::endl;
return false;
}
// Find the best visual
int BestScore = 0xFFFF;
XVisualInfo* BestVisual = NULL;
while (!BestVisual)
{
for (int i = 0; i < NbVisuals; ++i)
{
// Get the current visual attributes
int RGBA, DoubleBuffer, Red, Green, Blue, Alpha, Depth, Stencil, MultiSampling, Samples;
glXGetConfig(ourDisplay, &Visuals[i], GLX_RGBA, &RGBA);
glXGetConfig(ourDisplay, &Visuals[i], GLX_DOUBLEBUFFER, &DoubleBuffer);
glXGetConfig(ourDisplay, &Visuals[i], GLX_RED_SIZE, &Red);
glXGetConfig(ourDisplay, &Visuals[i], GLX_GREEN_SIZE, &Green);
glXGetConfig(ourDisplay, &Visuals[i], GLX_BLUE_SIZE, &Blue);
glXGetConfig(ourDisplay, &Visuals[i], GLX_ALPHA_SIZE, &Alpha);
glXGetConfig(ourDisplay, &Visuals[i], GLX_DEPTH_SIZE, &Depth);
glXGetConfig(ourDisplay, &Visuals[i], GLX_STENCIL_SIZE, &Stencil);
glXGetConfig(ourDisplay, &Visuals[i], GLX_SAMPLE_BUFFERS_ARB, &MultiSampling);
glXGetConfig(ourDisplay, &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 = EvaluateConfig(Mode, Params, Color, Depth, Stencil, MultiSampling ? Samples : 0);
// Keep it if it's better than the current best
if (Score < BestScore)
{
BestScore = Score;
BestVisual = &Visuals[i];
}
}
// If no visual has been found, try a lower level of antialiasing
if (!BestVisual)
{
if (Params.AntialiasingLevel > 2)
{
std::cerr << "Failed to find a pixel format supporting "
<< Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
Params.AntialiasingLevel = 2;
}
else if (Params.AntialiasingLevel > 0)
{
std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
Params.AntialiasingLevel = 0;
}
else
{
std::cerr << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl;
return false;
}
}
}
// Create the OpenGL context
myGLContext = glXCreateContext(ourDisplay, BestVisual, glXGetCurrentContext(), true);
if (myGLContext == NULL)
{
std::cerr << "Failed to create an OpenGL context for this window" << std::endl;
return false;
}
// Update the creation settings from the chosen format
int Depth, Stencil;
glXGetConfig(ourDisplay, BestVisual, GLX_DEPTH_SIZE, &Depth);
glXGetConfig(ourDisplay, BestVisual, GLX_STENCIL_SIZE, &Stencil);
Params.DepthBits = static_cast<unsigned int>(Depth);
Params.StencilBits = static_cast<unsigned int>(Stencil);
// Assign the chosen visual, and free the temporary visuals array
ChosenVisual = *BestVisual;
XFree(Visuals);
// Activate the context
SetActive(true);
// Enable multisampling if needed
if (Params.AntialiasingLevel > 0)
glEnable(GL_MULTISAMPLE_ARB);
return true;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Do some common initializations after the window has been created /// Do some common initializations after the window has been created
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void WindowImplX11::Initialize() void WindowImplX11::Initialize()
{ {
// Get the atom defining the close event // Get the atom defining the close event
myAtomClose = XInternAtom(ourDisplay, "WM_DELETE_WINDOW", false); myAtomClose = XInternAtom(myDisplay, "WM_DELETE_WINDOW", false);
XSetWMProtocols(ourDisplay, myWindow, &myAtomClose, 1); XSetWMProtocols(myDisplay, myWindow, &myAtomClose, 1);
// Create the input context // Create the input context
if (ourInputMethod) XIM InputMethod = myDisplayRef.GetInputMethod();
if (InputMethod)
{ {
myInputContext = XCreateIC(ourInputMethod, myInputContext = XCreateIC(InputMethod,
XNClientWindow, myWindow, XNClientWindow, myWindow,
XNFocusWindow, myWindow, XNFocusWindow, myWindow,
XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
@ -727,17 +486,14 @@ void WindowImplX11::Initialize()
} }
// Show the window // Show the window
XMapWindow(ourDisplay, myWindow); XMapWindow(myDisplay, myWindow);
XFlush(ourDisplay); XFlush(myDisplay);
// Create the hiden cursor // Create the hiden cursor
CreateHiddenCursor(); CreateHiddenCursor();
// Set our context as the current OpenGL context for rendering
SetActive();
// Flush the commands queue // Flush the commands queue
XFlush(ourDisplay); XFlush(myDisplay);
} }
@ -747,19 +503,19 @@ void WindowImplX11::Initialize()
void WindowImplX11::CreateHiddenCursor() void WindowImplX11::CreateHiddenCursor()
{ {
// Create the cursor's pixmap (1x1 pixels) // Create the cursor's pixmap (1x1 pixels)
Pixmap CursorPixmap = XCreatePixmap(ourDisplay, myWindow, 1, 1, 1); Pixmap CursorPixmap = XCreatePixmap(myDisplay, myWindow, 1, 1, 1);
GC GraphicsContext = XCreateGC(ourDisplay, CursorPixmap, 0, NULL); GC GraphicsContext = XCreateGC(myDisplay, CursorPixmap, 0, NULL);
XDrawPoint(ourDisplay, CursorPixmap, GraphicsContext, 0, 0); XDrawPoint(myDisplay, CursorPixmap, GraphicsContext, 0, 0);
XFreeGC(ourDisplay, GraphicsContext); XFreeGC(myDisplay, GraphicsContext);
// Create the cursor, using the pixmap as both the shape and the mask of the cursor // Create the cursor, using the pixmap as both the shape and the mask of the cursor
XColor Color; XColor Color;
Color.flags = DoRed | DoGreen | DoBlue; Color.flags = DoRed | DoGreen | DoBlue;
Color.red = Color.blue = Color.green = 0; Color.red = Color.blue = Color.green = 0;
myHiddenCursor = XCreatePixmapCursor(ourDisplay, CursorPixmap, CursorPixmap, &Color, &Color, 0, 0); myHiddenCursor = XCreatePixmapCursor(myDisplay, CursorPixmap, CursorPixmap, &Color, &Color, 0, 0);
// We don't need the pixmap any longer, free it // We don't need the pixmap any longer, free it
XFreePixmap(ourDisplay, CursorPixmap); XFreePixmap(myDisplay, CursorPixmap);
} }
@ -769,10 +525,10 @@ void WindowImplX11::CreateHiddenCursor()
void WindowImplX11::CleanUp() void WindowImplX11::CleanUp()
{ {
// Restore the previous video mode (in case we were running in fullscreen) // Restore the previous video mode (in case we were running in fullscreen)
if (ourFullscreenWindow == this) if (FullscreenWindow == this)
{ {
// Get current screen info // Get current screen info
XRRScreenConfiguration* Config = XRRGetScreenInfo(ourDisplay, RootWindow(ourDisplay, ourScreen)); XRRScreenConfiguration* Config = XRRGetScreenInfo(myDisplay, RootWindow(myDisplay, myScreen));
if (Config) if (Config)
{ {
// Get the current rotation // Get the current rotation
@ -780,25 +536,18 @@ void WindowImplX11::CleanUp()
XRRConfigCurrentConfiguration(Config, &CurrentRotation); XRRConfigCurrentConfiguration(Config, &CurrentRotation);
// Reset the video mode // Reset the video mode
XRRSetScreenConfig(ourDisplay, Config, RootWindow(ourDisplay, ourScreen), myOldVideoMode, CurrentRotation, CurrentTime); XRRSetScreenConfig(myDisplay, Config, RootWindow(myDisplay, myScreen), myOldVideoMode, CurrentRotation, CurrentTime);
// Free the configuration instance // Free the configuration instance
XRRFreeScreenConfigInfo(Config); XRRFreeScreenConfigInfo(Config);
} }
// Reset the fullscreen window // Reset the fullscreen window
ourFullscreenWindow = NULL; FullscreenWindow = NULL;
} }
// Unhide the mouse cursor (in case it was hidden) // Unhide the mouse cursor (in case it was hidden)
ShowMouseCursor(true); ShowMouseCursor(true);
// Destroy the OpenGL context
if (myGLContext)
{
glXDestroyContext(ourDisplay, myGLContext);
myGLContext = NULL;
}
} }
@ -1165,57 +914,6 @@ Key::Code WindowImplX11::KeysymToSF(KeySym Sym)
return Key::Code(0); return Key::Code(0);
} }
////////////////////////////////////////////////////////////
/// Open the display (if not already done)
////////////////////////////////////////////////////////////
bool WindowImplX11::OpenDisplay(bool AddWindow)
{
// If no display has been opened yet, open it
if (ourDisplay == NULL)
{
ourDisplay = XOpenDisplay(NULL);
if (ourDisplay)
{
ourScreen = DefaultScreen(ourDisplay);
// Get the input method (XIM) object
ourInputMethod = XOpenIM(ourDisplay, NULL, NULL, NULL);
}
else
{
std::cerr << "Failed to open a connection with the X server" << std::endl;
}
}
// Increase the number of windows
if (AddWindow)
ourWindowsCount++;
return ourDisplay != NULL;
}
////////////////////////////////////////////////////////////
/// Close the display
////////////////////////////////////////////////////////////
void WindowImplX11::CloseDisplay()
{
// Decrease the number of windows
ourWindowsCount--;
// If all windows have been destroyed, then we can close the display
if (ourWindowsCount == 0)
{
// Close the input method object
if (ourInputMethod)
XCloseIM(ourInputMethod);
XCloseDisplay(ourDisplay);
ourDisplay = NULL;
}
}
} // namespace priv } // namespace priv
} // namespace sf } // namespace sf

View File

@ -30,8 +30,8 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp> #include <SFML/Window/Event.hpp>
#include <SFML/Window/WindowImpl.hpp> #include <SFML/Window/WindowImpl.hpp>
#include <SFML/Window/Linux/DisplayRef.hpp>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <GL/glx.h>
#include <set> #include <set>
#include <string> #include <string>
@ -40,8 +40,6 @@ namespace sf
{ {
namespace priv namespace priv
{ {
class VideoModeSupport;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// WindowImplX11 is the Linux (X11) implementation of WindowImpl /// WindowImplX11 is the Linux (X11) implementation of WindowImpl
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -49,21 +47,13 @@ class WindowImplX11 : public WindowImpl
{ {
public : public :
////////////////////////////////////////////////////////////
/// Default constructor
/// (creates a dummy window to provide a valid OpenGL context)
///
////////////////////////////////////////////////////////////
WindowImplX11();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Construct the window implementation from an existing control /// Construct the window implementation from an existing control
/// ///
/// \param Handle : Platform-specific handle of the control /// \param Handle : Platform-specific handle of the control
/// \param Params : Creation settings
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplX11(WindowHandle Handle, WindowSettings& Params); WindowImplX11(WindowHandle Handle);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Create the window implementation /// Create the window implementation
@ -71,10 +61,9 @@ public :
/// \param Mode : Video mode to use /// \param Mode : Video mode to use
/// \param Title : Title of the window /// \param Title : Title of the window
/// \param WindowStyle : Window style (resizable, fixed, or fullscren) /// \param WindowStyle : Window style (resizable, fixed, or fullscren)
/// \param Params : Creation settings
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle, WindowSettings& Params); WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Destructor /// Destructor
@ -92,32 +81,12 @@ public :
private : private :
friend class VideoModeSupport;
////////////////////////////////////////////////////////////
/// /see WindowImpl::Display
///
////////////////////////////////////////////////////////////
virtual void Display();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see WindowImpl::ProcessEvents /// /see WindowImpl::ProcessEvents
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
virtual void ProcessEvents(); virtual void ProcessEvents();
////////////////////////////////////////////////////////////
/// /see WindowImpl::SetActive
///
////////////////////////////////////////////////////////////
virtual void SetActive(bool Active = true) const;
////////////////////////////////////////////////////////////
/// /see WindowImpl::UseVerticalSync
///
////////////////////////////////////////////////////////////
virtual void UseVerticalSync(bool Enabled);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// /see WindowImpl::ShowMouseCursor /// /see WindowImpl::ShowMouseCursor
/// ///
@ -168,20 +137,6 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void SwitchToFullscreen(const VideoMode& Mode); void SwitchToFullscreen(const VideoMode& Mode);
////////////////////////////////////////////////////////////
/// Create the OpenGL rendering context
///
/// \param Mode : Video mode to use
/// \param ChosenVisual : Visual that has been chosen for creating the contexte
/// \param Params : Creation parameters
/// \param Template : Visual infos to match
/// \param Mask : Visual attributes to check in Template
///
/// \return True on success, false on error
///
////////////////////////////////////////////////////////////
bool CreateContext(const VideoMode& Mode, XVisualInfo& ChosenVisual, WindowSettings& Params, XVisualInfo Template = XVisualInfo(), unsigned long Mask = 0);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// Do some common initializations after the window has been created /// Do some common initializations after the window has been created
/// ///
@ -230,38 +185,14 @@ private :
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static Key::Code KeysymToSF(KeySym Sym); static Key::Code KeysymToSF(KeySym Sym);
////////////////////////////////////////////////////////////
/// Open the display (if not already done)
///
/// \param AddWindow : Tell whether or not we must increase the windows count
///
/// \return True if the display is properly opened
///
////////////////////////////////////////////////////////////
static bool OpenDisplay(bool AddWindow = true);
////////////////////////////////////////////////////////////
/// Close the display
///
////////////////////////////////////////////////////////////
static void CloseDisplay();
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
static ::Display* ourDisplay; ///< Current opened display
static int ourScreen; ///< Default screen on the opened display
static WindowImplX11* ourFullscreenWindow; ///< Keep track of the active fullscreen window
static unsigned int ourWindowsCount; ///< Number of windows created
static unsigned long ourEventMask; ///< Mask defining the events that will be caught by our windows
static XIM ourInputMethod; ///< Input object used to get unicode characters from keypress messages
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
DisplayRef myDisplayRef; ///< Connection to the X server
::Window myWindow; ///< X11 structure defining our window ::Window myWindow; ///< X11 structure defining our window
::Display* myDisplay; ///< Pointer to the display
int myScreen; ///< Screen identifier
bool myIsExternal; ///< Tell whether the window has been created externally or by SFML bool myIsExternal; ///< Tell whether the window has been created externally or by SFML
GLXContext myGLContext; ///< OpenGL context attached to the window
Atom myAtomClose; ///< Atom used to identify the close event Atom myAtomClose; ///< Atom used to identify the close event
int myOldVideoMode; ///< Video mode in use before we switch to fullscreen int myOldVideoMode; ///< Video mode in use before we switch to fullscreen
Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one Cursor myHiddenCursor; ///< As X11 doesn't provide cursor hidding, we must create a transparent one

View File

@ -53,7 +53,7 @@ myOwnsWindow(true)
// Create the context // Create the context
if (myDC) if (myDC)
CreateContext(Shared, VideoMode::GetMode(0).BitsPerPixel, ContextSettings(0, 0, 0)); CreateContext(Shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
// ------------ TEMP ------------ // ------------ TEMP ------------
} }