mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 04:04:09 +02:00
ft-screens gave KWin a frame callback for every committed screen on each tick, and the tick was an 11 ms timer set again after each run, so it slid through the display's frame and came about 85 times a second at 90 Hz: the desktop repeated a frame several times a second (judder in scrolling and video), and KWin drew every screen in one burst at a random point of vrcompositor's frame. Hidden screens got the same 90 Hz unless Frametop was paused for a game. - Ticks run on a timerfd at absolute times, once per display frame, 1 ms after the vsync (IVRSystem::GetTimeSinceLastVsync and the HMD's display frequency, read once a second), so KWin gets its callbacks early in the frame. Measured with --no-vr: 91 wakeups a second instead of about 85. On the Frame the vsync times SteamVR reports lie on a 90 Hz grid. - Each screen's callbacks come at a rate for how much of it you see (vr.cpp, UpdateAttention): every frame while focused (within 12 degrees of where your head points, a laser or the mouse on it in the last 1.5 s, carried, or typed on), 15 a second for the rest of what you see (within 60 degrees), and 1 a second when hidden, behind you, or paused. Levels rise at once and fall after 1.5 s (focused) or 0.5 s (in view). KWin draws a screen only after its callback and its apps wait for theirs, so this throttles the apps too. A screen where nothing changes costs nothing at any rate, as before. - A video in view keeps every frame: 8 commits in a row that each redraw 6% or more of the screen, at 10 a second or more, count as one (from the surface's buffer damage). - "rates F V H" / --rates set the three rates (default 0 15 1, 0 = every frame), "rates?" shows them and each screen's level, "watch S" gives everything full rate for S seconds for a remote viewer (vnc-bridge.sh renews it), and "phase MS" moves the ticks for tuning. - ft-screens' main thread runs at nice -5 after the session starts: SteamOS allows down to -8 once the soft RLIMIT_NICE is raised, and KWin waits on these ticks. It had spent nearly 3 times as long waiting to run as running. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
75 lines
3.2 KiB
C
75 lines
3.2 KiB
C
// The OpenVR side of ft-screens (vr.cpp), called from the wlroots compositor (compositor.c).
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
struct ft_dmabuf {
|
|
int width, height;
|
|
uint32_t format; // DRM_FORMAT_*
|
|
uint64_t modifier; // DRM_FORMAT_MOD_*
|
|
int n_planes;
|
|
uint32_t offset[4], stride[4];
|
|
int fd[4];
|
|
};
|
|
|
|
enum ft_event_type { FT_MOTION, FT_BUTTON, FT_SCROLL, FT_LEAVE, FT_QUIT, FT_KEY, FT_KEYBOARD_CLOSED };
|
|
|
|
struct ft_event {
|
|
enum ft_event_type type;
|
|
int screen;
|
|
double x, y; // FT_MOTION: buffer pixels from the top left
|
|
uint32_t button; // FT_BUTTON: linux BTN_*
|
|
bool pressed;
|
|
bool controller; // FT_BUTTON: from a hand controller's laser (not the 3D mouse's)
|
|
double dx, dy; // FT_SCROLL: notches (positive dy: scroll down)
|
|
uint32_t key; // FT_KEY: linux KEY_* from our keyboard (pressed: down or up)
|
|
};
|
|
|
|
bool ft_vr_init(void);
|
|
void ft_vr_shutdown(void);
|
|
// Modifiers SteamVR can import for a DRM format. Returns the count (at most max).
|
|
int ft_vr_modifiers(uint32_t format, uint64_t *out, int max);
|
|
// The screens are showing (by the visibility mode; not counting a wrist-pinned screen).
|
|
bool ft_vr_screens_shown(void);
|
|
// Frametop is paused for a VR game ("pause on"): everything is hidden, and KWin slows down.
|
|
bool ft_vr_paused(void);
|
|
// How much of a screen you see, for its frame rate (compositor.c): hidden (or out of view),
|
|
// in view, or focused (you look at it, or a laser or the mouse is on it). Focused without
|
|
// SteamVR (--no-vr) or for an unknown screen.
|
|
enum ft_attention { FT_HIDDEN, FT_IN_VIEW, FT_FOCUSED };
|
|
enum ft_attention ft_vr_screen_attention(int index);
|
|
// The display's refresh rate and the time since its last vsync, in seconds. False without
|
|
// them (no SteamVR, or the headset isn't reporting).
|
|
bool ft_vr_vsync(double *since, double *hz);
|
|
// A panel for screen `index`, width in metres, placed in a row in front of the head.
|
|
void ft_vr_screen_create(int index, double metres, int count);
|
|
void ft_vr_screen_destroy(int index);
|
|
// A spare output's panel, for floating windows (slot numbers from 1): hidden until
|
|
// ft-floatd floats a window on it and KWin has the output turned on.
|
|
void ft_vr_float_create(int index, int slot);
|
|
void ft_vr_float_output(int index, bool on);
|
|
// Show a client buffer (identified by `key`) on the screen's panel. False if SteamVR
|
|
// can't import it.
|
|
bool ft_vr_screen_present(int index, const void *key, const struct ft_dmabuf *buf);
|
|
// A buffer is going away: drop its import.
|
|
void ft_vr_forget(const void *key);
|
|
// Poll panel input and SteamVR events.
|
|
void ft_vr_poll(void (*handle)(const struct ft_event *, void *), void *data);
|
|
// Our keyboard (keyboard.cpp), for typing on screen `index`: its keys arrive as FT_KEY
|
|
// events, and FT_KEYBOARD_CLOSED when its Close key is pressed or the screens hide. False if
|
|
// it can't be shown or there's no head pose. With the Steam menu or Steam's own keyboard
|
|
// up, it waits and appears when they're gone.
|
|
bool ft_vr_keyboard_show(int index);
|
|
void ft_vr_keyboard_hide(void);
|
|
// A command from the control socket (@ft_screens); writes the reply (see vr.cpp).
|
|
void ft_vr_command(const char *command, char *reply, int reply_size);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|