11 #include <msp/core/application.h>
12 #include <msp/strings/format.h>
14 #include "glcontext.h"
16 #include "display_priv.h"
21 GLOptions::GLOptions():
29 unsupported_gl_mode::unsupported_gl_mode(const GLOptions &opts):
30 runtime_error(format("{ .alpha=%s, .stencil=%s, .doublebuffer=%s, .multisample=%d }",
31 opts.alpha, opts.stencil, opts.doublebuffer, opts.multisample))
37 typedef HGLRC Context;
39 typedef GLXContext Context;
42 struct GLContext::Private
46 // In X11, we need to create a window with the chosen visual
53 GLContext::GLContext(Window &wnd, const GLOptions &opts):
54 display(wnd.get_display()),
61 HDC dc = GetDC(window.get_private().window);
63 PIXELFORMATDESCRIPTOR pfd;
64 memset(&pfd, 0, sizeof(pfd));
66 pfd.nSize = sizeof(pfd);
68 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
70 pfd.dwFlags |= PFD_DOUBLEBUFFER;
71 pfd.iPixelType = PFD_TYPE_RGBA;
78 int pf_index = ChoosePixelFormat(dc, &pfd);
80 throw unsupported_gl_mode(opts);
81 SetPixelFormat(dc, pf_index, &pfd);
83 priv->context = wglCreateContext(dc);
84 wglMakeCurrent(dc, priv->context);
86 ReleaseDC(window.get_private().window, dc);
88 std::vector<int> attribs;
90 attribs.push_back(GLX_RGBA);
91 attribs.push_back(GLX_DEPTH_SIZE);
96 attribs.push_back(GLX_ALPHA_SIZE);
102 attribs.push_back(GLX_STENCIL_SIZE);
103 attribs.push_back(1);
106 if(opts.doublebuffer)
107 attribs.push_back(GLX_DOUBLEBUFFER);
109 if(opts.multisample>0)
111 attribs.push_back(GLX_SAMPLE_BUFFERS_ARB);
112 attribs.push_back(opts.multisample);
115 attribs.push_back(0);
117 ::Display *dpy = display.get_private().display;
119 XVisualInfo *vi = glXChooseVisual(dpy, DefaultScreen(dpy), &attribs.front());
121 throw unsupported_gl_mode(opts);
122 priv->context = glXCreateContext(dpy, vi, 0, true);
124 XSetWindowAttributes attr;
125 attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vi->visual, AllocNone);
127 priv->subwnd = XCreateWindow(dpy, window.get_private().window, 0, 0, window.get_width(), window.get_height(), 0, vi->depth, InputOutput, vi->visual, CWColormap, &attr);
128 XMapWindow(dpy, priv->subwnd);
132 glXMakeCurrent(dpy, priv->subwnd, priv->context);
137 throw runtime_error("no OpenGL support");
140 window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized));
143 GLContext::~GLContext()
147 wglMakeCurrent(0, 0);
148 wglDeleteContext(priv->context);
150 ::Display *dpy = display.get_private().display;
152 glXMakeCurrent(dpy, 0, 0);
153 glXDestroyContext(dpy, priv->context);
154 XDestroyWindow(dpy, priv->subwnd);
160 void GLContext::swap_buffers()
164 HDC dc = GetDC(window.get_private().window);
166 ReleaseDC(window.get_private().window, dc);
168 glXSwapBuffers(display.get_private().display, priv->subwnd);
173 void GLContext::window_resized(unsigned w, unsigned h)
177 XMoveResizeWindow(display.get_private().display, priv->subwnd, 0, 0, w, h);
179 glViewport(0, 0, w, h);
186 } // namespace Graphics