]> git.mdlowis.com Git - proto/labwc.git/commitdiff
output: allow tearing with atomic mode setting
authorChristopher Snowhill <kode54@gmail.com>
Thu, 18 Jul 2024 00:10:04 +0000 (17:10 -0700)
committerAndrew J. Hesford <ajh@sideband.org>
Sat, 20 Jul 2024 12:09:00 +0000 (08:09 -0400)
Additionally, track errors and abandon the tearing allowance when it
cannot be set for two-seconds' worth of consecutive frames.

docs/labwc-config.5.scd
include/labwc.h
src/config/rcxml.c
src/output.c

index 25e1f0cfdb533d5e24b818d8d85d20337cbad49d..746904d4821c8b0432779ed0a54cf80393e51b2a 100644 (file)
@@ -186,10 +186,13 @@ this is for compatibility with Openbox.
        mode.
 
 *<core><allowTearing>* [yes|no]
-       Allow tearing to reduce input lag. Default is no.
-       This option requires setting the environment variable
-       WLR_DRM_NO_ATOMIC=1.
-       *yes* allow tearing if requested by the active window.
+       Allow tearing, if requested by the active window, to reduce input lag.
+       Default is no.
+
+       Note: Enabling this option with atomic mode setting is experimental. If
+       you experience undesirable side effects when tearing is allowed,
+       consider setting the environment variable WLR_DRM_NO_ATOMIC=1 when
+       launching labwc.
 
 *<core><reuseOutputMode>* [yes|no]
        Try to re-use the existing output mode (resolution / refresh rate).
index 21cab83b07db688853e8f1d522a4e7d6525ec190..468da5b5a9fdba7d17f23ea8772ca1abc9c2a2d1 100644 (file)
@@ -389,6 +389,8 @@ struct output {
 
        bool leased;
        bool gamma_lut_changed;
+
+       uint32_t nr_tearing_failures;
 };
 
 #undef LAB_NR_LAYERS
index 28eff198d70ce6793cab0cb19e8bb8354c148f6c..da4bb637b75154e293978f0834e101b8c31b439e 100644 (file)
@@ -885,13 +885,6 @@ entry(xmlNode *node, char *nodename, char *content)
                set_adaptive_sync_mode(content, &rc.adaptive_sync);
        } else if (!strcasecmp(nodename, "allowTearing.core")) {
                set_bool(content, &rc.allow_tearing);
-               if (rc.allow_tearing) {
-                       char *no_atomic_env = getenv("WLR_DRM_NO_ATOMIC");
-                       if (!no_atomic_env || strcmp(no_atomic_env, "1") != 0) {
-                               rc.allow_tearing = false;
-                               wlr_log(WLR_ERROR, "tearing requires WLR_DRM_NO_ATOMIC=1");
-                       }
-               }
        } else if (!strcasecmp(nodename, "reuseOutputMode.core")) {
                set_bool(content, &rc.reuse_output_mode);
        } else if (!strcmp(nodename, "policy.placement")) {
index 8ca93c47737ac70fefec72dd0ded3c67b384d96e..8ba8225a27207316c2d588db331eab57b95fb23e 100644 (file)
 #include "view.h"
 #include "xwayland.h"
 
+static unsigned int
+get_tearing_retry_count(struct output *output)
+{
+       /* Two seconds worth of frames, guessing 60Hz if refresh is invalid */
+       int refresh = output->wlr_output->refresh;
+       return refresh > 0 ? refresh / 500 : 120;
+}
+
 static bool
 get_tearing_preference(struct output *output)
 {
@@ -45,6 +53,11 @@ get_tearing_preference(struct output *output)
                return false;
        }
 
+       /* 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;
 }
@@ -112,11 +125,27 @@ output_frame_notify(struct wl_listener *listener, void *data)
                 */
                output_apply_gamma(output);
        } else {
-               output->pending.tearing_page_flip =
-                       get_tearing_preference(output);
+               struct wlr_scene_output *scene_output = output->scene_output;
+               struct wlr_output_state *pending = &output->pending;
 
-               lab_wlr_scene_output_commit(output->scene_output,
-                       &output->pending);
+               pending->tearing_page_flip = get_tearing_preference(output);
+
+               bool committed =
+                       lab_wlr_scene_output_commit(scene_output, pending);
+
+               if (pending->tearing_page_flip) {
+                       if (committed) {
+                               output->nr_tearing_failures = 0;
+                       } else {
+                               if (++output->nr_tearing_failures >=
+                                               get_tearing_retry_count(output)) {
+                                       wlr_log(WLR_INFO, "setting tearing allowance failed "
+                                               "for two consecutive seconds, disabling");
+                               }
+                               pending->tearing_page_flip = false;
+                               lab_wlr_scene_output_commit(scene_output, pending);
+                       }
+               }
        }
 
        struct timespec now = { 0 };