steamcompmgr: Implement dynamic refresh rate based on FPS limit
Adds a mode to dynamically change the refresh rate based on the existing FPS limit.
This commit is contained in:
parent
c5ab6f388b
commit
6d2cb3073c
4 changed files with 39 additions and 0 deletions
16
src/drm.cpp
16
src/drm.cpp
|
@ -1533,3 +1533,19 @@ bool drm_set_resolution( struct drm_t *drm, int width, int height )
|
|||
|
||||
return drm_set_mode(drm, mode);
|
||||
}
|
||||
|
||||
int drm_get_default_refresh(struct drm_t *drm)
|
||||
{
|
||||
if ( drm->preferred_refresh )
|
||||
return drm->preferred_refresh;
|
||||
|
||||
if ( drm->connector && drm->connector->connector )
|
||||
{
|
||||
drmModeConnector *connector = drm->connector->connector;
|
||||
const drmModeModeInfo *mode = find_mode( connector, g_nOutputWidth, g_nOutputHeight, 0);
|
||||
if ( mode )
|
||||
return mode->vrefresh;
|
||||
}
|
||||
|
||||
return 60;
|
||||
}
|
|
@ -162,3 +162,4 @@ bool drm_set_color_gain_blend(struct drm_t *drm, float blend);
|
|||
bool drm_update_gamma_lut(struct drm_t *drm);
|
||||
|
||||
char *find_drm_node_by_devid(dev_t devid);
|
||||
int drm_get_default_refresh(struct drm_t *drm);
|
|
@ -229,6 +229,10 @@ std::mutex g_FrameLimitCommitsMutex;
|
|||
std::queue< std::shared_ptr<commit_t> > g_FrameLimitCommits;
|
||||
|
||||
static int g_nSteamCompMgrTargetFPS = 0;
|
||||
static uint64_t g_uDynamicRefreshEqualityTime = 0;
|
||||
static bool g_bDynamicRefreshEnabled = false;
|
||||
// Delay to stop modes flickering back and forth.
|
||||
static const uint64_t g_uDynamicRefreshDelay = 600'000'000; // 600ms
|
||||
|
||||
bool steamcompmgr_window_should_limit_fps( win *w )
|
||||
{
|
||||
|
@ -1714,6 +1718,18 @@ paint_all()
|
|||
const bool bOverrideCompositeHack = false;
|
||||
#endif
|
||||
|
||||
int nTargetRefresh = g_nSteamCompMgrTargetFPS && g_bDynamicRefreshEnabled && steamcompmgr_window_should_limit_fps( global_focus.focusWindow ) && !global_focus.overlayWindow
|
||||
? g_nSteamCompMgrTargetFPS
|
||||
: drm_get_default_refresh( &g_DRM );
|
||||
|
||||
uint64_t now = get_time_in_nanos();
|
||||
|
||||
if ( g_nOutputRefresh == nTargetRefresh )
|
||||
g_uDynamicRefreshEqualityTime = now;
|
||||
|
||||
if ( !BIsNested() && g_nOutputRefresh != nTargetRefresh && g_uDynamicRefreshEqualityTime + g_uDynamicRefreshDelay < now )
|
||||
drm_set_refresh( &g_DRM, nTargetRefresh );
|
||||
|
||||
bool bNeedsNearest = !g_bFilterGameWindow && composite.data.vScale[0].x != 1.0f && composite.data.vScale[0].y != 1.0f;
|
||||
|
||||
bool bNeedsComposite = BIsNested();
|
||||
|
@ -3719,6 +3735,10 @@ handle_property_notify(xwayland_ctx_t *ctx, XPropertyEvent *ev)
|
|||
{
|
||||
steamcompmgr_set_target_fps( get_prop( ctx, ctx->root, ctx->atoms.gamescopeFPSLimit, 0 ) );
|
||||
}
|
||||
if ( ev->atom == ctx->atoms.gamescopeDynamicRefresh )
|
||||
{
|
||||
g_bDynamicRefreshEnabled = !!get_prop( ctx, ctx->root, ctx->atoms.gamescopeDynamicRefresh, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -4576,6 +4596,7 @@ void init_xwayland_ctx(gamescope_xwayland_server_t *xwayland_server)
|
|||
ctx->atoms.gamescopeColorLinearGainBlend = XInternAtom( ctx->dpy, "GAMESCOPE_COLOR_LINEARGAIN_BLEND", false );
|
||||
ctx->atoms.gamescopeXWaylandModeControl = XInternAtom( ctx->dpy, "GAMESCOPE_XWAYLAND_MODE_CONTROL", false );
|
||||
ctx->atoms.gamescopeFPSLimit = XInternAtom( ctx->dpy, "GAMESCOPE_FPS_LIMIT", false );
|
||||
ctx->atoms.gamescopeDynamicRefresh = XInternAtom( ctx->dpy, "GAMESCOPE_DYNAMIC_REFRESH", false );
|
||||
|
||||
ctx->root_width = DisplayWidth(ctx->dpy, ctx->scr);
|
||||
ctx->root_height = DisplayHeight(ctx->dpy, ctx->scr);
|
||||
|
|
|
@ -123,5 +123,6 @@ struct xwayland_ctx_t
|
|||
Atom gamescopeXWaylandModeControl;
|
||||
|
||||
Atom gamescopeFPSLimit;
|
||||
Atom gamescopeDynamicRefresh;
|
||||
} atoms;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue