aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2019-05-04 12:07:37 +0300
committerDrew DeVault <sir@cmpwn.com>2019-06-07 09:06:11 -0400
commit44ba603c0ef5ee05e89e7021c7df8061b3d5f56b (patch)
tree2ed839b37da289a1d5cb1985bc1dff1190020580
parentff6b352d754cd19fc33b87fbc3d9d524f6484e35 (diff)
backend/drm: hold buffers while scanning out
-rw-r--r--backend/drm/drm.c30
-rw-r--r--include/backend/drm/drm.h5
2 files changed, 30 insertions, 5 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 37116af8..70a1edde 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -350,6 +350,11 @@ static bool drm_connector_commit(struct wlr_output *output) {
}
conn->pageflip_pending = true;
+ if (output->pending.buffer_type == WLR_OUTPUT_STATE_BUFFER_SCANOUT) {
+ wlr_buffer_unref(conn->pending_buffer);
+ conn->pending_buffer = wlr_buffer_ref(output->pending.buffer);
+ }
+
wlr_output_update_enabled(output, true);
return true;
}
@@ -1440,9 +1445,21 @@ static void page_flip_handler(int fd, unsigned seq,
return;
}
- post_drm_surface(&conn->crtc->primary->surf);
- if (drm->parent) {
- post_drm_surface(&conn->crtc->primary->mgpu_surf);
+ // Release the old buffer as it's not displayed anymore. The pending
+ // buffer becomes the current buffer.
+ wlr_buffer_unref(conn->current_buffer);
+ conn->current_buffer = conn->pending_buffer;
+ conn->pending_buffer = NULL;
+
+ uint32_t present_flags = WLR_OUTPUT_PRESENT_VSYNC |
+ WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
+ if (conn->current_buffer != NULL) {
+ present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY;
+ } else {
+ post_drm_surface(&conn->crtc->primary->surf);
+ if (drm->parent) {
+ post_drm_surface(&conn->crtc->primary->mgpu_surf);
+ }
}
struct timespec present_time = {
@@ -1453,8 +1470,7 @@ static void page_flip_handler(int fd, unsigned seq,
.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,
+ .flags = present_flags,
};
wlr_output_send_present(&conn->output, &present_event);
@@ -1559,6 +1575,10 @@ static void drm_connector_cleanup(struct wlr_drm_connector *conn) {
conn->output.needs_frame = false;
conn->output.frame_pending = false;
+ wlr_buffer_unref(conn->pending_buffer);
+ wlr_buffer_unref(conn->current_buffer);
+ conn->pending_buffer = conn->current_buffer = NULL;
+
/* Fallthrough */
case WLR_DRM_CONN_NEEDS_MODESET:
wlr_log(WLR_INFO, "Emitting destruction signal for '%s'",
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index a20002b0..3821c358 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -149,7 +149,12 @@ struct wlr_drm_connector {
struct wl_event_source *retry_pageflip;
struct wl_list link;
+ // DMA-BUF to be displayed on next commit
struct wlr_dmabuf_attributes pending_dmabuf;
+ // Buffer submitted to the kernel but not yet displayed
+ struct wlr_buffer *pending_buffer;
+ // Buffer currently being displayed
+ struct wlr_buffer *current_buffer;
};
struct wlr_drm_backend *get_drm_backend_from_backend(