#include "HsGLWindow.h" static Display *display; static Window window; static GLXContext context; static int width, height, scrwidth, scrheight; static unsigned frame = 0; static double ftime, dtime; static int fullscreen = 0; typedef struct { unsigned long flags; unsigned long functions; unsigned long decorations; long inputMode; unsigned long status; } Hints; void WindowSetFullscreen(int f) { XWindowChanges changes; Hints hints; Atom property = XInternAtom(display,"_MOTIF_WM_HINTS",True); hints.flags = 2; if(f) { hints.decorations = False; changes.x = 0; changes.y = 0; changes.width = width = scrwidth; changes.height = height = scrheight; changes.stack_mode = Above; fullscreen = 1; } else { hints.decorations = True; changes.x = scrwidth/4; changes.y = scrheight/4; changes.width = width = scrwidth/2; changes.height = height = scrheight/2; changes.stack_mode = Above; fullscreen = 0; } XChangeProperty(display, window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); XConfigureWindow(display, window, CWX | CWY | CWWidth | CWHeight | CWStackMode, &changes); //XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); //XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); //XMapRaised(display, window); } int WindowInit(unsigned int const major, unsigned int const minor) { static const int glattr[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_X_RENDERABLE, 1, GLX_DOUBLEBUFFER, 1, GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, 0 }; int gl3attr[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, major, GLX_CONTEXT_MINOR_VERSION_ARB, minor, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, 0 }; if(!(display = XOpenDisplay(0))) { puts("Could not open display.\n"); return -1; } int nscreen = DefaultScreen(display); scrwidth = XDisplayWidth(display, nscreen); scrheight = XDisplayHeight(display, nscreen); width = scrwidth / 2; height = scrheight / 2; static XVisualInfo *visual; if(!(visual = glXChooseVisual(display, nscreen, (int*)glattr))) { puts("Could not find a visual.\n"); return -2; } int elemc; GLXFBConfig *fbcfg = glXChooseFBConfig(display, nscreen, glattr, &elemc); if(!fbcfg) { puts("Could not find FB config.\n"); return -3; } context = glXCreateContextAttribsARB(display, fbcfg[0], 0, 1, gl3attr); Window root = RootWindow(display, visual->screen); XSetWindowAttributes xattr; xattr.event_mask = KeyPressMask | ButtonPressMask | StructureNotifyMask; xattr.colormap = XCreateColormap(display, root, visual->visual, AllocNone); window = XCreateWindow(display, root, 0, 0, width, height, 0, visual->depth, InputOutput, visual->visual, CWColormap | CWEventMask, &xattr); XSetStandardProperties(display, window, "United Colors Of Funk", 0, None, 0, 0, 0); XGrabKeyboard(display, window, True, GrabModeAsync, GrabModeAsync, CurrentTime); XGrabPointer(display, window, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, window, None, CurrentTime); XMapRaised(display, window); glXMakeCurrent(display, window, context); glViewport(0, 0, width, height); XFree(fbcfg); XFree(visual); printf("OpenGL:\n\tvendor %s\n\trenderer %s\n\tversion %s\n\tshader language %s\n", glGetString(GL_VENDOR), glGetString(GL_RENDERER), glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION)); return 1; } void WindowLoop(void (*Loop)()) { struct timespec ts[3]; // even, odd, initial int done = 0; XEvent event; clock_gettime(CLOCK_MONOTONIC, ts+2); ts[0] = ts[1] = ts[2]; while(!done) { while(XPending(display) > 0) { XNextEvent(display, &event); switch(event.type) { case ConfigureNotify: if((event.xconfigure.width != width) || (event.xconfigure.height != height)) { width = event.xconfigure.width; height = event.xconfigure.height; glViewport(0, 0, width, height); } break; case ButtonPress: done = 1; break; case KeyPress: if(XLookupKeysym(&event.xkey, 0) == XK_Escape) done = 1; else if(XLookupKeysym(&event.xkey, 0) == XK_F1) WindowSetFullscreen(!fullscreen); break; } } Loop(); glXSwapBuffers(display, window); frame++; clock_gettime(CLOCK_MONOTONIC, ts+(frame%2)); dtime = 1e-9*(ts[frame%2].tv_nsec - ts[!(frame%2)].tv_nsec) + (ts[frame%2].tv_sec - ts[!(frame%2)].tv_sec); ftime = 1e-9*(ts[frame%2].tv_nsec - ts[2].tv_nsec) + (ts[frame%2].tv_sec - ts[2].tv_sec); } //WindowKill(0); } void WindowKill(const char *str) { puts(str); if(context) { glXMakeCurrent(display, 0, 0); glXDestroyContext(display, context); context = 0; } XCloseDisplay(display); } unsigned WindowFrame(){ return frame; } double WindowTime(){ return ftime; } double WindowDTime(){ return dtime; } unsigned WindowWidth(){ return width; } unsigned WindowHeight(){ return height; } unsigned WindowScrWidth(){ return scrwidth; } unsigned WindowScrHeight(){ return scrheight; }