packages feed

GLHUI (empty) → 1.0.0

raw patch · 8 files changed

+440/−0 lines, 8 filesdep +basesetup-changedbinary-added

Dependencies added: base

Files

+ .GLHUI.cabal.swp view

binary file changed (absent → 12288 bytes)

+ GLHUI.cabal view
@@ -0,0 +1,55 @@+name: GLHUI+version: 1.0.0+license: BSD3+license-file: LICENSE+author: Hugo Gomes <mr.hugo.gomes@gmail.com>+maintainer: Hugo Gomes <mr.hugo.gomes@gmail.com>+copyright: Hugo Gomes+homepage: http://www.hackological.com/projects/GLHUI+category: Graphics+synopsis: Open OpenGL context windows in X11 with libX11+description:+   .+   Haskell functions to open and manage a OpenGL window with libX11.+   .+   This module is intended to be imported qualified, to avoid clashes with+   Prelude functions, e.g.+   .+   > import qualified Graphics.UI.GLWindow as Window+   .+   As an example, here is a simple module that uses some of these functions +   to open a OpenGL 3.2 Context: +   .+   > module Main where                                                     +   >  +   > import Graphics.Rendering.OpenGL    +   > import qualified Graphics.UI.GLWindow as Window    +   > +   > myLoop = do clear [ColorBuffer]    +   >             t <- Window.time    +   >             clearColor $= Color4 (sin (realToFrac t) * 0.5 + 0.5)+   >                                  (sin (realToFrac (t+1)) * 0.5 + 0.5)+   >                                  (sin (realToFrac (t+2)) * 0.5 +0.5)+   >                                  0                                              +   > +   > main = do Window.init 3 2 -- initializes a OpenGL 3.2 context+   >           Window.loop myLoop -- stops when the ESC key is pressed+   >           Window.kill -- removes the window when the loop stops+   .+   Special thanks to Tiago Farto (aka xernobyl) for coding the C version of+   these functions+build-type: Simple+cabal-version: >=1.6+extra-source-files:+   README++library+   build-depends:+      base < 5+   exposed-modules:+      Graphics.UI.GLWindow+   include-dirs: include+   c-sources:+      c/HsGLWindow.c+   ghc-options: -Wall -O2+   extra-libraries: X11 GL rt
+ Graphics/UI/GLWindow.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE ForeignFunctionInterface #-}+-- |                                                                            +-- Module      : Graphics.UI.GLWindow+-- Copyright   : (c) 2011 Hugo Gomes+--                                                                              +-- License     : BSD-style                                                      +-- Maintainer  : mr.hugo.gomes@gmail.com+-- Stability   : experimental                                                   +-- Portability : GHC                                                            +--                                                                              +-- A simple OpenGL window creator that runs on X.Org with libX11.+-- This module allows the creation of different versions of OpenGL contexts+-- by initializing with the required versions.+--                                                                              +-- /Note/: The Haskell only has bindings up to OpenGL 3.2 +--    This module is intended to be imported qualified, to avoid clashes with      +--   Prelude functions, e.g.                                                      +--+--   > import qualified Graphics.UI.GLWindow as Window                            +--                                                                               +--   As an example, here is a simple module that uses some of these functions     +--   to open a OpenGL 3.2 Context:                                                +--                                                                               +--   > module Main where                                                          +--   >                                                                            +--   > import Graphics.Rendering.OpenGL                                           +--   > import qualified Graphics.UI.GLWindow as Window                            +--   >                                                                            +--   > myLoop = do clear [ColorBuffer]                                            +--   >             t <- Window.time                                               +--   >             clearColor $= Color4 (sin (realToFrac t) * 0.5 + 0.5)          +--   >                                  (sin (realToFrac (t+1)) * 0.5 + 0.5)      +--   >                                  (sin (realToFrac (t+2)) * 0.5 +0.5)       +--   >                                  0                                              +--   >                                                                            +--   > main = do Window.init 3 2 -- initializes a OpenGL 3.2 context              +--   >           Window.loop myLoop -- stops when the ESC key is pressed          +--   >           Window.kill -- removes the window when the loop stops            +--   ++module Graphics.UI.GLWindow +    (+    -- * Types+    LoopFunc+    -- * Window initialization+    , init+    , setFullscreen+    -- * Window elimination+    , kill+    -- * Window state query+    , frame+    , time+    , dtime+    , width+    , height+    , scrWidth+    , scrHeight+    -- * Loop+    , loop+    ) where++import Foreign.C+import Foreign.Ptr+import Control.Applicative+import Prelude hiding (init)++foreign import ccall unsafe "WindowInit" +  c_init :: CUInt -> CUInt -> IO (CInt)+init :: Integer -> Integer -> IO (Integer)+init glMajor glMinor = fromIntegral <$> c_init (fromIntegral glMajor) (fromIntegral glMinor)+foreign import ccall unsafe "WindowKill" +  kill :: IO ()++foreign import ccall unsafe "WindowSetFullscreen" +  c_fullscreen :: CInt -> IO ()+setFullscreen :: Bool -> IO ()+setFullscreen f = if f then c_fullscreen 1+                       else c_fullscreen 0++foreign import ccall unsafe "WindowFrame" +  c_frame :: IO (CUInt)+frame :: IO (Integer)+frame = fromIntegral <$> c_frame+foreign import ccall unsafe "WindowTime" +  c_time   :: IO (CDouble)+time :: IO (Double)+time = realToFrac <$> c_time+foreign import ccall unsafe "WindowDTime" +  c_dtime :: IO (CDouble)+dtime :: IO (Double)+dtime = realToFrac <$> c_dtime++foreign import ccall unsafe "WindowWidth" +  c_width :: IO (CUInt)+width :: IO (Integer)+width = fromIntegral <$> c_width+foreign import ccall unsafe "WindowHeight" +  c_height :: IO (CUInt)+height :: IO (Integer)+height = fromIntegral <$> c_height+foreign import ccall unsafe "WindowScrWidth" +  c_scrWidth :: IO (CUInt)+scrWidth :: IO (Integer)+scrWidth = fromIntegral <$> c_scrWidth+foreign import ccall unsafe "WindowScrHeight" +  c_scrHeight :: IO (CUInt)+scrHeight :: IO (Integer)+scrHeight = fromIntegral <$> c_scrHeight++type LoopFunc = IO ()+foreign import ccall "WindowLoop" +  c_loop :: FunPtr (LoopFunc) -> IO ()+loop :: LoopFunc -> IO ()+loop lf = mkLoop lf >>= c_loop ++foreign import ccall "wrapper"+  mkLoop :: LoopFunc -> IO( FunPtr (LoopFunc) )
+ LICENSE view
@@ -0,0 +1,28 @@+Copyright (c) 2011, Hugo Gomes+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice,+   this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of its contributors may be+   used to endorse or promote products derived from this software without+   specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README view
@@ -0,0 +1,1 @@+
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ c/HsGLWindow.c view
@@ -0,0 +1,212 @@+#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; }+
+ include/HsGLWindow.h view
@@ -0,0 +1,24 @@+#define GL_GLEXT_PROTOTYPES+#define GLX_GLXEXT_PROTOTYPES++#include <stdio.h>+#include <time.h>+#include <X11/Xlib.h>+#include <GL/gl.h>+#include <GL/glx.h>++int WindowInit(unsigned int const major, unsigned int const minor);+void WindowKill();++void WindowSetFullscreen(int f);++unsigned WindowFrame();+double WindowTime();+double WindowDTime();++unsigned WindowWidth();+unsigned WindowHeight();+unsigned WindowScrWidth();+unsigned WindowScrHeight();++void WindowLoop(void (*)());