PageRenderTime 32ms CodeModel.GetById 16ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/extlibs/SFML/src/SFML/Window/Linux/GlxContext.cpp

https://bitbucket.org/hugoruscitti/pilascpp
C++ | 300 lines | 195 code | 41 blank | 64 comment | 36 complexity | 509f6ceb130d5987f7c3757815f9562e MD5 | raw file
  1////////////////////////////////////////////////////////////
  2//
  3// SFML - Simple and Fast Multimedia Library
  4// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)
  5//
  6// This software is provided 'as-is', without any express or implied warranty.
  7// In no event will the authors be held liable for any damages arising from the use of this software.
  8//
  9// Permission is granted to anyone to use this software for any purpose,
 10// including commercial applications, and to alter it and redistribute it freely,
 11// subject to the following restrictions:
 12//
 13// 1. The origin of this software must not be misrepresented;
 14//    you must not claim that you wrote the original software.
 15//    If you use this software in a product, an acknowledgment
 16//    in the product documentation would be appreciated but is not required.
 17//
 18// 2. Altered source versions must be plainly marked as such,
 19//    and must not be misrepresented as being the original software.
 20//
 21// 3. This notice may not be removed or altered from any source distribution.
 22//
 23////////////////////////////////////////////////////////////
 24
 25////////////////////////////////////////////////////////////
 26// Headers
 27////////////////////////////////////////////////////////////
 28#define GLX_GLXEXT_LEGACY // so that our local glxext.h is used instead of the system one
 29#include <SFML/Window/Linux/GlxContext.hpp>
 30#include <SFML/Window/Linux/WindowImplX11.hpp>
 31#include <SFML/OpenGL.hpp>
 32#include <SFML/Window/glext/glxext.h>
 33#include <SFML/System/Err.hpp>
 34
 35
 36namespace sf
 37{
 38namespace priv
 39{
 40////////////////////////////////////////////////////////////
 41GlxContext::GlxContext(GlxContext* shared) :
 42myWindow    (0),
 43myContext   (NULL),
 44myOwnsWindow(true)
 45{
 46    // Open a connection with the X server
 47    myDisplay = XOpenDisplay(NULL);
 48
 49    // Create a dummy window (disabled and hidden)
 50    int screen = DefaultScreen(myDisplay);
 51    myWindow = XCreateWindow(myDisplay,
 52                             RootWindow(myDisplay, screen),
 53                             0, 0,
 54                             1, 1,
 55                             0,
 56                             DefaultDepth(myDisplay, screen),
 57                             InputOutput,
 58                             DefaultVisual(myDisplay, screen),
 59                             0, NULL);
 60
 61    // Create the context
 62    CreateContext(shared, VideoMode::GetDesktopMode().BitsPerPixel, ContextSettings(0, 0, 0));
 63
 64    // Activate the context
 65    SetActive(true);
 66}
 67
 68
 69////////////////////////////////////////////////////////////
 70GlxContext::GlxContext(GlxContext* shared, const WindowImpl* owner, unsigned int bitsPerPixel, const ContextSettings& settings) :
 71myWindow    (0),
 72myContext   (NULL),
 73myOwnsWindow(false)
 74{
 75    // Use the same context as the owner window (important!)
 76    myDisplay = static_cast<const WindowImplX11*>(owner)->GetDisplay();
 77
 78    // Get the owner window and its device context
 79    myWindow = static_cast<Window>(owner->GetSystemHandle());
 80
 81    // Create the context
 82    if (myWindow)
 83        CreateContext(shared, bitsPerPixel, settings);
 84
 85    // Activate the context
 86    SetActive(true);
 87}
 88
 89
 90////////////////////////////////////////////////////////////
 91GlxContext::~GlxContext()
 92{
 93    // Destroy the context
 94    if (myContext)
 95    {
 96        if (glXGetCurrentContext() == myContext)
 97            glXMakeCurrent(myDisplay, None, NULL);
 98        glXDestroyContext(myDisplay, myContext);
 99    }
100    
101    // Destroy the window if we own it
102    if (myWindow && myOwnsWindow)
103    {
104        XDestroyWindow(myDisplay, myWindow);
105        XFlush(myDisplay);
106    }
107    
108    // Close the connection with the X server
109    if (myOwnsWindow)
110    {
111        XCloseDisplay(myDisplay);
112    }
113}
114
115
116////////////////////////////////////////////////////////////
117bool GlxContext::MakeCurrent()
118{
119    if (myContext)
120    {
121        if (glXGetCurrentContext() != myContext)
122            return glXMakeCurrent(myDisplay, myWindow, myContext) != 0;
123        else
124            return true;
125    }
126    else
127    {
128        return false;
129    }
130}
131
132
133////////////////////////////////////////////////////////////
134void GlxContext::Display()
135{
136    if (myWindow)
137        glXSwapBuffers(myDisplay, myWindow);
138}
139
140
141////////////////////////////////////////////////////////////
142void GlxContext::UseVerticalSync(bool enabled)
143{
144    const GLubyte* name = reinterpret_cast<const GLubyte*>("glXSwapIntervalSGI");
145    PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(name));
146    if (glXSwapIntervalSGI)
147        glXSwapIntervalSGI(enabled ? 1 : 0);
148}
149
150
151////////////////////////////////////////////////////////////
152void GlxContext::CreateContext(GlxContext* shared, unsigned int bitsPerPixel, const ContextSettings& settings)
153{
154    // Save the creation settings
155    mySettings = settings;
156
157    // Get the attributes of the target window
158    XWindowAttributes windowAttributes;
159    if (XGetWindowAttributes(myDisplay, myWindow, &windowAttributes) == 0)
160    {
161        Err() << "Failed to get the window attributes" << std::endl;
162        return;
163    }
164
165    // Setup the visual infos to match
166    XVisualInfo tpl;
167    tpl.depth    = windowAttributes.depth;
168    tpl.visualid = XVisualIDFromVisual(windowAttributes.visual);
169    tpl.screen   = DefaultScreen(myDisplay);
170
171    // Get all the visuals matching the template
172    int nbVisuals = 0;
173    XVisualInfo* visuals = XGetVisualInfo(myDisplay, VisualDepthMask | VisualIDMask | VisualScreenMask, &tpl, &nbVisuals);
174    if (!visuals || (nbVisuals == 0))
175    {
176        if (visuals)
177            XFree(visuals);
178        Err() << "There is no valid visual for the selected screen" << std::endl;
179        return;
180    }
181
182    // Find the best visual
183    int          bestScore  = 0xFFFF;
184    XVisualInfo* bestVisual = NULL;
185    for (int i = 0; i < nbVisuals; ++i)
186    {
187        // Get the current visual attributes
188        int RGBA, doubleBuffer, red, green, blue, alpha, depth, stencil, multiSampling, samples;
189        glXGetConfig(myDisplay, &visuals[i], GLX_RGBA,               &RGBA);
190        glXGetConfig(myDisplay, &visuals[i], GLX_DOUBLEBUFFER,       &doubleBuffer); 
191        glXGetConfig(myDisplay, &visuals[i], GLX_RED_SIZE,           &red);
192        glXGetConfig(myDisplay, &visuals[i], GLX_GREEN_SIZE,         &green); 
193        glXGetConfig(myDisplay, &visuals[i], GLX_BLUE_SIZE,          &blue); 
194        glXGetConfig(myDisplay, &visuals[i], GLX_ALPHA_SIZE,         &alpha); 
195        glXGetConfig(myDisplay, &visuals[i], GLX_DEPTH_SIZE,         &depth);        
196        glXGetConfig(myDisplay, &visuals[i], GLX_STENCIL_SIZE,       &stencil);
197        glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &multiSampling);        
198        glXGetConfig(myDisplay, &visuals[i], GLX_SAMPLES_ARB,        &samples);
199
200        // First check the mandatory parameters
201        if ((RGBA == 0) || (doubleBuffer == 0))
202            continue;
203
204        // Evaluate the current configuration
205        int color = red + green + blue + alpha;
206        int score = EvaluateFormat(bitsPerPixel, mySettings, color, depth, stencil, multiSampling ? samples : 0);
207
208        // Keep it if it's better than the current best
209        if (score < bestScore)
210        {
211            bestScore  = score;
212            bestVisual = &visuals[i];
213        }
214    }
215
216    // Make sure that we have found a visual
217    if (!bestVisual)
218    {
219        Err() << "Failed to find a suitable pixel format for the window -- cannot create OpenGL context" << std::endl;
220        return;
221    }
222
223    // Get the context to share display lists with
224    GLXContext toShare = shared ? shared->myContext : NULL;
225
226    // Create the OpenGL context -- first try an OpenGL 3.0 context if it is requested
227    while (!myContext && (mySettings.MajorVersion >= 3))
228    {
229        const GLubyte* name = reinterpret_cast<const GLubyte*>("glXCreateContextAttribsARB");
230        PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = reinterpret_cast<PFNGLXCREATECONTEXTATTRIBSARBPROC>(glXGetProcAddress(name));
231        if (glXCreateContextAttribsARB)
232        {
233            int nbConfigs = 0;
234            GLXFBConfig* configs = glXChooseFBConfig(myDisplay, DefaultScreen(myDisplay), NULL, &nbConfigs);
235            if (configs && nbConfigs)
236            {
237                // Create the context
238                int attributes[] =
239                {
240                    GLX_CONTEXT_MAJOR_VERSION_ARB, mySettings.MajorVersion,
241                    GLX_CONTEXT_MINOR_VERSION_ARB, mySettings.MinorVersion,
242                    GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
243                    0, 0
244                };
245                myContext = glXCreateContextAttribsARB(myDisplay, configs[0], toShare, true, attributes);
246            }
247
248            if (configs)
249                XFree(configs);
250        }
251
252        // If we couldn't create an OpenGL 3 context, adjust the settings
253        if (!myContext)
254        {
255            if (mySettings.MinorVersion > 0)
256            {
257                // If the minor version is not 0, we decrease it and try again
258                mySettings.MinorVersion--;
259            }
260            else
261            {
262                // If the minor version is 0, we decrease the major version and stop with 3.x contexts
263                mySettings.MajorVersion = 2;
264            }
265        }
266    }
267
268    // If the OpenGL 3.0 context failed or if we don't want one, create a regular OpenGL 1.x/2.x context
269    if (!myContext)
270    {
271        myContext = glXCreateContext(myDisplay, bestVisual, toShare, true);
272        if (!myContext)
273        {
274            Err() << "Failed to create an OpenGL context for this window" << std::endl;
275            return;
276        }
277    }
278
279    // Update the creation settings from the chosen format
280    int depth, stencil, multiSampling, samples;
281    glXGetConfig(myDisplay, bestVisual, GLX_DEPTH_SIZE,         &depth);
282    glXGetConfig(myDisplay, bestVisual, GLX_STENCIL_SIZE,       &stencil);
283    glXGetConfig(myDisplay, bestVisual, GLX_SAMPLE_BUFFERS_ARB, &multiSampling);        
284    glXGetConfig(myDisplay, bestVisual, GLX_SAMPLES_ARB,        &samples);
285    mySettings.DepthBits         = static_cast<unsigned int>(depth);
286    mySettings.StencilBits       = static_cast<unsigned int>(stencil);
287    mySettings.AntialiasingLevel = multiSampling ? samples : 0;
288
289    // Change the target window's colormap so that it matches the context's one
290    ::Window root = RootWindow(myDisplay, DefaultScreen(myDisplay));
291    Colormap colorMap = XCreateColormap(myDisplay, root, bestVisual->visual, AllocNone);
292    XSetWindowColormap(myDisplay, myWindow, colorMap);
293
294    // Free the temporary visuals array
295    XFree(visuals);
296}
297
298} // namespace priv
299
300} // namespace sf