# HG changeset patch # User John Tsiombikas # Date 1309258322 -10800 # Node ID 6242b03e719126221c47393be6f71be749df2b95 # Parent 171aa71b97e7a2488b7ca3386d48d04a1009b5bd# Parent 25de96fb15263ce05d931f9bfb014dff5bd7e03b merged with win32 branch diff -r 171aa71b97e7 -r 6242b03e7191 sgl.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sgl.sln Tue Jun 28 13:52:02 2011 +0300 @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sgl", "sgl.vcxproj", "{5DA1BC2D-9C03-425E-BE3A-AAF75437045B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "simple", "tests\simple\simple.vcxproj", "{440D0E79-9B82-4FD5-B8D6-D552938ED172}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {5DA1BC2D-9C03-425E-BE3A-AAF75437045B}.Debug|Win32.ActiveCfg = Debug|Win32 + {5DA1BC2D-9C03-425E-BE3A-AAF75437045B}.Debug|Win32.Build.0 = Debug|Win32 + {5DA1BC2D-9C03-425E-BE3A-AAF75437045B}.Release|Win32.ActiveCfg = Release|Win32 + {5DA1BC2D-9C03-425E-BE3A-AAF75437045B}.Release|Win32.Build.0 = Release|Win32 + {440D0E79-9B82-4FD5-B8D6-D552938ED172}.Debug|Win32.ActiveCfg = Debug|Win32 + {440D0E79-9B82-4FD5-B8D6-D552938ED172}.Debug|Win32.Build.0 = Debug|Win32 + {440D0E79-9B82-4FD5-B8D6-D552938ED172}.Release|Win32.ActiveCfg = Release|Win32 + {440D0E79-9B82-4FD5-B8D6-D552938ED172}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 171aa71b97e7 -r 6242b03e7191 sgl.vcxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sgl.vcxproj Tue Jun 28 13:52:02 2011 +0300 @@ -0,0 +1,93 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + {5DA1BC2D-9C03-425E-BE3A-AAF75437045B} + Win32Proj + sgl + + + + StaticLibrary + true + Unicode + + + StaticLibrary + false + true + Unicode + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + 4996 + include + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + 4996 + include + + + Windows + true + true + true + + + + + + \ No newline at end of file diff -r 171aa71b97e7 -r 6242b03e7191 src/wsys_w32.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/wsys_w32.c Tue Jun 28 13:52:02 2011 +0300 @@ -0,0 +1,481 @@ +/* SimplyGL window system module for Win32/WGL */ +/* link-with: -lopengl32 */ + +#include "config.h" + +#ifdef USE_WSYS_MODULE_W32 + +#include +#include +#include +#include "sgl.h" +#include "wsys.h" +#include "log.h" + +struct window { + int id; + HWND win; + HDC dc; + HGLRC ctx; + int width, height; + int redisp_pending; + + struct window *next; +}; + +static int init(void); +static void shut_down(void); + +/* video mode switching */ +static int set_vidmode(int xsz, int ysz); +static int get_vidmode(int *xsz, int *ysz); + +/* create/destroy windows */ +static int create_window(int xsz, int ysz, unsigned int flags); +static void close_window(int id); + +/* window management */ +static int set_active(int id); +static struct window *find_window(int id); +static struct window *find_window_handle(HWND wh); +static int activate_window(struct window *win); +static int set_title(const char *str); +static void redisplay(void); +static void swap_buffers(void); + +static int get_modifiers(void); + +/* event handling and friends */ +static void set_bits(long *mask, long bits); +static void clear_bits(long *mask, long bits); +static void set_event(int idx, int enable); +static int process_events(void); + +static LRESULT CALLBACK handle_events(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); +static int mouse_button(unsigned int msg); +static void calc_win_size(int w, int h, int *width, int *height, int *posx, int *posy); + + +static struct wsys_module ws = { + "win32", 0, + init, + shut_down, + set_vidmode, + get_vidmode, + create_window, + close_window, + set_active, + set_title, + redisplay, + swap_buffers, + get_modifiers, + set_event, + process_events, + 0 +}; + +static struct window *winlist; +static struct window *active_win, *prev_active; +static int next_id = 1; + +/* this is the only exported function, everything else should be static */ +void sgl_register_w32(void) +{ + sgl_register_module(&ws); +} + + +static int init(void) +{ + winlist = 0; + active_win = prev_active = 0; + return 0; +} + +static void shut_down(void) +{ + /* TODO */ +} + +static int set_vidmode(int xsz, int ysz) +{ + DEVMODE dmode; + memset(&dmode, 0, sizeof dmode); + dmode.dmSize = sizeof dmode; + /*dmode.dmBitsPerPel = 32;*/ + dmode.dmPelsWidth = xsz; + dmode.dmPelsHeight = ysz; + dmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + if(ChangeDisplaySettings(&dmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) { + sgl_log("failed to set video mode: %dx%d\n", xsz, ysz); + return -1; + } + return 0; +} + +static int get_vidmode(int *xsz, int *ysz) +{ + /* TODO */ + return 0; +} + +static int create_window(int xsz, int ysz, unsigned int flags) +{ + WNDCLASS wclass; + int win_width, win_height, win_x, win_y; + unsigned int style; + HINSTANCE pid; + HWND win; + PIXELFORMATDESCRIPTOR fmt; + int pf_id; + struct window *wnode; + void (*func)(); + + if(!(wnode = malloc(sizeof *wnode))) { + return -1; + } + + pid = GetModuleHandle(0); + + memset(&wclass, 0, sizeof wclass); + wclass.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC; + wclass.lpfnWndProc = handle_events; + wclass.hInstance = pid; + wclass.lpszClassName = "simplygl"; + + if(!RegisterClass(&wclass)) { + sgl_log("failed to register window class\n"); + return -1; + } + + calc_win_size(xsz, ysz, &win_width, &win_height, &win_x, &win_y); + + style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_POPUP | WS_SYSMENU | WS_VISIBLE; + + if(!(win = CreateWindow("simplygl", "OpenGL/Win32", style, win_x, win_y, win_width, win_height, 0, 0, pid, 0))) { + sgl_log("failed to create window\n"); + return -1; + } + + ShowWindow(win, SW_SHOW); + SetForegroundWindow(win); + SetActiveWindow(win); + + wnode->win = win; + wnode->dc = GetDC(win); + + memset(&fmt, 0, sizeof fmt); + fmt.nSize = sizeof fmt; + fmt.nVersion = 1; + fmt.cColorBits = PFD_TYPE_RGBA; + fmt.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + + if(flags & SGL_DOUBLE) { + fmt.dwFlags |= PFD_DOUBLEBUFFER; + } + if(flags & SGL_DEPTH) { + fmt.cDepthBits = 24; + } + if(flags & SGL_STENCIL) { + fmt.cStencilBits = 8; + } + /* TODO: more... */ + + if(!(pf_id = ChoosePixelFormat(wnode->dc, &fmt))) { + sgl_log("can't find requested pixel format\n"); + return -1; + } + if(!SetPixelFormat(wnode->dc, pf_id, &fmt)) { + sgl_log("failed to set pixel format\n"); + return -1; + } + if(!(wnode->ctx = wglCreateContext(wnode->dc))) { + sgl_log("failed to create OpenGL context\n"); + return -1; + } + + wnode->id = next_id++; + wnode->width = xsz; + wnode->height = ysz; + wnode->redisp_pending = 1; + wnode->next = winlist; + winlist = wnode; + + if(!active_win) { + set_active(wnode->id); + } else { + activate_window(wnode); + } + + if((func = sgl_get_callback(SGL_CREATE))) { + func(wnode->id); + } + if((func = sgl_get_callback(SGL_RESHAPE))) { + func(xsz, ysz); + } + activate_window(prev_active); + return wnode->id; +} + +static void close_window(int id) +{ + struct window dummy, *win, *prev; + sgl_close_callback_t close_func; + + dummy.next = winlist; + + prev = &dummy; + win = prev->next; + + while(win) { + if(win->id == id) { + if((close_func = sgl_get_callback(SGL_CLOSE))) { + close_func(id); + } + wglDeleteContext(win->ctx); + ReleaseDC(win->win, win->dc); + DestroyWindow(win->win); + + prev->next = win->next; + free(win); + return; + } + prev = win; + win = win->next; + } +} + +static int set_active(int id) +{ + struct window *win = find_window(id); + if(!win) { + sgl_log("no such window: %d\n", id); + return -1; + } + /* only the user calls this, so don't revert this selection */ + prev_active = win; + return activate_window(win); +} + +static struct window *find_window(int id) +{ + struct window *win = winlist; + + while(win) { + if(win->id == id) { + return win; + } + win = win->next; + } + return 0; +} + +static struct window *find_window_handle(HWND wh) +{ + struct window *win = winlist; + + while(win) { + if(win->win == wh) { + return win; + } + win = win->next; + } + return 0; +} + +static int activate_window(struct window *win) +{ + if(!wglMakeCurrent(win->dc, win->ctx)) { + sgl_log("failed to activate window %d\n", (int)win->id); + return -1; + } + active_win = win; + return 0; +} + +static int set_title(const char *str) +{ + SetWindowText(active_win->win, str); + return 0; +} + +static void redisplay(void) +{ + InvalidateRect(active_win->win, 0, 0); +} + +static void swap_buffers(void) +{ + SwapBuffers(active_win->dc); +} + +static int get_modifiers(void) +{ + return 0; /* TODO */ +} + +static void set_event(int idx, int enable) +{ + /* not needed */ +} + +static int process_events(void) +{ + int ret = 0; + MSG msg; + sgl_idle_callback_t idle; + + idle = sgl_get_callback(SGL_IDLE); + + prev_active = active_win; + + if(!idle) { + if(!GetMessage(&msg, 0, 0, 0)) { + ret = -1; + goto end; + } + } else { + if(!PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + ret = 0; + goto end; + } + } + + do { + if(msg.message == WM_QUIT) { + ret = -1; + break; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)); + +end: + if(ret != -1 && idle) { + idle(); + } + activate_window(prev_active); + return ret; +} + +static LRESULT CALLBACK handle_events(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) +{ + static int state; + struct window *win; + void (*func)(); + + if((win = find_window_handle(hwnd))) { + activate_window(win); + } else { + return DefWindowProc(hwnd, msg, wparam, lparam); + } + + switch(msg) { + case WM_PAINT: + if((func = sgl_get_callback(SGL_DISPLAY))) { + func(); + } + ValidateRect(hwnd, 0); + break; + + case WM_KEYDOWN: + case WM_KEYUP: + if((func = sgl_get_callback(SGL_KEYBOARD))) { + func(MapVirtualKey(wparam, 2), msg == WM_KEYDOWN); + } + break; + + case WM_LBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_MBUTTONDOWN: + if(1) { + state++; + } else { + case WM_LBUTTONUP: + case WM_RBUTTONUP: + case WM_MBUTTONUP: + state--; + } + assert(state >= 0); + if((func = sgl_get_callback(SGL_MOUSE))) { + func(mouse_button(msg), state, LOWORD(lparam), HIWORD(lparam)); + } + break; + + case WM_MOUSEMOVE: + if(state) { + func = sgl_get_callback(SGL_MOTION); + } else { + func = sgl_get_callback(SGL_PASSIVE); + } + if(func) { + func(LOWORD(lparam), HIWORD(lparam)); + } + break; + + default: + return DefWindowProc(hwnd, msg, wparam, lparam); + } + return 0; +} + +static int mouse_button(unsigned int msg) +{ + switch(msg) { + case WM_LBUTTONDOWN: + case WM_LBUTTONUP: + return SGL_LEFT_BUTTON; + + case WM_RBUTTONDOWN: + case WM_RBUTTONUP: + return SGL_RIGHT_BUTTON; + + case WM_MBUTTONDOWN: + case WM_MBUTTONUP: + return SGL_MIDDLE_BUTTON; + + default: + break; + } + return -1; +} + +static void calc_win_size(int w, int h, int *width, int *height, int *posx, int *posy) +{ + RECT rect; + DEVMODE dmode; + unsigned int style = WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_POPUP | WS_SYSMENU | WS_VISIBLE; + + rect.left = rect.top = 0; + rect.right = w; + rect.bottom = h; + + AdjustWindowRect(&rect, style, 0); + + *width = rect.right - rect.left; + *height = rect.bottom - rect.top; + + *posx = *posy = 0; + + memset(&dmode, 0, sizeof dmode); + dmode.dmSize = sizeof dmode; + + if(EnumDisplaySettings(0, ENUM_CURRENT_SETTINGS, &dmode)) { + int x, y; + + x = (dmode.dmPelsWidth - *width) / 2; + if(x > 0) { + *posx = x; + } + + y = (dmode.dmPelsHeight - *height) / 2; + if(y > 0) { + *posy = y; + } + } +} + +#else +int sgl_wsys_w32_silence_the_fucking_empty_file_warnings; +#endif diff -r 171aa71b97e7 -r 6242b03e7191 tests/simple/simple.c --- a/tests/simple/simple.c Tue Jun 28 13:50:41 2011 +0300 +++ b/tests/simple/simple.c Tue Jun 28 13:52:02 2011 +0300 @@ -1,5 +1,8 @@ #include #include +#ifdef WIN32 +#include +#endif /* WIN32 */ #ifndef __APPLE__ #include #else diff -r 171aa71b97e7 -r 6242b03e7191 tests/simple/simple.vcxproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/simple/simple.vcxproj Tue Jun 28 13:52:02 2011 +0300 @@ -0,0 +1,88 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {440D0E79-9B82-4FD5-B8D6-D552938ED172} + Win32Proj + simple + + + + Application + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + true + + + false + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(SolutionDir)\include;%(AdditionalIncludeDirectories) + + + Console + true + $(SolutionDir)\Debug + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;sgl.lib;opengl32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + ..\..\sgl\include;%(AdditionalIncludeDirectories) + + + Console + true + true + true + $(SolutionDir)\Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;sgl.lib;opengl32.lib;%(AdditionalDependencies) + + + + + + + + + \ No newline at end of file