From: John Tsiombikas Date: Wed, 27 May 2020 05:19:25 +0000 (+0300) Subject: windows port X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=commitdiff_plain;h=1dcaa0cf790ced9f2245ae33d175de5f7bb9a0c9;p=miniglut windows port --- diff --git a/miniglut.c b/miniglut.c index 9268202..0038799 100644 --- a/miniglut.c +++ b/miniglut.c @@ -62,6 +62,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; @@ -130,6 +133,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 +606,8 @@ void glutWireTeapot(float size) } + +/* --------------- UNIX/X11 implementation ----------------- */ #ifdef BUILD_X11 static void handle_event(XEvent *ev); @@ -597,26 +619,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(); } } @@ -917,7 +937,316 @@ 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 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 @@ -1086,7 +1415,7 @@ 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); } diff --git a/miniglut.dsp b/miniglut.dsp new file mode 100644 index 0000000..5654a1d --- /dev/null +++ b/miniglut.dsp @@ -0,0 +1,102 @@ +# Microsoft Developer Studio Project File - Name="miniglut" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=miniglut - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "miniglut.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "miniglut.mak" CFG="miniglut - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "miniglut - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "miniglut - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "miniglut - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W2 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "miniglut - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W2 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "miniglut - Win32 Release" +# Name "miniglut - Win32 Debug" +# Begin Group "src" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\miniglut.c +# End Source File +# Begin Source File + +SOURCE=.\miniglut.h +# End Source File +# Begin Source File + +SOURCE=.\test.c +# End Source File +# End Group +# End Target +# End Project diff --git a/miniglut.dsw b/miniglut.dsw new file mode 100644 index 0000000..5df76dd --- /dev/null +++ b/miniglut.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "miniglut"=.\miniglut.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/miniglut.h b/miniglut.h index af9cfcd..56d7a97 100644 --- a/miniglut.h +++ b/miniglut.h @@ -21,6 +21,12 @@ along with this program. If not, see . #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN 1 #include + +#ifdef _MSC_VER +#pragma comment (lib, "opengl32") +#pragma comment (lib, "winmm") +#endif /* MSVC */ + #endif #include