diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 51ae5ae0..f1032169 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -92,6 +92,7 @@ struct weston_color_profile; struct weston_color_transform; struct pixel_format_info; struct weston_output_capture_info; +struct weston_tearing_control; enum weston_keyboard_modifier { MODIFIER_CTRL = (1 << 0), @@ -1733,6 +1734,8 @@ struct weston_surface { enum weston_hdcp_protection desired_protection; enum weston_hdcp_protection current_protection; enum weston_surface_protection_mode protection_mode; + + struct weston_tearing_control *tear_control; }; struct weston_subsurface { @@ -1854,6 +1857,8 @@ weston_layer_mask_is_infinite(struct weston_layer *layer); /* An invalid flag in presented_flags to catch logic errors. */ #define WP_PRESENTATION_FEEDBACK_INVALID (1U << 31) +/* Steal another bit from presented_flags for tearing */ +#define WESTON_FINISH_FRAME_TEARING (1U << 30) void weston_output_schedule_repaint(struct weston_output *output); diff --git a/libweston/compositor.c b/libweston/compositor.c index 31f7e6b2..c2533b4d 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -72,6 +72,8 @@ #include "shared/string-helpers.h" #include "shared/timespec-util.h" #include "shared/signal.h" +#include "shared/xalloc.h" +#include "tearing-control-v1-server-protocol.h" #include "git-version.h" #include #include @@ -2135,6 +2137,9 @@ weston_surface_unref(struct weston_surface *surface) fd_clear(&surface->acquire_fence_fd); + if (surface->tear_control) + surface->tear_control->surface = NULL; + free(surface); } @@ -3298,6 +3303,12 @@ weston_output_finish_frame(struct weston_output *output, output->frame_time = *stamp; + /* If we're tearing just repaint right away */ + if (presented_flags & WESTON_FINISH_FRAME_TEARING) { + output->next_repaint = now; + goto out; + } + timespec_add_nsec(&output->next_repaint, stamp, refresh_nsec); timespec_add_msec(&output->next_repaint, &output->next_repaint, -compositor->repaint_msec); @@ -7793,6 +7804,115 @@ compositor_bind(struct wl_client *client, compositor, NULL); } +static void +set_presentation_hint(struct wl_client *client, struct wl_resource *resource, uint32_t hint) +{ + struct weston_tearing_control *tc = wl_resource_get_user_data(resource); + struct weston_surface *surf = tc->surface; + + if (hint == WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC) + surf->tear_control->may_tear = true; + else + surf->tear_control->may_tear = false; +} + +static void +destroy_tearing_control(struct wl_client *client, struct wl_resource *res) +{ + struct weston_tearing_control *tc = wl_resource_get_user_data(res); + struct weston_surface *surf = tc->surface; + + if (surf) + surf->tear_control = NULL; + + wl_resource_destroy(res); +} + +static const struct wp_tearing_control_v1_interface tearing_interface = { + set_presentation_hint, + destroy_tearing_control, +}; + +static void +destroy_tearing_controller(struct wl_client *client, + struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +free_tearing_control(struct wl_resource *res) +{ + struct weston_tearing_control *tc = wl_resource_get_user_data(res); + struct weston_surface *surf = tc->surface; + + if (surf) + surf->tear_control = NULL; + + free(tc); +} + +static void +get_tearing_control(struct wl_client *client, + struct wl_resource *resource, + uint32_t id, + struct wl_resource *surface_resource) +{ + struct wl_resource *ctl_res; + struct weston_tearing_control *control; + struct weston_surface *surface; + uint32_t version; + + surface = wl_resource_get_user_data(surface_resource); + if (surface->tear_control) { + wl_resource_post_error(resource, + WP_TEARING_CONTROL_MANAGER_V1_ERROR_TEARING_CONTROL_EXISTS, + "Surface already has a tearing controller"); + return; + } + + version = wl_resource_get_version(resource); + ctl_res = wl_resource_create(client, + &wp_tearing_control_v1_interface, + version, id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + + control = xzalloc(sizeof *control); + control->may_tear = false; + control->surface = surface; + surface->tear_control = control; + wl_resource_set_implementation(ctl_res, &tearing_interface, + control, free_tearing_control); +} + +static const struct wp_tearing_control_manager_v1_interface +tearing_control_manager_implementation = { + destroy_tearing_controller, + get_tearing_control, +}; + +static void +bind_tearing_controller(struct wl_client *client, void *data, + uint32_t version, uint32_t id) +{ + struct weston_compositor *compositor = data; + struct wl_resource *resource; + + resource = wl_resource_create(client, + &wp_tearing_control_manager_v1_interface, + version, id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(resource, &tearing_control_manager_implementation, + compositor, NULL); +} + static const char * output_repaint_status_text(struct weston_output *output) { @@ -8186,6 +8306,11 @@ weston_compositor_create(struct wl_display *display, NULL, bind_single_pixel_buffer)) goto fail; + if (!wl_global_create(ec->wl_display, + &wp_tearing_control_manager_v1_interface, 1, + ec, bind_tearing_controller)) + goto fail; + if (weston_input_init(ec) != 0) goto fail; diff --git a/libweston/libweston-internal.h b/libweston/libweston-internal.h index bfdc889f..aac3c10b 100644 --- a/libweston/libweston-internal.h +++ b/libweston/libweston-internal.h @@ -105,6 +105,11 @@ struct weston_renderer { const struct pixman_renderer_interface *pixman; }; +struct weston_tearing_control { + struct weston_surface *surface; + bool may_tear; +}; + void weston_renderer_resize_output(struct weston_output *output, const struct weston_size *fb_size, diff --git a/libweston/meson.build b/libweston/meson.build index ad7d6d1d..f4143c79 100644 --- a/libweston/meson.build +++ b/libweston/meson.build @@ -53,6 +53,8 @@ srcs_libweston = [ relative_pointer_unstable_v1_server_protocol_h, single_pixel_buffer_v1_protocol_c, single_pixel_buffer_v1_server_protocol_h, + tearing_control_v1_protocol_c, + tearing_control_v1_server_protocol_h, text_cursor_position_protocol_c, text_cursor_position_server_protocol_h, text_input_unstable_v1_protocol_c,