00001
00002
00003
00004
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <memory.h>
00008 #include <sys/time.h>
00009 #include <GL/glx.h>
00010 #include <GL/glxext.h>
00011 #include "os.h"
00012
00013 static Display *g_display;
00014 static Window g_window;
00015 static int g_screen;
00016 static GLXContext g_context;
00017
00018 static OS_Event *g_eventHead = 0;
00019 static OS_Event **g_eventTail = &g_eventHead;
00020 static int g_keyboard[256];
00021
00022 void osInit(int width, int height, unsigned int flags, int *attribs)
00023 {
00024 int attrib[] = {
00025 GLX_RGBA,
00026 GLX_DEPTH_SIZE, 0,
00027 GLX_RED_SIZE, 1,
00028 GLX_GREEN_SIZE, 1,
00029 GLX_BLUE_SIZE, 1,
00030 GLX_DOUBLEBUFFER, None,
00031 };
00032
00033 XSetWindowAttributes attr;
00034 unsigned long mask;
00035 Window root;
00036 XVisualInfo *visinfo;
00037
00038 atexit(osQuit);
00039 g_display = XOpenDisplay(NULL);
00040 g_screen = DefaultScreen(g_display);
00041 root = RootWindow(g_display, g_screen);
00042 visinfo = glXChooseVisual(g_display, g_screen, attrib);
00043
00044 if (!visinfo)
00045 {
00046 printf("Error: couldn't create OpenGL window\n");
00047 exit(1);
00048 }
00049
00050 attr.background_pixel = 0;
00051 attr.border_pixel = 0;
00052 attr.colormap = XCreateColormap(g_display, root, visinfo->visual, AllocNone);
00053 attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask | KeyReleaseMask;
00054 mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
00055
00056 g_window = XCreateWindow(
00057 g_display,
00058 root,
00059 0, 0,
00060 width, height, 0,
00061 visinfo->depth,
00062 InputOutput,
00063 visinfo->visual,
00064 mask,
00065 &attr
00066 );
00067
00068 XStoreName(g_display, g_window, "Flatland Demo");
00069
00070 g_context = glXCreateContext(g_display, visinfo, NULL, True);
00071 glXMakeCurrent(g_display, g_window, g_context);
00072 XMapWindow(g_display, g_window);
00073 }
00074
00075 void osQuit(void)
00076 {
00077 glXDestroyContext(g_display, g_context);
00078 XDestroyWindow(g_display, g_window);
00079
00080 while (g_eventHead)
00081 {
00082 OS_Event *pending = g_eventHead;
00083 g_eventHead = pending->next;
00084 if (!g_eventHead)
00085 g_eventTail = &g_eventHead;
00086 free(pending);
00087 }
00088
00089 }
00090
00091 int osGetScreenWidth()
00092 {
00093 return DisplayWidth(g_display, g_screen);
00094 }
00095
00096 int osGetScreenHeight()
00097 {
00098 return DisplayHeight(g_display, g_screen);
00099 }
00100
00101
00102 void osWaitVsync(int interval)
00103 {
00104 PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
00105 glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC) glXGetProcAddress((const GLubyte*) "glXSwapIntervalSGI");
00106 if (glXSwapIntervalSGI)
00107 glXSwapIntervalSGI(interval);
00108 }
00109
00110 unsigned int osGetMilliseconds()
00111 {
00112 struct timeval tp;
00113 gettimeofday(&tp, NULL);
00114 return tp.tv_sec * 1000 + tp.tv_usec / 1000;
00115 }
00116
00117 int osPollEvent(struct OS_EventRec *e)
00118 {
00119 if (XPending(g_display))
00120 {
00121 OS_Event e;
00122 XEvent event;
00123 e.type = OS_NOEVENT;
00124
00125 XNextEvent(g_display, &event);
00126 switch (event.type)
00127 {
00128 case Expose:
00129
00130 break;
00131
00132 case ConfigureNotify:
00133
00134 break;
00135
00136 case KeyRelease:
00137 case KeyPress:
00138 {
00139 XComposeStatus composeStatus;
00140 char asciiCode[32];
00141 KeySym keySym;
00142 int len;
00143
00144 if (event.type == KeyPress)
00145 {
00146 e.type = OS_KEYDOWN;
00147 e.key.state = OSKS_DOWN;
00148 }
00149 else
00150 {
00151 e.type = OS_KEYUP;
00152 e.key.state = OSKS_UP;
00153 }
00154
00155
00156 len = XLookupString(&event.xkey, asciiCode, sizeof(asciiCode), &keySym, &composeStatus);
00157
00158
00159 if (len > 0)
00160 {
00161 e.key.key = (unsigned char) asciiCode[0];
00162 }
00163 else
00164 {
00165 switch (keySym)
00166 {
00167 case XK_Left: e.key.key = OSK_LEFT; break;
00168 case XK_Right: e.key.key = OSK_RIGHT; break;
00169 case XK_Up: e.key.key = OSK_UP; break;
00170 case XK_Down: e.key.key = OSK_DOWN; break;
00171 }
00172 }
00173
00174
00175 g_keyboard[e.key.key] = e.key.state;
00176 }
00177 break;
00178 }
00179
00180 if (e.type != OS_NOEVENT)
00181 {
00182 e.next = 0;
00183 *g_eventTail = (OS_Event*) malloc(sizeof(OS_Event));
00184 memcpy(*g_eventTail, &e, sizeof(OS_Event));
00185 g_eventTail = &((*g_eventTail)->next);
00186 }
00187 }
00188
00189 if (g_eventHead)
00190 {
00191 OS_Event *pending = g_eventHead;
00192 memcpy(e, pending, sizeof(OS_Event));
00193 g_eventHead = pending->next;
00194 if (!g_eventHead)
00195 g_eventTail = &g_eventHead;
00196 free(pending);
00197 return 1;
00198 }
00199 }
00200
00201 void osSwapBuffers()
00202 {
00203 glXSwapBuffers(g_display, g_window);
00204 }
00205
00206 int osIsKeyDown(int key)
00207 {
00208 if (key < 0 || key > 0xff)
00209 return 0;
00210
00211 return g_keyboard[key];
00212 }
00213
00214 int osShowCursor(int)
00215 {
00216 return 0;
00217 }
00218