Skip to content

Instantly share code, notes, and snippets.

@rhoot

rhoot/sway.patch Secret

Last active September 4, 2023 16:58
Show Gist options
  • Save rhoot/dcead8b195054387c067919fef499c5c to your computer and use it in GitHub Desktop.
Save rhoot/dcead8b195054387c067919fef499c5c to your computer and use it in GitHub Desktop.
Sway VRR cursor
diff --git a/include/sway/output.h b/include/sway/output.h
index 50d90d25..6e9f7aef 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -8,6 +8,7 @@
#include "config.h"
#include "sway/tree/node.h"
#include "sway/tree/view.h"
+#include <pixman.h>
struct sway_server;
struct sway_container;
@@ -58,6 +59,7 @@ struct sway_output {
int max_render_time; // In milliseconds
struct wl_event_source *repaint_timer;
bool gamma_lut_changed;
+ pixman_region32_t cursor_damage;
};
struct sway_output_non_desktop {
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 476bfd25..759e9cab 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -571,6 +571,9 @@ static int output_repaint_timer_handler(void *data) {
return 0;
}
+ wlr_damage_ring_add(&output->damage_ring, &output->cursor_damage);
+ pixman_region32_clear(&output->cursor_damage);
+
struct sway_workspace *workspace = output->current.active_workspace;
if (workspace == NULL) {
return 0;
@@ -601,7 +604,17 @@ static int output_repaint_timer_handler(void *data) {
pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
get_frame_damage(output, &pending.damage);
- if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
+ const bool adaptive_sync = output->wlr_output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
+ const bool has_fullscreen_view = fullscreen_con && fullscreen_con->view;
+ const bool no_cursor_move_frames = output->wlr_output->no_frames_for_cursor_moves;
+
+ if (has_fullscreen_view && adaptive_sync && !no_cursor_move_frames) {
+ output->wlr_output->no_frames_for_cursor_moves = true;
+ } else if ((!has_fullscreen_view || !adaptive_sync) && no_cursor_move_frames) {
+ output->wlr_output->no_frames_for_cursor_moves = false;
+ }
+
+ if (has_fullscreen_view && !debug.noscanout) {
// Try to scan-out the fullscreen view
static bool last_scanned_out = false;
bool scanned_out =
@@ -688,9 +701,19 @@ static void handle_damage(struct wl_listener *listener, void *user_data) {
struct sway_output *output =
wl_container_of(listener, output, damage);
struct wlr_output_event_damage *event = user_data;
- if (wlr_damage_ring_add(&output->damage_ring, event->damage)) {
- wlr_output_schedule_frame(output->wlr_output);
+
+ pixman_region32_t clipped;
+ pixman_region32_init(&clipped);
+ pixman_region32_intersect_rect(&clipped, event->damage,
+ 0, 0, output->damage_ring.width, output->damage_ring.height);
+ bool intersects = pixman_region32_not_empty(&clipped);
+ if (intersects) {
+ pixman_region32_union(&output->cursor_damage, &output->cursor_damage, &clipped);
+ if (!output->wlr_output->no_frames_for_cursor_moves) {
+ wlr_output_schedule_frame(output->wlr_output);
+ }
}
+ pixman_region32_fini(&clipped);
}
static void handle_frame(struct wl_listener *listener, void *user_data) {
diff --git a/sway/tree/output.c b/sway/tree/output.c
index eccab2f7..626d81a3 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -94,6 +94,7 @@ struct sway_output *output_create(struct wlr_output *wlr_output) {
wlr_output->data = output;
output->detected_subpixel = wlr_output->subpixel;
output->scale_filter = SCALE_FILTER_NEAREST;
+ pixman_region32_init(&output->cursor_damage);
wl_signal_init(&output->events.disable);
@@ -241,6 +242,7 @@ void output_destroy(struct sway_output *output) {
list_free(output->workspaces);
list_free(output->current.workspaces);
wl_event_source_remove(output->repaint_timer);
+ pixman_region32_fini(&output->cursor_damage);
free(output);
}
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index a4853ffa..9ede73bf 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -976,7 +976,8 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
conn->cursor_height = buffer->height;
}
- wlr_output_update_needs_frame(output);
+ if (!output->no_frames_for_cursor_moves)
+ wlr_output_update_needs_frame(output);
return true;
}
@@ -1006,7 +1007,8 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
conn->cursor_x = box.x;
conn->cursor_y = box.y;
- wlr_output_update_needs_frame(output);
+ if (!output->no_frames_for_cursor_moves)
+ wlr_output_update_needs_frame(output);
return true;
}
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index aa3d7a18..8e321dae 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -148,6 +148,7 @@ struct wlr_output {
// damage for cursors and fullscreen surface, in output-local coordinates
bool frame_pending;
float transform_matrix[9];
+ bool no_frames_for_cursor_moves;
// true for example with VR headsets
bool non_desktop;
@czak
Copy link

czak commented Sep 4, 2023

Oh thanks for the tip! I was directed to these patches somewhere and wasn't aware there's other work going on.

@GrabbenD
Copy link

GrabbenD commented Sep 4, 2023

Glad to help
Also make sure to try it without direct scanout, made a huge difference for me
swaywm/sway#7714 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment