mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 23:32:02 +00:00
- moved the Win32GLVideo class to its own file.
This and SystemFrameBuffer need splitting up to support both Vulkan and OpenGL
This commit is contained in:
parent
491898fe2c
commit
52102f3d4a
4 changed files with 605 additions and 583 deletions
|
@ -30,6 +30,9 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
void GetCenteredPos(int in_w, int in_h, int &winx, int &winy, int &winw, int &winh, int &scrwidth, int &scrheight);
|
||||||
|
void KeepWindowOnScreen(int &winx, int &winy, int winw, int winh, int scrwidth, int scrheight);
|
||||||
|
|
||||||
void PositionWindow(bool fullscreen);
|
void PositionWindow(bool fullscreen);
|
||||||
|
|
||||||
void ResetGammaTable();
|
void ResetGammaTable();
|
||||||
|
|
|
@ -50,6 +50,7 @@
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "doomerrors.h"
|
#include "doomerrors.h"
|
||||||
|
#include "win32glvideo.h"
|
||||||
|
|
||||||
#include "gl/renderer/gl_renderer.h"
|
#include "gl/renderer/gl_renderer.h"
|
||||||
#include "gl/system/gl_framebuffer.h"
|
#include "gl/system/gl_framebuffer.h"
|
||||||
|
@ -61,9 +62,6 @@ extern "C" {
|
||||||
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these get used before GLEW is initialized so we have to use separate pointers with different names
|
|
||||||
PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
|
||||||
PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB;
|
|
||||||
PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
|
PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc;
|
||||||
|
|
||||||
CVAR(Int, vid_adapter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Int, vid_adapter, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
@ -74,11 +72,6 @@ CVAR(Int, win_w, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
CVAR(Int, win_h, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Int, win_h, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||||
|
|
||||||
CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
|
||||||
{
|
|
||||||
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode.
|
// For broadest GL compatibility, require user to explicitly enable quad-buffered stereo mode.
|
||||||
// Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo,
|
// Setting vr_enable_quadbuffered_stereo does not automatically invoke quad-buffered stereo,
|
||||||
// but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo
|
// but makes it possible for subsequent "vr_mode 7" to invoke quad-buffered stereo
|
||||||
|
@ -89,575 +82,6 @@ CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFI
|
||||||
|
|
||||||
EXTERN_CVAR(Int, vid_defwidth)
|
EXTERN_CVAR(Int, vid_defwidth)
|
||||||
EXTERN_CVAR(Int, vid_defheight)
|
EXTERN_CVAR(Int, vid_defheight)
|
||||||
EXTERN_CVAR(Int, vid_adapter)
|
|
||||||
EXTERN_CVAR(Bool, fullscreen)
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
class Win32GLVideo : public IVideo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Win32GLVideo(int parm);
|
|
||||||
virtual ~Win32GLVideo();
|
|
||||||
|
|
||||||
DFrameBuffer *CreateFrameBuffer ();
|
|
||||||
void DumpAdapters();
|
|
||||||
bool InitHardware(HWND Window, int multisample);
|
|
||||||
void Shutdown();
|
|
||||||
|
|
||||||
HDC m_hDC;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
HMODULE hmRender;
|
|
||||||
|
|
||||||
char m_DisplayDeviceBuffer[CCHDEVICENAME];
|
|
||||||
char *m_DisplayDeviceName;
|
|
||||||
HMONITOR m_hMonitor;
|
|
||||||
|
|
||||||
HWND m_Window;
|
|
||||||
HGLRC m_hRC;
|
|
||||||
|
|
||||||
HWND InitDummy();
|
|
||||||
void ShutdownDummy(HWND dummy);
|
|
||||||
bool SetPixelFormat();
|
|
||||||
bool SetupPixelFormat(int multisample);
|
|
||||||
|
|
||||||
void GetDisplayDeviceName();
|
|
||||||
public:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
Win32GLVideo::Win32GLVideo(int parm)
|
|
||||||
{
|
|
||||||
I_SetWndProc();
|
|
||||||
|
|
||||||
GetDisplayDeviceName();
|
|
||||||
SetPixelFormat();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
Win32GLVideo::~Win32GLVideo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
struct MonitorEnumState
|
|
||||||
{
|
|
||||||
int curIdx;
|
|
||||||
HMONITOR hFoundMonitor;
|
|
||||||
};
|
|
||||||
|
|
||||||
static BOOL CALLBACK GetDisplayDeviceNameMonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
|
|
||||||
{
|
|
||||||
MonitorEnumState *state = reinterpret_cast<MonitorEnumState *>(dwData);
|
|
||||||
|
|
||||||
MONITORINFOEX mi;
|
|
||||||
mi.cbSize = sizeof mi;
|
|
||||||
GetMonitorInfo(hMonitor, &mi);
|
|
||||||
|
|
||||||
// This assumes the monitors are returned by EnumDisplayMonitors in the
|
|
||||||
// order they're found in the Direct3D9 adapters list. Fingers crossed...
|
|
||||||
if (state->curIdx == vid_adapter)
|
|
||||||
{
|
|
||||||
state->hFoundMonitor = hMonitor;
|
|
||||||
|
|
||||||
// Don't stop enumeration; this makes EnumDisplayMonitors fail. I like
|
|
||||||
// proper fails.
|
|
||||||
}
|
|
||||||
|
|
||||||
++state->curIdx;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void Win32GLVideo::GetDisplayDeviceName()
|
|
||||||
{
|
|
||||||
// If anything goes wrong, anything at all, everything uses the primary
|
|
||||||
// monitor.
|
|
||||||
m_DisplayDeviceName = 0;
|
|
||||||
m_hMonitor = 0;
|
|
||||||
|
|
||||||
MonitorEnumState mes;
|
|
||||||
|
|
||||||
mes.curIdx = 1;
|
|
||||||
mes.hFoundMonitor = 0;
|
|
||||||
|
|
||||||
// Could also use EnumDisplayDevices, I guess. That might work.
|
|
||||||
if (EnumDisplayMonitors(0, 0, &GetDisplayDeviceNameMonitorEnumProc, LPARAM(&mes)))
|
|
||||||
{
|
|
||||||
if (mes.hFoundMonitor)
|
|
||||||
{
|
|
||||||
MONITORINFOEX mi;
|
|
||||||
|
|
||||||
mi.cbSize = sizeof mi;
|
|
||||||
|
|
||||||
if (GetMonitorInfo(mes.hFoundMonitor, &mi))
|
|
||||||
{
|
|
||||||
strcpy(m_DisplayDeviceBuffer, mi.szDevice);
|
|
||||||
m_DisplayDeviceName = m_DisplayDeviceBuffer;
|
|
||||||
|
|
||||||
m_hMonitor = mes.hFoundMonitor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
DFrameBuffer *Win32GLVideo::CreateFrameBuffer()
|
|
||||||
{
|
|
||||||
SystemFrameBuffer *fb;
|
|
||||||
|
|
||||||
fb = new OpenGLFrameBuffer(m_hMonitor, fullscreen);
|
|
||||||
return fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
struct DumpAdaptersState
|
|
||||||
{
|
|
||||||
unsigned index;
|
|
||||||
char *displayDeviceName;
|
|
||||||
};
|
|
||||||
|
|
||||||
static BOOL CALLBACK DumpAdaptersMonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
|
|
||||||
{
|
|
||||||
DumpAdaptersState *state = reinterpret_cast<DumpAdaptersState *>(dwData);
|
|
||||||
|
|
||||||
MONITORINFOEX mi;
|
|
||||||
mi.cbSize=sizeof mi;
|
|
||||||
|
|
||||||
char moreinfo[64] = "";
|
|
||||||
|
|
||||||
bool active = true;
|
|
||||||
|
|
||||||
if (GetMonitorInfo(hMonitor, &mi))
|
|
||||||
{
|
|
||||||
bool primary = !!(mi.dwFlags & MONITORINFOF_PRIMARY);
|
|
||||||
|
|
||||||
mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s",
|
|
||||||
mi.rcMonitor.right - mi.rcMonitor.left,
|
|
||||||
mi.rcMonitor.bottom - mi.rcMonitor.top,
|
|
||||||
mi.rcMonitor.left, mi.rcMonitor.top,
|
|
||||||
primary ? " (Primary)" : "");
|
|
||||||
|
|
||||||
if (!state->displayDeviceName && !primary)
|
|
||||||
active = false;//primary selected, but this ain't primary
|
|
||||||
else if (state->displayDeviceName && strcmp(state->displayDeviceName, mi.szDevice) != 0)
|
|
||||||
active = false;//this isn't the selected one
|
|
||||||
}
|
|
||||||
|
|
||||||
Printf("%s%u. %s\n",
|
|
||||||
active ? TEXTCOLOR_BOLD : "",
|
|
||||||
state->index,
|
|
||||||
moreinfo);
|
|
||||||
|
|
||||||
++state->index;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void Win32GLVideo::DumpAdapters()
|
|
||||||
{
|
|
||||||
DumpAdaptersState das;
|
|
||||||
|
|
||||||
das.index = 1;
|
|
||||||
das.displayDeviceName = m_DisplayDeviceName;
|
|
||||||
|
|
||||||
EnumDisplayMonitors(0, 0, DumpAdaptersMonitorEnumProc, LPARAM(&das));
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
HWND Win32GLVideo::InitDummy()
|
|
||||||
{
|
|
||||||
HMODULE g_hInst = GetModuleHandle(NULL);
|
|
||||||
HWND dummy;
|
|
||||||
//Create a rect structure for the size/position of the window
|
|
||||||
RECT windowRect;
|
|
||||||
windowRect.left = 0;
|
|
||||||
windowRect.right = 64;
|
|
||||||
windowRect.top = 0;
|
|
||||||
windowRect.bottom = 64;
|
|
||||||
|
|
||||||
//Window class structure
|
|
||||||
WNDCLASS wc;
|
|
||||||
|
|
||||||
//Fill in window class struct
|
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
||||||
wc.lpfnWndProc = (WNDPROC) DefWindowProc;
|
|
||||||
wc.cbClsExtra = 0;
|
|
||||||
wc.cbWndExtra = 0;
|
|
||||||
wc.hInstance = g_hInst;
|
|
||||||
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
||||||
wc.hbrBackground = NULL;
|
|
||||||
wc.lpszMenuName = NULL;
|
|
||||||
wc.lpszClassName = "GZDoomOpenGLDummyWindow";
|
|
||||||
|
|
||||||
//Register window class
|
|
||||||
if(!RegisterClass(&wc))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Set window style & extended style
|
|
||||||
DWORD style, exStyle;
|
|
||||||
exStyle = WS_EX_CLIENTEDGE;
|
|
||||||
style = WS_SYSMENU | WS_BORDER | WS_CAPTION;// | WS_VISIBLE;
|
|
||||||
|
|
||||||
//Adjust the window size so that client area is the size requested
|
|
||||||
AdjustWindowRectEx(&windowRect, style, false, exStyle);
|
|
||||||
|
|
||||||
//Create Window
|
|
||||||
if(!(dummy = CreateWindowEx(exStyle,
|
|
||||||
"GZDoomOpenGLDummyWindow",
|
|
||||||
"GZDOOM",
|
|
||||||
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
|
|
||||||
0, 0,
|
|
||||||
windowRect.right-windowRect.left,
|
|
||||||
windowRect.bottom-windowRect.top,
|
|
||||||
NULL, NULL,
|
|
||||||
g_hInst,
|
|
||||||
NULL)))
|
|
||||||
{
|
|
||||||
UnregisterClass("GZDoomOpenGLDummyWindow", g_hInst);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ShowWindow(dummy, SW_HIDE);
|
|
||||||
|
|
||||||
return dummy;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void Win32GLVideo::ShutdownDummy(HWND dummy)
|
|
||||||
{
|
|
||||||
DestroyWindow(dummy);
|
|
||||||
UnregisterClass("GZDoomOpenGLDummyWindow", GetModuleHandle(NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool Win32GLVideo::SetPixelFormat()
|
|
||||||
{
|
|
||||||
HDC hDC;
|
|
||||||
HGLRC hRC;
|
|
||||||
HWND dummy;
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR pfd = {
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
1,
|
|
||||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
|
||||||
PFD_TYPE_RGBA,
|
|
||||||
32, // color depth
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
16, // z depth
|
|
||||||
0, // stencil buffer
|
|
||||||
0,
|
|
||||||
PFD_MAIN_PLANE,
|
|
||||||
0,
|
|
||||||
0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
int pixelFormat;
|
|
||||||
|
|
||||||
// we have to create a dummy window to init stuff from or the full init stuff fails
|
|
||||||
dummy = InitDummy();
|
|
||||||
|
|
||||||
hDC = GetDC(dummy);
|
|
||||||
pixelFormat = ChoosePixelFormat(hDC, &pfd);
|
|
||||||
DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd);
|
|
||||||
|
|
||||||
::SetPixelFormat(hDC, pixelFormat, &pfd);
|
|
||||||
|
|
||||||
hRC = wglCreateContext(hDC);
|
|
||||||
wglMakeCurrent(hDC, hRC);
|
|
||||||
|
|
||||||
myWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
|
||||||
myWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
|
||||||
// any extra stuff here?
|
|
||||||
|
|
||||||
wglMakeCurrent(NULL, NULL);
|
|
||||||
wglDeleteContext(hRC);
|
|
||||||
ReleaseDC(dummy, hDC);
|
|
||||||
ShutdownDummy(dummy);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool Win32GLVideo::SetupPixelFormat(int multisample)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int colorDepth;
|
|
||||||
HDC deskDC;
|
|
||||||
int attributes[28];
|
|
||||||
int pixelFormat;
|
|
||||||
unsigned int numFormats;
|
|
||||||
float attribsFloat[] = {0.0f, 0.0f};
|
|
||||||
|
|
||||||
deskDC = GetDC(GetDesktopWindow());
|
|
||||||
colorDepth = GetDeviceCaps(deskDC, BITSPIXEL);
|
|
||||||
ReleaseDC(GetDesktopWindow(), deskDC);
|
|
||||||
|
|
||||||
if (myWglChoosePixelFormatARB)
|
|
||||||
{
|
|
||||||
again:
|
|
||||||
attributes[0] = WGL_RED_BITS_ARB; //bits
|
|
||||||
attributes[1] = 8;
|
|
||||||
attributes[2] = WGL_GREEN_BITS_ARB; //bits
|
|
||||||
attributes[3] = 8;
|
|
||||||
attributes[4] = WGL_BLUE_BITS_ARB; //bits
|
|
||||||
attributes[5] = 8;
|
|
||||||
attributes[6] = WGL_ALPHA_BITS_ARB;
|
|
||||||
attributes[7] = 8;
|
|
||||||
attributes[8] = WGL_DEPTH_BITS_ARB;
|
|
||||||
attributes[9] = 24;
|
|
||||||
attributes[10] = WGL_STENCIL_BITS_ARB;
|
|
||||||
attributes[11] = 8;
|
|
||||||
|
|
||||||
attributes[12] = WGL_DRAW_TO_WINDOW_ARB; //required to be true
|
|
||||||
attributes[13] = true;
|
|
||||||
attributes[14] = WGL_SUPPORT_OPENGL_ARB;
|
|
||||||
attributes[15] = true;
|
|
||||||
attributes[16] = WGL_DOUBLE_BUFFER_ARB;
|
|
||||||
attributes[17] = true;
|
|
||||||
|
|
||||||
if (multisample > 0)
|
|
||||||
{
|
|
||||||
attributes[18] = WGL_SAMPLE_BUFFERS_ARB;
|
|
||||||
attributes[19] = true;
|
|
||||||
attributes[20] = WGL_SAMPLES_ARB;
|
|
||||||
attributes[21] = multisample;
|
|
||||||
i = 22;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
i = 18;
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes[i++] = WGL_ACCELERATION_ARB; //required to be FULL_ACCELERATION_ARB
|
|
||||||
attributes[i++] = WGL_FULL_ACCELERATION_ARB;
|
|
||||||
|
|
||||||
if (vr_enable_quadbuffered)
|
|
||||||
{
|
|
||||||
// [BB] Starting with driver version 314.07, NVIDIA GeForce cards support OpenGL quad buffered
|
|
||||||
// stereo rendering with 3D Vision hardware. Select the corresponding attribute here.
|
|
||||||
attributes[i++] = WGL_STEREO_ARB;
|
|
||||||
attributes[i++] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
attributes[i++] = 0;
|
|
||||||
attributes[i++] = 0;
|
|
||||||
|
|
||||||
if (!myWglChoosePixelFormatARB(m_hDC, attributes, attribsFloat, 1, &pixelFormat, &numFormats))
|
|
||||||
{
|
|
||||||
Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n");
|
|
||||||
goto oldmethod;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numFormats == 0)
|
|
||||||
{
|
|
||||||
if (vr_enable_quadbuffered)
|
|
||||||
{
|
|
||||||
Printf("R_OPENGL: No valid pixel formats found for VR quadbuffering. Retrying without this feature\n");
|
|
||||||
vr_enable_quadbuffered = false;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
Printf("R_OPENGL: No valid pixel formats found. Retrying in compatibility mode\n");
|
|
||||||
goto oldmethod;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
oldmethod:
|
|
||||||
// If wglChoosePixelFormatARB is not found we have to do it the old fashioned way.
|
|
||||||
static PIXELFORMATDESCRIPTOR pfd = {
|
|
||||||
sizeof(PIXELFORMATDESCRIPTOR),
|
|
||||||
1,
|
|
||||||
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
|
||||||
PFD_TYPE_RGBA,
|
|
||||||
32, // color depth
|
|
||||||
0, 0, 0, 0, 0, 0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
32, // z depth
|
|
||||||
8, // stencil buffer
|
|
||||||
0,
|
|
||||||
PFD_MAIN_PLANE,
|
|
||||||
0,
|
|
||||||
0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
pixelFormat = ChoosePixelFormat(m_hDC, &pfd);
|
|
||||||
DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd);
|
|
||||||
|
|
||||||
if (pfd.dwFlags & PFD_GENERIC_FORMAT)
|
|
||||||
{
|
|
||||||
I_Error("R_OPENGL: OpenGL driver not accelerated!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!::SetPixelFormat(m_hDC, pixelFormat, NULL))
|
|
||||||
{
|
|
||||||
I_Error("R_OPENGL: Couldn't set pixel format.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
bool Win32GLVideo::InitHardware (HWND Window, int multisample)
|
|
||||||
{
|
|
||||||
m_Window=Window;
|
|
||||||
m_hDC = GetDC(Window);
|
|
||||||
|
|
||||||
if (!SetupPixelFormat(multisample))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
int prof = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
|
||||||
const char *version = Args->CheckValue("-glversion");
|
|
||||||
|
|
||||||
if (version != nullptr && strtod(version, nullptr) < 3.0) prof = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
|
||||||
|
|
||||||
for (; prof <= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; prof++)
|
|
||||||
{
|
|
||||||
m_hRC = NULL;
|
|
||||||
if (myWglCreateContextAttribsARB != NULL)
|
|
||||||
{
|
|
||||||
// let's try to get the best version possible. Some drivers only give us the version we request
|
|
||||||
// which breaks all version checks for feature support. The highest used features we use are from version 4.4, and 3.0 is a requirement.
|
|
||||||
static int versions[] = { 46, 45, 44, 43, 42, 41, 40, 33, 32, 31, 30, -1 };
|
|
||||||
|
|
||||||
for (int i = 0; versions[i] > 0; i++)
|
|
||||||
{
|
|
||||||
int ctxAttribs[] = {
|
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB, versions[i] / 10,
|
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB, versions[i] % 10,
|
|
||||||
WGL_CONTEXT_FLAGS_ARB, gl_debug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
|
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB, prof,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
m_hRC = myWglCreateContextAttribsARB(m_hDC, 0, ctxAttribs);
|
|
||||||
if (m_hRC != NULL) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_hRC == NULL && prof == WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
|
|
||||||
{
|
|
||||||
m_hRC = wglCreateContext(m_hDC);
|
|
||||||
if (m_hRC == NULL)
|
|
||||||
{
|
|
||||||
I_Error("R_OPENGL: Unable to create an OpenGL render context.\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_hRC != NULL)
|
|
||||||
{
|
|
||||||
wglMakeCurrent(m_hDC, m_hRC);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// We get here if the driver doesn't support the modern context creation API which always means an old driver.
|
|
||||||
I_Error ("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//==========================================================================
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//==========================================================================
|
|
||||||
|
|
||||||
void Win32GLVideo::Shutdown()
|
|
||||||
{
|
|
||||||
if (m_hRC)
|
|
||||||
{
|
|
||||||
wglMakeCurrent(0, 0);
|
|
||||||
wglDeleteContext(m_hRC);
|
|
||||||
}
|
|
||||||
if (m_hDC) ReleaseDC(m_Window, m_hDC);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
42
src/win32/win32glvideo.h
Normal file
42
src/win32/win32glvideo.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "v_video.h"
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
class Win32GLVideo : public IVideo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Win32GLVideo(int parm);
|
||||||
|
virtual ~Win32GLVideo();
|
||||||
|
|
||||||
|
DFrameBuffer *CreateFrameBuffer();
|
||||||
|
void DumpAdapters();
|
||||||
|
bool InitHardware(HWND Window, int multisample);
|
||||||
|
void Shutdown();
|
||||||
|
|
||||||
|
HDC m_hDC;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
HMODULE hmRender;
|
||||||
|
|
||||||
|
char m_DisplayDeviceBuffer[CCHDEVICENAME];
|
||||||
|
char *m_DisplayDeviceName;
|
||||||
|
HMONITOR m_hMonitor;
|
||||||
|
|
||||||
|
HWND m_Window;
|
||||||
|
HGLRC m_hRC;
|
||||||
|
|
||||||
|
HWND InitDummy();
|
||||||
|
void ShutdownDummy(HWND dummy);
|
||||||
|
bool SetPixelFormat();
|
||||||
|
bool SetupPixelFormat(int multisample);
|
||||||
|
|
||||||
|
void GetDisplayDeviceName();
|
||||||
|
public:
|
||||||
|
|
||||||
|
};
|
|
@ -32,13 +32,566 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _WIN32_WINNT 0x0501
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <mmsystem.h>
|
#include <GL/gl.h>
|
||||||
|
#include "wglext.h"
|
||||||
|
|
||||||
// HEADER FILES ------------------------------------------------------------
|
#include "gl_sysfb.h"
|
||||||
|
#include "hardware.h"
|
||||||
#include "c_cvars.h"
|
#include "x86.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "c_console.h"
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "i_input.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
#include "doomstat.h"
|
||||||
|
#include "v_text.h"
|
||||||
|
#include "m_argv.h"
|
||||||
|
#include "doomerrors.h"
|
||||||
|
#include "win32glvideo.h"
|
||||||
|
|
||||||
|
#include "gl/system/gl_framebuffer.h"
|
||||||
|
|
||||||
|
EXTERN_CVAR(Int, vid_adapter)
|
||||||
|
EXTERN_CVAR(Bool, fullscreen)
|
||||||
|
EXTERN_CVAR(Bool, vr_enable_quadbuffered)
|
||||||
|
|
||||||
|
CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||||
|
{
|
||||||
|
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// these get used before GLEW is initialized so we have to use separate pointers with different names
|
||||||
|
PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||||
|
PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB;
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
Win32GLVideo::Win32GLVideo(int parm)
|
||||||
|
{
|
||||||
|
I_SetWndProc();
|
||||||
|
|
||||||
|
GetDisplayDeviceName();
|
||||||
|
SetPixelFormat();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
Win32GLVideo::~Win32GLVideo()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
struct MonitorEnumState
|
||||||
|
{
|
||||||
|
int curIdx;
|
||||||
|
HMONITOR hFoundMonitor;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL CALLBACK GetDisplayDeviceNameMonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
|
||||||
|
{
|
||||||
|
MonitorEnumState *state = reinterpret_cast<MonitorEnumState *>(dwData);
|
||||||
|
|
||||||
|
MONITORINFOEX mi;
|
||||||
|
mi.cbSize = sizeof mi;
|
||||||
|
GetMonitorInfo(hMonitor, &mi);
|
||||||
|
|
||||||
|
// This assumes the monitors are returned by EnumDisplayMonitors in the
|
||||||
|
// order they're found in the Direct3D9 adapters list. Fingers crossed...
|
||||||
|
if (state->curIdx == vid_adapter)
|
||||||
|
{
|
||||||
|
state->hFoundMonitor = hMonitor;
|
||||||
|
|
||||||
|
// Don't stop enumeration; this makes EnumDisplayMonitors fail. I like
|
||||||
|
// proper fails.
|
||||||
|
}
|
||||||
|
|
||||||
|
++state->curIdx;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void Win32GLVideo::GetDisplayDeviceName()
|
||||||
|
{
|
||||||
|
// If anything goes wrong, anything at all, everything uses the primary
|
||||||
|
// monitor.
|
||||||
|
m_DisplayDeviceName = 0;
|
||||||
|
m_hMonitor = 0;
|
||||||
|
|
||||||
|
MonitorEnumState mes;
|
||||||
|
|
||||||
|
mes.curIdx = 1;
|
||||||
|
mes.hFoundMonitor = 0;
|
||||||
|
|
||||||
|
// Could also use EnumDisplayDevices, I guess. That might work.
|
||||||
|
if (EnumDisplayMonitors(0, 0, &GetDisplayDeviceNameMonitorEnumProc, LPARAM(&mes)))
|
||||||
|
{
|
||||||
|
if (mes.hFoundMonitor)
|
||||||
|
{
|
||||||
|
MONITORINFOEX mi;
|
||||||
|
|
||||||
|
mi.cbSize = sizeof mi;
|
||||||
|
|
||||||
|
if (GetMonitorInfo(mes.hFoundMonitor, &mi))
|
||||||
|
{
|
||||||
|
strcpy(m_DisplayDeviceBuffer, mi.szDevice);
|
||||||
|
m_DisplayDeviceName = m_DisplayDeviceBuffer;
|
||||||
|
|
||||||
|
m_hMonitor = mes.hFoundMonitor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
DFrameBuffer *Win32GLVideo::CreateFrameBuffer()
|
||||||
|
{
|
||||||
|
SystemFrameBuffer *fb;
|
||||||
|
|
||||||
|
fb = new OpenGLFrameBuffer(m_hMonitor, fullscreen);
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
struct DumpAdaptersState
|
||||||
|
{
|
||||||
|
unsigned index;
|
||||||
|
char *displayDeviceName;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BOOL CALLBACK DumpAdaptersMonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
|
||||||
|
{
|
||||||
|
DumpAdaptersState *state = reinterpret_cast<DumpAdaptersState *>(dwData);
|
||||||
|
|
||||||
|
MONITORINFOEX mi;
|
||||||
|
mi.cbSize = sizeof mi;
|
||||||
|
|
||||||
|
char moreinfo[64] = "";
|
||||||
|
|
||||||
|
bool active = true;
|
||||||
|
|
||||||
|
if (GetMonitorInfo(hMonitor, &mi))
|
||||||
|
{
|
||||||
|
bool primary = !!(mi.dwFlags & MONITORINFOF_PRIMARY);
|
||||||
|
|
||||||
|
mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s",
|
||||||
|
mi.rcMonitor.right - mi.rcMonitor.left,
|
||||||
|
mi.rcMonitor.bottom - mi.rcMonitor.top,
|
||||||
|
mi.rcMonitor.left, mi.rcMonitor.top,
|
||||||
|
primary ? " (Primary)" : "");
|
||||||
|
|
||||||
|
if (!state->displayDeviceName && !primary)
|
||||||
|
active = false;//primary selected, but this ain't primary
|
||||||
|
else if (state->displayDeviceName && strcmp(state->displayDeviceName, mi.szDevice) != 0)
|
||||||
|
active = false;//this isn't the selected one
|
||||||
|
}
|
||||||
|
|
||||||
|
Printf("%s%u. %s\n",
|
||||||
|
active ? TEXTCOLOR_BOLD : "",
|
||||||
|
state->index,
|
||||||
|
moreinfo);
|
||||||
|
|
||||||
|
++state->index;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void Win32GLVideo::DumpAdapters()
|
||||||
|
{
|
||||||
|
DumpAdaptersState das;
|
||||||
|
|
||||||
|
das.index = 1;
|
||||||
|
das.displayDeviceName = m_DisplayDeviceName;
|
||||||
|
|
||||||
|
EnumDisplayMonitors(0, 0, DumpAdaptersMonitorEnumProc, LPARAM(&das));
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
HWND Win32GLVideo::InitDummy()
|
||||||
|
{
|
||||||
|
HMODULE g_hInst = GetModuleHandle(NULL);
|
||||||
|
HWND dummy;
|
||||||
|
//Create a rect structure for the size/position of the window
|
||||||
|
RECT windowRect;
|
||||||
|
windowRect.left = 0;
|
||||||
|
windowRect.right = 64;
|
||||||
|
windowRect.top = 0;
|
||||||
|
windowRect.bottom = 64;
|
||||||
|
|
||||||
|
//Window class structure
|
||||||
|
WNDCLASS wc;
|
||||||
|
|
||||||
|
//Fill in window class struct
|
||||||
|
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
|
wc.lpfnWndProc = (WNDPROC)DefWindowProc;
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hInstance = g_hInst;
|
||||||
|
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
|
||||||
|
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||||
|
wc.hbrBackground = NULL;
|
||||||
|
wc.lpszMenuName = NULL;
|
||||||
|
wc.lpszClassName = "GZDoomOpenGLDummyWindow";
|
||||||
|
|
||||||
|
//Register window class
|
||||||
|
if (!RegisterClass(&wc))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set window style & extended style
|
||||||
|
DWORD style, exStyle;
|
||||||
|
exStyle = WS_EX_CLIENTEDGE;
|
||||||
|
style = WS_SYSMENU | WS_BORDER | WS_CAPTION;// | WS_VISIBLE;
|
||||||
|
|
||||||
|
//Adjust the window size so that client area is the size requested
|
||||||
|
AdjustWindowRectEx(&windowRect, style, false, exStyle);
|
||||||
|
|
||||||
|
//Create Window
|
||||||
|
if (!(dummy = CreateWindowEx(exStyle,
|
||||||
|
"GZDoomOpenGLDummyWindow",
|
||||||
|
"GZDOOM",
|
||||||
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
|
||||||
|
0, 0,
|
||||||
|
windowRect.right - windowRect.left,
|
||||||
|
windowRect.bottom - windowRect.top,
|
||||||
|
NULL, NULL,
|
||||||
|
g_hInst,
|
||||||
|
NULL)))
|
||||||
|
{
|
||||||
|
UnregisterClass("GZDoomOpenGLDummyWindow", g_hInst);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ShowWindow(dummy, SW_HIDE);
|
||||||
|
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void Win32GLVideo::ShutdownDummy(HWND dummy)
|
||||||
|
{
|
||||||
|
DestroyWindow(dummy);
|
||||||
|
UnregisterClass("GZDoomOpenGLDummyWindow", GetModuleHandle(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool Win32GLVideo::SetPixelFormat()
|
||||||
|
{
|
||||||
|
HDC hDC;
|
||||||
|
HGLRC hRC;
|
||||||
|
HWND dummy;
|
||||||
|
|
||||||
|
PIXELFORMATDESCRIPTOR pfd = {
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
1,
|
||||||
|
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||||
|
PFD_TYPE_RGBA,
|
||||||
|
32, // color depth
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
16, // z depth
|
||||||
|
0, // stencil buffer
|
||||||
|
0,
|
||||||
|
PFD_MAIN_PLANE,
|
||||||
|
0,
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
int pixelFormat;
|
||||||
|
|
||||||
|
// we have to create a dummy window to init stuff from or the full init stuff fails
|
||||||
|
dummy = InitDummy();
|
||||||
|
|
||||||
|
hDC = GetDC(dummy);
|
||||||
|
pixelFormat = ChoosePixelFormat(hDC, &pfd);
|
||||||
|
DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd);
|
||||||
|
|
||||||
|
::SetPixelFormat(hDC, pixelFormat, &pfd);
|
||||||
|
|
||||||
|
hRC = wglCreateContext(hDC);
|
||||||
|
wglMakeCurrent(hDC, hRC);
|
||||||
|
|
||||||
|
myWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
|
||||||
|
myWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
|
||||||
|
// any extra stuff here?
|
||||||
|
|
||||||
|
wglMakeCurrent(NULL, NULL);
|
||||||
|
wglDeleteContext(hRC);
|
||||||
|
ReleaseDC(dummy, hDC);
|
||||||
|
ShutdownDummy(dummy);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool Win32GLVideo::SetupPixelFormat(int multisample)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int colorDepth;
|
||||||
|
HDC deskDC;
|
||||||
|
int attributes[28];
|
||||||
|
int pixelFormat;
|
||||||
|
unsigned int numFormats;
|
||||||
|
float attribsFloat[] = { 0.0f, 0.0f };
|
||||||
|
|
||||||
|
deskDC = GetDC(GetDesktopWindow());
|
||||||
|
colorDepth = GetDeviceCaps(deskDC, BITSPIXEL);
|
||||||
|
ReleaseDC(GetDesktopWindow(), deskDC);
|
||||||
|
|
||||||
|
if (myWglChoosePixelFormatARB)
|
||||||
|
{
|
||||||
|
again:
|
||||||
|
attributes[0] = WGL_RED_BITS_ARB; //bits
|
||||||
|
attributes[1] = 8;
|
||||||
|
attributes[2] = WGL_GREEN_BITS_ARB; //bits
|
||||||
|
attributes[3] = 8;
|
||||||
|
attributes[4] = WGL_BLUE_BITS_ARB; //bits
|
||||||
|
attributes[5] = 8;
|
||||||
|
attributes[6] = WGL_ALPHA_BITS_ARB;
|
||||||
|
attributes[7] = 8;
|
||||||
|
attributes[8] = WGL_DEPTH_BITS_ARB;
|
||||||
|
attributes[9] = 24;
|
||||||
|
attributes[10] = WGL_STENCIL_BITS_ARB;
|
||||||
|
attributes[11] = 8;
|
||||||
|
|
||||||
|
attributes[12] = WGL_DRAW_TO_WINDOW_ARB; //required to be true
|
||||||
|
attributes[13] = true;
|
||||||
|
attributes[14] = WGL_SUPPORT_OPENGL_ARB;
|
||||||
|
attributes[15] = true;
|
||||||
|
attributes[16] = WGL_DOUBLE_BUFFER_ARB;
|
||||||
|
attributes[17] = true;
|
||||||
|
|
||||||
|
if (multisample > 0)
|
||||||
|
{
|
||||||
|
attributes[18] = WGL_SAMPLE_BUFFERS_ARB;
|
||||||
|
attributes[19] = true;
|
||||||
|
attributes[20] = WGL_SAMPLES_ARB;
|
||||||
|
attributes[21] = multisample;
|
||||||
|
i = 22;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i = 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes[i++] = WGL_ACCELERATION_ARB; //required to be FULL_ACCELERATION_ARB
|
||||||
|
attributes[i++] = WGL_FULL_ACCELERATION_ARB;
|
||||||
|
|
||||||
|
if (vr_enable_quadbuffered)
|
||||||
|
{
|
||||||
|
// [BB] Starting with driver version 314.07, NVIDIA GeForce cards support OpenGL quad buffered
|
||||||
|
// stereo rendering with 3D Vision hardware. Select the corresponding attribute here.
|
||||||
|
attributes[i++] = WGL_STEREO_ARB;
|
||||||
|
attributes[i++] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes[i++] = 0;
|
||||||
|
attributes[i++] = 0;
|
||||||
|
|
||||||
|
if (!myWglChoosePixelFormatARB(m_hDC, attributes, attribsFloat, 1, &pixelFormat, &numFormats))
|
||||||
|
{
|
||||||
|
Printf("R_OPENGL: Couldn't choose pixel format. Retrying in compatibility mode\n");
|
||||||
|
goto oldmethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numFormats == 0)
|
||||||
|
{
|
||||||
|
if (vr_enable_quadbuffered)
|
||||||
|
{
|
||||||
|
Printf("R_OPENGL: No valid pixel formats found for VR quadbuffering. Retrying without this feature\n");
|
||||||
|
vr_enable_quadbuffered = false;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
Printf("R_OPENGL: No valid pixel formats found. Retrying in compatibility mode\n");
|
||||||
|
goto oldmethod;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldmethod:
|
||||||
|
// If wglChoosePixelFormatARB is not found we have to do it the old fashioned way.
|
||||||
|
static PIXELFORMATDESCRIPTOR pfd = {
|
||||||
|
sizeof(PIXELFORMATDESCRIPTOR),
|
||||||
|
1,
|
||||||
|
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
|
||||||
|
PFD_TYPE_RGBA,
|
||||||
|
32, // color depth
|
||||||
|
0, 0, 0, 0, 0, 0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0, 0, 0, 0,
|
||||||
|
32, // z depth
|
||||||
|
8, // stencil buffer
|
||||||
|
0,
|
||||||
|
PFD_MAIN_PLANE,
|
||||||
|
0,
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
pixelFormat = ChoosePixelFormat(m_hDC, &pfd);
|
||||||
|
DescribePixelFormat(m_hDC, pixelFormat, sizeof(pfd), &pfd);
|
||||||
|
|
||||||
|
if (pfd.dwFlags & PFD_GENERIC_FORMAT)
|
||||||
|
{
|
||||||
|
I_Error("R_OPENGL: OpenGL driver not accelerated!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!::SetPixelFormat(m_hDC, pixelFormat, NULL))
|
||||||
|
{
|
||||||
|
I_Error("R_OPENGL: Couldn't set pixel format.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
bool Win32GLVideo::InitHardware(HWND Window, int multisample)
|
||||||
|
{
|
||||||
|
m_Window = Window;
|
||||||
|
m_hDC = GetDC(Window);
|
||||||
|
|
||||||
|
if (!SetupPixelFormat(multisample))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int prof = WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
|
||||||
|
const char *version = Args->CheckValue("-glversion");
|
||||||
|
|
||||||
|
if (version != nullptr && strtod(version, nullptr) < 3.0) prof = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
|
||||||
|
|
||||||
|
for (; prof <= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; prof++)
|
||||||
|
{
|
||||||
|
m_hRC = NULL;
|
||||||
|
if (myWglCreateContextAttribsARB != NULL)
|
||||||
|
{
|
||||||
|
// let's try to get the best version possible. Some drivers only give us the version we request
|
||||||
|
// which breaks all version checks for feature support. The highest used features we use are from version 4.4, and 3.0 is a requirement.
|
||||||
|
static int versions[] = { 46, 45, 44, 43, 42, 41, 40, 33, 32, 31, 30, -1 };
|
||||||
|
|
||||||
|
for (int i = 0; versions[i] > 0; i++)
|
||||||
|
{
|
||||||
|
int ctxAttribs[] = {
|
||||||
|
WGL_CONTEXT_MAJOR_VERSION_ARB, versions[i] / 10,
|
||||||
|
WGL_CONTEXT_MINOR_VERSION_ARB, versions[i] % 10,
|
||||||
|
WGL_CONTEXT_FLAGS_ARB, gl_debug ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
|
||||||
|
WGL_CONTEXT_PROFILE_MASK_ARB, prof,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
m_hRC = myWglCreateContextAttribsARB(m_hDC, 0, ctxAttribs);
|
||||||
|
if (m_hRC != NULL) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hRC == NULL && prof == WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB)
|
||||||
|
{
|
||||||
|
m_hRC = wglCreateContext(m_hDC);
|
||||||
|
if (m_hRC == NULL)
|
||||||
|
{
|
||||||
|
I_Error("R_OPENGL: Unable to create an OpenGL render context.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hRC != NULL)
|
||||||
|
{
|
||||||
|
wglMakeCurrent(m_hDC, m_hRC);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We get here if the driver doesn't support the modern context creation API which always means an old driver.
|
||||||
|
I_Error("R_OPENGL: Unable to create an OpenGL render context. Insufficient driver support for context creation\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void Win32GLVideo::Shutdown()
|
||||||
|
{
|
||||||
|
if (m_hRC)
|
||||||
|
{
|
||||||
|
wglMakeCurrent(0, 0);
|
||||||
|
wglDeleteContext(m_hRC);
|
||||||
|
}
|
||||||
|
if (m_hDC) ReleaseDC(m_Window, m_hDC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue