aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIsaac Freund <mail@isaacfreund.com>2021-12-11 12:25:53 +0100
committerSimon Ser <contact@emersion.fr>2021-12-13 15:21:05 +0000
commitfb1f613510b871bcc117179a9d3a32aabc4508c0 (patch)
treeb0d41204945e23fb6615bf431f353b92351f65dd
parent0215dffba51b63dc394ee028039ac811e1330c60 (diff)
scene: add primary output to wlr_scene_surface
This allows compositors to avoid sending multiple frame done events to a surface that is rendered on multiple outputs at once. This may also be used in the same way for presentation feedback.
-rw-r--r--include/wlr/types/wlr_scene.h8
-rw-r--r--types/scene/wlr_scene.c13
2 files changed, 19 insertions, 2 deletions
diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h
index 1238653d..6c2928ee 100644
--- a/include/wlr/types/wlr_scene.h
+++ b/include/wlr/types/wlr_scene.h
@@ -74,6 +74,14 @@ struct wlr_scene_surface {
struct wlr_scene_node node;
struct wlr_surface *surface;
+ /**
+ * The output that the largest area of this surface is displayed on.
+ * This may be NULL if the surface is not currently displayed on any
+ * outputs. This is the output that should be used for frame callbacks,
+ * presentation feedback, etc.
+ */
+ struct wlr_output *primary_output;
+
// private state
int prev_width, prev_height;
diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c
index d2f3f4a7..42697074 100644
--- a/types/scene/wlr_scene.c
+++ b/types/scene/wlr_scene.c
@@ -175,6 +175,9 @@ static void scene_surface_update_outputs(
.height = scene_surface->surface->current.height,
};
+ int largest_overlap = 0;
+ scene_surface->primary_output = NULL;
+
struct wlr_scene_output *scene_output;
wl_list_for_each(scene_output, &scene->outputs, link) {
struct wlr_box output_box = {
@@ -184,10 +187,16 @@ static void scene_surface_update_outputs(
wlr_output_effective_resolution(scene_output->output,
&output_box.width, &output_box.height);
- // These enter/leave functions are a noop if the event has already been
- // sent for the given output.
struct wlr_box intersection;
if (wlr_box_intersection(&intersection, &surface_box, &output_box)) {
+ int overlap = intersection.width * intersection.height;
+ if (overlap > largest_overlap) {
+ largest_overlap = overlap;
+ scene_surface->primary_output = scene_output->output;
+ }
+
+ // These enter/leave functions are a noop if the event has already been
+ // sent for the given output.
wlr_surface_send_enter(scene_surface->surface, scene_output->output);
} else {
wlr_surface_send_leave(scene_surface->surface, scene_output->output);