summaryrefslogtreecommitdiff
path: root/libweston/compositor-drm.c
diff options
context:
space:
mode:
Diffstat (limited to 'libweston/compositor-drm.c')
-rw-r--r--libweston/compositor-drm.c58
1 files changed, 42 insertions, 16 deletions
diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c
index 2a96ce4a..02d38548 100644
--- a/libweston/compositor-drm.c
+++ b/libweston/compositor-drm.c
@@ -1556,7 +1556,12 @@ drm_output_get_disable_state(struct drm_output *output)
return state;
}
-static int drm_output_apply_state(struct drm_output_state *state);
+enum drm_output_apply_state_mode {
+ DRM_OUTPUT_APPLY_STATE_TEST,
+ DRM_OUTPUT_APPLY_STATE_REAL,
+};
+static int drm_output_apply_state(struct drm_output_state *state,
+ enum drm_output_apply_state_mode mode);
/**
* Mark a drm_output_state (the output's last state) as complete. This handles
@@ -1585,7 +1590,7 @@ drm_output_update_complete(struct drm_output *output, uint32_t flags,
goto out;
} else if (output->dpms_off_pending) {
os = drm_output_get_disable_state(output);
- drm_output_apply_state(os);
+ drm_output_apply_state(os, DRM_OUTPUT_APPLY_STATE_REAL);
}
ts.tv_sec = sec;
@@ -1857,7 +1862,8 @@ drm_waitvblank_pipe(struct drm_output *output)
}
static int
-drm_output_apply_state_legacy(struct drm_output_state *state)
+drm_output_apply_state_legacy(struct drm_output_state *state,
+ enum drm_output_apply_state_mode mode)
{
struct drm_output *output = state->output;
struct drm_backend *backend = to_drm_backend(output->base.compositor);
@@ -1865,9 +1871,14 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
struct drm_plane_state *scanout_state;
struct drm_plane_state *ps;
struct drm_plane *p;
- struct drm_mode *mode;
+ struct drm_mode *display_mode;
int ret = 0;
+ /* The legacy DRM API gives us no way to test commits without actually
+ * applying them. */
+ if (mode == DRM_OUTPUT_APPLY_STATE_TEST)
+ return 0;
+
if (state->dpms != WESTON_DPMS_ON) {
wl_list_for_each(ps, &state->plane_list, link) {
p = ps->plane;
@@ -1917,7 +1928,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
assert(scanout_state->src_w == scanout_state->dest_w << 16);
assert(scanout_state->src_h == scanout_state->dest_h << 16);
- mode = to_drm_mode(output->base.current_mode);
+ display_mode = to_drm_mode(output->base.current_mode);
if (!scanout_plane->state_cur->fb ||
scanout_plane->state_cur->fb->strides[0] !=
scanout_state->fb->strides[0]) {
@@ -1925,7 +1936,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
scanout_state->fb->fb_id,
0, 0,
&output->connector_id, 1,
- &mode->mode_info);
+ &display_mode->mode_info);
if (ret) {
weston_log("set mode failed: %m\n");
goto err;
@@ -2081,14 +2092,15 @@ drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode)
}
static int
-drm_output_apply_state_atomic(struct drm_output_state *state)
+drm_output_apply_state_atomic(struct drm_output_state *state,
+ enum drm_output_apply_state_mode mode)
{
struct drm_output *output = state->output;
struct drm_backend *backend = to_drm_backend(output->base.compositor);
struct drm_plane_state *plane_state;
drmModeAtomicReq *req = drmModeAtomicAlloc();
struct drm_mode *current_mode = to_drm_mode(output->base.current_mode);
- uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
+ uint32_t flags = 0;
int ret = 0;
if (!req)
@@ -2149,7 +2161,16 @@ drm_output_apply_state_atomic(struct drm_output_state *state)
}
}
- if (drmModeAtomicCommit(backend->drm.fd, req, flags, output) != 0) {
+ if (mode == DRM_OUTPUT_APPLY_STATE_TEST)
+ flags |= DRM_MODE_ATOMIC_TEST_ONLY;
+ else
+ flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
+
+ ret = drmModeAtomicCommit(backend->drm.fd, req, flags, output);
+ if (mode == DRM_OUTPUT_APPLY_STATE_TEST)
+ return ret;
+
+ if (ret != 0) {
weston_log("couldn't commit new state: %m\n");
goto err;
}
@@ -2166,16 +2187,17 @@ err:
#endif
static int
-drm_output_apply_state(struct drm_output_state *state)
+drm_output_apply_state(struct drm_output_state *state,
+ enum drm_output_apply_state_mode mode)
{
#ifdef HAVE_DRM_ATOMIC
struct drm_backend *b = to_drm_backend(state->output->base.compositor);
if (b->atomic_modeset)
- return drm_output_apply_state_atomic(state);
+ return drm_output_apply_state_atomic(state, mode);
else
#endif
- return drm_output_apply_state_legacy(state);
+ return drm_output_apply_state_legacy(state, mode);
}
static int
@@ -2202,7 +2224,8 @@ drm_output_repaint(struct weston_output *output_base,
if (!scanout_state || !scanout_state->fb)
goto err;
- return drm_output_apply_state(output->state_pending);
+ return drm_output_apply_state(output->state_pending,
+ DRM_OUTPUT_APPLY_STATE_REAL);
err:
drm_output_state_free(output->state_pending);
@@ -2276,7 +2299,8 @@ drm_output_start_repaint_loop(struct weston_output *output_base)
drm_output_state_duplicate(output->state_cur,
DRM_OUTPUT_STATE_PRESERVE_PLANES);
- ret = drm_output_apply_state(output->state_pending);
+ ret = drm_output_apply_state(output->state_pending,
+ DRM_OUTPUT_APPLY_STATE_REAL);
if (ret != 0) {
weston_log("applying repaint-start state failed: %m\n");
goto finish_frame;
@@ -3469,7 +3493,8 @@ drm_set_dpms(struct weston_output *output_base, enum dpms_enum level)
}
output->state_pending = drm_output_get_disable_state(output);
- ret = drm_output_apply_state(output->state_pending);
+ ret = drm_output_apply_state(output->state_pending,
+ DRM_OUTPUT_APPLY_STATE_REAL);
if (ret != 0)
weston_log("drm_set_dpms: couldn't disable output?\n");
}
@@ -4286,7 +4311,8 @@ drm_output_disable(struct weston_output *base)
output->disable_pending = 0;
output->state_pending = drm_output_get_disable_state(output);
- ret = drm_output_apply_state(output->state_pending);
+ ret = drm_output_apply_state(output->state_pending,
+ DRM_OUTPUT_APPLY_STATE_REAL);
if (ret) {
weston_log("Couldn't disable output output %s\n",
output->base.name);