#include "opengl.hpp" #include #include #include #include "options.hpp" #define UNUSED(foo) (void) foo; timespec diff(timespec start, timespec end) { timespec result; if ((end.tv_nsec - start.tv_nsec) < 0) { result.tv_sec = end.tv_sec - start.tv_sec - 1; result.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec; } else { result.tv_sec = end.tv_sec - start.tv_sec; result.tv_nsec = end.tv_nsec - start.tv_nsec; } return result; } endofthejedi::GLWindow::GLWindow(unsigned int width, unsigned int height) : m_width(width), m_height(height) { m_display = XOpenDisplay(NULL); if (m_display == NULL) { throw std::runtime_error("XOpenDisplay NULL"); } m_rootwnd = DefaultRootWindow(m_display); m_visualinfo = glXChooseVisual(m_display, 0, m_attributes); if (m_visualinfo == NULL) { throw std::runtime_error("glXChooseVisual NULL"); } m_colormap = XCreateColormap(m_display, m_rootwnd, m_visualinfo->visual, AllocNone); m_swa.colormap = m_colormap; m_swa.event_mask = ExposureMask | KeyPressMask; m_window = XCreateWindow( m_display, m_rootwnd, 0, 0, width, height, 0, m_visualinfo->depth, InputOutput, m_visualinfo->visual, CWColormap | CWEventMask, &m_swa); m_atomWmDeleteWindow = XInternAtom(m_display, "WM_DELETE_WINDOW", False); XSetWMProtocols(m_display, m_window, &m_atomWmDeleteWindow, 1); XMapWindow(m_display, m_window); XStoreName(m_display, m_window, "NAME"); m_glcontext = glXCreateContext(m_display, m_visualinfo, NULL, GL_TRUE); XSync(m_display, False); glXMakeCurrent(m_display, m_window, m_glcontext); std::cout << "GL Renderer: " << glGetString(GL_RENDERER) << "\n"; std::cout << "GL Version: " << glGetString(GL_VERSION) << "\n"; std::cout << "GLSL Version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << "\n"; init(); XClearWindow(m_display, m_window); XMapRaised(m_display, m_window); } endofthejedi::GLWindow::~GLWindow() { glXMakeCurrent(m_display, None, NULL); glXDestroyContext(m_display, m_glcontext); XFree(m_visualinfo); XDestroyWindow(m_display, m_window); XCloseDisplay(m_display); } void endofthejedi::GLWindow::handleevents() { if (XPending(m_display) > 0) { XEvent xev; XNextEvent(m_display, &xev); handle(xev); } } void endofthejedi::GLWindow::handle(XEvent event) { if (event.type == Expose) { XWindowAttributes attribs; XGetWindowAttributes(m_display, m_window, &attribs); m_width = attribs.width; m_height = attribs.height; resize(); } else if (event.type == ClientMessage) { if (event.xclient.data.l[0] == m_atomWmDeleteWindow) { stop(); } } else if (event.type == DestroyNotify) { stop(); } } void endofthejedi::GLWindow::swap() { glXSwapBuffers(m_display, m_window); } void endofthejedi::GLWindow::poll() { clock_gettime(CLOCK_MONOTONIC_RAW, &prev); clock_gettime(CLOCK_MONOTONIC_RAW, ¤t); handleevents(); render(delta); swap(); if (m_maxfps > 0) { sleeptime = ((1000000000.0/m_maxfps) - delta) + sleeptime; if (sleeptime > 0.0) { usleep((unsigned int)(sleeptime/1000.0)); sleeptime = sleeptime - (unsigned int)(sleeptime/1000.0); } } } void endofthejedi::GLWindow::stop() { m_running = false; } bool endofthejedi::GLWindow::running() { return m_running; } void endofthejedi::GLWindow::init() { m_running = true; } void endofthejedi::GLWindow::render(double time) { UNUSED(time) } void endofthejedi::GLWindow::resize() {}