mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-06 13:48:21 +02:00
drm: Don't test reused states
We shouldn't need to test state, because the state that worked previously should work again. However, to be completely safe against unpredictable edge cases, we've kept a state check. Remove that check and instead force a state rebuild in the case of an application failure. Keep track of how often this happens so we can fall back to checking instead of consistently failing state application. fixes #1081 Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
This commit is contained in:
parent
fcb195cbd0
commit
4b7586ea15
3 changed files with 46 additions and 5 deletions
|
|
@ -82,6 +82,8 @@
|
|||
#define MAX_DMABUF_PLANES 4
|
||||
#endif
|
||||
|
||||
#define DRM_MAX_REUSE_FAILURES 10
|
||||
|
||||
/**
|
||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||
*
|
||||
|
|
@ -240,6 +242,8 @@ struct drm_device {
|
|||
|
||||
/* struct drm_colorop_3x1d_lut::link */
|
||||
struct wl_list drm_colorop_3x1d_lut_list;
|
||||
|
||||
int reused_state_failures;
|
||||
};
|
||||
|
||||
struct drm_backend {
|
||||
|
|
@ -664,6 +668,9 @@ struct drm_output {
|
|||
submit_frame_cb virtual_submit_frame;
|
||||
|
||||
enum wdrm_content_type content_type;
|
||||
|
||||
bool reused_state;
|
||||
bool force_rebuild_state;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -1201,6 +1201,7 @@ drm_repaint_flush_device(struct drm_device *device)
|
|||
struct drm_pending_state *pending_state;
|
||||
struct weston_output *base;
|
||||
int ret;
|
||||
bool failed_reuse = false;
|
||||
|
||||
pending_state = device->repaint_data;
|
||||
if (!pending_state)
|
||||
|
|
@ -1222,7 +1223,27 @@ drm_repaint_flush_device(struct drm_device *device)
|
|||
if (!base->will_repaint || !tmp || tmp->device != device)
|
||||
continue;
|
||||
|
||||
if (ret == -EBUSY)
|
||||
/* We shouldn't be failing at all when using a previous state,
|
||||
* and when we do it can lead to choppy frame scheduling.
|
||||
* Keep track of any failures and if we have a few, just give
|
||||
* up on ever reusing state.
|
||||
*/
|
||||
if (tmp->reused_state) {
|
||||
failed_reuse = true;
|
||||
tmp->force_rebuild_state = true;
|
||||
device->reused_state_failures++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed_reuse)
|
||||
drm_debug(b, "[repaint] failed with reused state, will rebuild and try again.\n");
|
||||
|
||||
wl_list_for_each(base, &b->compositor->output_list, link) {
|
||||
struct drm_output *tmp = to_drm_output(base);
|
||||
if (!base->will_repaint || !tmp || tmp->device != device)
|
||||
continue;
|
||||
|
||||
if (ret == -EBUSY || failed_reuse)
|
||||
weston_output_schedule_repaint_restart(base);
|
||||
else
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
|
|
|
|||
|
|
@ -1033,6 +1033,11 @@ drm_output_propose_state_try_reuse(struct weston_output *output_base,
|
|||
struct weston_paint_node *pnode;
|
||||
struct drm_output_state *state;
|
||||
|
||||
if (output->force_rebuild_state) {
|
||||
debug_propose_fail(output, mode, "previous state failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* These states are where we end up when we can't use planes
|
||||
* at all, sometimes simply because we don't have a renderer
|
||||
* fb yet. In that case we'd immediately get into a better
|
||||
|
|
@ -1139,10 +1144,13 @@ drm_output_propose_state_try_reuse(struct weston_output *output_base,
|
|||
pnode->surface->buffer_release_ref.buffer_release);
|
||||
}
|
||||
|
||||
if (drm_pending_state_test(pending_state) != 0) {
|
||||
debug_propose_fail(output, mode, "atomic test not OK");
|
||||
drm_output_state_free(state);
|
||||
return NULL;
|
||||
if (device->reused_state_failures > DRM_MAX_REUSE_FAILURES) {
|
||||
drm_debug(b, "\t\t[reuse] must test due to high number of failures\n");
|
||||
if (drm_pending_state_test(pending_state) != 0) {
|
||||
debug_propose_fail(output, mode, "atomic test not OK");
|
||||
drm_output_state_free(state);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* In any state with the renderer, we need to unreference and remove
|
||||
|
|
@ -1163,6 +1171,7 @@ drm_output_propose_state_try_reuse(struct weston_output *output_base,
|
|||
pstate->fb = NULL;
|
||||
}
|
||||
|
||||
output->reused_state = true;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
|
@ -1192,6 +1201,8 @@ drm_output_propose_state(struct weston_output *output_base,
|
|||
/* Record the current lowest zpos of the underlay plane */
|
||||
uint64_t current_lowest_zpos_underlay = DRM_PLANE_ZPOS_INVALID_PLANE;
|
||||
|
||||
output->reused_state = false;
|
||||
|
||||
if (mode & DRM_OUTPUT_PROPOSE_STATE_REUSE) {
|
||||
return drm_output_propose_state_try_reuse(output_base,
|
||||
pending_state,
|
||||
|
|
@ -1603,6 +1614,8 @@ drm_assign_planes(struct weston_output *output_base)
|
|||
assert(state);
|
||||
assert(state->planes_enabled == !output_base->disable_planes);
|
||||
|
||||
output->force_rebuild_state = false;
|
||||
|
||||
drm_debug(b, "\t[repaint] Using %s composition\n",
|
||||
drm_propose_state_mode_to_string(mode));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue