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