Completed implementation of OpenGL context on Linux

git-svn-id: https://sfml.svn.sourceforge.net/svnroot/sfml/branches/sfml2@1069 4e206d99-4929-0410-ac5d-dfc041789085
This commit is contained in:
laurentgom 2009-03-28 20:39:38 +00:00
parent b194b9969a
commit 392eb219f2
6 changed files with 94 additions and 97 deletions

View File

@ -15,16 +15,16 @@
////////////////////////////////////////////////////////////
int main()
{
// Create main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML OpenGL");
App.PreserveOpenGLStates(true);
// Create a sprite for the background
sf::Image BackgroundImage;
if (!BackgroundImage.LoadFromFile("datas/opengl/background.jpg"))
return EXIT_FAILURE;
sf::Sprite Background(BackgroundImage);
// Create main window
sf::RenderWindow App(sf::VideoMode(800, 600), "SFML OpenGL");
App.PreserveOpenGLStates(true);
// Load an OpenGL texture.
// We could directly use a sf::Image as an OpenGL texture (with its Bind() member function),
// but here we want more control on it (generate mipmaps, ...) so we create a new one from the image pixels

View File

@ -41,41 +41,34 @@ namespace priv
/// Create a new context, not associated to a window
////////////////////////////////////////////////////////////
ContextGLX::ContextGLX(ContextGLX* Shared) :
myWindow (NULL),
myContext (NULL)/*,
myOwnsWindow(true)*/
myWindow (0),
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),
int Screen = DefaultScreen(myDisplay.GetDisplay());
myWindow = XCreateWindow(myDisplay.GetDisplay(),
RootWindow(myDisplay.GetDisplay(), Screen),
0, 0,
myWidth, myHeight,
1, 1,
0,
Visual.depth,
DefaultDepth(myDisplay.GetDisplay(), Screen),
InputOutput,
Visual.visual,
CWColormap, &Attributes);*/
DefaultVisual(myDisplay.GetDisplay(), Screen),
0, NULL);
// Create the context
CreateContext(Shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
}
////////////////////////////////////////////////////////////
/// 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)*/
ContextGLX::ContextGLX(ContextGLX* Shared, const WindowImpl* Owner, unsigned int BitsPerPixel, const ContextSettings& Settings) :
myWindow (0),
myContext (NULL),
myOwnsWindow(false)
{
// Get the owner window and its device context
myWindow = static_cast<Window>(Owner->GetHandle());
@ -91,20 +84,20 @@ myOwnsWindow(false)*/
////////////////////////////////////////////////////////////
ContextGLX::~ContextGLX()
{
// Destroy the OpenGL context
// Destroy the context
if (myContext)
{
if (glXGetCurrentContext() == myContext)
glXMakeCurrent(myDisplay.GetDisplay(), None, NULL);
glXDestroyContext(myContext);
glXDestroyContext(myDisplay.GetDisplay(), myContext);
}
// Destroy the window if we own it
/*if (myWindow && myOwnsWindow)
if (myWindow && myOwnsWindow)
{
XDestroyWindow(myDisplay.GetDisplay(), myWindow);
XFlush(myDisplay.GetDisplay());
}*/
}
}
@ -115,7 +108,7 @@ bool ContextGLX::MakeCurrent(bool Active)
{
if (Active)
{
if (myWindow && myContext)
if (myContext)
{
if (glXGetCurrentContext() != myContext)
return glXMakeCurrent(myDisplay.GetDisplay(), myWindow, myContext) != 0;
@ -130,7 +123,7 @@ bool ContextGLX::MakeCurrent(bool Active)
else
{
if (glXGetCurrentContext() == myContext)
return wglMakeCurrent(myDisplay.GetDisplay(), None, NULL) != 0;
return glXMakeCurrent(myDisplay.GetDisplay(), None, NULL) != 0;
else
return true;
}
@ -173,23 +166,23 @@ bool ContextGLX::IsContextActive()
////////////////////////////////////////////////////////////
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;
}
// Save the creation settings
mySettings = Settings;
// Setup the visual infos to match
Template.depth = WindowAttributes.depth;
Template.visualid = XVisualIDFromVisual(WindowAttributes.visual);
// Get the attributes of the target window
XWindowAttributes WindowAttributes;
if (XGetWindowAttributes(myDisplay.GetDisplay(), myWindow, &WindowAttributes) == 0)
{
std::cerr << "Failed to get the window attributes" << std::endl;
return;
}
// Setup the visual infos to match
XVisualInfo Template;
Template.depth = WindowAttributes.depth;
Template.visualid = XVisualIDFromVisual(WindowAttributes.visual);
Template.screen = DefaultScreen(myDisplay.GetDisplay());
// Get all the visuals matching the template
int NbVisuals = 0;
XVisualInfo* Visuals = XGetVisualInfo(myDisplay.GetDisplay(), VisualDepthMask | VisualIDMask | VisualScreenMask, &Template, &NbVisuals);
@ -210,16 +203,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(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);
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);
// First check the mandatory parameters
if ((RGBA == 0) || (DoubleBuffer == 0))
@ -240,16 +233,16 @@ void ContextGLX::CreateContext(ContextGLX* Shared, unsigned int BitsPerPixel, co
// If no visual has been found, try a lower level of antialiasing
if (!BestVisual)
{
if (Params.AntialiasingLevel > 2)
if (mySettings.AntialiasingLevel > 2)
{
std::cerr << "Failed to find a pixel format supporting "
<< Params.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
Params.AntialiasingLevel = 2;
<< mySettings.AntialiasingLevel << " antialiasing levels ; trying with 2 levels" << std::endl;
mySettings.AntialiasingLevel = 2;
}
else if (Params.AntialiasingLevel > 0)
else if (mySettings.AntialiasingLevel > 0)
{
std::cerr << "Failed to find a pixel format supporting antialiasing ; antialiasing will be disabled" << std::endl;
Params.AntialiasingLevel = 0;
mySettings.AntialiasingLevel = 0;
}
else
{
@ -278,12 +271,9 @@ void ContextGLX::CreateContext(ContextGLX* Shared, unsigned int BitsPerPixel, co
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);
}
::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);

View File

@ -108,27 +108,13 @@ private :
////////////////////////////////////////////////////////////
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?
bool myOwnsWindow; ///< Do we own the window associated to the context?
};
} // namespace priv

View File

@ -47,13 +47,14 @@ void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
// Get an access to the display
DisplayRef Disp;
int Screen = DefaultScreen(Disp.GetDisplay());
// Check if the XRandR extension is present
int Version;
if (XQueryExtension(Disp.GetDisplay(), "RANDR", &Version, &Version, &Version))
{
// Get the current configuration
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), DefaultScreen(Disp.GetDisplay())));
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), Screen));
if (Config)
{
// Get the available screen sizes
@ -63,7 +64,7 @@ void VideoModeSupport::GetSupportedVideoModes(std::vector<VideoMode>& Modes)
{
// Get the list of supported depths
int NbDepths = 0;
int* Depths = XListDepths(Disp, Screen, &NbDepths);
int* Depths = XListDepths(Disp.GetDisplay(), Screen, &NbDepths);
if (Depths && (NbDepths > 0))
{
// Combine depths and sizes to fill the array of supported modes
@ -108,13 +109,14 @@ VideoMode VideoModeSupport::GetDesktopVideoMode()
// Get an access to the display
DisplayRef Disp;
int Screen = DefaultScreen(Disp.GetDisplay());
// Check if the XRandR extension is present
int Version;
if (XQueryExtension(Disp.GetDisplay(), "RANDR", &Version, &Version, &Version))
{
// Get the current configuration
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), DefaultScreen(Disp.GetDisplay())));
XRRScreenConfiguration* Config = XRRGetScreenInfo(Disp.GetDisplay(), RootWindow(Disp.GetDisplay(), Screen));
if (Config)
{
// Get the current video mode
@ -125,7 +127,7 @@ VideoMode VideoModeSupport::GetDesktopVideoMode()
int NbSizes;
XRRScreenSize* Sizes = XRRConfigSizes(Config, &NbSizes);
if (Sizes && (NbSizes > 0))
DesktopMode = VideoMode(Sizes[CurrentMode].width, Sizes[CurrentMode].height, DefaultDepth(Disp, Screen));
DesktopMode = VideoMode(Sizes[CurrentMode].width, Sizes[CurrentMode].height, DefaultDepth(Disp.GetDisplay(), Screen));
// Free the configuration instance
XRRFreeScreenConfigInfo(Config);

View File

@ -28,6 +28,7 @@
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Linux/WindowImplX11.hpp>
#include <SFML/System/Unicode.hpp>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/Xrandr.h>
#include <iostream>
@ -40,10 +41,10 @@
////////////////////////////////////////////////////////////
namespace
{
WindowImplX11* FullscreenWindow = NULL;
unsigned long EventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask;
sf::priv::WindowImplX11* FullscreenWindow = NULL;
unsigned long EventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask |
EnterWindowMask | LeaveWindowMask;
////////////////////////////////////////////////////////////
/// Filter the events received by windows
@ -107,13 +108,16 @@ myKeyRepeat (true)
WindowImplX11::WindowImplX11(VideoMode Mode, const std::string& Title, unsigned long WindowStyle) :
myWindow (0),
myIsExternal (false),
myGLContext (NULL),
myAtomClose (0),
myOldVideoMode(-1),
myHiddenCursor(0),
myInputContext(NULL),
myKeyRepeat (true)
{
// Get the display and screen
myDisplay = myDisplayRef.GetDisplay();
myScreen = DefaultScreen(myDisplay);
// Compute position and size
int Left, Top;
bool Fullscreen = (WindowStyle & Style::Fullscreen) != 0;
@ -145,10 +149,10 @@ myKeyRepeat (true)
Left, Top,
Width, Height,
0,
Visual.depth,
DefaultDepth(myDisplay, myScreen),
InputOutput,
Visual.visual,
CWEventMask | CWColormap | CWOverrideRedirect, &Attributes);
DefaultVisual(myDisplay, myScreen),
CWEventMask | CWOverrideRedirect, &Attributes);
if (!myWindow)
{
std::cerr << "Failed to create window" << std::endl;
@ -260,6 +264,15 @@ WindowImplX11::~WindowImplX11()
}
////////////////////////////////////////////////////////////
/// /see WindowImpl::GetHandle
////////////////////////////////////////////////////////////
WindowHandle WindowImplX11::GetHandle() const
{
return myWindow;
}
////////////////////////////////////////////////////////////
/// /see WindowImpl::ProcessEvents
////////////////////////////////////////////////////////////

View File

@ -81,6 +81,12 @@ public :
private :
////////////////////////////////////////////////////////////
/// /see WindowImpl::GetHandle
///
////////////////////////////////////////////////////////////
virtual WindowHandle GetHandle() const;
////////////////////////////////////////////////////////////
/// /see WindowImpl::ProcessEvents
///