| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2012 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2013-04-17 23:43:35 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-05 02:29:56 +02:00
										 |  |  | #include <windows.h>
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | #include <array>
 | 
					
						
							| 
									
										
										
										
											2014-03-12 15:33:41 -04:00
										 |  |  | #include <string>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-19 04:40:00 +12:00
										 |  |  | #include "Common/GL/GLInterface/WGL.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-19 05:40:46 +12:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "Common/MsgHandler.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | // from wglext.h
 | 
					
						
							|  |  |  | #ifndef WGL_ARB_pbuffer
 | 
					
						
							|  |  |  | #define WGL_ARB_pbuffer 1
 | 
					
						
							|  |  |  | DECLARE_HANDLE(HPBUFFERARB); | 
					
						
							|  |  |  | #define WGL_DRAW_TO_PBUFFER_ARB 0x202D
 | 
					
						
							|  |  |  | #define WGL_MAX_PBUFFER_PIXELS_ARB 0x202E
 | 
					
						
							|  |  |  | #define WGL_MAX_PBUFFER_WIDTH_ARB 0x202F
 | 
					
						
							|  |  |  | #define WGL_MAX_PBUFFER_HEIGHT_ARB 0x2030
 | 
					
						
							|  |  |  | #define WGL_PBUFFER_LARGEST_ARB 0x2033
 | 
					
						
							|  |  |  | #define WGL_PBUFFER_WIDTH_ARB 0x2034
 | 
					
						
							|  |  |  | #define WGL_PBUFFER_HEIGHT_ARB 0x2035
 | 
					
						
							|  |  |  | #define WGL_PBUFFER_LOST_ARB 0x2036
 | 
					
						
							|  |  |  | typedef HPBUFFERARB(WINAPI* PFNWGLCREATEPBUFFERARBPROC)(HDC hDC, int iPixelFormat, int iWidth, | 
					
						
							|  |  |  |                                                         int iHeight, const int* piAttribList); | 
					
						
							|  |  |  | typedef HDC(WINAPI* PFNWGLGETPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer); | 
					
						
							|  |  |  | typedef int(WINAPI* PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer, HDC hDC); | 
					
						
							|  |  |  | typedef BOOL(WINAPI* PFNWGLDESTROYPBUFFERARBPROC)(HPBUFFERARB hPbuffer); | 
					
						
							|  |  |  | typedef BOOL(WINAPI* PFNWGLQUERYPBUFFERARBPROC)(HPBUFFERARB hPbuffer, int iAttribute, int* piValue); | 
					
						
							|  |  |  | #endif /* WGL_ARB_pbuffer */
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | #ifndef WGL_ARB_pixel_format
 | 
					
						
							|  |  |  | #define WGL_ARB_pixel_format 1
 | 
					
						
							|  |  |  | #define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
 | 
					
						
							|  |  |  | #define WGL_DRAW_TO_WINDOW_ARB 0x2001
 | 
					
						
							|  |  |  | #define WGL_DRAW_TO_BITMAP_ARB 0x2002
 | 
					
						
							|  |  |  | #define WGL_ACCELERATION_ARB 0x2003
 | 
					
						
							|  |  |  | #define WGL_NEED_PALETTE_ARB 0x2004
 | 
					
						
							|  |  |  | #define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
 | 
					
						
							|  |  |  | #define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
 | 
					
						
							|  |  |  | #define WGL_SWAP_METHOD_ARB 0x2007
 | 
					
						
							|  |  |  | #define WGL_NUMBER_OVERLAYS_ARB 0x2008
 | 
					
						
							|  |  |  | #define WGL_NUMBER_UNDERLAYS_ARB 0x2009
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_ARB 0x200A
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
 | 
					
						
							|  |  |  | #define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
 | 
					
						
							|  |  |  | #define WGL_SHARE_DEPTH_ARB 0x200C
 | 
					
						
							|  |  |  | #define WGL_SHARE_STENCIL_ARB 0x200D
 | 
					
						
							|  |  |  | #define WGL_SHARE_ACCUM_ARB 0x200E
 | 
					
						
							|  |  |  | #define WGL_SUPPORT_GDI_ARB 0x200F
 | 
					
						
							|  |  |  | #define WGL_SUPPORT_OPENGL_ARB 0x2010
 | 
					
						
							|  |  |  | #define WGL_DOUBLE_BUFFER_ARB 0x2011
 | 
					
						
							|  |  |  | #define WGL_STEREO_ARB 0x2012
 | 
					
						
							|  |  |  | #define WGL_PIXEL_TYPE_ARB 0x2013
 | 
					
						
							|  |  |  | #define WGL_COLOR_BITS_ARB 0x2014
 | 
					
						
							|  |  |  | #define WGL_RED_BITS_ARB 0x2015
 | 
					
						
							|  |  |  | #define WGL_RED_SHIFT_ARB 0x2016
 | 
					
						
							|  |  |  | #define WGL_GREEN_BITS_ARB 0x2017
 | 
					
						
							|  |  |  | #define WGL_GREEN_SHIFT_ARB 0x2018
 | 
					
						
							|  |  |  | #define WGL_BLUE_BITS_ARB 0x2019
 | 
					
						
							|  |  |  | #define WGL_BLUE_SHIFT_ARB 0x201A
 | 
					
						
							|  |  |  | #define WGL_ALPHA_BITS_ARB 0x201B
 | 
					
						
							|  |  |  | #define WGL_ALPHA_SHIFT_ARB 0x201C
 | 
					
						
							|  |  |  | #define WGL_ACCUM_BITS_ARB 0x201D
 | 
					
						
							|  |  |  | #define WGL_ACCUM_RED_BITS_ARB 0x201E
 | 
					
						
							|  |  |  | #define WGL_ACCUM_GREEN_BITS_ARB 0x201F
 | 
					
						
							|  |  |  | #define WGL_ACCUM_BLUE_BITS_ARB 0x2020
 | 
					
						
							|  |  |  | #define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
 | 
					
						
							|  |  |  | #define WGL_DEPTH_BITS_ARB 0x2022
 | 
					
						
							|  |  |  | #define WGL_STENCIL_BITS_ARB 0x2023
 | 
					
						
							|  |  |  | #define WGL_AUX_BUFFERS_ARB 0x2024
 | 
					
						
							|  |  |  | #define WGL_NO_ACCELERATION_ARB 0x2025
 | 
					
						
							|  |  |  | #define WGL_GENERIC_ACCELERATION_ARB 0x2026
 | 
					
						
							|  |  |  | #define WGL_FULL_ACCELERATION_ARB 0x2027
 | 
					
						
							|  |  |  | #define WGL_SWAP_EXCHANGE_ARB 0x2028
 | 
					
						
							|  |  |  | #define WGL_SWAP_COPY_ARB 0x2029
 | 
					
						
							|  |  |  | #define WGL_SWAP_UNDEFINED_ARB 0x202A
 | 
					
						
							|  |  |  | #define WGL_TYPE_RGBA_ARB 0x202B
 | 
					
						
							|  |  |  | #define WGL_TYPE_COLORINDEX_ARB 0x202C
 | 
					
						
							|  |  |  | typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC hdc, int iPixelFormat, | 
					
						
							|  |  |  |                                                           int iLayerPlane, UINT nAttributes, | 
					
						
							|  |  |  |                                                           const int* piAttributes, int* piValues); | 
					
						
							|  |  |  | typedef BOOL(WINAPI* PFNWGLGETPIXELFORMATATTRIBFVARBPROC)(HDC hdc, int iPixelFormat, | 
					
						
							|  |  |  |                                                           int iLayerPlane, UINT nAttributes, | 
					
						
							|  |  |  |                                                           const int* piAttributes, FLOAT* pfValues); | 
					
						
							|  |  |  | typedef BOOL(WINAPI* PFNWGLCHOOSEPIXELFORMATARBPROC)(HDC hdc, const int* piAttribIList, | 
					
						
							|  |  |  |                                                      const FLOAT* pfAttribFList, UINT nMaxFormats, | 
					
						
							|  |  |  |                                                      int* piFormats, UINT* nNumFormats); | 
					
						
							|  |  |  | #endif /* WGL_ARB_pixel_format */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef WGL_ARB_create_context
 | 
					
						
							|  |  |  | #define WGL_ARB_create_context 1
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_FLAGS_ARB 0x2094
 | 
					
						
							|  |  |  | #define ERROR_INVALID_VERSION_ARB 0x2095
 | 
					
						
							|  |  |  | typedef HGLRC(WINAPI* PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC hDC, HGLRC hShareContext, | 
					
						
							|  |  |  |                                                          const int* attribList); | 
					
						
							|  |  |  | #endif /* WGL_ARB_create_context */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef WGL_ARB_create_context_profile
 | 
					
						
							|  |  |  | #define WGL_ARB_create_context_profile 1
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
 | 
					
						
							|  |  |  | #define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
 | 
					
						
							|  |  |  | #define ERROR_INVALID_PROFILE_ARB 0x2096
 | 
					
						
							|  |  |  | #endif /* WGL_ARB_create_context_profile */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef WGL_EXT_swap_control
 | 
					
						
							|  |  |  | #define WGL_EXT_swap_control 1
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | typedef BOOL(WINAPI* PFNWGLSWAPINTERVALEXTPROC)(int interval); | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | typedef int(WINAPI* PFNWGLGETSWAPINTERVALEXTPROC)(void); | 
					
						
							|  |  |  | #endif /* WGL_EXT_swap_control */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Persistent pointers
 | 
					
						
							| 
									
										
										
										
											2014-03-09 21:14:26 +01:00
										 |  |  | static PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = nullptr; | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = nullptr; | 
					
						
							|  |  |  | static PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = nullptr; | 
					
						
							|  |  |  | static PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = nullptr; | 
					
						
							|  |  |  | static PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = nullptr; | 
					
						
							|  |  |  | static PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = nullptr; | 
					
						
							|  |  |  | static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void LoadWGLExtensions() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   wglSwapIntervalEXT = reinterpret_cast<PFNWGLSWAPINTERVALEXTPROC>( | 
					
						
							|  |  |  |       GLInterface->GetFuncAddress("wglSwapIntervalEXT")); | 
					
						
							|  |  |  |   wglCreateContextAttribsARB = reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>( | 
					
						
							|  |  |  |       wglGetProcAddress("wglCreateContextAttribsARB")); | 
					
						
							|  |  |  |   wglChoosePixelFormatARB = reinterpret_cast<PFNWGLCHOOSEPIXELFORMATARBPROC>( | 
					
						
							|  |  |  |       wglGetProcAddress("wglChoosePixelFormatARB")); | 
					
						
							|  |  |  |   wglCreatePbufferARB = | 
					
						
							|  |  |  |       reinterpret_cast<PFNWGLCREATEPBUFFERARBPROC>(wglGetProcAddress("wglCreatePbufferARB")); | 
					
						
							|  |  |  |   wglGetPbufferDCARB = | 
					
						
							|  |  |  |       reinterpret_cast<PFNWGLGETPBUFFERDCARBPROC>(wglGetProcAddress("wglGetPbufferDCARB")); | 
					
						
							|  |  |  |   wglReleasePbufferDCARB = | 
					
						
							|  |  |  |       reinterpret_cast<PFNWGLRELEASEPBUFFERDCARBPROC>(wglGetProcAddress("wglReleasePbufferDCARB")); | 
					
						
							|  |  |  |   wglDestroyPbufferARB = | 
					
						
							|  |  |  |       reinterpret_cast<PFNWGLDESTROYPBUFFERARBPROC>(wglGetProcAddress("wglGetPbufferDCARB")); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void ClearWGLExtensionPointers() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   wglSwapIntervalEXT = nullptr; | 
					
						
							|  |  |  |   wglCreateContextAttribsARB = nullptr; | 
					
						
							|  |  |  |   wglChoosePixelFormatARB = nullptr; | 
					
						
							|  |  |  |   wglCreatePbufferARB = nullptr; | 
					
						
							|  |  |  |   wglGetPbufferDCARB = nullptr; | 
					
						
							|  |  |  |   wglReleasePbufferDCARB = nullptr; | 
					
						
							|  |  |  |   wglDestroyPbufferARB = nullptr; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-12-31 00:03:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-24 10:31:08 -06:00
										 |  |  | void cInterfaceWGL::SwapInterval(int Interval) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (wglSwapIntervalEXT) | 
					
						
							|  |  |  |     wglSwapIntervalEXT(Interval); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); | 
					
						
							| 
									
										
										
										
											2013-01-24 10:31:08 -06:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2012-12-26 00:34:09 -06:00
										 |  |  | void cInterfaceWGL::Swap() | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   SwapBuffers(m_dc); | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 18:17:12 -05:00
										 |  |  | void* cInterfaceWGL::GetFuncAddress(const std::string& name) | 
					
						
							| 
									
										
										
										
											2013-12-30 07:22:50 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   FARPROC func = wglGetProcAddress(name.c_str()); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (func == nullptr) | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   { | 
					
						
							|  |  |  |     // Using GetModuleHandle here is okay, since we import functions from opengl32.dll, it's
 | 
					
						
							|  |  |  |     // guaranteed to be loaded.
 | 
					
						
							|  |  |  |     HMODULE opengl_module = GetModuleHandle(TEXT("opengl32.dll")); | 
					
						
							|  |  |  |     func = GetProcAddress(opengl_module, name.c_str()); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return func; | 
					
						
							| 
									
										
										
										
											2013-12-30 07:22:50 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | // Draw messages on top of the screen
 | 
					
						
							|  |  |  | bool cInterfaceWGL::PeekMessages() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // TODO: peekmessage
 | 
					
						
							|  |  |  |   MSG msg; | 
					
						
							|  |  |  |   while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (msg.message == WM_QUIT) | 
					
						
							|  |  |  |       return FALSE; | 
					
						
							|  |  |  |     TranslateMessage(&msg); | 
					
						
							|  |  |  |     DispatchMessage(&msg); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return TRUE; | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create rendering window.
 | 
					
						
							| 
									
										
										
										
											2014-02-16 23:51:41 -05:00
										 |  |  | // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize()
 | 
					
						
							| 
									
										
										
										
											2017-06-26 12:32:09 +02:00
										 |  |  | bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   if (!window_handle) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   RECT window_rect = {}; | 
					
						
							|  |  |  |   m_window_handle = reinterpret_cast<HWND>(window_handle); | 
					
						
							|  |  |  |   if (!GetClientRect(m_window_handle, &window_rect)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   // Clear extension function pointers before creating the first context.
 | 
					
						
							|  |  |  |   ClearWGLExtensionPointers(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Control window size and picture scaling
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   int twidth = window_rect.right - window_rect.left; | 
					
						
							|  |  |  |   int theight = window_rect.bottom - window_rect.top; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   s_backbuffer_width = twidth; | 
					
						
							|  |  |  |   s_backbuffer_height = theight; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-26 12:32:09 +02:00
										 |  |  |   const DWORD stereo_flag = stereo ? PFD_STEREO : 0; | 
					
						
							|  |  |  |   static const PIXELFORMATDESCRIPTOR pfd = { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |       sizeof(PIXELFORMATDESCRIPTOR),  // Size Of This Pixel Format Descriptor
 | 
					
						
							|  |  |  |       1,                              // Version Number
 | 
					
						
							|  |  |  |       PFD_DRAW_TO_WINDOW |            // Format Must Support Window
 | 
					
						
							|  |  |  |           PFD_SUPPORT_OPENGL |        // Format Must Support OpenGL
 | 
					
						
							| 
									
										
										
										
											2017-06-26 12:32:09 +02:00
										 |  |  |           PFD_DOUBLEBUFFER |          // Must Support Double Buffering
 | 
					
						
							|  |  |  |           stereo_flag,                // Could Support Quad Buffering
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |       PFD_TYPE_RGBA,                  // Request An RGBA Format
 | 
					
						
							|  |  |  |       32,                             // Select Our Color Depth
 | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       0, 0, 0, 0, 0,   // Color Bits Ignored
 | 
					
						
							|  |  |  |       0,               // 8bit Alpha Buffer
 | 
					
						
							|  |  |  |       0,               // Shift Bit Ignored
 | 
					
						
							|  |  |  |       0,               // No Accumulation Buffer
 | 
					
						
							|  |  |  |       0, 0, 0, 0,      // Accumulation Bits Ignored
 | 
					
						
							|  |  |  |       0,               // 0Bit Z-Buffer (Depth Buffer)
 | 
					
						
							|  |  |  |       0,               // 0bit Stencil Buffer
 | 
					
						
							|  |  |  |       0,               // No Auxiliary Buffer
 | 
					
						
							|  |  |  |       PFD_MAIN_PLANE,  // Main Drawing Layer
 | 
					
						
							|  |  |  |       0,               // Reserved
 | 
					
						
							|  |  |  |       0, 0, 0          // Layer Masks Ignored
 | 
					
						
							|  |  |  |   }; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   m_dc = GetDC(m_window_handle); | 
					
						
							|  |  |  |   if (!m_dc) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     PanicAlert("(1) Can't create an OpenGL Device context. Fail."); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-07 04:42:41 -07:00
										 |  |  |   int pixel_format = ChoosePixelFormat(m_dc, &pfd); | 
					
						
							|  |  |  |   if (!pixel_format) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     PanicAlert("(2) Can't find a suitable PixelFormat."); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   if (!SetPixelFormat(m_dc, pixel_format, &pfd)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     PanicAlert("(3) Can't set the PixelFormat."); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-07 04:42:41 -07:00
										 |  |  |   m_rc = wglCreateContext(m_dc); | 
					
						
							|  |  |  |   if (!m_rc) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							|  |  |  |     PanicAlert("(4) Can't create an OpenGL rendering context."); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   // WGL only supports desktop GL, for now.
 | 
					
						
							|  |  |  |   if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) | 
					
						
							|  |  |  |     s_opengl_mode = GLInterfaceMode::MODE_OPENGL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (core) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     // Make the fallback context current, temporarily.
 | 
					
						
							|  |  |  |     // This is because we need an active context to use wglCreateContextAttribsARB.
 | 
					
						
							|  |  |  |     if (!wglMakeCurrent(m_dc, m_rc)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       PanicAlert("(5) Can't make dummy WGL context current."); | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Load WGL extension function pointers.
 | 
					
						
							|  |  |  |     LoadWGLExtensions(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Attempt creating a core context.
 | 
					
						
							|  |  |  |     HGLRC core_context = CreateCoreContext(m_dc, nullptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Switch out the temporary context before continuing, regardless of whether we got a core
 | 
					
						
							|  |  |  |     // context. If we didn't get a core context, the caller expects that the context is not current.
 | 
					
						
							|  |  |  |     if (!wglMakeCurrent(m_dc, nullptr)) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       PanicAlert("(6) Failed to switch out temporary context"); | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If we got a core context, destroy and replace the temporary context.
 | 
					
						
							|  |  |  |     if (core_context) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       wglDeleteContext(m_rc); | 
					
						
							|  |  |  |       m_rc = core_context; | 
					
						
							|  |  |  |       m_core = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       WARN_LOG(VIDEO, "Failed to create a core OpenGL context. Using fallback context."); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | bool cInterfaceWGL::Create(cInterfaceBase* main_context) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   cInterfaceWGL* wgl_main_context = static_cast<cInterfaceWGL*>(main_context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead.
 | 
					
						
							|  |  |  |   if (!CreatePBuffer(wgl_main_context->m_dc, 1, 1, &m_pbuffer_handle, &m_dc)) | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_rc = CreateCoreContext(m_dc, wgl_main_context->m_rc); | 
					
						
							|  |  |  |   if (!m_rc) | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_core = true; | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::unique_ptr<cInterfaceBase> cInterfaceWGL::CreateSharedContext() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   std::unique_ptr<cInterfaceWGL> context = std::make_unique<cInterfaceWGL>(); | 
					
						
							|  |  |  |   if (!context->Create(this)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     context->Shutdown(); | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return std::move(context); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | HGLRC cInterfaceWGL::CreateCoreContext(HDC dc, HGLRC share_context) | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   if (!wglCreateContextAttribsARB) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     WARN_LOG(VIDEO, "Missing WGL_ARB_create_context extension"); | 
					
						
							|  |  |  |     return nullptr; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // List of versions to attempt context creation for. (4.5-3.2, geometry shaders is a minimum
 | 
					
						
							|  |  |  |   // requirement since we're using core profile)
 | 
					
						
							|  |  |  |   static constexpr std::array<std::pair<int, int>, 8> try_versions = { | 
					
						
							|  |  |  |       {{4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}}}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (const auto& version : try_versions) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |     // Construct list of attributes. Prefer a forward-compatible, core context.
 | 
					
						
							|  |  |  |     std::array<int, 5 * 2> attribs = { | 
					
						
							|  |  |  |         WGL_CONTEXT_PROFILE_MASK_ARB, | 
					
						
							|  |  |  |         WGL_CONTEXT_CORE_PROFILE_BIT_ARB, | 
					
						
							|  |  |  | #ifdef _DEBUG
 | 
					
						
							|  |  |  |         WGL_CONTEXT_FLAGS_ARB, | 
					
						
							|  |  |  |         WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  |         WGL_CONTEXT_FLAGS_ARB, | 
					
						
							|  |  |  |         WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |         WGL_CONTEXT_MAJOR_VERSION_ARB, | 
					
						
							|  |  |  |         version.first, | 
					
						
							|  |  |  |         WGL_CONTEXT_MINOR_VERSION_ARB, | 
					
						
							|  |  |  |         version.second, | 
					
						
							|  |  |  |         0, | 
					
						
							|  |  |  |         0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Attempt creating this context.
 | 
					
						
							|  |  |  |     HGLRC core_context = wglCreateContextAttribsARB(dc, nullptr, attribs.data()); | 
					
						
							|  |  |  |     if (core_context) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       // If we're creating a shared context, share the resources before the context is used.
 | 
					
						
							|  |  |  |       if (share_context) | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         if (!wglShareLists(share_context, core_context)) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |           ERROR_LOG(VIDEO, "wglShareLists failed"); | 
					
						
							|  |  |  |           wglDeleteContext(core_context); | 
					
						
							|  |  |  |           return nullptr; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       INFO_LOG(VIDEO, "WGL: Created a GL %d.%d core context", version.first, version.second); | 
					
						
							|  |  |  |       return core_context; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  |   WARN_LOG(VIDEO, "Unable to create a core OpenGL context of an acceptable version"); | 
					
						
							|  |  |  |   return nullptr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool cInterfaceWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, | 
					
						
							|  |  |  |                                   HDC* pbuffer_dc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (!wglChoosePixelFormatARB || !wglCreatePbufferARB || !wglGetPbufferDCARB || | 
					
						
							|  |  |  |       !wglReleasePbufferDCARB || !wglDestroyPbufferARB) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, "Missing WGL_ARB_pbuffer extension"); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static constexpr std::array<int, 7 * 2> pf_iattribs = { | 
					
						
							|  |  |  |       WGL_DRAW_TO_PBUFFER_ARB, | 
					
						
							|  |  |  |       1,  // Pixel format compatible with pbuffer rendering
 | 
					
						
							|  |  |  |       WGL_RED_BITS_ARB, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       WGL_GREEN_BITS_ARB, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       WGL_BLUE_BITS_ARB, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       WGL_DEPTH_BITS_ARB, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       WGL_STENCIL_BITS_ARB, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       0, | 
					
						
							|  |  |  |       0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static constexpr std::array<float, 1 * 2> pf_fattribs = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   int pixel_format; | 
					
						
							|  |  |  |   UINT num_pixel_formats; | 
					
						
							|  |  |  |   if (!wglChoosePixelFormatARB(onscreen_dc, pf_iattribs.data(), pf_fattribs.data(), 1, | 
					
						
							|  |  |  |                                &pixel_format, &num_pixel_formats)) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, "Failed to obtain a compatible pbuffer pixel format"); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   static constexpr std::array<int, 1 * 2> pb_attribs = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   HPBUFFERARB pbuffer = | 
					
						
							|  |  |  |       wglCreatePbufferARB(onscreen_dc, pixel_format, width, height, pb_attribs.data()); | 
					
						
							|  |  |  |   if (!pbuffer) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, "Failed to create pbuffer"); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   HDC dc = wglGetPbufferDCARB(pbuffer); | 
					
						
							|  |  |  |   if (!dc) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ERROR_LOG(VIDEO, "Failed to get drawing context from pbuffer"); | 
					
						
							|  |  |  |     wglDestroyPbufferARB(pbuffer); | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   *pbuffer_handle = pbuffer; | 
					
						
							|  |  |  |   *pbuffer_dc = dc; | 
					
						
							|  |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool cInterfaceWGL::MakeCurrent() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   return wglMakeCurrent(m_dc, m_rc) == TRUE; | 
					
						
							| 
									
										
										
										
											2013-04-11 03:32:07 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-27 23:50:51 +02:00
										 |  |  | bool cInterfaceWGL::ClearCurrent() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   return wglMakeCurrent(m_dc, nullptr) == TRUE; | 
					
						
							| 
									
										
										
										
											2014-06-27 23:50:51 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | // Update window width, size and etc. Called from Render.cpp
 | 
					
						
							|  |  |  | void cInterfaceWGL::Update() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   RECT rcWindow; | 
					
						
							|  |  |  |   GetClientRect(m_window_handle, &rcWindow); | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Get the new window width and height
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   s_backbuffer_width = rcWindow.right - rcWindow.left; | 
					
						
							|  |  |  |   s_backbuffer_height = rcWindow.bottom - rcWindow.top; | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Close backend
 | 
					
						
							|  |  |  | void cInterfaceWGL::Shutdown() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   if (m_rc) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |     if (!wglMakeCurrent(m_dc, nullptr)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       NOTICE_LOG(VIDEO, "Could not release drawing context."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |     if (!wglDeleteContext(m_rc)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |       ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |     m_rc = nullptr; | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |   if (m_dc) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   { | 
					
						
							| 
									
										
										
										
											2016-10-05 20:37:11 +10:00
										 |  |  |     if (m_pbuffer_handle) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(m_pbuffer_handle), m_dc); | 
					
						
							|  |  |  |       m_dc = nullptr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       wglDestroyPbufferARB(static_cast<HPBUFFERARB>(m_pbuffer_handle)); | 
					
						
							|  |  |  |       m_pbuffer_handle = nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (!ReleaseDC(m_window_handle, m_dc)) | 
					
						
							|  |  |  |         ERROR_LOG(VIDEO, "Attempt to release device context failed."); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       m_dc = nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2012-12-17 15:01:52 -06:00
										 |  |  | } |