From e346dc20fb1fcbc8f895d7c46e3ec54628d3db0c Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 29 Apr 2012 02:12:26 +0000 Subject: Windows implementation. --- pugl/pugl_win.cpp | 193 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ pugl_test.c | 17 ++++- wscript | 52 +++++++++------ 3 files changed, 242 insertions(+), 20 deletions(-) create mode 100644 pugl/pugl_win.cpp diff --git a/pugl/pugl_win.cpp b/pugl/pugl_win.cpp new file mode 100644 index 0000000..a27a2c5 --- /dev/null +++ b/pugl/pugl_win.cpp @@ -0,0 +1,193 @@ +/* + Copyright 2012 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include + +#include +#include +#include + +#include "pugl_internal.h" + +struct PuglPlatformDataImpl { + HWND hwnd; + HDC hdc; + HGLRC hglrc; +}; + +PuglWindow* +puglCreate(PuglNativeWindow parent, const char* title, int width, int height) +{ + PuglWindow* win = (PuglWindow*)calloc(1, sizeof(PuglWindow)); + + win->impl = (PuglPlatformData*)calloc(1, sizeof(PuglPlatformData)); + + PuglPlatformData* impl = win->impl; + + WNDCLASS wc; + wc.style = CS_OWNDC; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = 0; + wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = "Pugl"; + RegisterClass(&wc); + + impl->hwnd = CreateWindow("Pugl", title, + WS_CAPTION | WS_POPUPWINDOW | WS_VISIBLE, + 0, 0, width, height, + (HWND)parent, NULL, NULL, NULL); + + + impl->hdc = GetDC(impl->hwnd); + + PIXELFORMATDESCRIPTOR pfd; + ZeroMemory(&pfd, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cDepthBits = 16; + pfd.iLayerType = PFD_MAIN_PLANE; + + int format = ChoosePixelFormat(impl->hdc, &pfd); + SetPixelFormat(impl->hdc, format, &pfd); + + impl->hglrc = wglCreateContext(impl->hdc); + wglMakeCurrent(impl->hdc, impl->hglrc); + + win->width = width; + win->height = height; + + return win; +} + +void +puglDestroy(PuglWindow* win) +{ + wglMakeCurrent(NULL, NULL); + wglDeleteContext(win->impl->hglrc); + ReleaseDC(win->impl->hwnd, win->impl->hdc); + DestroyWindow(win->impl->hwnd); + free(win); +} + +void +puglDisplay(PuglWindow* win) +{ + glViewport(0, 0, win->width, win->height); + + if (win->displayFunc) { + win->displayFunc(win); + } + + SwapBuffers(win->impl->hdc); + win->redisplay = false; +} + +static void +processMouseEvent(PuglWindow* win, int button, bool down, LPARAM lParam) +{ + if (win->mouseFunc) { + win->mouseFunc(win, button, down, + GET_X_LPARAM(lParam), + GET_Y_LPARAM(lParam)); + } +} + +PuglStatus +puglProcessEvents(PuglWindow* win) +{ + MSG msg; + PAINTSTRUCT ps; + int button; + bool down = true; + while (PeekMessage(&msg, win->impl->hwnd, 0, 0, PM_REMOVE)) { + switch (msg.message) { + case WM_PAINT: + BeginPaint(win->impl->hwnd, &ps); + puglDisplay(win); + EndPaint(win->impl->hwnd, &ps); + break; + case WM_SIZE: + if (win->reshapeFunc) { + win->reshapeFunc(win, LOWORD(msg.lParam), HIWORD(msg.lParam)); + } + break; + case WM_MOUSEMOVE: + if (win->motionFunc) { + win->motionFunc( + win, GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); + } + break; + case WM_LBUTTONDOWN: + processMouseEvent(win, 1, true, msg.lParam); + break; + case WM_MBUTTONDOWN: + processMouseEvent(win, 2, true, msg.lParam); + break; + case WM_RBUTTONDOWN: + processMouseEvent(win, 3, true, msg.lParam); + break; + case WM_LBUTTONUP: + processMouseEvent(win, 1, false, msg.lParam); + break; + case WM_MBUTTONUP: + processMouseEvent(win, 2, false, msg.lParam); + break; + case WM_RBUTTONUP: + processMouseEvent(win, 3, false, msg.lParam); + break; + case WM_KEYDOWN: + case WM_KEYUP: + if (win->keyboardFunc) { + win->keyboardFunc(win, msg.message == WM_KEYDOWN, msg.wParam); + } + break; + case WM_QUIT: + if (win->closeFunc) { + win->closeFunc(win); + } + break; + default: + DefWindowProc( + win->impl->hwnd, msg.message, msg.wParam, msg.lParam); + } + } + + if (win->redisplay) { + puglDisplay(win); + } + + return PUGL_SUCCESS; +} + +void +puglPostRedisplay(PuglWindow* win) +{ + win->redisplay = true; +} + +PuglNativeWindow +puglGetNativeWindow(PuglWindow* win) +{ + return (PuglNativeWindow)win->impl->hwnd; +} diff --git a/pugl_test.c b/pugl_test.c index 3122a89..f6d9ac2 100644 --- a/pugl_test.c +++ b/pugl_test.c @@ -18,6 +18,14 @@ @file pugl_test.c A simple Pugl test that creates a top-level window. */ +/* + This program uses only the the Pugl and OpenGL APIs, but the Windows + gl.h is broken and requires windows.h to be included first... +*/ +#ifdef _WIN32 +# include +#endif + #include #include "GL/gl.h" @@ -51,7 +59,7 @@ onDisplay(PuglWindow* win) static void onKeyboard(PuglWindow* win, bool press, uint32_t key) { - if (key == 'q' || key == KEY_ESCAPE) { + if (key == 'q' || key == 'Q' || key == KEY_ESCAPE) { quit = 1; } } @@ -64,6 +72,12 @@ onMotion(PuglWindow* win, int x, int y) puglPostRedisplay(win); } +static void +onMouse(PuglWindow* handle, int button, int state, int x, int y) +{ + fprintf(stderr, "Mouse %d at %d,%d\n", button, x, y); +} + static void onClose(PuglWindow* win) { @@ -76,6 +90,7 @@ main(int argc, char** argv) PuglWindow* win = puglCreate(0, "Pugl Test", 512, 512); puglSetKeyboardFunc(win, onKeyboard); puglSetMotionFunc(win, onMotion); + puglSetMouseFunc(win, onMouse); puglSetDisplayFunc(win, onDisplay); puglSetCloseFunc(win, onClose); diff --git a/wscript b/wscript index 1bf5b07..6643408 100644 --- a/wscript +++ b/wscript @@ -27,14 +27,20 @@ out = 'build' def options(opt): opt.load('compiler_c') + if Options.platform == 'win32': + opt.load('compiler_cxx') autowaf.set_options(opt) opt.add_option('--test', action='store_true', default=False, dest='build_tests', help="Build unit tests") opt.add_option('--static', action='store_true', default=False, dest='static', help="Build static library") + opt.add_option('--shared', action='store_true', default=False, dest='shared', + help="Build shared library") def configure(conf): conf.load('compiler_c') + if Options.platform == 'win32': + conf.load('compiler_cxx') autowaf.configure(conf) autowaf.display_header('Pugl Configuration') @@ -43,7 +49,10 @@ def configure(conf): else: conf.env.append_unique('CFLAGS', '-std=c99') + # Shared library building is broken on win32 for some reason conf.env['BUILD_TESTS'] = Options.options.build_tests + conf.env['BUILD_SHARED'] = (Options.platform != 'win32' or + Options.options.shared) conf.env['BUILD_STATIC'] = (Options.options.build_tests or Options.options.static) @@ -69,32 +78,37 @@ def build(bld): {'PUGL_MAJOR_VERSION' : PUGL_MAJOR_VERSION}) libflags = [ '-fvisibility=hidden' ] - libs = [ 'X11', 'GL' ] - defines = [] + if Options.platform == 'win32': + lang = 'cxx' + lib_source = ['pugl/pugl_win.cpp'] + libs = ['opengl32', 'gdi32', 'user32'] + defines = [] + else: + lang = 'c' + lib_source = ['pugl/pugl_x11.c'] + libs = ['X11', 'GL'] + defines = [] if bld.env['MSVC_COMPILER']: libflags = [] - libs = [] - defines = ['snprintf=_snprintf'] - - lib_source = ['./pugl/pugl_x11.c'] # Shared Library - obj = bld(features = 'c cshlib', - export_includes = ['.'], - source = lib_source, - includes = ['.', './src'], - lib = libs, - name = 'libpugl', - target = 'pugl-%s' % PUGL_MAJOR_VERSION, - vnum = PUGL_LIB_VERSION, - install_path = '${LIBDIR}', - defines = defines, - cflags = libflags + [ '-DPUGL_SHARED', - '-DPUGL_INTERNAL' ]) + if bld.env['BUILD_SHARED']: + obj = bld(features = '%s %sshlib' % (lang, lang), + export_includes = ['.'], + source = lib_source, + includes = ['.', './src'], + lib = libs, + name = 'libpugl', + target = 'pugl-%s' % PUGL_MAJOR_VERSION, + vnum = PUGL_LIB_VERSION, + install_path = '${LIBDIR}', + defines = defines, + cflags = libflags + [ '-DPUGL_SHARED', + '-DPUGL_INTERNAL' ]) # Static library if bld.env['BUILD_STATIC']: - obj = bld(features = 'c cstlib', + obj = bld(features = '%s %sstlib' % (lang, lang), export_includes = ['.'], source = lib_source, includes = ['.', './src'], -- cgit v1.2.1