diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index 96044bea9..20d293ae2 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -55,6 +55,8 @@ - fixed a crash on level load if an animation has no frames (#2746, regression from 0.8) - fixed a crash in custom levels with large rooms (#2749) - fixed flares missing the flicker effect in 60 FPS (#2806) +- fixed the viewport not always in sync with the window (#2820) +- improved performance when moving the window around - improved pause exit dialog - it can now be canceled with escape - removed the need to specify in the game flow levels that have no secrets (secrets will be automatically counted) (#1582) - removed the hard-coded end-level behaviour of the bird guardian for custom levels (#1583) diff --git a/src/libtrx/game/shell/common.c b/src/libtrx/game/shell/common.c index 2e180264e..7da027943 100644 --- a/src/libtrx/game/shell/common.c +++ b/src/libtrx/game/shell/common.c @@ -130,31 +130,35 @@ void Shell_ExitSystemFmt(const char *fmt, ...) Memory_FreePointer(&message); } -int32_t Shell_GetCurrentDisplayWidth(void) +bool Shell_IsFullscreen(void) { - SDL_DisplayMode dm; - SDL_GetCurrentDisplayMode(0, &dm); - return dm.w; -} - -int32_t Shell_GetCurrentDisplayHeight(void) -{ - SDL_DisplayMode dm; - SDL_GetCurrentDisplayMode(0, &dm); - return dm.h; -} - -void Shell_GetWindowSize(int32_t *const out_width, int32_t *const out_height) -{ - ASSERT(out_width != nullptr); - ASSERT(out_height != nullptr); SDL_Window *const window = Shell_GetWindow(); - if (window == nullptr) { - *out_width = -1; - *out_height = -1; - } else { - SDL_GetWindowSize(window, out_width, out_height); + ASSERT(window != nullptr); + const Uint32 flags = SDL_GetWindowFlags(window); + return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; +} + +SHELL_SIZE Shell_GetWindowSize(void) +{ + SDL_Window *const window = Shell_GetWindow(); + SHELL_SIZE result = { .w = -1, .h = -1 }; + if (window != nullptr) { + SDL_GetWindowSize(window, &result.w, &result.h); } + return result; +} + +SHELL_SIZE Shell_GetCurrentSize(void) +{ + return Shell_IsFullscreen() ? Shell_GetCurrentDisplaySize() + : Shell_GetWindowSize(); +} + +SHELL_SIZE Shell_GetCurrentDisplaySize(void) +{ + SDL_DisplayMode dm; + SDL_GetCurrentDisplayMode(0, &dm); + return (SHELL_SIZE) { .w = dm.w, .h = dm.h }; } void Shell_ScheduleExit(void) diff --git a/src/libtrx/include/libtrx/game/shell.h b/src/libtrx/include/libtrx/game/shell.h index 99b922576..3128bda38 100644 --- a/src/libtrx/include/libtrx/game/shell.h +++ b/src/libtrx/include/libtrx/game/shell.h @@ -3,6 +3,11 @@ #include #include +typedef struct { + int32_t w; + int32_t h; +} SHELL_SIZE; + extern void Shell_Shutdown(void); extern SDL_Window *Shell_GetWindow(void); @@ -16,9 +21,10 @@ void Shell_GetCommandLine(int *arg_count, const char ***args); void Shell_ScheduleExit(void); bool Shell_IsExiting(void); -int32_t Shell_GetCurrentDisplayWidth(void); -int32_t Shell_GetCurrentDisplayHeight(void); -void Shell_GetWindowSize(int32_t *out_width, int32_t *out_height); +bool Shell_IsFullscreen(void); +SHELL_SIZE Shell_GetWindowSize(void); +SHELL_SIZE Shell_GetCurrentSize(void); +SHELL_SIZE Shell_GetCurrentDisplaySize(void); extern const char *Shell_GetConfigPath(void); extern const char *Shell_GetGameFlowPath(void); diff --git a/src/tr1/game/screen.c b/src/tr1/game/screen.c index 387fb599d..d0ee41efd 100644 --- a/src/tr1/game/screen.c +++ b/src/tr1/game/screen.c @@ -71,9 +71,10 @@ void Screen_Init(void) } // set the first resolution size to desktop size + const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize(); res = &m_Resolutions[0]; - res->width = Shell_GetCurrentDisplayWidth(); - res->height = Shell_GetCurrentDisplayHeight(); + res->width = display_size.w; + res->height = display_size.h; // select matching resolution from config if (g_Config.rendering.resolution_width > 0 diff --git a/src/tr2/game/fmv.c b/src/tr2/game/fmv.c index 9906fd79d..41001bce8 100644 --- a/src/tr2/game/fmv.c +++ b/src/tr2/game/fmv.c @@ -123,9 +123,8 @@ static bool M_Play(const char *const file_name) ? 0 : g_Config.audio.sound_volume / (float)Sound_GetMaxVolume()); - Video_SetSurfaceSize( - video, Shell_GetCurrentDisplayWidth(), - Shell_GetCurrentDisplayHeight()); + const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize(); + Video_SetSurfaceSize(video, display_size.w, display_size.h); if (g_Config.rendering.render_mode == RM_SOFTWARE) { Video_SetSurfacePixelFormat(video, AV_PIX_FMT_RGB8); GFX_2D_Renderer_SetPalette(renderer_2d, palette); diff --git a/src/tr2/game/shell/common.c b/src/tr2/game/shell/common.c index 1b2b9f59e..c28f95929 100644 --- a/src/tr2/game/shell/common.c +++ b/src/tr2/game/shell/common.c @@ -77,10 +77,12 @@ static SHELL_ARGS m_Args = { .save_to_load = -1, }; +static SHELL_SIZE m_ViewportSize = { .w = -1, .h = -1 }; static Uint64 m_UpdateDebounce = 0; static void M_SyncToWindow(void); -static void M_SyncFromWindow(void); +static void M_SyncFromWindow(bool update_viewport); +static bool M_MustUpdateRendererViewport(void); static void M_RefreshRendererViewport(void); static void M_HandleFocusGained(void); static void M_HandleFocusLost(void); @@ -136,8 +138,9 @@ static void M_SyncToWindow(void) height = 720; } if (x <= 0 || y <= 0) { - x = (Shell_GetCurrentDisplayWidth() - width) / 2; - y = (Shell_GetCurrentDisplayHeight() - height) / 2; + const SHELL_SIZE display_size = Shell_GetCurrentDisplaySize(); + x = (display_size.w - width) / 2; + y = (display_size.h - height) / 2; } SDL_SetWindowFullscreen(g_SDLWindow, 0); @@ -147,7 +150,7 @@ static void M_SyncToWindow(void) } } -static void M_SyncFromWindow(void) +static void M_SyncFromWindow(const bool update_viewport) { // Determine if this call should sync config, i.e., skip immediate // programmatic events @@ -177,13 +180,22 @@ static void M_SyncFromWindow(void) } } - // Always refresh viewport to reflect the actual window size - M_RefreshRendererViewport(); + if (update_viewport || M_MustUpdateRendererViewport()) { + // Refresh viewport to reflect the actual window size + M_RefreshRendererViewport(); + } +} + +static bool M_MustUpdateRendererViewport(void) +{ + const SHELL_SIZE size = Shell_GetCurrentSize(); + return m_ViewportSize.w != size.w || m_ViewportSize.h != size.h; } static void M_RefreshRendererViewport(void) { Viewport_Reset(); + m_ViewportSize = Shell_GetCurrentSize(); } static void M_HandleFocusGained(void) @@ -201,7 +213,7 @@ static void M_HandleWindowShown(void) static void M_HandleWindowRestored(void) { - M_SyncFromWindow(); + M_SyncFromWindow(true); } static void M_HandleWindowMinimized(void) @@ -211,17 +223,17 @@ static void M_HandleWindowMinimized(void) static void M_HandleWindowMaximized(void) { - M_SyncFromWindow(); + M_SyncFromWindow(true); } static void M_HandleWindowMoved(const int32_t x, const int32_t y) { - M_SyncFromWindow(); + M_SyncFromWindow(false); } static void M_HandleWindowResized(int32_t width, int32_t height) { - M_SyncFromWindow(); + M_SyncFromWindow(true); } static void M_HandleKeyDown(const SDL_Event *const event) @@ -352,9 +364,9 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data) } if (CHANGED(window.is_fullscreen) || CHANGED(window.is_maximized) - || CHANGED(window.x) || CHANGED(window.y) || CHANGED(window.width) - || CHANGED(window.height) || CHANGED(rendering.scaler) - || CHANGED(rendering.sizer) || CHANGED(rendering.aspect_mode)) { + || CHANGED(window.width) || CHANGED(window.height) + || CHANGED(rendering.scaler) || CHANGED(rendering.sizer) + || CHANGED(rendering.aspect_mode)) { LOG_DEBUG("Change in settings detected"); M_SyncToWindow(); M_RefreshRendererViewport(); @@ -378,7 +390,11 @@ static void M_HandleConfigChange(const EVENT *const event, void *const data) } } - Output_ApplyLevelSettings(); + if (CHANGED(visuals.fog_start) || CHANGED(visuals.fog_end) + || CHANGED(visuals.water_color.g) || CHANGED(visuals.water_color.b) + || CHANGED(visuals.water_color.r)) { + Output_ApplyLevelSettings(); + } } // TODO: refactor the hell out of me @@ -562,12 +578,6 @@ void Shell_Start(void) M_RefreshRendererViewport(); } -bool Shell_IsFullscreen(void) -{ - const Uint32 flags = SDL_GetWindowFlags(g_SDLWindow); - return (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != 0; -} - // TODO: try to call this function in a single place after introducing phases. void Shell_ProcessEvents(void) { diff --git a/src/tr2/game/viewport.c b/src/tr2/game/viewport.c index 5b66ff19b..245e1c11c 100644 --- a/src/tr2/game/viewport.c +++ b/src/tr2/game/viewport.c @@ -120,14 +120,7 @@ static void M_ApplyGameVars(const VIEWPORT *const vp) void Viewport_Reset(void) { - int32_t win_width; - int32_t win_height; - if (Shell_IsFullscreen()) { - win_width = Shell_GetCurrentDisplayWidth(); - win_height = Shell_GetCurrentDisplayHeight(); - } else { - SDL_GetWindowSize(g_SDLWindow, &win_width, &win_height); - } + const SHELL_SIZE size = Shell_GetCurrentSize(); VIEWPORT *const vp = &m_Viewport; switch (g_Config.rendering.aspect_mode) { @@ -138,12 +131,12 @@ void Viewport_Reset(void) vp->render_ar = 16.0 / 9.0; break; case AM_ANY: - vp->render_ar = win_width / (double)win_height; + vp->render_ar = size.w / (double)size.h; break; } - vp->width = win_width / g_Config.rendering.scaler; - vp->height = win_height / g_Config.rendering.scaler; + vp->width = size.w / g_Config.rendering.scaler; + vp->height = size.h / g_Config.rendering.scaler; if (g_Config.rendering.aspect_mode != AM_ANY) { vp->width = vp->height * vp->render_ar; } @@ -171,9 +164,8 @@ void Viewport_Reset(void) M_InitGameVars(&m_Viewport); M_ApplyGameVars(&m_Viewport); - const int32_t win_border = win_height * (1.0 - g_Config.rendering.sizer); - Render_SetupDisplay( - win_border, win_width, win_height, vp->width, vp->height); + const int32_t win_border = size.h * (1.0 - g_Config.rendering.sizer); + Render_SetupDisplay(win_border, size.w, size.h, vp->width, vp->height); } const VIEWPORT *Viewport_Get(void)