From 5d14ae68a69bb0a707977b018967381e07e4b2f7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 24 Jun 2018 23:54:25 +0200 Subject: [PATCH] - missed two added files. --- src/win32/base_sysfb.cpp | 387 +++++++++++++++++++++++++++++++++++++++ src/win32/base_sysfb.h | 42 +++++ 2 files changed, 429 insertions(+) create mode 100644 src/win32/base_sysfb.cpp create mode 100644 src/win32/base_sysfb.h diff --git a/src/win32/base_sysfb.cpp b/src/win32/base_sysfb.cpp new file mode 100644 index 0000000000..5e2f5c21ea --- /dev/null +++ b/src/win32/base_sysfb.cpp @@ -0,0 +1,387 @@ +/* +** +** +**--------------------------------------------------------------------------- +** Copyright 2003-2005 Tim Stump +** Copyright 2005-2016 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include "wglext.h" + +#include "gl_sysfb.h" +#include "hardware.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 "doomstat.h" +#include "v_text.h" +#include "m_argv.h" +#include "doomerrors.h" +#include "base_sysfb.h" +#include "win32basevideo.h" + + +extern HWND Window; + +extern "C" { + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; +} + +CVAR(Int, win_x, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Int, win_y, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Int, win_w, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Int, win_h, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) + +EXTERN_CVAR(Int, vid_defwidth) +EXTERN_CVAR(Int, vid_defheight) + + +//========================================================================== +// +// Windows framebuffer +// +//========================================================================== + + +//========================================================================== +// +// +// +//========================================================================== + + void SystemBaseFrameBuffer::GetCenteredPos(int in_w, int in_h, int &winx, int &winy, int &winw, int &winh, int &scrwidth, int &scrheight) +{ + DEVMODE displaysettings; + RECT rect; + int cx, cy; + + memset(&displaysettings, 0, sizeof(displaysettings)); + displaysettings.dmSize = sizeof(displaysettings); + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &displaysettings); + scrwidth = (int)displaysettings.dmPelsWidth; + scrheight = (int)displaysettings.dmPelsHeight; + GetWindowRect(Window, &rect); + cx = scrwidth / 2; + cy = scrheight / 2; + if (in_w > 0) winw = in_w; + else winw = rect.right - rect.left; + if (in_h > 0) winh = in_h; + else winh = rect.bottom - rect.top; + winx = cx - winw / 2; + winy = cy - winh / 2; +} + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::KeepWindowOnScreen(int &winx, int &winy, int winw, int winh, int scrwidth, int scrheight) +{ + // If the window is too large to fit entirely on the screen, at least + // keep its upperleft corner visible. + if (winx + winw > scrwidth) + { + winx = scrwidth - winw; + } + if (winx < 0) + { + winx = 0; + } + if (winy + winh > scrheight) + { + winy = scrheight - winh; + } + if (winy < 0) + { + winy = 0; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::SaveWindowedPos() +{ + // Don't save if we were run with the -0 option. + if (Args->CheckParm("-0")) + { + return; + } + // Make sure we only save the window position if it's not fullscreen. + static const int WINDOW_STYLE = WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX; + if ((GetWindowLong(Window, GWL_STYLE) & WINDOW_STYLE) == WINDOW_STYLE) + { + RECT wrect; + + if (GetWindowRect(Window, &wrect)) + { + // If (win_x,win_y) specify to center the window, don't change them + // if the window is still centered. + if (win_x < 0 || win_y < 0 || win_w < 0 || win_h < 0) + { + int winx, winy, winw, winh, scrwidth, scrheight; + + GetCenteredPos(win_w, win_h, winx, winy, winw, winh, scrwidth, scrheight); + KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight); + if (win_x < 0 && winx == wrect.left) + { + wrect.left = win_x; + } + if (win_y < 0 && winy == wrect.top) + { + wrect.top = win_y; + } + wrect.right = winw + wrect.left; + wrect.bottom = winh + wrect.top; + } + + win_x = wrect.left; + win_y = wrect.top; + win_w = wrect.right - wrect.left; + win_h = wrect.bottom - wrect.top; + } + + win_maximized = IsZoomed(Window) == TRUE; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::RestoreWindowedPos() +{ + int winx, winy, winw, winh, scrwidth, scrheight; + + GetCenteredPos(win_w, win_h, winx, winy, winw, winh, scrwidth, scrheight); + + // Just move to (0,0) if we were run with the -0 option. + if (Args->CheckParm("-0")) + { + winx = winy = 0; + } + else + { + if (win_x >= 0) + { + winx = win_x; + } + if (win_y >= 0) + { + winy = win_y; + } + KeepWindowOnScreen(winx, winy, winw, winh, scrwidth, scrheight); + } + SetWindowPos(Window, nullptr, winx, winy, winw, winh, SWP_NOZORDER | SWP_FRAMECHANGED); + + if (win_maximized && !Args->CheckParm("-0")) + ShowWindow(Window, SW_MAXIMIZE); +} + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::PositionWindow(bool fullscreen) +{ + RECT r; + LONG style, exStyle; + + RECT monRect; + + if (!m_Fullscreen) SaveWindowedPos(); + if (m_Monitor) + { + MONITORINFOEX mi; + mi.cbSize = sizeof mi; + + if (GetMonitorInfo(HMONITOR(m_Monitor), &mi)) + { + strcpy(m_displayDeviceNameBuffer, mi.szDevice); + m_displayDeviceName = m_displayDeviceNameBuffer; + monRect = mi.rcMonitor; + } + } + + ShowWindow(Window, SW_SHOW); + + GetWindowRect(Window, &r); + style = WS_VISIBLE | WS_CLIPSIBLINGS; + exStyle = 0; + + if (fullscreen) + style |= WS_POPUP; + else + { + style |= WS_OVERLAPPEDWINDOW; + exStyle |= WS_EX_WINDOWEDGE; + } + + SetWindowLong(Window, GWL_STYLE, style); + SetWindowLong(Window, GWL_EXSTYLE, exStyle); + + m_Fullscreen = fullscreen; + if (fullscreen) + { + SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + MoveWindow(Window, monRect.left, monRect.top, monRect.right-monRect.left, monRect.bottom-monRect.top, FALSE); + + // And now, seriously, it IS in the right place. Promise. + } + else + { + RestoreWindowedPos(); + } + SetSize(GetClientWidth(), GetClientHeight()); +} + +//========================================================================== +// +// +// +//========================================================================== + +SystemBaseFrameBuffer::SystemBaseFrameBuffer(void *hMonitor, bool fullscreen) : DFrameBuffer(vid_defwidth, vid_defheight) +{ + m_Monitor = hMonitor; + m_displayDeviceName = 0; + PositionWindow(fullscreen); + + HDC hDC = GetDC(Window); + + m_supportsGamma = !!GetDeviceGammaRamp(hDC, (void *)m_origGamma); + ReleaseDC(Window, hDC); +} + +//========================================================================== +// +// +// +//========================================================================== + +SystemBaseFrameBuffer::~SystemBaseFrameBuffer() +{ + ResetGammaTable(); + SaveWindowedPos(); + + ShowWindow (Window, SW_SHOW); + SetWindowLong(Window, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW); + SetWindowLong(Window, GWL_EXSTYLE, WS_EX_WINDOWEDGE); + SetWindowPos(Window, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + I_GetEvent(); + + static_cast(Video)->Shutdown(); +} + + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::ResetGammaTable() +{ + if (m_supportsGamma) + { + HDC hDC = GetDC(Window); + SetDeviceGammaRamp(hDC, (void *)m_origGamma); + ReleaseDC(Window, hDC); + } +} + +void SystemBaseFrameBuffer::SetGammaTable(uint16_t *tbl) +{ + if (m_supportsGamma) + { + HDC hDC = GetDC(Window); + SetDeviceGammaRamp(hDC, (void *)tbl); + ReleaseDC(Window, hDC); + } +} + +//========================================================================== +// +// +// +//========================================================================== + +bool SystemBaseFrameBuffer::IsFullscreen() +{ + return m_Fullscreen; +} + +//========================================================================== +// +// +// +//========================================================================== + +void SystemBaseFrameBuffer::ToggleFullscreen(bool yes) +{ + PositionWindow(yes); +} + +//========================================================================== +// +// +// +//========================================================================== + +int SystemBaseFrameBuffer::GetClientWidth() +{ + RECT rect = { 0 }; + GetClientRect(Window, &rect); + return rect.right - rect.left; +} + +int SystemBaseFrameBuffer::GetClientHeight() +{ + RECT rect = { 0 }; + GetClientRect(Window, &rect); + return rect.bottom - rect.top; +} diff --git a/src/win32/base_sysfb.h b/src/win32/base_sysfb.h new file mode 100644 index 0000000000..01672c2806 --- /dev/null +++ b/src/win32/base_sysfb.h @@ -0,0 +1,42 @@ +#pragma once + +#include "v_video.h" + +class SystemBaseFrameBuffer : public DFrameBuffer +{ + typedef DFrameBuffer Super; + + void SaveWindowedPos(); + void RestoreWindowedPos(); + +public: + SystemBaseFrameBuffer() {} + // Actually, hMonitor is a HMONITOR, but it's passed as a void * as there + // look to be some cross-platform bits in the way. + SystemBaseFrameBuffer(void *hMonitor, bool fullscreen); + virtual ~SystemBaseFrameBuffer(); + + int GetClientWidth() override; + int GetClientHeight() override; + + bool IsFullscreen() override; + void ToggleFullscreen(bool yes) override; + +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 ResetGammaTable(); + void SetGammaTable(uint16_t * tbl); + + float m_Gamma, m_Brightness, m_Contrast; + uint16_t m_origGamma[768]; + bool m_supportsGamma; + bool m_Fullscreen; + char m_displayDeviceNameBuffer[32/*CCHDEVICENAME*/]; // do not use windows.h constants here! + char *m_displayDeviceName; + void *m_Monitor; +};