mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-11-16 19:47:55 +01:00
Add option to set timeout for liftoff_output_apply()
The default limit of 1ms might be too short if the compositor calls liftoff_output_apply() early in the vblank cycle, or too long if the refresh rate is high. The compositor is in a better spot to decide how much time should be spent on atomic tests, so add an option for that. Closes: https://gitlab.freedesktop.org/emersion/libliftoff/-/issues/78
This commit is contained in:
parent
c63676eda7
commit
35c06e8995
12 changed files with 43 additions and 21 deletions
22
alloc.c
22
alloc.c
|
@ -79,6 +79,7 @@ struct alloc_result {
|
|||
int best_score;
|
||||
|
||||
struct timespec started_at;
|
||||
int64_t timeout_ns;
|
||||
|
||||
/* per-output */
|
||||
bool has_composition_layer;
|
||||
|
@ -108,10 +109,10 @@ timespec_to_nsec(struct timespec ts)
|
|||
return (int64_t)ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
|
||||
}
|
||||
|
||||
static const int64_t ALLOC_TIMEOUT_NSEC = 1000 * 1000; // 1ms
|
||||
static const int64_t DEFAULT_ALLOC_TIMEOUT_NSEC = 1000 * 1000; // 1ms
|
||||
|
||||
static bool
|
||||
check_deadline(struct timespec start)
|
||||
check_deadline(struct timespec start, int64_t timeout_ns)
|
||||
{
|
||||
struct timespec now;
|
||||
int64_t deadline;
|
||||
|
@ -121,7 +122,7 @@ check_deadline(struct timespec start)
|
|||
return false;
|
||||
}
|
||||
|
||||
deadline = timespec_to_nsec(start) + ALLOC_TIMEOUT_NSEC;
|
||||
deadline = timespec_to_nsec(start) + timeout_ns;
|
||||
return timespec_to_nsec(now) < deadline;
|
||||
}
|
||||
|
||||
|
@ -478,7 +479,7 @@ output_choose_layers(struct liftoff_output *output, struct alloc_result *result,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!check_deadline(result->started_at)) {
|
||||
if (!check_deadline(result->started_at, result->timeout_ns)) {
|
||||
liftoff_log(LIFTOFF_DEBUG, "%s Deadline exceeded",
|
||||
step->log_prefix);
|
||||
break;
|
||||
|
@ -887,17 +888,23 @@ non_composition_layers_length(struct liftoff_output *output)
|
|||
|
||||
int
|
||||
liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
const struct liftoff_output_apply_options *options)
|
||||
{
|
||||
struct liftoff_device *device;
|
||||
struct liftoff_plane *plane;
|
||||
struct liftoff_layer *layer;
|
||||
struct alloc_result result = {0};
|
||||
struct alloc_step step = {0};
|
||||
const struct liftoff_output_apply_options default_options = {0};
|
||||
size_t i, candidate_planes;
|
||||
int ret;
|
||||
bool found_layer;
|
||||
|
||||
if (options == NULL) {
|
||||
options = &default_options;
|
||||
}
|
||||
|
||||
device = output->device;
|
||||
|
||||
update_layers_priority(device);
|
||||
|
@ -960,6 +967,11 @@ liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
|
|||
return -errno;
|
||||
}
|
||||
|
||||
result.timeout_ns = options->timeout_ns;
|
||||
if (result.timeout_ns == 0) {
|
||||
result.timeout_ns = DEFAULT_ALLOC_TIMEOUT_NSEC;
|
||||
}
|
||||
|
||||
/* For each plane, try to find a layer. Don't do it the other
|
||||
* way around (ie. for each layer, try to find a plane) because
|
||||
* some drivers want user-space to enable the primary plane
|
||||
|
|
|
@ -195,7 +195,7 @@ main(int argc, char *argv[])
|
|||
|
||||
flags = DRM_MODE_ATOMIC_NONBLOCK;
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, flags);
|
||||
ret = liftoff_output_apply(output, req, flags, NULL);
|
||||
if (ret != 0) {
|
||||
perror("liftoff_output_apply");
|
||||
return 1;
|
||||
|
|
|
@ -114,7 +114,7 @@ draw(void)
|
|||
|
||||
flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT;
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, flags);
|
||||
ret = liftoff_output_apply(output, req, flags, NULL);
|
||||
if (ret != 0) {
|
||||
perror("liftoff_output_apply");
|
||||
return false;
|
||||
|
|
|
@ -157,7 +157,7 @@ main(int argc, char *argv[])
|
|||
flags = DRM_MODE_ATOMIC_NONBLOCK;
|
||||
req = drmModeAtomicAlloc();
|
||||
for (i = 0; i < outputs_len; i++) {
|
||||
ret = liftoff_output_apply(outputs[i], req, flags);
|
||||
ret = liftoff_output_apply(outputs[i], req, flags, NULL);
|
||||
if (ret != 0) {
|
||||
perror("liftoff_output_apply");
|
||||
return 1;
|
||||
|
|
|
@ -130,7 +130,7 @@ main(int argc, char *argv[])
|
|||
|
||||
flags = DRM_MODE_ATOMIC_NONBLOCK;
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, flags);
|
||||
ret = liftoff_output_apply(output, req, flags, NULL);
|
||||
if (ret != 0) {
|
||||
perror("liftoff_output_apply");
|
||||
return 1;
|
||||
|
|
|
@ -62,19 +62,29 @@ liftoff_plane_destroy(struct liftoff_plane *plane);
|
|||
uint32_t
|
||||
liftoff_plane_get_id(struct liftoff_plane *plane);
|
||||
|
||||
/**
|
||||
* Options for liftoff_output_apply().
|
||||
*/
|
||||
struct liftoff_output_apply_options {
|
||||
/* Timeout in nanoseconds. If zero, a default timeout is used. */
|
||||
int64_t timeout_ns;
|
||||
};
|
||||
|
||||
/**
|
||||
* Build a layer to plane mapping and append the plane configuration to req.
|
||||
*
|
||||
* Callers are expected to commit req afterwards and can figure out which
|
||||
* layers need composition via liftoff_layer_needs_composition().
|
||||
*
|
||||
* flags is the atomic commit flags the caller intends to use.
|
||||
* flags is the atomic commit flags the caller intends to use. If options is
|
||||
* NULL, defaults are used.
|
||||
*
|
||||
* Zero is returned on success, negative errno on error.
|
||||
*/
|
||||
int
|
||||
liftoff_output_apply(struct liftoff_output *output, drmModeAtomicReq *req,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
const struct liftoff_output_apply_options *options);
|
||||
|
||||
/**
|
||||
* Make the device manage a CRTC's planes.
|
||||
|
|
|
@ -104,7 +104,7 @@ main(int argc, char *argv[])
|
|||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
drmModeAtomicFree(req);
|
||||
|
||||
|
|
|
@ -803,7 +803,7 @@ run_test(const struct test_case *test)
|
|||
}
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
@ -875,7 +875,7 @@ test_basic(void)
|
|||
liftoff_mock_plane_add_compatible_layer(mock_plane, layer);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
@ -913,7 +913,7 @@ test_no_props_fail(void)
|
|||
liftoff_mock_plane_add_compatible_layer(mock_plane, layer);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
@ -959,7 +959,7 @@ test_composition_no_props(void)
|
|||
liftoff_mock_plane_add_compatible_layer(mock_plane, layer_with_fb);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
|
|
@ -60,7 +60,7 @@ test_basic(void)
|
|||
liftoff_layer_set_property(layer, "COLOR_RANGE", 0);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
|
|
@ -50,7 +50,7 @@ first_commit(struct context *ctx)
|
|||
assert(ctx->commit_count == 0);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(ctx->output, req, 0);
|
||||
ret = liftoff_output_apply(ctx->output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(ctx->drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
@ -72,7 +72,7 @@ second_commit(struct context *ctx, bool want_reuse_prev_alloc)
|
|||
int ret;
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(ctx->output, req, 0);
|
||||
ret = liftoff_output_apply(ctx->output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
if (want_reuse_prev_alloc) {
|
||||
/* The library should perform only one TEST_ONLY commit with the
|
||||
|
|
|
@ -76,7 +76,7 @@ main(int argc, char *argv[])
|
|||
|
||||
liftoff_layer_set_property(layer, "FB_ID", fbs[j % 2]);
|
||||
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
|
|
@ -34,7 +34,7 @@ commit(int drm_fd, struct liftoff_output *output)
|
|||
int ret;
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
ret = liftoff_output_apply(output, req, 0);
|
||||
ret = liftoff_output_apply(output, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
ret = drmModeAtomicCommit(drm_fd, req, 0, NULL);
|
||||
assert(ret == 0);
|
||||
|
|
Loading…
Reference in a new issue