wayland: dynamically report display fps

Only reports the most recently entered output if the window is displayed on
2 or more outputs. Should be changed to the lowest fps of all outputs the
window is visible. Until no one complains this will have to wait.

Look for the VO framedropping for more information on this topic.
This commit is contained in:
Alexander Preisinger 2014-08-18 22:00:39 +02:00
parent 39b8b0a41f
commit 752dce9284
2 changed files with 60 additions and 21 deletions

View File

@ -183,6 +183,7 @@ static void output_handle_mode(void *data,
output->width = width; output->width = width;
output->height = height; output->height = height;
output->flags = flags; output->flags = flags;
output->refresh_rate = refresh;
} }
static const struct wl_output_listener output_listener = { static const struct wl_output_listener output_listener = {
@ -190,6 +191,40 @@ static const struct wl_output_listener output_listener = {
output_handle_mode output_handle_mode
}; };
/* SURFACE LISTENER */
static void surface_handle_enter(void *data,
struct wl_surface *wl_surface,
struct wl_output *output)
{
struct vo_wayland_state *wl = data;
wl->display.current_output = NULL;
struct vo_wayland_output *o;
wl_list_for_each(o, &wl->display.output_list, link) {
if (o->output == output) {
wl->display.current_output = o;
break;
}
}
}
static void surface_handle_leave(void *data,
struct wl_surface *wl_surface,
struct wl_output *output)
{
// window can be displayed at 2 output, but we only use the most recently
// entered and discard the previous one even if a part of the window is
// still visible on the previous entered output.
// Don't bother with a "leave" logic
}
static const struct wl_surface_listener surface_listener = {
surface_handle_enter,
surface_handle_leave
};
/* KEYBOARD LISTENER */ /* KEYBOARD LISTENER */
static void keyboard_handle_keymap(void *data, static void keyboard_handle_keymap(void *data,
struct wl_keyboard *wl_keyboard, struct wl_keyboard *wl_keyboard,
@ -738,7 +773,7 @@ static bool create_display (struct vo_wayland_state *wl)
wl->display.registry = wl_display_get_registry(wl->display.display); wl->display.registry = wl_display_get_registry(wl->display.display);
wl_registry_add_listener(wl->display.registry, &registry_listener, wl); wl_registry_add_listener(wl->display.registry, &registry_listener, wl);
wl_display_dispatch(wl->display.display); wl_display_roundtrip(wl->display.display);
wl->display.display_fd = wl_display_get_fd(wl->display.display); wl->display.display_fd = wl_display_get_fd(wl->display.display);
@ -784,6 +819,9 @@ static bool create_window (struct vo_wayland_state *wl)
wl->window.video_surface = wl->window.video_surface =
wl_compositor_create_surface(wl->display.compositor); wl_compositor_create_surface(wl->display.compositor);
wl_surface_add_listener(wl->window.video_surface,
&surface_listener, wl);
if (wl->display.shell) { if (wl->display.shell) {
wl->window.shell_surface = wl_shell_get_shell_surface(wl->display.shell, wl->window.shell_surface = wl_shell_get_shell_surface(wl->display.shell,
wl->window.video_surface); wl->window.video_surface);
@ -1047,7 +1085,6 @@ static void vo_wayland_update_screeninfo(struct vo *vo, struct mp_rect *screenrc
{ {
struct vo_wayland_state *wl = vo->wayland; struct vo_wayland_state *wl = vo->wayland;
struct mp_vo_opts *opts = vo->opts; struct mp_vo_opts *opts = vo->opts;
bool mode_received = false;
wl_display_roundtrip(wl->display.display); wl_display_roundtrip(wl->display.display);
@ -1059,24 +1096,16 @@ static void vo_wayland_update_screeninfo(struct vo *vo, struct mp_rect *screenrc
struct vo_wayland_output *first_output = NULL; struct vo_wayland_output *first_output = NULL;
struct vo_wayland_output *fsscreen_output = NULL; struct vo_wayland_output *fsscreen_output = NULL;
wl_list_for_each_reverse(output, &wl->display.output_list, link) { if (opts->fsscreen_id >= 0) {
if (!output || !output->width) wl_list_for_each_reverse(output, &wl->display.output_list, link) {
continue; if (!output || !output->width)
continue;
mode_received = true; if (opts->fsscreen_id == screen_id)
fsscreen_output = output;
if (opts->fsscreen_id == screen_id) screen_id++;
fsscreen_output = output; }
if (!first_output)
first_output = output;
screen_id++;
}
if (!mode_received) {
MP_ERR(wl, "no output mode detected\n");
return;
} }
if (fsscreen_output) { if (fsscreen_output) {
@ -1088,8 +1117,8 @@ static void vo_wayland_update_screeninfo(struct vo *vo, struct mp_rect *screenrc
wl->display.fs_output = NULL; /* current output is always 0 */ wl->display.fs_output = NULL; /* current output is always 0 */
if (first_output) { if (first_output) {
screenrc->x1 = first_output->width; screenrc->x1 = wl->display.current_output->width;
screenrc->y1 = first_output->height; screenrc->y1 = wl->display.current_output->height;
} }
} }
@ -1138,6 +1167,15 @@ int vo_wayland_control (struct vo *vo, int *events, int request, void *arg)
case VOCTRL_UPDATE_WINDOW_TITLE: case VOCTRL_UPDATE_WINDOW_TITLE:
window_set_title(wl, (char*) arg); window_set_title(wl, (char*) arg);
return VO_TRUE; return VO_TRUE;
case VOCTRL_GET_DISPLAY_FPS: {
if (!wl->display.current_output)
break;
// refresh rate is stored in milli-Hertz (mHz)
double fps = wl->display.current_output->refresh_rate / 1000;
*(double*) arg = fps;
return VO_TRUE;
}
} }
return VO_NOTIMPL; return VO_NOTIMPL;
} }

View File

@ -41,6 +41,7 @@ struct vo_wayland_output {
uint32_t flags; uint32_t flags;
int32_t width; int32_t width;
int32_t height; int32_t height;
int32_t refresh_rate; // fps (mHz)
struct wl_list link; struct wl_list link;
}; };
@ -72,7 +73,7 @@ struct vo_wayland_state {
struct wl_list output_list; struct wl_list output_list;
struct wl_output *fs_output; /* fullscreen output */ struct wl_output *fs_output; /* fullscreen output */
int output_mode_received; struct vo_wayland_output *current_output;
int display_fd; int display_fd;