From c3657a01ec8ce2c159978d1ee4d36b5456413ca1 Mon Sep 17 00:00:00 2001 From: Wolfgang Draxinger Date: Fri, 17 Apr 2015 22:08:23 +0200 Subject: changed build system from plain Makefile to CMake --- CMakeLists.txt | 9 + build.sh | 31 +++ cmake/Toolchain-cross-mingw32-linux.cmake | 26 +++ cmake/Toolchain-cross-mingw64-linux.cmake | 26 +++ src/CMakeLists.txt | 43 ++++ src/wglarb.c | 238 +++++++++++++++++++++ src/wglarb.h | 43 ++++ test/CMakeLists.txt | 37 ++++ test/customframe.c | 345 ++++++++++++++++++++++++++++++ test/customframe.rc | 3 + 10 files changed, 801 insertions(+) create mode 100644 CMakeLists.txt create mode 100755 build.sh create mode 100644 cmake/Toolchain-cross-mingw32-linux.cmake create mode 100644 cmake/Toolchain-cross-mingw64-linux.cmake create mode 100644 src/CMakeLists.txt create mode 100644 src/wglarb.c create mode 100644 src/wglarb.h create mode 100644 test/CMakeLists.txt create mode 100644 test/customframe.c create mode 100644 test/customframe.rc diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3016bb4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 2.8) +project(wglarb) + +find_package(OpenGL) + +add_subdirectory(src) + +include_directories(src) +add_subdirectory(test) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..670dacb --- /dev/null +++ b/build.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SOURCE_TREE=$(dirname $(readlink -f "$0")) + +echo "build directory: ${PWD}" +echo "source tree directory: ${SOURCE_TREE}" + +if [ ${PWD} = ${SOURCE_TREE} ] ; then + echo "$0 must be executed out-of-tree" +fi + +BUILD_BASE_DIR="${PWD}" + +BUILD_DIR_W32="${BUILD_BASE_DIR}/windows-x86_32" +BUILD_DIR_W64="${BUILD_BASE_DIR}/windows-x86_64" + +if [ ! -d ${BUILD_DIR_W32} ] ; then + mkdir -p ${BUILD_DIR_W32} +fi + +if [ ! -d ${BUILD_DIR_W64} ] ; then + mkdir -p ${BUILD_DIR_W64} +fi + +cd ${BUILD_DIR_W32} +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="${SOURCE_TREE}/cmake/Toolchain-cross-mingw32-linux.cmake" "${SOURCE_TREE}" +make ${MAKEOPTS} + +cd ${BUILD_DIR_W64} +cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="${SOURCE_TREE}/cmake/Toolchain-cross-mingw64-linux.cmake" "${SOURCE_TREE}" +make ${MAKEOPTS} diff --git a/cmake/Toolchain-cross-mingw32-linux.cmake b/cmake/Toolchain-cross-mingw32-linux.cmake new file mode 100644 index 0000000..2ee0e33 --- /dev/null +++ b/cmake/Toolchain-cross-mingw32-linux.cmake @@ -0,0 +1,26 @@ +# the name of the target operating system +set(CMAKE_SYSTEM_NAME Windows) + +# Choose an appropriate compiler prefix + +# for 32 or 64 bits mingw-w64 +# see http://mingw-w64.sourceforge.net/ +set(COMPILER_PREFIX "i686-w64-mingw32") + +set(DLL_OUTPUT_PREFIX "" CACHE STRING "DLL name prefix" FORCE) +set(DLL_OUTPUT_SUFFIX "-x86_32" CACHE STRING "DLL name suffix" FORCE) + +# which compilers to use for C and C++ +find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres) +find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc) +find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++) + +# here is the target environment located +set(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX}) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/cmake/Toolchain-cross-mingw64-linux.cmake b/cmake/Toolchain-cross-mingw64-linux.cmake new file mode 100644 index 0000000..9b631a1 --- /dev/null +++ b/cmake/Toolchain-cross-mingw64-linux.cmake @@ -0,0 +1,26 @@ +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) + +# Choose an appropriate compiler prefix + +# for 32 or 64 bits mingw-w64 +# see http://mingw-w64.sourceforge.net/ +set(COMPILER_PREFIX "x86_64-w64-mingw32") + +set(DLL_OUTPUT_PREFIX "" CACHE STRING "DLL name prefix" FORCE) +set(DLL_OUTPUT_SUFFIX "-x86_64" CACHE STRING "DLL name suffix" FORCE) + +# which compilers to use for C and C++ +find_program(CMAKE_RC_COMPILER NAMES ${COMPILER_PREFIX}-windres) +find_program(CMAKE_C_COMPILER NAMES ${COMPILER_PREFIX}-gcc) +find_program(CMAKE_CXX_COMPILER NAMES ${COMPILER_PREFIX}-g++) + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH /usr/${COMPILER_PREFIX}) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..c6abaf4 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 2.8) +project(libwglarb) + +include(GenerateExportHeader) + +# GCC intrinsics support and C++ standard library should be linked statically +# so that no external dependencies are created. +if(NOT MSVC) # TODO: this should test for GCC and not "not MSVC" compiler + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -static-libgcc -std=c99") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++") + set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -static-libgcc -s") + set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS} -static-libgcc -static-libstdc++ -s") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++ -s ") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--output-def,wglarb${DLL_OUTPUT_SUFFIX}.def,--out-implib,wglarb.dll.a") +endif() + +set(OPENGL_API_LIBRARY opengl32) + +set(LIBWGLARB_INCLUDE_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE STRING "wglarb source directory" FORCE) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} ) +set(LIBWGLARB_SRC_FILES + wglarb.c ) + +add_library(wglarb_static STATIC + ${LIBWGLARB_SRC_FILES} ) + +add_library(wglarb_shared SHARED + ${LIBWGLARB_SRC_FILES} ) + +target_link_libraries( + wglarb_shared + ${OPENGL_API_LIBRARY} ) + +set_target_properties(wglarb_shared PROPERTIES DEFINE_SYMBOL "wglarb_EXPORTS") +set_target_properties(wglarb_shared PROPERTIES DEFINE_SYMBOL "wglarb_EXPORTS") + +set_target_properties(wglarb_shared PROPERTIES OUTPUT_NAME "wglarb") +set_target_properties(wglarb_static PROPERTIES OUTPUT_NAME "wglarb") + +set_target_properties(wglarb_shared PROPERTIES PREFIX "${DLL_OUTPUT_PREFIX}") +set_target_properties(wglarb_shared PROPERTIES SUFFIX "${DLL_OUTPUT_SUFFIX}.dll") diff --git a/src/wglarb.c b/src/wglarb.c new file mode 100644 index 0000000..c9ba7d7 --- /dev/null +++ b/src/wglarb.c @@ -0,0 +1,238 @@ +/* +Copyright (c) 2014 Wolfgang 'datenwolf' Draxinger + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#include +#include "wglarb.h" + +#define wglarb_BuildAssert(cond) ((void)sizeof(char[1 - 2*!(cond)])) + +static HANDLE wglarb_intermediary_mutex = NULL; + +static DWORD wglarb_intermediary_lock(void) +{ + wglarb_BuildAssert( sizeof(PVOID) == sizeof(HANDLE) ); + + if( !wglarb_intermediary_mutex ) { + /* Between testing for the validity of the mutex handle, + * creating a new mutex handle and using the interlocked + * exchange there is a race... */ + + /* //// START \\\\ */ + + HANDLE const new_mutex = + CreateMutex(NULL, TRUE, NULL); + + HANDLE const dst_mutex = + InterlockedCompareExchangePointer( + &wglarb_intermediary_mutex, + new_mutex, + NULL ); + + /* //// FINISH \\\\ */ + + if( !dst_mutex ) { + /* mutex created in one time initialization and held + * by calling thread. Return signaled status. */ + return WAIT_OBJECT_0; + } + /* In this case we lost the race and another thread + * beat this thread in creating a mutex object. + * Clean up and wait for the proper mutex. */ + ReleaseMutex(new_mutex); + CloseHandle(new_mutex); + } + return WaitForSingleObject(wglarb_intermediary_mutex, INFINITE); +} + +static BOOL wglarb_intermediary_unlock(void) +{ + return ReleaseMutex(wglarb_intermediary_mutex); +} + +#define WGLARB_INTERMEDIARY_CLASS "wglarb intermediary" +#define WGLARB_INTERMEDIARY_STYLE (WS_CLIPSIBLINGS|WS_CLIPCHILDREN) +#define WGLARB_INTERMEDIARY_EXSTYLE 0 + +static HWND wglarb_intermediary_hWnd = 0; + +static BOOL wglarb_intermediary_create_Wnd(void) +{ + HINSTANCE const hInstance = GetModuleHandle(NULL); + + WNDCLASS wc; + memset(&wc,0,sizeof(wc)); + wc.hInstance = hInstance; + wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = WGLARB_INTERMEDIARY_CLASS; + RegisterClass(&wc); + + wglarb_intermediary_hWnd = + CreateWindowEx( + WGLARB_INTERMEDIARY_EXSTYLE, + WGLARB_INTERMEDIARY_CLASS, + NULL, + WGLARB_INTERMEDIARY_STYLE, + 0,0,0,0, + NULL,NULL, + hInstance, + NULL ); + + if( !wglarb_intermediary_hWnd ) { + return FALSE; + } + + return TRUE; +} + +static HDC wglarb_intermediary_hDC = 0; + +static BOOL wglarb_intermediary_create_DC(void) +{ + if( !wglarb_intermediary_hWnd + && !wglarb_intermediary_create_Wnd() ) { + return FALSE; + } + + wglarb_intermediary_hDC = GetDC(wglarb_intermediary_hWnd); + if( !wglarb_intermediary_hDC ) { + return FALSE; + } + + return TRUE; +} + +static HGLRC wglarb_intermediary_hRC = 0; + +static BOOL wglarb_intermediary_create_RC(void) +{ + if( !wglarb_intermediary_hDC + && !wglarb_intermediary_create_DC() ) { + return FALSE; + } + + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd,0,sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_SUPPORT_OPENGL|PFD_GENERIC_ACCELERATED|PFD_DRAW_TO_WINDOW; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.iLayerType = PFD_MAIN_PLANE; + + int iPF; + if( !(iPF = ChoosePixelFormat(wglarb_intermediary_hDC, &pfd)) + || !(SetPixelFormat(wglarb_intermediary_hDC, iPF, &pfd)) + || !(wglarb_intermediary_hRC = wglCreateContext(wglarb_intermediary_hDC)) + ) { + return FALSE; + } + + return TRUE; +} + +static BOOL wglarb_intermediary_makecurrent(HDC *hOrigDC, HGLRC *hOrigRC) +{ + *hOrigDC = wglGetCurrentDC(); + *hOrigRC = wglGetCurrentContext(); + + if( !wglarb_intermediary_hRC + && !wglarb_intermediary_create_RC() ) { + return FALSE; + } + + return wglMakeCurrent(wglarb_intermediary_hDC, wglarb_intermediary_hRC); +} + +HGLRC WINAPI wglarb_CreateContextAttribsARB( + HDC hDC, + HGLRC hShareContext, + const int *attribList) +{ + if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) { + return NULL; + } + + HDC hOrigDC; + HGLRC hOrigRC; + if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) { + wglarb_intermediary_unlock(); + return NULL; + } + + PFNWGLCREATECONTEXTATTRIBSARBPROC impl = + (PFNWGLCREATECONTEXTATTRIBSARBPROC) + wglGetProcAddress("wglCreateContextAttribsARB"); + + HGLRC ret = NULL; + if( impl ) { + ret = impl(hDC, hShareContext, attribList); + } + + wglMakeCurrent(hOrigDC, hOrigRC); + wglarb_intermediary_unlock(); + return ret; +} + +BOOL WINAPI wglarb_ChoosePixelFormatARB( + HDC hdc, + const int *piAttribIList, + const FLOAT *pfAttribFList, + UINT nMaxFormats, + int *piFormats, + UINT *nNumFormats) +{ + if( WAIT_OBJECT_0 != wglarb_intermediary_lock() ) { + return FALSE; + } + + HDC hOrigDC; + HGLRC hOrigRC; + if( !wglarb_intermediary_makecurrent(&hOrigDC, &hOrigRC) ) { + wglarb_intermediary_unlock(); + return FALSE; + } + + PFNWGLCHOOSEPIXELFORMATARBPROC impl = NULL; + + impl = (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatARB"); + if( !impl ) { + /* WGL_EXT_pixel_format uses the same function prototypes + * as the WGL_ARB_pixel_format extension */ + impl = (PFNWGLCHOOSEPIXELFORMATARBPROC) + wglGetProcAddress("wglChoosePixelFormatEXT"); + } + + BOOL ret = FALSE; + if( impl ) { + ret = impl( + hdc, + piAttribIList, + pfAttribFList, + nMaxFormats, + piFormats, + nNumFormats ); + } + + wglMakeCurrent(hOrigDC, hOrigRC); + wglarb_intermediary_unlock(); + return ret; +} diff --git a/src/wglarb.h b/src/wglarb.h new file mode 100644 index 0000000..8c2b883 --- /dev/null +++ b/src/wglarb.h @@ -0,0 +1,43 @@ +/* +Copyright (c) 2014 Wolfgang 'datenwolf' Draxinger + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +#pragma once + +#ifndef WGLARB_H +#define WGLARB_H + +#include +#include + +HGLRC WINAPI wglarb_CreateContextAttribsARB( + HDC hDC, + HGLRC hShareContext, + const int *attribList); + +BOOL WINAPI wglarb_ChoosePixelFormatARB( + HDC hdc, + const int *piAttribIList, + const FLOAT *pfAttribFList, + UINT nMaxFormats, + int *piFormats, + UINT *nNumFormats); + +#endif/*WGLARB_H*/ diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..d7b2cf6 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,37 @@ +cmake_minimum_required(VERSION 2.8) +project(wglarbtest) + +if(MINGW) + set(CMAKE_RC_COMPILER_INIT windres) + enable_language(RC) + set(CMAKE_RC_COMPILE_OBJECT + " -O coff -i -o " ) +endif(MINGW) + +add_subdirectory(dwm_load) +include_directories(dwm_load) + +add_executable(layered + layered.c + layered.rc ) + +target_link_libraries(layered + wglarb_static + ${OPENGL_gl_LIBRARY} ) + +add_executable(shared + shared.c + shared.rc ) + +target_link_libraries(shared + wglarb_static + ${OPENGL_gl_LIBRARY} ) + +add_executable(customframe + customframe.c + customframe.rc ) + +target_link_libraries(customframe + wglarb_static + dwm_load + ${OPENGL_gl_LIBRARY} ) diff --git a/test/customframe.c b/test/customframe.c new file mode 100644 index 0000000..d3cbeb5 --- /dev/null +++ b/test/customframe.c @@ -0,0 +1,345 @@ +#include +#include + +#include +#include + +#include +#include + +#include +#include "dwm_load.h" + +LRESULT CALLBACK ViewProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam); + +void display(HWND hWnd); + +HGLRC hRC = NULL; + +BOOL use_dwm = FALSE; +float bg_color[3]; + +int win_width; +int win_height; + +HWND OpenGLWindowCreate( + LPCTSTR lpszWindowName, + LPCTSTR lpszClassName, + WNDPROC lpfnWndProc, + HINSTANCE hInstance, + DWORD dwStyle, + DWORD dwExStyle, + HWND hWndParent) +{ + if(!hInstance) { + hInstance = GetModuleHandle(NULL); + } + + WNDCLASS wc; + memset(&wc,0,sizeof(wc)); + wc.hInstance = hInstance; + wc.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC; + + /* Register DefWindowProc with each the intermediary and the + * proper window class. We're setting the window proc of the + * proper window to the user supplied window proc later so that + * we can use the default proper window class name if no class + * name was supplied by the user. It also allows to use the same + * user supplied window class name with multiple, different + * window functions. */ + wc.lpfnWndProc = DefWindowProc; + /* register proper window class */ + if( !lpszClassName ) { + return FALSE; + } + wc.lpszClassName = lpszClassName; + RegisterClass(&wc); + + RECT rect; + if( hWndParent + && (dwStyle & WS_CHILD) ) { + GetClientRect(hWndParent, &rect); + } + else { + rect.left = + rect.top = + rect.right = + rect.bottom = CW_USEDEFAULT; + } + + HWND hWnd = + CreateWindowEx( + dwExStyle, + wc.lpszClassName, + lpszWindowName, + dwStyle, + rect.left, + rect.top, + rect.right, + rect.bottom, + hWndParent, + NULL, + hInstance, + NULL); + if(!hWnd) { + return NULL; + } + + SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)ViewProc); + + HDC hDC = GetDC(hWnd); + if(!hDC) { + fprintf(stderr, "error retrieving proper DC\n"); + DestroyWindow(hWnd); + return NULL; + } + + int attribs[] = { + WGL_DRAW_TO_WINDOW_ARB, TRUE, + WGL_DOUBLE_BUFFER_ARB, TRUE, + WGL_SUPPORT_OPENGL_ARB, TRUE, + WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB, + WGL_TRANSPARENT_ARB, TRUE, + WGL_COLOR_BITS_ARB, 32, + WGL_RED_BITS_ARB, 8, + WGL_GREEN_BITS_ARB, 8, + WGL_BLUE_BITS_ARB, 8, + WGL_ALPHA_BITS_ARB, 8, + WGL_DEPTH_BITS_ARB, 24, + WGL_STENCIL_BITS_ARB, 8, + 0, 0 + }; + + INT iPF; + UINT num_formats_choosen; + if( !wglarb_ChoosePixelFormatARB( + hDC, + attribs, + NULL, + 1, + &iPF, + &num_formats_choosen) ) { + fprintf(stderr, "error choosing proper pixel format\n"); + return NULL; + } + if( !num_formats_choosen ) { + return NULL; + } + + PIXELFORMATDESCRIPTOR pfd; + memset(&pfd, 0, sizeof(pfd)); + /* now this is a kludge; we need to pass something in the PIXELFORMATDESCRIPTOR + * to SetPixelFormat; it will be ignored, mostly. OTOH we want to send something + * sane, we're nice people after all - it doesn't hurt if this fails. */ + DescribePixelFormat(hDC, iPF, sizeof(pfd), &pfd); + + if( !SetPixelFormat(hDC, iPF, &pfd) ) { + fprintf(stderr, "error setting proper pixel format\n"); + ReleaseDC(hWnd, hDC); + DestroyWindow(hWnd); + + return NULL; + } + + int context_attribs[] = { + WGL_CONTEXT_MAJOR_VERSION_ARB, 2, + WGL_CONTEXT_MINOR_VERSION_ARB, 1, + 0, 0 + }; + hRC = wglarb_CreateContextAttribsARB(hDC, NULL, context_attribs); + if(!hRC) { + ReleaseDC(hWnd, hDC); + DestroyWindow(hWnd); + + return NULL; + } + ReleaseDC(hWnd, hDC); + + if( use_dwm ) { + DWM_BLURBEHIND bb = {0}; + bb.dwFlags = DWM_BB_ENABLE; + bb.fEnable = TRUE; + bb.hRgnBlur = NULL; + DwmEnableBlurBehindWindow(hWnd, &bb); + + MARGINS margins = {-1}; + DwmExtendFrameIntoClientArea(hWnd, &margins); + } + + return hWnd; + +fail_create_rc: +fail_set_pf: +fail_choose_pf: + ReleaseDC(hWnd, hDC); +fail_get_dc: + DestroyWindow(hWnd); +fail_create_wnd: + + return NULL; +} + +void OnOpenGLWindowDestroy() +{ + wglMakeCurrent(NULL,NULL); + wglDeleteContext(hRC); + PostQuitMessage(0); +} + +BOOL cursor_needs_setting = TRUE; + +LRESULT CALLBACK ViewProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) +{ + DWORD bgcol; + BOOL opaque; + switch(uMsg) + { + case WM_CREATE: + case WM_DWMNCRENDERINGCHANGED: + if( use_dwm ) { + DwmGetColorizationColor(&bgcol, &opaque); + if( opaque ) { + bg_color[0] = (float)GetRValue(bgcol)/255.f; + bg_color[1] = (float)GetGValue(bgcol)/255.f; + bg_color[2] = (float)GetBValue(bgcol)/255.f; + } + else { + bg_color[0] = 0.f; + bg_color[1] = 0.f; + bg_color[2] = 0.f; + } + } + break; + + case WM_MOUSELEAVE: + cursor_needs_setting = TRUE; + break; + + case WM_MOUSEMOVE: + if( cursor_needs_setting ) { + SetClassLongPtr(hWnd, GCLP_HCURSOR, (LONG_PTR)LoadCursor(NULL, IDC_ARROW)); + cursor_needs_setting = FALSE; + } + + break; + + case WM_DESTROY: + OnOpenGLWindowDestroy(); + break; + + case WM_PAINT: + display(hWnd); + break; + + default: + break; + } + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +void display(HWND hWnd) +{ + HDC hDC = GetDC(hWnd); + RECT rect; + GetClientRect(hWnd, &rect); + + wglMakeCurrent(hDC, hRC); + + float const ratio = (float)rect.right/(float)rect.bottom; + glViewport( + 0, + 0, + rect.right, + rect.bottom); + + glClearColor( + bg_color[0], + bg_color[1], + bg_color[2], + 0.); + glClearDepth(1.); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(-ratio, ratio, -1., 1., -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + float const cos60 = cosf(M_PI*60./180.); + float const sin60 = sinf(M_PI*60./180.); + + GLfloat const triangle[] = { + -1., -sin60, 1., 0., 0., + 1., -sin60, 0., 1., 0., + 0., sin60, 0., 0., 1. + }; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(2, GL_FLOAT, sizeof(GLfloat)*5, &triangle[0]); + glColorPointer( 3, GL_FLOAT, sizeof(GLfloat)*5, &triangle[0]); + + glDrawArrays(GL_TRIANGLES, 0, 3); + + SwapBuffers(hDC); + glFinish(); + + wglMakeCurrent(NULL, NULL); + ReleaseDC(hWnd, hDC); +} + +#if 1 +int CALLBACK WinMain( + HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ +#else +int main(int argc, char *argv[]) +{ + HINSTANCE hInstance = GetModuleHandle(NULL); +#endif + MSG msg; + BOOL bRet; + + OSVERSIONINFO os_vinfo; + memset(&os_vinfo, 0, sizeof(os_vinfo)); + os_vinfo.dwOSVersionInfoSize = sizeof(os_vinfo); + GetVersionEx(&os_vinfo); + use_dwm = 6 <= os_vinfo.dwMajorVersion; + + HWND hWndGL = OpenGLWindowCreate( + "Test", "TestWnd", + ViewProc, + hInstance, +#if 1 + WS_OVERLAPPEDWINDOW +#else + WS_POPUP +#endif + , WS_EX_APPWINDOW, + NULL); + if(!hWndGL) { + return -1; + } + UpdateWindow(hWndGL); + ShowWindow(hWndGL, SW_SHOW); + + while( (bRet = GetMessage(&msg, NULL, 0, 0)) ) { + if(bRet == -1) { + // Handle Error + } + else { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + return msg.wParam; +} diff --git a/test/customframe.rc b/test/customframe.rc new file mode 100644 index 0000000..7c46d6e --- /dev/null +++ b/test/customframe.rc @@ -0,0 +1,3 @@ +#include "winuser.h" +CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml + -- cgit v1.2.3