aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2019-04-29 23:25:47 +0300
committerDrew DeVault <sir@cmpwn.com>2019-06-07 09:06:11 -0400
commitafe7b207d5ff630d85c0d428ab7234f6740cfc0c (patch)
treec71798557c95174d83839fc9062298c68b219da3
parent1d222309b8ad929d01746689b30c2c78cdc12142 (diff)
output: fix attach_buffer semantics
-rw-r--r--backend/drm/drm.c66
-rw-r--r--include/backend/drm/drm.h2
-rw-r--r--include/wlr/types/wlr_output.h9
-rw-r--r--types/wlr_output.c15
4 files changed, 52 insertions, 40 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 0f548f45..37116af8 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -301,11 +301,44 @@ static bool drm_connector_commit(struct wlr_output *output) {
damage = &output->pending.damage;
}
- struct gbm_bo *bo = swap_drm_surface_buffers(&plane->surf, damage);
- if (drm->parent) {
- bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
+ struct gbm_bo *bo;
+ uint32_t fb_id = 0;
+ assert(output->pending.committed & WLR_OUTPUT_STATE_BUFFER);
+ switch (output->pending.buffer_type) {
+ case WLR_OUTPUT_STATE_BUFFER_RENDER:
+ bo = swap_drm_surface_buffers(&plane->surf, damage);
+ if (bo == NULL) {
+ wlr_log(WLR_ERROR, "swap_drm_surface_buffers failed");
+ return false;
+ }
+
+ if (drm->parent) {
+ bo = copy_drm_surface_mgpu(&plane->mgpu_surf, bo);
+ if (bo == NULL) {
+ wlr_log(WLR_ERROR, "copy_drm_surface_mgpu failed");
+ return false;
+ }
+ }
+ fb_id = get_fb_for_bo(bo, plane->drm_format);
+ if (fb_id == 0) {
+ wlr_log(WLR_ERROR, "get_fb_for_bo failed");
+ return false;
+ }
+ break;
+ case WLR_OUTPUT_STATE_BUFFER_SCANOUT:
+ bo = import_gbm_bo(&drm->renderer, &conn->pending_dmabuf);
+ if (bo == NULL) {
+ wlr_log(WLR_ERROR, "import_gbm_bo failed");
+ return false;
+ }
+
+ fb_id = get_fb_for_bo(bo, gbm_bo_get_format(bo));
+ if (fb_id == 0) {
+ wlr_log(WLR_ERROR, "get_fb_for_bo failed");
+ return false;
+ }
+ break;
}
- uint32_t fb_id = get_fb_for_bo(bo, plane->drm_format);
if (conn->pageflip_pending) {
wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
@@ -903,30 +936,7 @@ static bool drm_connector_attach_buffer(struct wlr_output *output,
}
}
- struct gbm_bo *bo = import_gbm_bo(&drm->renderer, &attribs);
- if (bo == NULL) {
- wlr_log(WLR_ERROR, "import_gbm_bo failed");
- return NULL;
- }
-
- uint32_t fb_id = get_fb_for_bo(bo, gbm_bo_get_format(bo));
- if (fb_id == 0) {
- wlr_log(WLR_ERROR, "get_fb_for_bo failed");
- return false;
- }
-
- if (conn->pageflip_pending) {
- wlr_log(WLR_ERROR, "Skipping pageflip on output '%s'", conn->output.name);
- return false;
- }
-
- if (!drm->iface->crtc_pageflip(drm, conn, crtc, fb_id, NULL)) {
- wlr_log(WLR_ERROR, "crtc_pageflip failed");
- return false;
- }
-
- conn->pageflip_pending = true;
- wlr_output_update_enabled(output, true);
+ memcpy(&conn->pending_dmabuf, &attribs, sizeof(attribs));
return true;
}
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index ba08449a..a20002b0 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -148,6 +148,8 @@ struct wlr_drm_connector {
bool pageflip_pending;
struct wl_event_source *retry_pageflip;
struct wl_list link;
+
+ struct wlr_dmabuf_attributes pending_dmabuf;
};
struct wlr_drm_backend *get_drm_backend_from_backend(
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index ffe13fb8..cd05cfb4 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -52,12 +52,21 @@ enum wlr_output_state_field {
WLR_OUTPUT_STATE_DAMAGE = 1 << 1,
};
+enum wlr_output_state_buffer_type {
+ WLR_OUTPUT_STATE_BUFFER_RENDER,
+ WLR_OUTPUT_STATE_BUFFER_SCANOUT,
+};
+
/**
* Holds the double-buffered output state.
*/
struct wlr_output_state {
uint32_t committed; // enum wlr_output_state_field
pixman_region32_t damage; // output-buffer-local coordinates
+
+ // only valid if WLR_OUTPUT_STATE_BUFFER
+ enum wlr_output_state_buffer_type buffer_type;
+ struct wlr_buffer *buffer; // if WLR_OUTPUT_STATE_BUFFER_SCANOUT
};
struct wlr_output_impl;
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 389d4c1e..941d3ce8 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -404,6 +404,7 @@ bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
}
output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
+ output->pending.buffer_type = WLR_OUTPUT_STATE_BUFFER_RENDER;
return true;
}
@@ -480,15 +481,6 @@ bool wlr_output_commit(struct wlr_output *output) {
bool wlr_output_attach_buffer(struct wlr_output *output,
struct wlr_buffer *buffer) {
- if (output->frame_pending) {
- wlr_log(WLR_ERROR, "Tried to swap buffers when a frame is pending");
- return false;
- }
- if (output->idle_frame != NULL) {
- wl_event_source_remove(output->idle_frame);
- output->idle_frame = NULL;
- }
-
if (!output->impl->attach_buffer) {
return false;
}
@@ -496,9 +488,8 @@ bool wlr_output_attach_buffer(struct wlr_output *output,
return false;
}
- output->frame_pending = true;
- output->needs_frame = false;
- pixman_region32_clear(&output->damage);
+ output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
+ output->pending.buffer_type = WLR_OUTPUT_STATE_BUFFER_SCANOUT;
return true;
}