X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=miniglut.c;h=c9cc1f01493a9006695c781f2fa87489d9f9854a;hb=f703c3cc1fb72bb38eb0a79b56dbb34115f70b85;hp=92682024590c3e97ceb0d5f3ee52dfcddaed68a6;hpb=02536825844445fbb648cf2a69c97760e7eef885;p=miniglut diff --git a/miniglut.c b/miniglut.c index 9268202..c9cc1f0 100644 --- a/miniglut.c +++ b/miniglut.c @@ -15,24 +15,15 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ -/*#define MINIGLUT_GCC_NO_BUILTIN*/ - #ifdef MINIGLUT_USE_LIBC #define _GNU_SOURCE #include #include #else - -#if defined(__GNUC__) && !defined(MINIGLUT_GCC_NO_BUILTIN) -#define mglut_sincosf(a, s, c) __builtin_sincosf(a, s, c) -#define mglut_atan(x) __builtin_atan(x) -#else static void mglut_sincosf(float angle, float *sptr, float *cptr); static float mglut_atan(float x); #endif -#endif - #define PI 3.1415926536f #if defined(__unix__) @@ -62,6 +53,9 @@ static unsigned int evmask; #include #define BUILD_WIN32 +static HRESULT CALLBACK handle_message(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam); + +static HINSTANCE hinst; static HWND win; static HDC dc; static HGLRC ctx; @@ -113,7 +107,7 @@ static glut_cb_sbbutton cb_sball_button; static int win_width, win_height; static int mapped; static int quit; -static int upd_pending, reshape_pending; +static int upd_pending; static int modstate; @@ -130,6 +124,23 @@ void glutInit(int *argc, char **argv) evmask = ExposureMask | StructureNotifyMask; #endif +#ifdef BUILD_WIN32 + WNDCLASSEX wc = {0}; + + hinst = GetModuleHandle(0); + + wc.cbSize = sizeof wc; + wc.hbrBackground = GetStockObject(BLACK_BRUSH); + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hIcon = wc.hIconSm = LoadIcon(0, IDI_APPLICATION); + wc.hInstance = hinst; + wc.lpfnWndProc = handle_message; + wc.lpszClassName = "MiniGLUT"; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + if(!RegisterClassEx(&wc)) { + panic("Failed to register \"MiniGLUT\" window class\n"); + } +#endif } void glutInitWindowPosition(int x, int y) @@ -586,6 +597,8 @@ void glutWireTeapot(float size) } + +/* --------------- UNIX/X11 implementation ----------------- */ #ifdef BUILD_X11 static void handle_event(XEvent *ev); @@ -597,26 +610,24 @@ void glutMainLoopEvent(void) panic("display callback not set"); } - for(;;) { - if(!upd_pending && !cb_idle) { - XNextEvent(dpy, &ev); - handle_event(&ev); - if(quit) return; - } - while(XPending(dpy)) { - XNextEvent(dpy, &ev); - handle_event(&ev); - if(quit) return; - } + if(!upd_pending && !cb_idle) { + XNextEvent(dpy, &ev); + handle_event(&ev); + if(quit) return; + } + while(XPending(dpy)) { + XNextEvent(dpy, &ev); + handle_event(&ev); + if(quit) return; + } - if(cb_idle) { - cb_idle(); - } + if(cb_idle) { + cb_idle(); + } - if(upd_pending && mapped) { - upd_pending = 0; - cb_display(); - } + if(upd_pending && mapped) { + upd_pending = 0; + cb_display(); } } @@ -789,16 +800,23 @@ void glutSetCursor(int cidx) static XVisualInfo *choose_visual(unsigned int mode) { XVisualInfo *vi; - int attr[32] = { - GLX_RGBA, - GLX_DOUBLEBUFFER, - GLX_RED_SIZE, 4, - GLX_GREEN_SIZE, 4, - GLX_BLUE_SIZE, 4 - }; - int *aptr = attr + 8; + int attr[32]; + int *aptr = attr; int *samples = 0; + if(mode & GLUT_DOUBLE) { + *aptr++ = GLX_DOUBLEBUFFER; + } + + if(mode & GLUT_INDEX) { + *aptr++ = GLX_BUFFER_SIZE; + *aptr++ = 1; + } else { + *aptr++ = GLX_RGBA; + *aptr++ = GLX_RED_SIZE; *aptr++ = 4; + *aptr++ = GLX_GREEN_SIZE; *aptr++ = 4; + *aptr++ = GLX_BLUE_SIZE; *aptr++ = 4; + } if(mode & GLUT_ALPHA) { *aptr++ = GLX_ALPHA_SIZE; *aptr++ = 4; @@ -917,17 +935,334 @@ static void get_screen_size(int *scrw, int *scrh) *scrw = wattr.width; *scrh = wattr.height; } -#endif +#endif /* BUILD_X11 */ + + +/* --------------- windows implementation ----------------- */ +#ifdef BUILD_WIN32 +static int reshape_pending; + +static void update_modkeys(void); +static int translate_vkey(int vkey); +static void handle_mbutton(int bn, int st, WPARAM wparam, LPARAM lparam); + +void glutMainLoopEvent(void) +{ + MSG msg; + + if(!cb_display) { + panic("display callback not set"); + } + + if(reshape_pending && cb_reshape) { + reshape_pending = 0; + get_window_size(&win_width, &win_height); + cb_reshape(win_width, win_height); + } + + if(!upd_pending && !cb_idle) { + GetMessage(&msg, 0, 0, 0); + TranslateMessage(&msg); + DispatchMessage(&msg); + if(quit) return; + } + while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + if(quit) return; + } + + if(cb_idle) { + cb_idle(); + } + + if(upd_pending && mapped) { + upd_pending = 0; + cb_display(); + } +} + +void glutSwapBuffers(void) +{ + SwapBuffers(dc); +} + +void glutPositionWindow(int x, int y) +{ + RECT rect; + GetWindowRect(win, &rect); + MoveWindow(win, x, y, rect.right - rect.left, rect.bottom - rect.top, 1); +} + +void glutReshapeWindow(int xsz, int ysz) +{ + RECT rect; + GetWindowRect(win, &rect); + MoveWindow(win, rect.left, rect.top, xsz, ysz, 1); +} + +void glutFullScreen(void) +{ + /* TODO */ +} + +void glutSetWindowTitle(const char *title) +{ + SetWindowText(win, title); +} + +void glutSetIconTitle(const char *title) +{ +} + +void glutSetCursor(int cidx) +{ + switch(cidx) { + case GLUT_CURSOR_NONE: + ShowCursor(0); + break; + case GLUT_CURSOR_INHERIT: + case GLUT_CURSOR_LEFT_ARROW: + default: + SetCursor(LoadCursor(0, IDC_ARROW)); + ShowCursor(1); + } +} + + +static void create_window(const char *title) +{ + int pixfmt; + PIXELFORMATDESCRIPTOR pfd = {0}; + + if(!(win = CreateWindow("MiniGLUT", title, WS_OVERLAPPEDWINDOW, init_x, init_y, + init_width, init_height, 0, 0, hinst, 0))) { + panic("Failed to create window\n"); + } + dc = GetDC(win); + + pfd.nSize = sizeof pfd; + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + if(init_mode & GLUT_STEREO) { + pfd.dwFlags |= PFD_STEREO; + } + pfd.iPixelType = init_mode & GLUT_INDEX ? PFD_TYPE_COLORINDEX : PFD_TYPE_RGBA; + pfd.cColorBits = 24; + if(init_mode & GLUT_ALPHA) { + pfd.cAlphaBits = 8; + } + if(init_mode & GLUT_ACCUM) { + pfd.cAccumBits = 24; + } + if(init_mode & GLUT_DEPTH) { + pfd.cDepthBits = 24; + } + if(init_mode & GLUT_STENCIL) { + pfd.cStencilBits = 8; + } + pfd.iLayerType = PFD_MAIN_PLANE; + + if(!(pixfmt = ChoosePixelFormat(dc, &pfd))) { + panic("Failed to find suitable pixel format\n"); + } + if(!SetPixelFormat(dc, pixfmt, &pfd)) { + panic("Failed to set the selected pixel format\n"); + } + if(!(ctx = wglCreateContext(dc))) { + panic("Failed to create the OpenGL context\n"); + } + wglMakeCurrent(dc, ctx); + + DescribePixelFormat(dc, pixfmt, sizeof pfd, &pfd); + ctx_info.rsize = pfd.cRedBits; + ctx_info.gsize = pfd.cGreenBits; + ctx_info.bsize = pfd.cBlueBits; + ctx_info.asize = pfd.cAlphaBits; + ctx_info.zsize = pfd.cDepthBits; + ctx_info.ssize = pfd.cStencilBits; + ctx_info.dblbuf = pfd.dwFlags & PFD_DOUBLEBUFFER ? 1 : 0; + ctx_info.samples = 1; /* TODO */ + ctx_info.srgb = 0; /* TODO */ + + ShowWindow(win, 1); + upd_pending = 1; + reshape_pending = 1; +} + +static HRESULT CALLBACK handle_message(HWND win, unsigned int msg, WPARAM wparam, LPARAM lparam) +{ + static int mouse_x, mouse_y; + int key; + + switch(msg) { + case WM_CLOSE: + if(win) DestroyWindow(win); + break; + + case WM_DESTROY: + wglMakeCurrent(dc, 0); + wglDeleteContext(ctx); + quit = 1; + PostQuitMessage(0); + break; + + case WM_PAINT: + upd_pending = 1; + ValidateRect(win, 0); + break; + + case WM_SIZE: + win_width = lparam & 0xffff; + win_height = lparam >> 16; + if(cb_reshape) { + reshape_pending = 0; + cb_reshape(win_width, win_height); + } + break; + + case WM_SHOWWINDOW: + mapped = wparam; + if(cb_vis) cb_vis(mapped ? GLUT_VISIBLE : GLUT_NOT_VISIBLE); + break; + + case WM_KEYDOWN: + update_modkeys(); + key = translate_vkey(wparam); + if(key < 256) { + if(cb_keydown) { + cb_keydown((unsigned char)key, mouse_x, mouse_y); + } + } else { + if(cb_skeydown) { + cb_skeydown(key, mouse_x, mouse_y); + } + } + break; + + case WM_KEYUP: + update_modkeys(); + key = translate_vkey(wparam); + if(key < 256) { + if(cb_keyup) { + cb_keyup((unsigned char)key, mouse_x, mouse_y); + } + } else { + if(cb_skeyup) { + cb_skeyup(key, mouse_x, mouse_y); + } + } + break; + + case WM_LBUTTONDOWN: + handle_mbutton(0, 1, wparam, lparam); + break; + case WM_MBUTTONDOWN: + handle_mbutton(1, 1, wparam, lparam); + break; + case WM_RBUTTONDOWN: + handle_mbutton(2, 1, wparam, lparam); + break; + case WM_LBUTTONUP: + handle_mbutton(0, 0, wparam, lparam); + break; + case WM_MBUTTONUP: + handle_mbutton(1, 0, wparam, lparam); + break; + case WM_RBUTTONUP: + handle_mbutton(2, 0, wparam, lparam); + break; + + case WM_MOUSEMOVE: + if(wparam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { + if(cb_motion) cb_motion(lparam & 0xffff, lparam >> 16); + } else { + if(cb_passive) cb_passive(lparam & 0xffff, lparam >> 16); + } + break; + + default: + return DefWindowProc(win, msg, wparam, lparam); + } + + return 0; +} + +static void update_modkeys(void) +{ + if(GetKeyState(VK_SHIFT)) { + modstate |= GLUT_ACTIVE_SHIFT; + } else { + modstate &= ~GLUT_ACTIVE_SHIFT; + } + if(GetKeyState(VK_CONTROL)) { + modstate |= GLUT_ACTIVE_CTRL; + } else { + modstate &= ~GLUT_ACTIVE_CTRL; + } + if(GetKeyState(VK_MENU)) { + modstate |= GLUT_ACTIVE_ALT; + } else { + modstate &= ~GLUT_ACTIVE_ALT; + } +} + +static int translate_vkey(int vkey) +{ + return vkey; /* TODO */ +} + +static void handle_mbutton(int bn, int st, WPARAM wparam, LPARAM lparam) +{ + int x, y; + + update_modkeys(); + + if(cb_mouse) { + x = lparam & 0xffff; + y = lparam >> 16; + cb_mouse(bn, st ? GLUT_DOWN : GLUT_UP, x, y); + } +} + +static void get_window_pos(int *x, int *y) +{ + RECT rect; + GetWindowRect(win, &rect); + *x = rect.left; + *y = rect.top; +} + +static void get_window_size(int *w, int *h) +{ + RECT rect; + GetClientRect(win, &rect); + *w = rect.right - rect.left; + *h = rect.bottom - rect.top; +} + +static void get_screen_size(int *scrw, int *scrh) +{ + *scrw = GetSystemMetrics(SM_CXSCREEN); + *scrh = GetSystemMetrics(SM_CYSCREEN); +} +#endif /* BUILD_WIN32 */ #if defined(__unix__) || defined(__APPLE__) #include +#ifdef MINIGLUT_USE_LIBC +#define sys_gettimeofday(tv, tz) gettimeofday(tv, tz) +#else +static int sys_gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + static long get_msec(void) { static struct timeval tv0; struct timeval tv; - gettimeofday(&tv, 0); + sys_gettimeofday(&tv, 0); if(tv0.tv_sec == 0 && tv0.tv_usec == 0) { tv0 = tv; return 0; @@ -939,12 +1274,18 @@ static long get_msec(void) static long get_msec(void) { static long t0; + long tm; +#ifdef MINIGLUT_NO_WINMM + tm = GetTickCount(); +#else + tm = timeGetTime(); +#endif if(!t0) { - t0 = timeGetTime(); + t0 = tm; return 0; } - return timeGetTime() - t0; + return tm - t0; } #endif @@ -968,9 +1309,14 @@ static int sys_write(int fd, const void *buf, int count) return write(fd, buf, count); } +static int sys_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + return gettimeofday(tv, tz); +} + #else /* !MINIGLUT_USE_LIBC */ -#if defined(__GNUC__) && defined(MINIGLUT_GCC_NO_BUILTIN) +#ifdef __GNUC__ static void mglut_sincosf(float angle, float *sptr, float *cptr) { asm volatile( @@ -1048,8 +1394,7 @@ static void sys_exit(int status) { asm volatile( "syscall\n\t" - :: "a"(60), "D"(status) - ); + :: "a"(60), "D"(status)); } static int sys_write(int fd, const void *buf, int count) { @@ -1057,8 +1402,16 @@ static int sys_write(int fd, const void *buf, int count) asm volatile( "syscall\n\t" : "=a"(res) - : "a"(1), "D"(fd), "S"(buf), "d"(count) - ); + : "a"(1), "D"(fd), "S"(buf), "d"(count)); + return res; +} +static int sys_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + int res; + asm volatile( + "syscall\n\t" + : "=a"(res) + : "a"(96), "D"(tv), "S"(tz)); return res; } #endif @@ -1066,19 +1419,25 @@ static int sys_write(int fd, const void *buf, int count) static void sys_exit(int status) { asm volatile( - "mov $1, %%eax\n\t" "int $0x80\n\t" - :: "b"(status) - : "eax" - ); + :: "a"(1), "b"(status)); } static int sys_write(int fd, const void *buf, int count) { int res; asm volatile( - "mov $4, %%eax\n\t" "int $0x80\n\t" - :: "b"(fd), "c"(buf), "d"(count)); + : "=a"(res) + : "a"(4), "b"(fd), "c"(buf), "d"(count)); + return res; +} +static int sys_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + int res; + asm volatile( + "int $0x80\n\t" + : "=a"(res) + : "a"(78), "b"(tv), "c"(tz)); return res; } #endif @@ -1086,13 +1445,13 @@ static int sys_write(int fd, const void *buf, int count) #endif /* __linux__ */ #ifdef _WIN32 -static int sys_exit(int status) +static void sys_exit(int status) { ExitProcess(status); } static int sys_write(int fd, const void *buf, int count) { - int wrsz; + unsigned long wrsz = 0; HANDLE out = GetStdHandle(fd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); if(!WriteFile(out, buf, count, &wrsz, 0)) {