tearing: add fullscreen options (#1941)

Co-authored-by: Consolatis <35009135+Consolatis@users.noreply.github.com>
This commit is contained in:
Jens Peters 2024-08-06 22:23:10 +02:00 committed by GitHub
parent 19f0b769de
commit 433a4509af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 105 additions and 20 deletions

View file

@ -1109,9 +1109,22 @@ actions_run(struct view *activator, struct server *server,
break;
case ACTION_TYPE_TOGGLE_TEARING:
if (view) {
view->tearing_hint = !view->tearing_hint;
wlr_log(WLR_DEBUG, "tearing %sabled",
view->tearing_hint ? "en" : "dis");
switch (view->force_tearing) {
case LAB_STATE_UNSPECIFIED:
view->force_tearing =
output_get_tearing_allowance(view->output)
? LAB_STATE_DISABLED : LAB_STATE_ENABLED;
break;
case LAB_STATE_DISABLED:
view->force_tearing = LAB_STATE_ENABLED;
break;
case LAB_STATE_ENABLED:
view->force_tearing = LAB_STATE_DISABLED;
break;
}
wlr_log(WLR_ERROR, "force tearing %sabled",
view->force_tearing == LAB_STATE_ENABLED
? "en" : "dis");
}
break;
case ACTION_TYPE_TOGGLE_SHADE:

View file

@ -772,6 +772,20 @@ set_adaptive_sync_mode(const char *str, enum adaptive_sync_mode *variable)
}
}
static void
set_tearing_mode(const char *str, enum tearing_mode *variable)
{
if (!strcasecmp(str, "fullscreen")) {
*variable = LAB_TEARING_FULLSCREEN;
} else if (!strcasecmp(str, "fullscreenForced")) {
*variable = LAB_TEARING_FULLSCREEN_FORCED;
} else if (parse_bool(str, -1) == 1) {
*variable = LAB_TEARING_ENABLED;
} else {
*variable = LAB_TEARING_DISABLED;
}
}
static void
entry(xmlNode *node, char *nodename, char *content)
{
@ -886,7 +900,7 @@ entry(xmlNode *node, char *nodename, char *content)
} else if (!strcasecmp(nodename, "adaptiveSync.core")) {
set_adaptive_sync_mode(content, &rc.adaptive_sync);
} else if (!strcasecmp(nodename, "allowTearing.core")) {
set_bool(content, &rc.allow_tearing);
set_tearing_mode(content, &rc.allow_tearing);
} else if (!strcasecmp(nodename, "reuseOutputMode.core")) {
set_bool(content, &rc.reuse_output_mode);
} else if (!strcmp(nodename, "policy.placement")) {

View file

@ -38,28 +38,50 @@ get_tearing_retry_count(struct output *output)
return refresh > 0 ? refresh / 500 : 120;
}
static bool
get_tearing_preference(struct output *output)
bool
output_get_tearing_allowance(struct output *output)
{
struct server *server = output->server;
/* Never allow tearing when disabled */
/* never allow tearing when disabled */
if (!rc.allow_tearing) {
return false;
}
/* Tearing is only allowed for the output with the active view */
if (!server->active_view || server->active_view->output != output) {
struct view *view = server->active_view;
/* tearing is only allowed for the output with the active view */
if (!view || view->output != output) {
return false;
}
/* Tearing should not have failed too many times */
/* tearing should not have failed too many times */
if (output->nr_tearing_failures >= get_tearing_retry_count(output)) {
return false;
}
/* If the active view requests tearing, or it is toggled on with action, allow it */
return server->active_view->tearing_hint;
/* allow tearing for any window when requested or forced */
if (rc.allow_tearing == LAB_TEARING_ENABLED) {
if (view->force_tearing == LAB_STATE_UNSPECIFIED) {
return view->tearing_hint;
} else {
return view->force_tearing == LAB_STATE_ENABLED;
}
}
/* remaining tearing options apply only to full-screen windows */
if (!view->fullscreen) {
return false;
}
if (view->force_tearing == LAB_STATE_UNSPECIFIED) {
/* honor the tearing hint or the fullscreen-force preference */
return view->tearing_hint ||
rc.allow_tearing == LAB_TEARING_FULLSCREEN_FORCED;
}
/* honor tearing as requested by action */
return view->force_tearing == LAB_STATE_ENABLED;
}
static void
@ -128,7 +150,7 @@ output_frame_notify(struct wl_listener *listener, void *data)
struct wlr_scene_output *scene_output = output->scene_output;
struct wlr_output_state *pending = &output->pending;
pending->tearing_page_flip = get_tearing_preference(output);
pending->tearing_page_flip = output_get_tearing_allowance(output);
bool committed =
lab_wlr_scene_output_commit(scene_output, pending);

View file

@ -15,8 +15,15 @@ set_tearing_hint(struct wl_listener *listener, void *data)
{
struct tearing_controller *controller = wl_container_of(listener, controller, set_hint);
struct view *view = view_from_wlr_surface(controller->tearing_control->surface);
if (view && controller->tearing_control->current) {
view->tearing_hint = true;
if (view) {
/*
* tearing_control->current is actually an enum:
* WP_TEARING_CONTROL_V1_PRESENTATION_HINT_VSYNC = 0
* WP_TEARING_CONTROL_V1_PRESENTATION_HINT_ASYNC = 1
*
* Using it as a bool here allows us to not ship the XML.
*/
view->tearing_hint = controller->tearing_control->current;
}
}