X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=miniglut.c;h=c9cc1f01493a9006695c781f2fa87489d9f9854a;hb=f703c3cc1fb72bb38eb0a79b56dbb34115f70b85;hp=04ffcfbb555831e4291ff6601ce3789098eda1eb;hpb=ea1f048408daa719d70e78dd88f7ff12f03ac902;p=miniglut diff --git a/miniglut.c b/miniglut.c index 04ffcfb..c9cc1f0 100644 --- a/miniglut.c +++ b/miniglut.c @@ -19,6 +19,9 @@ along with this program. If not, see . #define _GNU_SOURCE #include #include +#else +static void mglut_sincosf(float angle, float *sptr, float *cptr); +static float mglut_atan(float x); #endif #define PI 3.1415926536f @@ -50,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; @@ -71,9 +77,9 @@ struct ctx_info { }; static void create_window(const char *title); -static void get_window_pos(Window win, int *x, int *y); -static void get_window_size(Window win, int *w, int *h); -static void get_screen_size(Window win, int *scrw, int *scrh); +static void get_window_pos(int *x, int *y); +static void get_window_size(int *w, int *h); +static void get_screen_size(int *scrw, int *scrh); static long get_msec(void); static void panic(const char *msg); @@ -101,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; @@ -118,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) @@ -277,16 +300,16 @@ int glutGet(unsigned int s) int x, y; switch(s) { case GLUT_WINDOW_X: - get_window_pos(win, &x, &y); + get_window_pos(&x, &y); return x; case GLUT_WINDOW_Y: - get_window_pos(win, &x, &y); + get_window_pos(&x, &y); return y; case GLUT_WINDOW_WIDTH: - get_window_size(win, &x, &y); + get_window_size(&x, &y); return x; case GLUT_WINDOW_HEIGHT: - get_window_size(win, &x, &y); + get_window_size(&x, &y); return y; case GLUT_WINDOW_BUFFER_SIZE: return ctx_info.rsize + ctx_info.gsize + ctx_info.bsize + ctx_info.asize; @@ -315,10 +338,10 @@ int glutGet(unsigned int s) case GLUT_WINDOW_CURSOR: return cur_cursor; case GLUT_SCREEN_WIDTH: - get_screen_size(win, &x, &y); + get_screen_size(&x, &y); return x; case GLUT_SCREEN_HEIGHT: - get_screen_size(win, &x, &y); + get_screen_size(&x, &y); return y; case GLUT_INIT_DISPLAY_MODE: return init_mode; @@ -397,8 +420,8 @@ void glutSolidSphere(float rad, int slices, int stacks) t = gray & 2 ? v + dv : v; theta = s * PI * 2.0f; phi = t * PI; - sincosf(theta, &sintheta, &costheta); - sincosf(phi, &sinphi, &cosphi); + mglut_sincosf(theta, &sintheta, &costheta); + mglut_sincosf(phi, &sinphi, &cosphi); x = sintheta * sinphi; y = costheta * sinphi; z = cosphi; @@ -462,8 +485,9 @@ static void draw_cylinder(float rbot, float rtop, float height, int slices, int float du = 1.0f / (float)slices; float dv = 1.0f / (float)stacks; - phi = atan(fabs(rbot - rtop) / height); - sincosf(phi, &sinphi, &cosphi); + rad = rbot - rtop; + phi = mglut_atan((rad < 0 ? -rad : rad) / height); + mglut_sincosf(phi, &sinphi, &cosphi); glBegin(GL_QUADS); for(i=0; i> 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; @@ -926,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 @@ -954,8 +1308,85 @@ 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 */ +#ifdef __GNUC__ +static void mglut_sincosf(float angle, float *sptr, float *cptr) +{ + asm volatile( + "flds %2\n\t" + "fsincos\n\t" + "fstps %1\n\t" + "fstps %0\n\t" + : "=m"(*sptr), "=m"(*cptr) + : "m"(angle) + ); +} + +static float mglut_atan(float x) +{ + float res; + asm volatile( + "flds %1\n\t" + "fld1\n\t" + "fpatan\n\t" + "fstps %0\n\t" + : "=m"(res) + : "m"(x) + ); + return res; +} +#endif + +#ifdef _MSC_VER +static void mglut_sincosf(float angle, float *sptr, float *cptr) +{ + float s, c; + __asm { + fld angle + fsincos + fstp c + fstp s + } + *sptr = s; + *cptr = c; +} + +static float mglut_atan(float x) +{ + float res; + __asm { + fld x + fld1 + fpatan + fstp res + } + return res; +} +#endif + +#ifdef __WATCOMC__ +#pragma aux mglut_sincosf = \ + "fsincos" \ + "fstp dword ptr [edx]" \ + "fstp dword ptr [eax]" \ + parm[8087][eax][edx] \ + modify[8087]; + +#pragma aux mglut_atan = \ + "fld1" \ + "fpatan" \ + parm[8087] \ + value[8087] \ + modify [8087]; +#endif + #ifdef __linux__ #ifdef __x86_64__ @@ -963,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) { @@ -972,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 @@ -981,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 @@ -1001,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)) {