]> git.tdb.fi Git - libs/gui.git/blob - source/gbase/glcontext.cpp
4783e0cbc995c0eee85908e4e63f7ab76a0333fc
[libs/gui.git] / source / gbase / glcontext.cpp
1 /* $Id$
2
3 This file is part of libmspgbase
4 Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <vector>
9 #ifdef WIN32
10 #include <windows.h>
11 #endif
12 #ifdef WITH_OPENGL
13 #include <GL/gl.h>
14 #ifndef WIN32
15 #include <GL/glx.h>
16 #endif
17 #endif
18 #include <msp/core/application.h>
19 #include <msp/core/except.h>
20 #include "display.h"
21 #include "glcontext.h"
22 #include "types.h"
23 #include "window.h"
24
25 namespace Msp {
26 namespace Graphics {
27
28 GLOptions::GLOptions():
29         alpha(false),
30         stencil(false),
31         doublebuffer(true),
32         multisample(0)
33 { }
34
35
36 #ifdef WITH_OPENGL
37 #ifdef WIN32
38 typedef HGLRC Context;
39 #else
40 typedef GLXContext Context;
41 #endif
42
43 struct GLContext::Private
44 {
45         Context context;
46 #ifndef WIN32
47         // In X11, we need to create a window with the chosen visual
48         WindowHandle subwnd;
49 #endif
50 };
51 #endif
52
53
54 GLContext::GLContext(Window &wnd, const GLOptions &opts):
55         display(wnd.get_display()),
56         window(wnd)
57 {
58 #ifdef WITH_OPENGL
59         priv=new Private;
60
61 #ifdef WIN32
62         HDC dc=GetDC(window.get_handle());
63
64         PIXELFORMATDESCRIPTOR pfd;
65         memset(&pfd, 0, sizeof(pfd));
66
67         pfd.nSize=sizeof(pfd);
68         pfd.nVersion=1;
69         pfd.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
70         if(opts.doublebuffer)
71                 pfd.dwFlags|=PFD_DOUBLEBUFFER;
72         pfd.iPixelType=PFD_TYPE_RGBA;
73         if(opts.alpha)
74                 pfd.cAlphaBits=1;
75         pfd.cDepthBits=1;
76         if(opts.stencil)
77                 pfd.cStencilBits=1;
78
79         int pf_index=ChoosePixelFormat(dc, &pfd);
80         if(!pf_index)
81                 throw Exception("Couldn't find a suitable pixel format");
82         SetPixelFormat(dc, pf_index, &pfd);
83
84         priv->context=wglCreateContext(dc);
85         wglMakeCurrent(dc, priv->context);
86
87         ReleaseDC(window.get_handle(), dc);
88 #else
89         std::vector<int> attribs;
90         
91         attribs.push_back(GLX_RGBA);
92         attribs.push_back(GLX_DEPTH_SIZE);
93         attribs.push_back(1);
94         
95         if(opts.alpha)
96         {
97                 attribs.push_back(GLX_ALPHA_SIZE);
98                 attribs.push_back(1);
99         }
100         
101         if(opts.stencil)
102         {
103                 attribs.push_back(GLX_STENCIL_SIZE);
104                 attribs.push_back(1);
105         }
106         
107         if(opts.doublebuffer)
108                 attribs.push_back(GLX_DOUBLEBUFFER);
109         
110         if(opts.multisample>0)
111         {
112                 attribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
113                 attribs.push_back(opts.multisample);
114         }
115         
116         attribs.push_back(0);
117
118         ::Display *dpy=display.get_display();
119
120         XVisualInfo *vi=glXChooseVisual(dpy, DefaultScreen(dpy), &attribs.front());
121         if(!vi)
122                 throw Exception("Couldn't find a suitable GLX visual");
123         priv->context=glXCreateContext(dpy, vi, 0, true);
124
125         XSetWindowAttributes attr;
126         attr.colormap=XCreateColormap(dpy, DefaultRootWindow(dpy), vi->visual, AllocNone);
127
128         priv->subwnd=XCreateWindow(dpy, window.get_handle(), 0, 0, window.get_width(), window.get_height(), 0, vi->depth, InputOutput, vi->visual, CWColormap, &attr);
129         XMapWindow(display.get_display(), priv->subwnd);
130
131         XFree(vi);
132
133         glXMakeCurrent(dpy, priv->subwnd, priv->context);
134 #endif
135 #else
136         (void)wnd;
137         (void)opts;
138         throw Exception("OpenGL support not compiled in");
139 #endif
140
141         window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized));
142 }
143
144 GLContext::~GLContext()
145 {
146 #ifdef WITH_OPENGL
147 #ifdef WIN32
148         wglMakeCurrent(0, 0);
149         wglDeleteContext(priv->context);
150 #else
151         ::Display *dpy=display.get_display();
152
153         glXMakeCurrent(dpy, 0, 0);
154         glXDestroyContext(dpy, priv->context);
155         XDestroyWindow(dpy, priv->subwnd);
156 #endif
157         delete priv;
158 #endif
159 }
160
161 void GLContext::swap_buffers()
162 {
163 #ifdef WITH_OPENGL
164 #ifdef WIN32
165         HDC dc=GetDC(window.get_handle());
166         SwapBuffers(dc);
167         ReleaseDC(window.get_handle(), dc);
168 #else
169         glXSwapBuffers(display.get_display(), priv->subwnd);
170 #endif
171 #endif
172 }
173
174 void GLContext::window_resized(unsigned w, unsigned h)
175 {
176 #ifdef WITH_OPENGL
177 #ifndef WIN32
178         XMoveResizeWindow(display.get_display(), priv->subwnd, 0, 0, w, h);
179 #endif
180         glViewport(0, 0, w, h);
181 #else
182         (void)w;
183         (void)h;
184 #endif
185 }
186
187 } // namespace Graphics
188 } // namespace Msp