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