mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2025-12-19 23:50:02 +01:00
The goal is to control the rate of capture while in screencast, as it can represent a performance issue and can cause input lag and the feeling of having a laggy mouse. This commit addresses the issue reported in #66. The code measures the time elapsed to make a single screen capture, and calculates how much to wait for the next capture to achieve the targeted frame rate. To delay the capturing of the next frame, the code introduces timers into the event loop based on the event loop in https://github.com/emersion/mako Added a command-line argument and an entry in the config file as well for the max FPS. The default value is 0, meaning no rate control. Added code to measure the average FPS every 5 seconds and print it with DEBUG level.
69 lines
1.5 KiB
C
69 lines
1.5 KiB
C
#include <poll.h>
|
|
#include <wayland-util.h>
|
|
#include <sys/timerfd.h>
|
|
|
|
#include "xdpw.h"
|
|
#include "logger.h"
|
|
#include "timespec_util.h"
|
|
|
|
static void update_timer(struct xdpw_state *state) {
|
|
int timer_fd = state->timer_poll_fd;
|
|
if (timer_fd < 0) {
|
|
return;
|
|
}
|
|
|
|
bool updated = false;
|
|
struct xdpw_timer *timer;
|
|
wl_list_for_each(timer, &state->timers, link) {
|
|
if (state->next_timer == NULL ||
|
|
timespec_less(&timer->at, &state->next_timer->at)) {
|
|
state->next_timer = timer;
|
|
updated = true;
|
|
}
|
|
}
|
|
|
|
if (updated) {
|
|
struct itimerspec delay = { .it_value = state->next_timer->at };
|
|
errno = 0;
|
|
int ret = timerfd_settime(timer_fd, TFD_TIMER_ABSTIME, &delay, NULL);
|
|
if (ret < 0) {
|
|
fprintf(stderr, "failed to timerfd_settime(): %s\n",
|
|
strerror(errno));
|
|
}
|
|
}
|
|
}
|
|
|
|
struct xdpw_timer *xdpw_add_timer(struct xdpw_state *state,
|
|
uint64_t delay_ns, xdpw_event_loop_timer_func_t func, void *data) {
|
|
struct xdpw_timer *timer = calloc(1, sizeof(struct xdpw_timer));
|
|
if (timer == NULL) {
|
|
logprint(ERROR, "Timer allocation failed");
|
|
return NULL;
|
|
}
|
|
timer->state = state;
|
|
timer->func = func;
|
|
timer->user_data = data;
|
|
wl_list_insert(&state->timers, &timer->link);
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, &timer->at);
|
|
timespec_add(&timer->at, delay_ns);
|
|
|
|
update_timer(state);
|
|
return timer;
|
|
}
|
|
|
|
void xdpw_destroy_timer(struct xdpw_timer *timer) {
|
|
if (timer == NULL) {
|
|
return;
|
|
}
|
|
struct xdpw_state *state = timer->state;
|
|
|
|
if (state->next_timer == timer) {
|
|
state->next_timer = NULL;
|
|
}
|
|
|
|
wl_list_remove(&timer->link);
|
|
free(timer);
|
|
|
|
update_timer(state);
|
|
}
|