diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 2fa7463a..9396ebae 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -34,6 +34,12 @@ enum adaptive_sync_mode { LAB_ADAPTIVE_SYNC_FULLSCREEN, }; +enum tearing_mode { + LAB_TEARING_DISABLED, + LAB_TEARING_ENABLED, + LAB_TEARING_FULLSCREEN, +}; + struct usable_area_override { struct border margin; char *output; @@ -53,6 +59,7 @@ struct rcxml { bool xdg_shell_server_side_deco; int gap; enum adaptive_sync_mode adaptive_sync; + enum tearing_mode allow_tearing; bool reuse_output_mode; enum view_placement_policy placement_policy; diff --git a/include/labwc.h b/include/labwc.h index 88dfbec5..74bd3fe9 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -357,6 +357,7 @@ struct output { bool leased; bool gamma_lut_changed; + bool tearing; }; #undef LAB_NR_LAYERS diff --git a/src/config/rcxml.c b/src/config/rcxml.c index f1a9c110..5aa2b693 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -625,6 +625,26 @@ 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 { + int ret = parse_bool(str, -1); + if (ret == 1) { + *variable = LAB_TEARING_ENABLED; + } else { + *variable = LAB_TEARING_DISABLED; + } + } + if (*variable != LAB_TEARING_DISABLED && + strcmp(getenv("WLR_DRM_NO_ATOMIC"), "1")) { + *variable = LAB_TEARING_DISABLED; + wlr_log(WLR_INFO, "WLR_DRM_NO_ATOMIC is not 1, tearing disabled"); + } +} + static void entry(xmlNode *node, char *nodename, char *content) { @@ -727,6 +747,8 @@ entry(xmlNode *node, char *nodename, char *content) rc.gap = atoi(content); } else if (!strcasecmp(nodename, "adaptiveSync.core")) { set_adaptive_sync_mode(content, &rc.adaptive_sync); + } else if (!strcasecmp(nodename, "allowTearing.core")) { + 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")) { diff --git a/src/output.c b/src/output.c index 7f2f5520..8103eea6 100644 --- a/src/output.c +++ b/src/output.c @@ -68,7 +68,11 @@ output_frame_notify(struct wl_listener *listener, void *data) return; } - wlr_scene_output_commit(output->scene_output, NULL); + if (output->tearing) { + output->wlr_output->pending.tearing_page_flip = true; + } + + lab_wlr_scene_output_commit(output->scene_output); struct timespec now = { 0 }; clock_gettime(CLOCK_MONOTONIC, &now); @@ -273,6 +277,12 @@ new_output_notify(struct wl_listener *listener, void *data) wl_list_init(&output->regions); + if (rc.allow_tearing == LAB_TEARING_ENABLED) { + output->tearing = true; + } else { + output->tearing = false; + } + /* * Create layer-trees (background, bottom, top and overlay) and * a layer-popup-tree. diff --git a/src/view.c b/src/view.c index f0562f9f..15c6256e 100644 --- a/src/view.c +++ b/src/view.c @@ -273,6 +273,16 @@ set_adaptive_sync_fullscreen(struct view *view) wlr_output_commit(view->output->wlr_output); } +static void +set_tearing_fullscreen(struct view *view) +{ + if (rc.allow_tearing != LAB_TEARING_FULLSCREEN) { + return; + } + /* Enable tearing if view is fullscreen */ + view->output->tearing = view->fullscreen; +} + void view_set_activated(struct view *view, bool activated) { @@ -297,6 +307,7 @@ view_set_activated(struct view *view, bool activated) } } set_adaptive_sync_fullscreen(view); + set_tearing_fullscreen(view); } void @@ -1199,6 +1210,7 @@ view_set_fullscreen(struct view *view, bool fullscreen) view_apply_special_geometry(view); } set_adaptive_sync_fullscreen(view); + set_tearing_fullscreen(view); } void @@ -1869,6 +1881,9 @@ view_destroy(struct view *view) if (rc.adaptive_sync == LAB_ADAPTIVE_SYNC_FULLSCREEN) { wlr_output_enable_adaptive_sync(view->output->wlr_output, false); } + if (rc.allow_tearing == LAB_TEARING_FULLSCREEN) { + view->output->tearing = false; + } } /* If we spawned a window menu, close it */