mirror of
https://github.com/dhewm/dhewm3.git
synced 2025-01-31 05:30:40 +00:00
HighDPI support, hopefully
This commit is contained in:
parent
28d81ed5f5
commit
5376c6d74c
6 changed files with 84 additions and 16 deletions
|
@ -1,5 +1,7 @@
|
|||
#ifndef IMGUI_DISABLE
|
||||
|
||||
#include <SDL.h> // to show display size
|
||||
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -1833,6 +1835,22 @@ static void DrawVideoOptionsMenu()
|
|||
AddTooltip( "r_customWidth / r_customHeight" );
|
||||
}
|
||||
}
|
||||
int sdlDisplayIdx = SDL_GetWindowDisplayIndex( SDL_GL_GetCurrentWindow() );
|
||||
SDL_Rect displayRect = {};
|
||||
SDL_GetDisplayBounds( sdlDisplayIdx, &displayRect );
|
||||
if ( (int)glConfig.winWidth != glConfig.vidWidth ) {
|
||||
ImGui::TextDisabled( "Current Resolution: %g x %g (Physical: %d x %d)",
|
||||
glConfig.winWidth, glConfig.winHeight, glConfig.vidWidth, glConfig.vidHeight );
|
||||
AddDescrTooltip( "Apparently your system is using a HighDPI mode, where the logical resolution (used to specify"
|
||||
" window sizes) is lower than the physical resolution (number of pixels actually rendered)." );
|
||||
float scale = float(glConfig.vidWidth)/glConfig.winWidth;
|
||||
int pw = scale * displayRect.w;
|
||||
int ph = scale * displayRect.h;
|
||||
ImGui::TextDisabled( "Display Size: %d x %d (Physical: %d x %d)", displayRect.w, displayRect.h, pw, ph );
|
||||
} else {
|
||||
ImGui::TextDisabled( "Current Resolution: %d x %d", glConfig.vidWidth, glConfig.vidHeight );
|
||||
ImGui::TextDisabled( "Display Size: %d x %d", displayRect.w, displayRect.h );
|
||||
}
|
||||
|
||||
static const char* msaaLevels[] = { "No Antialiasing", "2x", "4x", "8x", "16x" };
|
||||
const char* curLvl = msaaLevels[msaaModeIndex];
|
||||
|
|
|
@ -79,6 +79,7 @@ typedef struct glconfig_s {
|
|||
bool textureNonPowerOfTwoAvailable;
|
||||
bool depthBoundsTestAvailable;
|
||||
|
||||
// GL framebuffer size, see also winWidth and winHeight
|
||||
int vidWidth, vidHeight; // passed to R_BeginFrame
|
||||
|
||||
int displayFrequency;
|
||||
|
@ -92,6 +93,23 @@ typedef struct glconfig_s {
|
|||
// DG: current video backend is known to need opaque default framebuffer
|
||||
// used if r_fillWindowAlphaChan == -1
|
||||
bool shouldFillWindowAlpha;
|
||||
|
||||
// For some reason people decided that we need displays with ultra small pixels,
|
||||
// so everything rendered on them must be scaled up to be legible.
|
||||
// unfortunately, this bullshit feature was "improved" upon by deciding that the best
|
||||
// way to implement "High DPI" was to pretend that windows have fewer pixels than they
|
||||
// actually do, so the window size you get and mouse coordinates in them etc
|
||||
// are in e.g. 1024x768, while the physical window size is e.g. 1536x1152 pixels
|
||||
// (when the scaling factor is 1.5), and ideally the GL framebuffer has the physical
|
||||
// window size so things still look crisp.
|
||||
// Of course the reasonable solution would be to go back and time and nuke Cupertino,
|
||||
// where this nonsense scheme was invented, but as I lack the necessary funds,
|
||||
// I reluctantly add winWidth and winHeight and adjust the code that deals with window
|
||||
// coordinates, as far as that's possible..
|
||||
// (Isn't it fun that you have a 2256x1504 display, tell SDL to create a 1920x1080 window
|
||||
// and you get one that's much bigger and doesn't fit on the screen?)
|
||||
|
||||
float winWidth, winHeight; // logical window size (different to vidWidth/height in HighDPI cases)
|
||||
} glconfig_t;
|
||||
|
||||
|
||||
|
@ -171,7 +189,11 @@ public:
|
|||
virtual bool IsOpenGLRunning( void ) const = 0;
|
||||
|
||||
virtual bool IsFullScreen( void ) const = 0;
|
||||
// NOTE: this is the physical width of the GL drawable (framebuffer) in pixels,
|
||||
// *not* the logical window size (in case of HighDPI that's not the same!)
|
||||
virtual int GetScreenWidth( void ) const = 0;
|
||||
// NOTE: this is the physical height of the GL drawable (framebuffer) in pixels,
|
||||
// *not* the logical window size (in case of HighDPI that's not the same!)
|
||||
virtual int GetScreenHeight( void ) const = 0;
|
||||
|
||||
// allocate a renderWorld to be used for drawing
|
||||
|
|
|
@ -1914,6 +1914,10 @@ static void GfxInfo_f( const idCmdArgs &args ) {
|
|||
"fullscreen"
|
||||
};
|
||||
|
||||
const char* fsmode = fsstrings[r_fullscreen.GetBool()];
|
||||
if ( r_fullscreen.GetBool() && r_fullscreenDesktop.GetBool() )
|
||||
fsmode = "desktop-fullscreen";
|
||||
|
||||
common->Printf( "\nGL_VENDOR: %s\n", glConfig.vendor_string );
|
||||
common->Printf( "GL_RENDERER: %s\n", glConfig.renderer_string );
|
||||
common->Printf( "GL_VERSION: %s\n", glConfig.version_string );
|
||||
|
@ -1923,13 +1927,14 @@ static void GfxInfo_f( const idCmdArgs &args ) {
|
|||
common->Printf( "GL_MAX_TEXTURE_COORDS_ARB: %d\n", glConfig.maxTextureCoords );
|
||||
common->Printf( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits );
|
||||
common->Printf( "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
|
||||
common->Printf( "MODE: %d, %d x %d %s hz:", r_mode.GetInteger(), glConfig.vidWidth, glConfig.vidHeight, fsstrings[r_fullscreen.GetBool()] );
|
||||
common->Printf( "MODE: %d, %d x %d %s hz:", r_mode.GetInteger(), glConfig.vidWidth, glConfig.vidHeight, fsmode );
|
||||
|
||||
if ( glConfig.displayFrequency ) {
|
||||
common->Printf( "%d\n", glConfig.displayFrequency );
|
||||
} else {
|
||||
common->Printf( "N/A\n" );
|
||||
}
|
||||
common->Printf( "Logical Window size: %g x %g\n", glConfig.winWidth, glConfig.winHeight );
|
||||
|
||||
const char *active[2] = { "", " (ACTIVE)" };
|
||||
|
||||
|
@ -2033,8 +2038,8 @@ void R_VidRestart_f( const idCmdArgs &args ) {
|
|||
globalImages->ReloadAllImages();
|
||||
} else {
|
||||
glimpParms_t parms;
|
||||
parms.width = glConfig.vidWidth;
|
||||
parms.height = glConfig.vidHeight;
|
||||
parms.width = glConfig.winWidth; // DG: HighDPI adjustment: explicitly use window size
|
||||
parms.height = glConfig.winHeight;
|
||||
parms.fullScreen = ( forceWindow ) ? false : r_fullscreen.GetBool();
|
||||
parms.displayHz = r_displayRefresh.GetInteger();
|
||||
parms.multiSamples = r_multiSamples.GetInteger();
|
||||
|
|
|
@ -165,6 +165,8 @@ bool GLimp_Init(glimpParms_t parms) {
|
|||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
flags |= SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
|
||||
/* Doom3 has the nasty habit of modifying the default framebuffer's alpha channel and then
|
||||
* relying on those modifications in blending operations (using GL_DST_(ONE_MINUS_)ALPHA).
|
||||
* So far that hasn't been much of a problem, because Windows, macOS, X11 etc
|
||||
|
@ -272,14 +274,14 @@ try_again:
|
|||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
|
||||
const char* windowMode = "";
|
||||
if(r_fullscreen.GetBool()) {
|
||||
windowMode = r_fullscreenDesktop.GetBool() ? "desktop-fullscreen-" : "fullscreen-";
|
||||
if ( r_fullscreen.GetBool() && r_fullscreenDesktop.GetBool() ) {
|
||||
common->Printf( "Will create a pseudo-fullscreen window at the current desktop resolution\n" );
|
||||
} else {
|
||||
const char* windowMode = r_fullscreen.GetBool() ? "fullscreen-" : "";
|
||||
common->Printf("Will create a %swindow with resolution %dx%d (r_mode = %d)\n",
|
||||
windowMode, parms.width, parms.height, r_mode.GetInteger());
|
||||
}
|
||||
|
||||
common->Printf("Will create a %swindow with resolution %dx%d (r_mode = %d)\n",
|
||||
windowMode, parms.width, parms.height, r_mode.GetInteger());
|
||||
|
||||
int displayIndex = 0;
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
||||
// try to put the window on the display the mousecursor currently is on
|
||||
|
@ -407,11 +409,23 @@ try_again:
|
|||
GLimp_SetSwapInterval( r_swapInterval.GetInteger() );
|
||||
r_swapInterval.ClearModified();
|
||||
|
||||
SDL_GetWindowSize(window, &glConfig.vidWidth, &glConfig.vidHeight);
|
||||
// for HighDPI, window size and drawable size can differ
|
||||
int ww=0, wh=0;
|
||||
SDL_GetWindowSize(window, &ww, &wh);
|
||||
glConfig.winWidth = ww;
|
||||
glConfig.winHeight = wh;
|
||||
SDL_GL_GetDrawableSize(window, &glConfig.vidWidth, &glConfig.vidHeight);
|
||||
|
||||
SetSDLIcon(); // for SDL2 this must be done after creating the window
|
||||
|
||||
glConfig.isFullscreen = (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) == SDL_WINDOW_FULLSCREEN;
|
||||
const char* fsStr = glConfig.isFullscreen ? "fullscreen " : "";
|
||||
if ( ww != glConfig.vidWidth ) {
|
||||
common->Printf( "Got a HighDPI %swindow with physical resolution %d x %d and virtual resolution %d x %d\n",
|
||||
fsStr, glConfig.vidWidth, glConfig.vidHeight, ww, wh );
|
||||
} else {
|
||||
common->Printf( "Got a %swindow with resolution %d x %d\n", fsStr, ww, wh );
|
||||
}
|
||||
#else
|
||||
SDL_WM_SetCaption(ENGINE_VERSION, ENGINE_VERSION);
|
||||
|
||||
|
|
|
@ -187,6 +187,11 @@ static float GetDefaultDPI()
|
|||
|
||||
static float GetDefaultScale()
|
||||
{
|
||||
if ( glConfig.winWidth != glConfig.vidWidth ) {
|
||||
// in HighDPI mode, the font sizes are already scaled (to window coordinates), apparently
|
||||
return 1.0f;
|
||||
}
|
||||
// TODO: different reference DPI on mac? also, doesn't work that well on my laptop..
|
||||
float ret = GetDefaultDPI() / 96.0f;
|
||||
ret = round(ret*2.0)*0.5; // round to .0 or .5
|
||||
return ret;
|
||||
|
@ -464,8 +469,8 @@ bool ShouldShowCursor()
|
|||
// in a black bar (Doom3 cursor is not drawn there), show the ImGui cursor
|
||||
if ( r_scaleMenusTo43.GetBool() ) {
|
||||
ImVec2 mousePos = ImGui::GetMousePos();
|
||||
float w = renderSystem->GetScreenWidth();
|
||||
float h = renderSystem->GetScreenHeight();
|
||||
float w = glConfig.winWidth;
|
||||
float h = glConfig.winHeight;
|
||||
float aspectRatio = w/h;
|
||||
static const float virtualAspectRatio = float(VIRTUAL_WIDTH)/float(VIRTUAL_HEIGHT); // 4:3 = 1.333
|
||||
if(aspectRatio > 1.4f) {
|
||||
|
|
|
@ -36,6 +36,8 @@ If you have questions concerning this license or the applicable additional terms
|
|||
|
||||
#include "ui/UserInterfaceLocal.h"
|
||||
|
||||
#include "renderer/tr_local.h" // glConfig for winWidth/winHeight
|
||||
|
||||
extern idCVar r_skipGuiShaders; // 1 = don't render any gui elements on surfaces
|
||||
extern idCVar r_scaleMenusTo43; // DG: for the "scale menus to 4:3" hack
|
||||
|
||||
|
@ -355,12 +357,14 @@ const char *idUserInterfaceLocal::HandleEvent( const sysEvent_t *event, int _tim
|
|||
// DG: this is a fullscreen GUI, scale the mousedelta added to cursorX/Y
|
||||
// by 640/w, because the GUI pretends that everything is 640x480
|
||||
// even if the actual resolution is higher => mouse moved too fast
|
||||
float w = renderSystem->GetScreenWidth();
|
||||
float h = renderSystem->GetScreenHeight();
|
||||
float w = glConfig.winWidth;
|
||||
float h = glConfig.winHeight;
|
||||
if( w <= 0.0f || h <= 0.0f ) {
|
||||
w = VIRTUAL_WIDTH;
|
||||
h = VIRTUAL_HEIGHT;
|
||||
}
|
||||
const float realW = w;
|
||||
const float realH = h;
|
||||
|
||||
if(r_scaleMenusTo43.GetBool()) {
|
||||
// in case we're scaling menus to 4:3, we need to take that into account
|
||||
|
@ -387,8 +391,8 @@ const char *idUserInterfaceLocal::HandleEvent( const sysEvent_t *event, int _tim
|
|||
// Note: In case of scaling to 4:3, w and h are already scaled down
|
||||
// to the 4:3 size that fits into the real resolution.
|
||||
// Otherwise xOffset/yOffset will just be 0
|
||||
float xOffset = (renderSystem->GetScreenWidth() - w) * 0.5f;
|
||||
float yOffset = (renderSystem->GetScreenHeight() - h) * 0.5f;
|
||||
float xOffset = (realW - w) * 0.5f;
|
||||
float yOffset = (realH - h) * 0.5f;
|
||||
// offset the mouse coordinates into 4:3 area and scale down to 640x480
|
||||
// yes, result could be negative, doesn't matter, code below checks that anyway
|
||||
cursorX = (event->evValue - xOffset) * (float(VIRTUAL_WIDTH)/w);
|
||||
|
|
Loading…
Reference in a new issue