aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt9
-rwxr-xr-xbuild.sh31
-rw-r--r--cmake/Toolchain-cross-mingw32-linux.cmake26
-rw-r--r--cmake/Toolchain-cross-mingw64-linux.cmake26
-rw-r--r--src/CMakeLists.txt43
-rw-r--r--src/wglarb.c238
-rw-r--r--src/wglarb.h43
-rw-r--r--test/CMakeLists.txt37
-rw-r--r--test/customframe.c345
-rw-r--r--test/customframe.rc3
10 files changed, 801 insertions, 0 deletions
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 <GL/gl.h>
+#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 <windows.h>
+#include <GL/wglext.h>
+
+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
+ "<CMAKE_RC_COMPILER> <FLAGS> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>" )
+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 <windows.h>
+#include <wingdi.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include <wglarb.h>
+#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
+