diff --git a/src/Utils/Process.cpp b/src/Utils/Process.cpp index f5191af..434d7f4 100644 --- a/src/Utils/Process.cpp +++ b/src/Utils/Process.cpp @@ -423,9 +423,7 @@ namespace gamescope::Process void SetNice( int nNice ) { #if defined(__linux__) - if ( !HasCapSysNice() ) - return; - + // Try regardless of CAP_SYS_NICE — succeeds if RLIMIT_NICE permits. errno = 0; int nOldNice = nice( 0 ); if ( nOldNice != -1 || errno == 0 ) @@ -494,9 +492,7 @@ namespace gamescope::Process bool SetRealtime() { #if defined(__linux__) - if ( !HasCapSysNice() ) - return false; - + // Try regardless of CAP_SYS_NICE — succeeds if RLIMIT_RTPRIO permits. g_oOldSchedulerInfo = SchedulerInfo::Get(); if ( !g_oOldSchedulerInfo ) return false; diff --git a/src/main.cpp b/src/main.cpp index 1397028..bffdbdc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -171,7 +171,7 @@ const char usage[] = " -h, --nested-height game height\n" " -r, --nested-refresh game refresh rate (frames per second)\n" " -m, --max-scale maximum scale factor\n" - " -S, --scaler upscaler type (auto, integer, fit, fill, stretch)\n" + " -S, --scaler upscaler type (auto, integer, fit, fill, stretch, stretch_aspect)\n" " -F, --filter upscaler filter (linear, nearest, fsr, nis, pixel)\n" " fsr => AMD FidelityFX™ Super Resolution 1.0\n" " nis => NVIDIA Image Scaling v1.0.3\n" @@ -392,6 +392,8 @@ static enum GamescopeUpscaleScaler parse_upscaler_scaler(const char *str) return GamescopeUpscaleScaler::FILL; } else if (strcmp(str, "stretch") == 0) { return GamescopeUpscaleScaler::STRETCH; + } else if (strcmp(str, "stretch_aspect") == 0) { + return GamescopeUpscaleScaler::STRETCH_ASPECT; } else { fprintf( stderr, "gamescope: invalid value for --scaler\n" ); exit(1); @@ -843,16 +845,12 @@ int main(int argc, char **argv) } } - if ( gamescope::Process::HasCapSysNice() ) + // Try elevating priority unconditionally; the calls succeed when either + // CAP_SYS_NICE is set or RLIMIT_NICE/RTPRIO permit it (PAM loginLimits). + gamescope::Process::SetNice( -20 ); + if ( g_bRt && !gamescope::Process::SetRealtime() && !gamescope::Process::HasCapSysNice() ) { - gamescope::Process::SetNice( -20 ); - - if ( g_bRt ) - gamescope::Process::SetRealtime(); - } - else - { - fprintf( stderr, "No CAP_SYS_NICE, falling back to regular-priority compute and threads.\nPerformance will be affected.\n" ); + fprintf( stderr, "Failed to set realtime scheduling. Need CAP_SYS_NICE or RLIMIT_RTPRIO > 0.\n" ); } #if 0 diff --git a/src/main.hpp b/src/main.hpp index 2e6fb83..89d6bc9 100644 --- a/src/main.hpp +++ b/src/main.hpp @@ -54,6 +54,7 @@ enum class GamescopeUpscaleScaler : uint32_t FIT, FILL, STRETCH, + STRETCH_ASPECT, }; extern GamescopeUpscaleFilter g_upscaleFilter; diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp index 0518950..2f5db9f 100644 --- a/src/steamcompmgr.cpp +++ b/src/steamcompmgr.cpp @@ -1508,6 +1508,31 @@ window_is_fullscreen( steamcompmgr_win_t *w ) void calc_scale_factor_scaler(float &out_scale_x, float &out_scale_y, float sourceWidth, float sourceHeight) { + // Stretches source to a sub-rect of the output that matches the -W/-H aspect ratio, + // pillar/letterboxing the rest. Useful for e.g. 4:3-stretched on a 21:9 panel. + // Uses g_nPreferredOutput{Width,Height} (the user-supplied -W/-H, never mutated) + // rather than g_nOutput{Width,Height} (which backends overwrite on resize/fullscreen). + extern int g_nPreferredOutputWidth; + extern int g_nPreferredOutputHeight; + if (g_upscaleScaler == GamescopeUpscaleScaler::STRETCH_ASPECT + && g_nPreferredOutputWidth > 0 && g_nPreferredOutputHeight > 0 + && currentOutputWidth > 0 && currentOutputHeight > 0) + { + float targetAspect = (float)g_nPreferredOutputWidth / (float)g_nPreferredOutputHeight; + float currentAspect = (float)currentOutputWidth / (float)currentOutputHeight; + float effW, effH; + if (currentAspect > targetAspect) { + effH = (float)currentOutputHeight; + effW = effH * targetAspect; + } else { + effW = (float)currentOutputWidth; + effH = effW / targetAspect; + } + out_scale_x = effW / sourceWidth; + out_scale_y = effH / sourceHeight; + return; + } + float XOutputRatio = currentOutputWidth / (float)g_nNestedWidth; float YOutputRatio = currentOutputHeight / (float)g_nNestedHeight; float outputScaleRatio = std::min(XOutputRatio, YOutputRatio);