From d3d8180f578924b275defd937e10cd3cb370922e Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:04:36 +0200 Subject: [PATCH 1/7] Resize framebuffer in windowed mode to match the client area --- src/v_video.cpp | 42 ++++++++++++++++++++++++++++++++++++------ src/v_video.h | 4 ++++ src/win32/fb_d3d9.cpp | 18 ++++++++++++++++++ src/win32/i_input.cpp | 16 ++++++++++++---- 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index b9917a1cb..9d377b7fd 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -725,6 +725,21 @@ void DCanvas::CalcGamma (float gamma, BYTE gammalookup[256]) DSimpleCanvas::DSimpleCanvas (int width, int height) : DCanvas (width, height) { + MemBuffer = nullptr; + Resize(width, height); +} + +void DSimpleCanvas::Resize(int width, int height) +{ + Width = width; + Height = height; + + if (MemBuffer != NULL) + { + delete[] MemBuffer; + MemBuffer = NULL; + } + // Making the pitch a power of 2 is very bad for performance // Try to maximize the number of cache lines that can be filled // for each column drawing operation by making the pitch slightly @@ -761,7 +776,7 @@ DSimpleCanvas::DSimpleCanvas (int width, int height) } } MemBuffer = new BYTE[Pitch * height]; - memset (MemBuffer, 0, Pitch * height); + memset(MemBuffer, 0, Pitch * height); } //========================================================================== @@ -1259,7 +1274,6 @@ CCMD(clean) bool V_DoModeSetup (int width, int height, int bits) { DFrameBuffer *buff = I_SetMode (width, height, screen); - int cx1, cx2; if (buff == NULL) { @@ -1274,6 +1288,17 @@ bool V_DoModeSetup (int width, int height, int bits) // if D3DFB is being used for the display. FFont::StaticPreloadFonts(); + DisplayBits = bits; + V_UpdateModeSize(width, height); + + M_RefreshModesList (); + + return true; +} + +void V_UpdateModeSize (int width, int height) +{ + int cx1, cx2; V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2); CleanWidth = width / CleanXfac; @@ -1314,14 +1339,19 @@ bool V_DoModeSetup (int width, int height, int bits) DisplayWidth = width; DisplayHeight = height; - DisplayBits = bits; R_OldBlend = ~0; Renderer->OnModeSet(); - - M_RefreshModesList (); +} - return true; +void V_OutputResized (int width, int height) +{ + V_UpdateModeSize(width, height); + setsizeneeded = true; + if (StatusBar != NULL) + { + StatusBar->ScreenSizeChanged(); + } } void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) diff --git a/src/v_video.h b/src/v_video.h index 4f0a78675..11a10c8d8 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -47,6 +47,8 @@ extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1; extern int DisplayWidth, DisplayHeight, DisplayBits; bool V_DoModeSetup (int width, int height, int bits); +void V_UpdateModeSize (int width, int height); +void V_OutputResized (int width, int height); void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *cx1=NULL, int *cx2=NULL); class FTexture; @@ -300,6 +302,8 @@ public: void Unlock (); protected: + void Resize(int width, int height); + BYTE *MemBuffer; DSimpleCanvas() {} diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index efdced151..06bfa0569 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -1220,6 +1220,24 @@ void D3DFB::Flip() CurrRenderTexture ^= RenderTextureToggle; TempRenderTexture = RenderTexture[CurrRenderTexture]; } + + if (Windowed) + { + RECT box; + GetClientRect(Window, &box); + if (box.right > 0 && box.right > 0 && (Width != box.right || Height != box.bottom)) + { + Resize(box.right, box.bottom); + + TrueHeight = Height; + PixelDoubling = 0; + LBOffsetI = 0; + LBOffset = 0.0f; + Reset(); + + V_OutputResized(Width, Height); + } + } } //========================================================================== diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 2b0659c83..1e6390392 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -537,10 +537,18 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (screen && !VidResizing) { LPMINMAXINFO mmi = (LPMINMAXINFO)lParam; - RECT rect = { 0, 0, screen->GetWidth(), screen->GetHeight() }; - AdjustWindowRectEx(&rect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); - mmi->ptMinTrackSize.x = rect.right - rect.left; - mmi->ptMinTrackSize.y = rect.bottom - rect.top; + if (screen->IsFullscreen()) + { + RECT rect = { 0, 0, screen->GetWidth(), screen->GetHeight() }; + AdjustWindowRectEx(&rect, WS_VISIBLE | WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); + mmi->ptMinTrackSize.x = rect.right - rect.left; + mmi->ptMinTrackSize.y = rect.bottom - rect.top; + } + else + { + mmi->ptMinTrackSize.x = 320; + mmi->ptMinTrackSize.y = 200; + } return 0; } break; From b003c47e3e02bed94b76757a512b195b1d7d70c8 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:37:05 +0200 Subject: [PATCH 2/7] Improve CheckRatio to always return the closest ratio --- src/v_video.cpp | 77 +++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 47 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index 9d377b7fd..78995f300 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1610,13 +1610,36 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) // 2: 16:10 // 3: 17:10 // 4: 5:4 -// 5: 17:10 (redundant) +// 5: 17:10 (redundant, never returned) // 6: 21:9 int CheckRatio (int width, int height, int *trueratio) { - int fakeratio = -1; - int ratio; + float aspect = width / (float)height; + static std::pair ratioTypes[] = + { + { 21 / 9.0f , 6 }, + { 16 / 9.0f , 1 }, + { 17 / 10.0f , 3 }, + { 16 / 10.0f , 2 }, + { 4 / 3.0f , 0 }, + { 5 / 4.0f , 4 }, + { 0.0f, 0 } + }; + + int ratio = ratioTypes[0].second; + float distance = abs(ratioTypes[0].first - aspect); + for (int i = 1; ratioTypes[i].first != 0.0f; i++) + { + float d = abs(ratioTypes[i].first - aspect); + if (d < distance) + { + ratio = ratioTypes[i].second; + distance = d; + } + } + + int fakeratio = ratio; if ((vid_aspect >= 1) && (vid_aspect <= 6)) { // [SP] User wants to force aspect ratio; let them. @@ -1628,7 +1651,7 @@ int CheckRatio (int width, int height, int *trueratio) else if (fakeratio == 5) { fakeratio = 3; - } + } } if (vid_nowidescreen) { @@ -1638,53 +1661,13 @@ int CheckRatio (int width, int height, int *trueratio) } else { - fakeratio = (height * 5/4 == width) ? 4 : 0; + fakeratio = (height * 5 / 4 == width) ? 4 : 0; } } - // If the size is approximately 16:9, consider it so. - if (abs (height * 16/9 - width) < 10) - { - ratio = 1; - } - // Consider 17:10 as well. - else if (abs (height * 17/10 - width) < 10) - { - ratio = 3; - } - // 16:10 has more variance in the pixel dimensions. Grr. - else if (abs (height * 16/10 - width) < 60) - { - // 320x200 and 640x400 are always 4:3, not 16:10 - if ((width == 320 && height == 200) || (width == 640 && height == 400)) - { - ratio = 0; - } - else - { - ratio = 2; - } - } - // Unless vid_tft is set, 1280x1024 is 4:3, not 5:4. - else if (height * 5/4 == width && vid_tft) - { - ratio = 4; - } - // test for 21:9 (actually 64:27, 21:9 is a semi-accurate ratio used in marketing) - else if (abs (height * 64/27 - width) < 30) - { - ratio = 6; - } - // Assume anything else is 4:3. (Which is probably wrong these days...) - else - { - ratio = 0; - } - if (trueratio != NULL) - { + if (trueratio) *trueratio = ratio; - } - return (fakeratio >= 0) ? fakeratio : ratio; + return fakeratio; } // First column: Base width From 5720634045b0812bc838eb4671a4039917582a94 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 13:59:01 +0200 Subject: [PATCH 3/7] Add ActiveRatio to be used where CheckRatio is used today --- src/v_video.cpp | 81 ++++++++++++++++++++++++++++++++++--------------- src/v_video.h | 2 ++ 2 files changed, 58 insertions(+), 25 deletions(-) diff --git a/src/v_video.cpp b/src/v_video.cpp index 78995f300..dcc5789ee 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1603,6 +1603,59 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) } } +// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none. +int ActiveFakeRatio(int width, int height) +{ + int fakeratio = -1; + if ((vid_aspect >= 1) && (vid_aspect <= 6)) + { + // [SP] User wants to force aspect ratio; let them. + fakeratio = int(vid_aspect); + if (fakeratio == 3) + { + fakeratio = 0; + } + else if (fakeratio == 5) + { + fakeratio = 3; + } + } + if (vid_nowidescreen) + { + if (!vid_tft) + { + fakeratio = 0; + } + else + { + fakeratio = (height * 5 / 4 == width) ? 4 : 0; + } + } + return fakeratio; +} + +// Active screen ratio based on cvars and size +float ActiveRatio(int width, int height, float *trueratio) +{ + static float forcedRatioTypes[] = + { + 4 / 3.0f, + 16 / 9.0f, + 16 / 10.0f, + 17 / 10.0f, + 5 / 4.0f, + 17 / 10.0f, + 21 / 9.0f + }; + + float ratio = width / (float)height; + int fakeratio = ActiveFakeRatio(width, height); + + if (trueratio) + *trueratio = ratio; + return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : ratio; +} + // Tries to guess the physical dimensions of the screen based on the // screen's pixel dimensions. Can return: // 0: 4:3 @@ -1639,31 +1692,9 @@ int CheckRatio (int width, int height, int *trueratio) } } - int fakeratio = ratio; - if ((vid_aspect >= 1) && (vid_aspect <= 6)) - { - // [SP] User wants to force aspect ratio; let them. - fakeratio = int(vid_aspect); - if (fakeratio == 3) - { - fakeratio = 0; - } - else if (fakeratio == 5) - { - fakeratio = 3; - } - } - if (vid_nowidescreen) - { - if (!vid_tft) - { - fakeratio = 0; - } - else - { - fakeratio = (height * 5 / 4 == width) ? 4 : 0; - } - } + int fakeratio = ActiveFakeRatio(width, height); + if (fakeratio == -1) + fakeratio = ratio; if (trueratio) *trueratio = ratio; diff --git a/src/v_video.h b/src/v_video.h index 11a10c8d8..6b46fa278 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -516,6 +516,8 @@ extern "C" void ASM_PatchPitch (void); int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } +float ActiveRatio (int width, int height, float *trueratio = NULL); +static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } extern const int BaseRatioSizes[7][4]; inline bool IsRatioWidescreen(int ratio) { From 6d4e4dad25ffa3978f5bf54d0fc60dd59b29d119 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 14:37:10 +0200 Subject: [PATCH 4/7] BaseRatioSizes replacement functions --- src/v_video.cpp | 20 ++++++++++++++++++++ src/v_video.h | 5 +++++ 2 files changed, 25 insertions(+) diff --git a/src/v_video.cpp b/src/v_video.cpp index dcc5789ee..acd34f37f 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1721,6 +1721,26 @@ const int BaseRatioSizes[7][4] = { 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three }; +int AspectBaseWidth(float aspect) +{ + return (int)round(240.0f * aspect * 3.0f); +} + +int AspectBaseHeight(float aspect) +{ + return (int)round(200.0f * (320.0f / (240.0f * aspect)) * 3.0f); +} + +int AspectPspriteOffset(float aspect) +{ + return aspect < 1.3f ? (int)(6.5*FRACUNIT) : 0; +} + +int AspectMultiplier(float aspect) +{ + return (int)round(320.0f / (240.0f * aspect) * 48.0f); +} + void IVideo::DumpAdapters () { Printf("Multi-monitor support unavailable.\n"); diff --git a/src/v_video.h b/src/v_video.h index 6b46fa278..2dc3bbddc 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -518,6 +518,11 @@ int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } float ActiveRatio (int width, int height, float *trueratio = NULL); static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } + +int AspectBaseWidth(float aspect); +int AspectBaseHeight(float aspect); +int AspectPspriteOffset(float aspect); +int AspectMultiplier(float aspect); extern const int BaseRatioSizes[7][4]; inline bool IsRatioWidescreen(int ratio) { From 5b438d220f918e4d5b604e970f0f45f96963e8d1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 15:51:50 +0200 Subject: [PATCH 5/7] Switch from ratio enum to float --- src/g_shared/shared_hud.cpp | 6 +++--- src/g_shared/shared_sbar.cpp | 17 +++++++++-------- src/r_main.cpp | 16 ++++++++-------- src/r_renderer.h | 2 +- src/r_swrenderer.cpp | 4 ++-- src/r_swrenderer.h | 2 +- src/r_things.cpp | 2 +- src/r_utility.cpp | 11 +++++------ src/r_utility.h | 2 +- src/v_draw.cpp | 34 +++++++++++++++++----------------- src/v_video.cpp | 30 +++++------------------------- src/v_video.h | 11 ++--------- 12 files changed, 55 insertions(+), 82 deletions(-) diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index 25a88cb35..e40233def 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -1108,13 +1108,13 @@ void DrawHUD() } else { - if (WidescreenRatio == 4) + if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) == 4) { - hudheight = hudwidth * 30 / BaseRatioSizes[WidescreenRatio][3]; // BaseRatioSizes is inverted for this mode + hudheight = hudwidth * 30 / AspectMultiplier(WidescreenRatio); // BaseRatioSizes is inverted for this mode } else { - hudheight = hudwidth * 30 / (48*48/BaseRatioSizes[WidescreenRatio][3]); + hudheight = hudwidth * 30 / (48*48/AspectMultiplier(WidescreenRatio)); } } } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 4631a99aa..3c41d18ca 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -299,14 +299,15 @@ void DBaseStatusBar::SetScaled (bool scale, bool force) { ST_X = 0; ST_Y = VirticalResolution - RelTop; - if (CheckRatio(SCREENWIDTH, SCREENHEIGHT) != 4) + float aspect = ActiveRatio(SCREENWIDTH, SCREENHEIGHT); + if (aspect >= 1.3f) { // Normal resolution ::ST_Y = Scale (ST_Y, SCREENHEIGHT, VirticalResolution); } else { // 5:4 resolution - ::ST_Y = Scale(ST_Y - VirticalResolution/2, SCREENHEIGHT*3, Scale(VirticalResolution, BaseRatioSizes[4][1], 200)) + SCREENHEIGHT/2 - + (SCREENHEIGHT - SCREENHEIGHT * BaseRatioSizes[4][3] / 48) / 2; + ::ST_Y = Scale(ST_Y - VirticalResolution/2, SCREENHEIGHT*3, Scale(VirticalResolution, AspectBaseHeight(aspect), 200)) + SCREENHEIGHT/2 + + (SCREENHEIGHT - SCREENHEIGHT * AspectMultiplier(aspect) / 48) / 2; } Displacement = 0; } @@ -1035,10 +1036,10 @@ void DBaseStatusBar::DrSmallNumberOuter (int val, int x, int y, bool center) con void DBaseStatusBar::RefreshBackground () const { - int x, x2, y, ratio; + int x, x2, y; - ratio = CheckRatio (SCREENWIDTH, SCREENHEIGHT); - x = (!IsRatioWidescreen(ratio) || !Scaled) ? ST_X : SCREENWIDTH*(48-BaseRatioSizes[ratio][3])/(48*2); + float ratio = ActiveRatio (SCREENWIDTH, SCREENHEIGHT); + x = (ratio < 1.5f || !Scaled) ? ST_X : SCREENWIDTH*(48-AspectMultiplier(ratio))/(48*2); y = x == ST_X && x > 0 ? ST_Y : ::ST_Y; if(!CompleteBorder) @@ -1058,8 +1059,8 @@ void DBaseStatusBar::RefreshBackground () const { if(!CompleteBorder) { - x2 = !IsRatioWidescreen(ratio) || !Scaled ? ST_X+HorizontalResolution : - SCREENWIDTH - (SCREENWIDTH*(48-BaseRatioSizes[ratio][3])+48*2-1)/(48*2); + x2 = ratio < 1.5f || !Scaled ? ST_X+HorizontalResolution : + SCREENWIDTH - (SCREENWIDTH*(48-AspectMultiplier(ratio))+48*2-1)/(48*2); } else { diff --git a/src/r_main.cpp b/src/r_main.cpp index ecbd4cb34..d84698b7c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -232,7 +232,7 @@ void R_SetVisibility(double vis) else r_WallVisibility = r_BaseVisibility; - r_WallVisibility = (InvZtoScale * SCREENWIDTH*BaseRatioSizes[WidescreenRatio][1] / + r_WallVisibility = (InvZtoScale * SCREENWIDTH*AspectBaseHeight(WidescreenRatio) / (viewwidth*SCREENHEIGHT*3)) * (r_WallVisibility * FocalTangent); // Prevent overflow on floors/ceilings. Note that the calculation of @@ -295,7 +295,7 @@ CCMD (r_visibility) // //========================================================================== -void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) +void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) { int virtheight, virtwidth, virtwidth2, virtheight2; @@ -318,22 +318,22 @@ void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, virtwidth = virtwidth2 = fullWidth; virtheight = virtheight2 = fullHeight; - if (Is54Aspect(trueratio)) + if (trueratio < 1.3f) { - virtheight2 = virtheight2 * BaseRatioSizes[trueratio][3] / 48; + virtheight2 = virtheight2 * AspectMultiplier(trueratio) / 48; } else { - virtwidth2 = virtwidth2 * BaseRatioSizes[trueratio][3] / 48; + virtwidth2 = virtwidth2 * AspectMultiplier(trueratio) / 48; } - if (Is54Aspect(WidescreenRatio)) + if (WidescreenRatio < 1.3f) { - virtheight = virtheight * BaseRatioSizes[WidescreenRatio][3] / 48; + virtheight = virtheight * AspectMultiplier(WidescreenRatio) / 48; } else { - virtwidth = virtwidth * BaseRatioSizes[WidescreenRatio][3] / 48; + virtwidth = virtwidth * AspectMultiplier(WidescreenRatio) / 48; } BaseYaspectMul = 320.0 * virtheight2 / (r_Yaspect * virtwidth2); diff --git a/src/r_renderer.h b/src/r_renderer.h index 6c65fc12f..a39520b49 100644 --- a/src/r_renderer.h +++ b/src/r_renderer.h @@ -55,7 +55,7 @@ struct FRenderer virtual void ErrorCleanup () {} virtual void ClearBuffer(int color) = 0; virtual void Init() = 0; - virtual void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) {} + virtual void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) {} virtual void SetupFrame(player_t *player) {} virtual void CopyStackedViewParameters() {} virtual void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov) = 0; diff --git a/src/r_swrenderer.cpp b/src/r_swrenderer.cpp index 07edf25e9..4d1fd0371 100644 --- a/src/r_swrenderer.cpp +++ b/src/r_swrenderer.cpp @@ -45,7 +45,7 @@ class FArchive; -void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio); +void R_SWRSetWindow(int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); void R_SetupColormap(player_t *); void R_SetupFreelook(); void R_InitRenderer(); @@ -275,7 +275,7 @@ void FSoftwareRenderer::ClearBuffer(int color) // //=========================================================================== -void FSoftwareRenderer::SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio) +void FSoftwareRenderer::SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio) { R_SWRSetWindow(windowSize, fullWidth, fullHeight, stHeight, trueratio); } diff --git a/src/r_swrenderer.h b/src/r_swrenderer.h index 3e5fed9bc..2856d9586 100644 --- a/src/r_swrenderer.h +++ b/src/r_swrenderer.h @@ -30,7 +30,7 @@ struct FSoftwareRenderer : public FRenderer void ErrorCleanup (); void ClearBuffer(int color); void Init(); - void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, int trueratio); + void SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight, float trueratio); void SetupFrame(player_t *player); void CopyStackedViewParameters(); void RenderTextureView (FCanvasTexture *tex, AActor *viewpoint, int fov); diff --git a/src/r_things.cpp b/src/r_things.cpp index 28b52129b..a62525d08 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1393,7 +1393,7 @@ void R_DrawPSprite(DPSprite *pspr, AActor *owner, float bobx, float boby, double } if (pspr->GetID() < PSP_TARGETCENTER) { // Move the weapon down for 1280x1024. - vis->texturemid -= BaseRatioSizes[WidescreenRatio][2]; + vis->texturemid -= AspectPspriteOffset(WidescreenRatio); } vis->x1 = x1 < 0 ? 0 : x1; vis->x2 = x2 >= viewwidth ? viewwidth : x2; diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 00ac91c97..8e4284b7e 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -138,7 +138,7 @@ angle_t LocalViewAngle; int LocalViewPitch; bool LocalKeyboardTurner; -int WidescreenRatio; +float WidescreenRatio; int setblocks; int extralight; bool setsizeneeded; @@ -200,7 +200,7 @@ void R_SetViewSize (int blocks) void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) { - int trueratio; + float trueratio; if (windowSize >= 11) { @@ -220,8 +220,7 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) freelookviewheight = ((setblocks*fullHeight)/10)&~7; } - // If the screen is approximately 16:9 or 16:10, consider it widescreen. - WidescreenRatio = CheckRatio (fullWidth, fullHeight, &trueratio); + WidescreenRatio = ActiveRatio (fullWidth, fullHeight, &trueratio); DrawFSHUD = (windowSize == 11); @@ -230,13 +229,13 @@ void R_SetWindow (int windowSize, int fullWidth, int fullHeight, int stHeight) centery = viewheight/2; centerx = viewwidth/2; - if (Is54Aspect(WidescreenRatio)) + if (WidescreenRatio < 1.3f) { centerxwide = centerx; } else { - centerxwide = centerx * BaseRatioSizes[WidescreenRatio][3] / 48; + centerxwide = centerx * AspectMultiplier(WidescreenRatio) / 48; } diff --git a/src/r_utility.h b/src/r_utility.h index 8cabfa600..e9fd436e5 100644 --- a/src/r_utility.h +++ b/src/r_utility.h @@ -33,7 +33,7 @@ extern int validcount; extern angle_t LocalViewAngle; // [RH] Added to consoleplayer's angle extern int LocalViewPitch; // [RH] Used directly instead of consoleplayer's pitch extern bool LocalKeyboardTurner; // [RH] The local player used the keyboard to turn, so interpolate -extern int WidescreenRatio; +extern float WidescreenRatio; extern double r_TicFracF; extern DWORD r_FrameTime; diff --git a/src/v_draw.cpp b/src/v_draw.cpp index dada0cd57..a33fd618b 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -863,37 +863,37 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect) const { - int myratio = handleaspect ? CheckRatio (Width, Height) : 0; + float myratio = handleaspect ? ActiveRatio (Width, Height) : (4.0f / 3.0f); // if 21:9 AR, map to 16:9 for all callers. // this allows for black bars and stops the stretching of fullscreen images - if (myratio == 6) { - myratio = 2; + if (myratio > 1.7f) { + myratio = 16.0f / 9.0f; } double right = x + w; double bottom = y + h; - if (myratio != 0 && myratio != 4) + if (myratio > 1.4f) { // The target surface is either 16:9 or 16:10, so expand the // specified virtual size to avoid undesired stretching of the // image. Does not handle non-4:3 virtual sizes. I'll worry about // those if somebody expresses a desire to use them. - x = (x - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5; - w = (right - vwidth * 0.5) * Width * 960 / (vwidth * BaseRatioSizes[myratio][0]) + Width * 0.5 - x; + x = (x - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5; + w = (right - vwidth * 0.5) * Width * 960 / (vwidth * AspectBaseWidth(myratio)) + Width * 0.5 - x; } else { x = x * Width / vwidth; w = right * Width / vwidth - x; } - if (myratio == 4) + if (myratio < 1.3f) { // The target surface is 5:4 - y = (y - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5; - h = (bottom - vheight * 0.5) * Height * 600 / (vheight * BaseRatioSizes[myratio][1]) + Height * 0.5 - y; + y = (y - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5; + h = (bottom - vheight * 0.5) * Height * 600 / (vheight * AspectBaseHeight(myratio)) + Height * 0.5 - y; if (vbottom) { - y += (Height - Height * BaseRatioSizes[myratio][3] / 48.0) * 0.5; + y += (Height - Height * AspectMultiplier(myratio) / 48.0) * 0.5; } } else @@ -937,30 +937,30 @@ void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, void DCanvas::FillBorder (FTexture *img) { - int myratio = CheckRatio (Width, Height); + float myratio = ActiveRatio (Width, Height); // if 21:9 AR, fill borders akin to 16:9, since all fullscreen // images are being drawn to that scale. - if (myratio == 6) { - myratio = 2; + if (myratio > 1.7f) { + myratio = 16 / 9.0f; } - if (myratio == 0) + if (myratio >= 1.3f && myratio <= 1.4f) { // This is a 4:3 display, so no border to show return; } int bordtop, bordbottom, bordleft, bordright, bord; - if (Is54Aspect(myratio)) + if (myratio < 1.3f) { // Screen is taller than it is wide bordleft = bordright = 0; - bord = Height - Height * BaseRatioSizes[myratio][3] / 48; + bord = Height - Height * AspectMultiplier(myratio) / 48; bordtop = bord / 2; bordbottom = bord - bordtop; } else { // Screen is wider than it is tall bordtop = bordbottom = 0; - bord = Width - Width * BaseRatioSizes[myratio][3] / 48; + bord = Width - Width * AspectMultiplier(myratio) / 48; bordleft = bord / 2; bordright = bord - bordleft; } diff --git a/src/v_video.cpp b/src/v_video.cpp index acd34f37f..43458dc63 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1356,20 +1356,20 @@ void V_OutputResized (int width, int height) void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2) { - int ratio; + float ratio; int cwidth; int cheight; int cx1, cy1, cx2, cy2; - ratio = CheckRatio(realwidth, realheight); - if (Is54Aspect(ratio)) + ratio = ActiveRatio(realwidth, realheight); + if (ratio < 1.3f) { cwidth = realwidth; - cheight = realheight * BaseRatioSizes[ratio][3] / 48; + cheight = realheight * AspectMultiplier(ratio) / 48; } else { - cwidth = realwidth * BaseRatioSizes[ratio][3] / 48; + cwidth = realwidth * AspectMultiplier(ratio) / 48; cheight = realheight; } // Use whichever pair of cwidth/cheight or width/height that produces less difference @@ -1701,26 +1701,6 @@ int CheckRatio (int width, int height, int *trueratio) return fakeratio; } -// First column: Base width -// Second column: Base height (used for wall visibility multiplier) -// Third column: Psprite offset (needed for "tallscreen" modes) -// Fourth column: Width or height multiplier - -// For widescreen aspect ratio x:y ... -// base_width = 240 * x / y -// multiplier = 320 / base_width -// base_height = 200 * multiplier -const int BaseRatioSizes[7][4] = -{ - { 960, 600, 0, 48 }, // 4:3 320, 200, multiplied by three - { 1280, 450, 0, 48*3/4 }, // 16:9 426.6667, 150, multiplied by three - { 1152, 500, 0, 48*5/6 }, // 16:10 386, 166.6667, multiplied by three - { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three - { 960, 640, (int)(6.5*FRACUNIT), 48*15/16 }, // 5:4 320, 213.3333, multiplied by three - { 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three (REDUNDANT) - { 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three -}; - int AspectBaseWidth(float aspect) { return (int)round(240.0f * aspect * 3.0f); diff --git a/src/v_video.h b/src/v_video.h index 2dc3bbddc..8d785e43f 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -516,6 +516,8 @@ extern "C" void ASM_PatchPitch (void); int CheckRatio (int width, int height, int *trueratio=NULL); static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); } +inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; } + float ActiveRatio (int width, int height, float *trueratio = NULL); static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); } @@ -523,15 +525,6 @@ int AspectBaseWidth(float aspect); int AspectBaseHeight(float aspect); int AspectPspriteOffset(float aspect); int AspectMultiplier(float aspect); -extern const int BaseRatioSizes[7][4]; - -inline bool IsRatioWidescreen(int ratio) { - return (ratio & 3)!=0; -} - -inline bool Is54Aspect(int ratio) { - return ratio == 4; -} EXTERN_CVAR(Int, uiscale); From 4e58e6626cf0372a3fbca5649a66aa7e2441554c Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 16:05:42 +0200 Subject: [PATCH 6/7] Fix buffer overrun in CommandAspectRatio for 21:9 aspect ratio --- src/g_shared/sbarinfo_commands.cpp | 33 +++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index a9fac2ee1..47785076e 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1914,7 +1914,7 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl { SBarInfoCommandFlowControl::Tick(block, statusBar, hudChanged); - SetTruth(ratioMap[CheckRatio(screen->GetWidth(), screen->GetHeight())] == ratio, block, statusBar); + SetTruth(ratioMap[FindRatio()] == ratio, block, statusBar); } protected: enum Ratio @@ -1931,6 +1931,37 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl static Ratio ratioMap[5]; Ratio ratio; + + private: + int FindRatio() + { + float aspect = ActiveRatio(screen->GetWidth(), screen->GetHeight()); + + static std::pair ratioTypes[] = + { + { 21 / 9.0f , ASPECTRATIO_16_9 }, + { 16 / 9.0f , ASPECTRATIO_16_9 }, + { 17 / 10.0f , ASPECTRATIO_17_10 }, + { 16 / 10.0f , ASPECTRATIO_16_10 }, + { 4 / 3.0f , ASPECTRATIO_4_3 }, + { 5 / 4.0f , ASPECTRATIO_5_4 }, + { 0.0f, 0 } + }; + + int ratio = ratioTypes[0].second; + float distance = abs(ratioTypes[0].first - aspect); + for (int i = 1; ratioTypes[i].first != 0.0f; i++) + { + float d = abs(ratioTypes[i].first - aspect); + if (d < distance) + { + ratio = ratioTypes[i].second; + distance = d; + } + } + + return ratio; + } }; CommandAspectRatio::Ratio CommandAspectRatio::ratioMap[5] = {ASPECTRATIO_4_3,ASPECTRATIO_16_9,ASPECTRATIO_16_10,ASPECTRATIO_16_10,ASPECTRATIO_5_4}; From 01b1efe9eec9877a409d14f749b9934a10224a58 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Mon, 12 Sep 2016 18:44:04 +0200 Subject: [PATCH 7/7] Switch from abs to fabs --- src/g_shared/sbarinfo_commands.cpp | 4 ++-- src/v_video.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 47785076e..b7827f6bd 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -1949,10 +1949,10 @@ class CommandAspectRatio : public SBarInfoCommandFlowControl }; int ratio = ratioTypes[0].second; - float distance = abs(ratioTypes[0].first - aspect); + float distance = fabs(ratioTypes[0].first - aspect); for (int i = 1; ratioTypes[i].first != 0.0f; i++) { - float d = abs(ratioTypes[i].first - aspect); + float d = fabs(ratioTypes[i].first - aspect); if (d < distance) { ratio = ratioTypes[i].second; diff --git a/src/v_video.cpp b/src/v_video.cpp index 43458dc63..20e1f526c 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -1681,10 +1681,10 @@ int CheckRatio (int width, int height, int *trueratio) }; int ratio = ratioTypes[0].second; - float distance = abs(ratioTypes[0].first - aspect); + float distance = fabs(ratioTypes[0].first - aspect); for (int i = 1; ratioTypes[i].first != 0.0f; i++) { - float d = abs(ratioTypes[i].first - aspect); + float d = fabs(ratioTypes[i].first - aspect); if (d < distance) { ratio = ratioTypes[i].second;