packages feed

GLHUI-1.0.0: c/HsGLWindow.c

#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; }