libweston: Add support for tearing-control

Add core support for tearing control.

Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
Derek Foreman 2022-11-24 14:05:28 -06:00
parent 030edb5c48
commit 974a707add
4 changed files with 137 additions and 0 deletions

View File

@ -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);

View File

@ -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 <libweston/version.h>
#include <libweston/plugin-registry.h>
@ -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;

View File

@ -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,

View File

@ -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,