aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_presentation_time.h20
-rw-r--r--types/scene/surface.c20
-rw-r--r--types/wlr_presentation_time.c22
3 files changed, 48 insertions, 14 deletions
diff --git a/include/wlr/types/wlr_presentation_time.h b/include/wlr/types/wlr_presentation_time.h
index 817730b3..a8df292d 100644
--- a/include/wlr/types/wlr_presentation_time.h
+++ b/include/wlr/types/wlr_presentation_time.h
@@ -33,11 +33,12 @@ struct wlr_presentation {
struct wlr_presentation_feedback {
struct wl_list resources; // wl_resource_get_link()
- // Only when the wlr_presentation_surface_sampled_on_output() helper has
- // been called.
+ // Only when the wlr_presentation_surface_textured_on_output() or
+ // wlr_presentation_surface_scanned_out_on_output() helper has been called.
struct wlr_output *output;
bool output_committed;
uint32_t output_commit_seq;
+ bool zero_copy;
struct wl_listener output_commit;
struct wl_listener output_present;
@@ -85,14 +86,23 @@ void wlr_presentation_event_from_output(struct wlr_presentation_event *event,
const struct wlr_output_event_present *output_event);
/**
- * Mark the current surface's buffer as sampled on the given output.
+ * Mark the current surface's buffer as textured on the given output.
*
* Instead of calling wlr_presentation_surface_sampled() and managing the
* struct wlr_presentation_feedback itself, the compositor can call this function
* before a wlr_output_commit() call to indicate that the surface's current
- * contents will be displayed on the output.
+ * contents have been copied to a buffer which will be displayed on the output.
*/
-void wlr_presentation_surface_sampled_on_output(
+void wlr_presentation_surface_textured_on_output(
+ struct wlr_presentation *presentation, struct wlr_surface *surface,
+ struct wlr_output *output);
+/**
+ * Mark the current surface's buffer as scanned out on the given output.
+ *
+ * Same as wlr_presentation_surface_textured_on_output(), but indicates direct
+ * scan-out.
+ */
+void wlr_presentation_surface_scanned_out_on_output(
struct wlr_presentation *presentation, struct wlr_surface *surface,
struct wlr_output *output);
diff --git a/types/scene/surface.c b/types/scene/surface.c
index afefb917..1b585e8c 100644
--- a/types/scene/surface.c
+++ b/types/scene/surface.c
@@ -42,15 +42,21 @@ static void handle_scene_buffer_output_sample(
wl_container_of(listener, surface, output_sample);
const struct wlr_scene_output_sample_event *event = data;
struct wlr_scene_output *scene_output = event->output;
+ if (surface->buffer->primary_output != scene_output) {
+ return;
+ }
- if (surface->buffer->primary_output == scene_output) {
- struct wlr_scene *root = scene_node_get_root(&surface->buffer->node);
- struct wlr_presentation *presentation = root->presentation;
+ struct wlr_scene *root = scene_node_get_root(&surface->buffer->node);
+ if (!root->presentation) {
+ return;
+ }
- if (presentation) {
- wlr_presentation_surface_sampled_on_output(
- presentation, surface->surface, scene_output->output);
- }
+ if (event->direct_scanout) {
+ wlr_presentation_surface_scanned_out_on_output(
+ root->presentation, surface->surface, scene_output->output);
+ } else {
+ wlr_presentation_surface_textured_on_output(
+ root->presentation, surface->surface, scene_output->output);
}
}
diff --git a/types/wlr_presentation_time.c b/types/wlr_presentation_time.c
index 2a6610f4..f13f3179 100644
--- a/types/wlr_presentation_time.c
+++ b/types/wlr_presentation_time.c
@@ -295,6 +295,9 @@ static void feedback_handle_output_present(struct wl_listener *listener,
if (output_event->presented) {
struct wlr_presentation_event event = {0};
wlr_presentation_event_from_output(&event, output_event);
+ if (!feedback->zero_copy) {
+ event.flags &= ~WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
+ }
wlr_presentation_feedback_send_presented(feedback, &event);
}
wlr_presentation_feedback_destroy(feedback);
@@ -307,9 +310,9 @@ static void feedback_handle_output_destroy(struct wl_listener *listener,
wlr_presentation_feedback_destroy(feedback);
}
-void wlr_presentation_surface_sampled_on_output(
+static void presentation_surface_queued_on_output(
struct wlr_presentation *presentation, struct wlr_surface *surface,
- struct wlr_output *output) {
+ struct wlr_output *output, bool zero_copy) {
struct wlr_presentation_feedback *feedback =
wlr_presentation_surface_sampled(presentation, surface);
if (feedback == NULL) {
@@ -318,6 +321,7 @@ void wlr_presentation_surface_sampled_on_output(
assert(feedback->output == NULL);
feedback->output = output;
+ feedback->zero_copy = zero_copy;
feedback->output_commit.notify = feedback_handle_output_commit;
wl_signal_add(&output->events.commit, &feedback->output_commit);
@@ -326,3 +330,17 @@ void wlr_presentation_surface_sampled_on_output(
feedback->output_destroy.notify = feedback_handle_output_destroy;
wl_signal_add(&output->events.destroy, &feedback->output_destroy);
}
+
+void wlr_presentation_surface_textured_on_output(
+ struct wlr_presentation *presentation, struct wlr_surface *surface,
+ struct wlr_output *output) {
+ return presentation_surface_queued_on_output(presentation, surface,
+ output, false);
+}
+
+void wlr_presentation_surface_scanned_out_on_output(
+ struct wlr_presentation *presentation, struct wlr_surface *surface,
+ struct wlr_output *output) {
+ return presentation_surface_queued_on_output(presentation, surface,
+ output, true);
+}