X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fgraphics%2Fglcontext.cpp;fp=source%2Fgraphics%2Fglcontext.cpp;h=b71383063c05d6edb036959e8034349897bff228;hb=1023b38fa278cea71fba3d2881e1bfde930cd025;hp=0000000000000000000000000000000000000000;hpb=7d2b4349289578b8e7f322186a1f251684ddeb01;p=libs%2Fgui.git diff --git a/source/graphics/glcontext.cpp b/source/graphics/glcontext.cpp new file mode 100644 index 0000000..b713830 --- /dev/null +++ b/source/graphics/glcontext.cpp @@ -0,0 +1,187 @@ +#include +#ifdef WIN32 +#include +#endif +#ifdef WITH_OPENGL +#include +#ifndef WIN32 +#include +#endif +#endif +#include +#include +#include "display.h" +#include "glcontext.h" +#include "window.h" +#include "display_priv.h" + +namespace Msp { +namespace Graphics { + +GLOptions::GLOptions(): + alpha(false), + stencil(false), + doublebuffer(true), + multisample(0) +{ } + + +unsupported_gl_mode::unsupported_gl_mode(const GLOptions &opts): + runtime_error(format("{ .alpha=%s, .stencil=%s, .doublebuffer=%s, .multisample=%d }", + opts.alpha, opts.stencil, opts.doublebuffer, opts.multisample)) +{ } + + +#ifdef WITH_OPENGL +#ifdef WIN32 +typedef HGLRC Context; +#else +typedef GLXContext Context; +#endif + +struct GLContext::Private +{ + Context context; +#ifndef WIN32 + // In X11, we need to create a window with the chosen visual + WindowHandle subwnd; +#endif +}; +#endif + + +GLContext::GLContext(Window &wnd, const GLOptions &opts): + display(wnd.get_display()), + window(wnd) +{ +#ifdef WITH_OPENGL + priv = new Private; + +#ifdef WIN32 + HDC dc = GetDC(window.get_private().window); + + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd, 0, sizeof(pfd)); + + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + if(opts.doublebuffer) + pfd.dwFlags |= PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + if(opts.alpha) + pfd.cAlphaBits = 1; + pfd.cDepthBits = 1; + if(opts.stencil) + pfd.cStencilBits = 1; + + int pf_index = ChoosePixelFormat(dc, &pfd); + if(!pf_index) + throw unsupported_gl_mode(opts); + SetPixelFormat(dc, pf_index, &pfd); + + priv->context = wglCreateContext(dc); + wglMakeCurrent(dc, priv->context); + + ReleaseDC(window.get_private().window, dc); +#else + std::vector attribs; + + attribs.push_back(GLX_RGBA); + attribs.push_back(GLX_DEPTH_SIZE); + attribs.push_back(1); + + if(opts.alpha) + { + attribs.push_back(GLX_ALPHA_SIZE); + attribs.push_back(1); + } + + if(opts.stencil) + { + attribs.push_back(GLX_STENCIL_SIZE); + attribs.push_back(1); + } + + if(opts.doublebuffer) + attribs.push_back(GLX_DOUBLEBUFFER); + + if(opts.multisample>0) + { + attribs.push_back(GLX_SAMPLE_BUFFERS_ARB); + attribs.push_back(opts.multisample); + } + + attribs.push_back(0); + + ::Display *dpy = display.get_private().display; + + XVisualInfo *vi = glXChooseVisual(dpy, DefaultScreen(dpy), &attribs.front()); + if(!vi) + throw unsupported_gl_mode(opts); + priv->context = glXCreateContext(dpy, vi, 0, true); + + XSetWindowAttributes attr; + attr.colormap = XCreateColormap(dpy, DefaultRootWindow(dpy), vi->visual, AllocNone); + + priv->subwnd = XCreateWindow(dpy, window.get_private().window, 0, 0, window.get_width(), window.get_height(), 0, vi->depth, InputOutput, vi->visual, CWColormap, &attr); + XMapWindow(dpy, priv->subwnd); + + XFree(vi); + + glXMakeCurrent(dpy, priv->subwnd, priv->context); +#endif +#else + (void)wnd; + (void)opts; + throw runtime_error("no OpenGL support"); +#endif + + window.signal_resize.connect(sigc::mem_fun(this, &GLContext::window_resized)); +} + +GLContext::~GLContext() +{ +#ifdef WITH_OPENGL +#ifdef WIN32 + wglMakeCurrent(0, 0); + wglDeleteContext(priv->context); +#else + ::Display *dpy = display.get_private().display; + + glXMakeCurrent(dpy, 0, 0); + glXDestroyContext(dpy, priv->context); + XDestroyWindow(dpy, priv->subwnd); +#endif + delete priv; +#endif +} + +void GLContext::swap_buffers() +{ +#ifdef WITH_OPENGL +#ifdef WIN32 + HDC dc = GetDC(window.get_private().window); + SwapBuffers(dc); + ReleaseDC(window.get_private().window, dc); +#else + glXSwapBuffers(display.get_private().display, priv->subwnd); +#endif +#endif +} + +void GLContext::window_resized(unsigned w, unsigned h) +{ +#ifdef WITH_OPENGL +#ifndef WIN32 + XMoveResizeWindow(display.get_private().display, priv->subwnd, 0, 0, w, h); +#endif + glViewport(0, 0, w, h); +#else + (void)w; + (void)h; +#endif +} + +} // namespace Graphics +} // namespace Msp