summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2016-12-08 17:27:17 +0000
committerDaniel Stone <daniels@collabora.com>2017-02-07 19:16:33 +0000
commit6e4a1d74c053129748593cee84331476ebdcfd6e (patch)
treeb9a310d1d5cc2a7f74749d1c5ef0ba23a5953c58
parentf03d54fb8a20cb6e91d7c07f0fc38cc494caa221 (diff)
compositor-drm: Add test-only mode to state application
The atomic API can allow us to test state before we apply it, to see if it will be valid. Add support for this, which we will later use in assign_planes to ensure our plane configuration is valid. Signed-off-by: Daniel Stone <daniels@collabora.com> Differential Revision: https://phabricator.freedesktop.org/D1533
-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);