aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/drm.c15
-rw-r--r--backend/headless/output.c5
-rw-r--r--backend/wayland/output.c2
-rw-r--r--backend/x11/output.c2
-rw-r--r--include/wlr/interfaces/wlr_output.h4
-rw-r--r--include/wlr/types/wlr_output.h13
-rw-r--r--rootston/output.c2
-rw-r--r--types/wlr_output.c23
-rw-r--r--types/wlr_presentation_time.c4
9 files changed, 47 insertions, 23 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 753b6ab8..0187e5d0 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -1154,6 +1154,10 @@ void scan_drm_connectors(struct wlr_drm_backend *drm) {
attempt_enable_needs_modeset(drm);
}
+static int mhz_to_nsec(int mhz) {
+ return 1000000000000LL / mhz;
+}
+
static void page_flip_handler(int fd, unsigned seq,
unsigned tv_sec, unsigned tv_usec, void *data) {
struct wlr_drm_connector *conn = data;
@@ -1180,9 +1184,14 @@ static void page_flip_handler(int fd, unsigned seq,
.tv_sec = tv_sec,
.tv_nsec = tv_usec * 1000,
};
- uint32_t present_flags = WLR_OUTPUT_PRESENT_VSYNC |
- WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
- wlr_output_send_present(&conn->output, &present_time, seq, present_flags);
+ struct wlr_output_event_present present_event = {
+ .when = &present_time,
+ .seq = seq,
+ .refresh = mhz_to_nsec(conn->output.refresh),
+ .flags = WLR_OUTPUT_PRESENT_VSYNC | WLR_OUTPUT_PRESENT_HW_CLOCK |
+ WLR_OUTPUT_PRESENT_HW_COMPLETION,
+ };
+ wlr_output_send_present(&conn->output, &present_event);
if (drm->session->active) {
wlr_output_send_frame(&conn->output);
diff --git a/backend/headless/output.c b/backend/headless/output.c
index ad0050d8..3cb35dce 100644
--- a/backend/headless/output.c
+++ b/backend/headless/output.c
@@ -67,8 +67,9 @@ static bool output_make_current(struct wlr_output *wlr_output, int *buffer_age)
static bool output_swap_buffers(struct wlr_output *wlr_output,
pixman_region32_t *damage) {
- wlr_output_send_present(wlr_output, NULL, 0, 0);
- return true; // No-op
+ // Nothing needs to be done for pbuffers
+ wlr_output_send_present(wlr_output, NULL);
+ return true;
}
static void output_destroy(struct wlr_output *wlr_output) {
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index 4fbfe9d2..bc7a9f05 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -72,7 +72,7 @@ static bool output_swap_buffers(struct wlr_output *wlr_output,
}
// TODO: if available, use the presentation-time protocol
- wlr_output_send_present(wlr_output, NULL, 0, 0);
+ wlr_output_send_present(wlr_output, NULL);
return true;
}
diff --git a/backend/x11/output.c b/backend/x11/output.c
index 8cd8ee33..1ac12a8d 100644
--- a/backend/x11/output.c
+++ b/backend/x11/output.c
@@ -106,7 +106,7 @@ static bool output_swap_buffers(struct wlr_output *wlr_output,
return false;
}
- wlr_output_send_present(wlr_output, NULL, 0, 0);
+ wlr_output_send_present(wlr_output, NULL);
return true;
}
diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h
index b06c5db0..52581768 100644
--- a/include/wlr/interfaces/wlr_output.h
+++ b/include/wlr/interfaces/wlr_output.h
@@ -45,7 +45,7 @@ void wlr_output_update_enabled(struct wlr_output *output, bool enabled);
void wlr_output_update_needs_swap(struct wlr_output *output);
void wlr_output_damage_whole(struct wlr_output *output);
void wlr_output_send_frame(struct wlr_output *output);
-void wlr_output_send_present(struct wlr_output *output, struct timespec *when,
- unsigned seq, uint32_t flags);
+void wlr_output_send_present(struct wlr_output *output,
+ struct wlr_output_event_present *event);
#endif
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index fb3becd1..9ccfbbb5 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -130,15 +130,28 @@ struct wlr_output_event_swap_buffers {
};
enum wlr_output_present_flag {
+ // The presentation was synchronized to the "vertical retrace" by the
+ // display hardware such that tearing does not happen.
WLR_OUTPUT_PRESENT_VSYNC = 0x1,
+ // The display hardware provided measurements that the hardware driver
+ // converted into a presentation timestamp.
WLR_OUTPUT_PRESENT_HW_CLOCK = 0x2,
+ // The display hardware signalled that it started using the new image
+ // content.
WLR_OUTPUT_PRESENT_HW_COMPLETION = 0x4,
+ // The presentation of this update was done zero-copy.
+ WLR_OUTPUT_PRESENT_ZERO_COPY = 0x8,
};
struct wlr_output_event_present {
struct wlr_output *output;
+ // Time when the content update turned into light the first time.
struct timespec *when;
+ // Vertical retrace counter. Zero if unavailable.
unsigned seq;
+ // Prediction of how many nanoseconds after `when` the very next output
+ // refresh may occur. Zero if unknown.
+ int refresh; // nsec
uint32_t flags; // enum wlr_output_present_flag
};
diff --git a/rootston/output.c b/rootston/output.c
index 8168a0c3..9d376f8e 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -855,7 +855,7 @@ static void output_handle_present(struct wl_listener *listener, void *data) {
.output = output->wlr_output,
.tv_sec = (uint64_t)output_event->when->tv_sec,
.tv_nsec = (uint32_t)output_event->when->tv_nsec,
- .refresh = 0, // TODO: predict next output vsync delay
+ .refresh = (uint32_t)output_event->refresh,
.seq = (uint64_t)output_event->seq,
.flags = output_event->flags,
};
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 25cd0734..b3840415 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -561,10 +561,17 @@ void wlr_output_schedule_frame(struct wlr_output *output) {
wl_event_loop_add_idle(ev, schedule_frame_handle_idle_timer, output);
}
-void wlr_output_send_present(struct wlr_output *output, struct timespec *when,
- unsigned seq, uint32_t flags) {
+void wlr_output_send_present(struct wlr_output *output,
+ struct wlr_output_event_present *event) {
+ struct wlr_output_event_present _event = {0};
+ if (event == NULL) {
+ event = &_event;
+ }
+
+ event->output = output;
+
struct timespec now;
- if (when == NULL) {
+ if (event->when == NULL) {
clockid_t clock = wlr_backend_get_presentation_clock(output->backend);
errno = 0;
if (clock_gettime(clock, &now) != 0) {
@@ -572,16 +579,10 @@ void wlr_output_send_present(struct wlr_output *output, struct timespec *when,
"failed to read clock");
return;
}
- when = &now;
+ event->when = &now;
}
- struct wlr_output_event_present event = {
- .output = output,
- .when = when,
- .seq = seq,
- .flags = flags,
- };
- wlr_signal_emit_safe(&output->events.present, &event);
+ wlr_signal_emit_safe(&output->events.present, event);
}
bool wlr_output_set_gamma(struct wlr_output *output, size_t size,
diff --git a/types/wlr_presentation_time.c b/types/wlr_presentation_time.c
index c83b5e99..eeba47b6 100644
--- a/types/wlr_presentation_time.c
+++ b/types/wlr_presentation_time.c
@@ -42,8 +42,8 @@ static void feedback_send_presented(struct wlr_presentation_feedback *feedback,
uint32_t seq_hi = event->seq >> 32;
uint32_t seq_lo = event->seq & 0xFFFFFFFF;
wp_presentation_feedback_send_presented(feedback->resource,
- tv_sec_hi, tv_sec_lo, event->tv_nsec, event->refresh, seq_hi, seq_lo,
- event->flags);
+ tv_sec_hi, tv_sec_lo, event->tv_nsec, event->refresh,
+ seq_hi, seq_lo, event->flags);
wl_resource_destroy(feedback->resource);
}