diff options
Diffstat (limited to 'libweston/compositor-drm.c')
-rw-r--r-- | libweston/compositor-drm.c | 58 |
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); |