diff --git a/doc/compositor.md b/doc/compositor.md index 5cf2312..2a3fcc1 100644 --- a/doc/compositor.md +++ b/doc/compositor.md @@ -84,7 +84,7 @@ used to tell libliftoff that composition will happen on this special layer. If all regular layers can be put into a plane, the composition layer won't be used. Otherwise, the compositor needs to perform the composition prior to performing a page-flip. Each layer that didn't make it into a hardware plane -(ie. `liftoff_layer_get_plane` returns NULL) needs to be composited. +(ie. `liftoff_layer_needs_composition` returns true) needs to be composited. ## Disabling layers diff --git a/example/compositor.c b/example/compositor.c index d3fbb84..97d34e6 100644 --- a/example/compositor.c +++ b/example/compositor.c @@ -202,7 +202,7 @@ int main(int argc, char *argv[]) /* Composite layers that didn't make it into a plane */ for (i = 1; i < layers_len; i++) { - if (liftoff_layer_get_plane(layers[i]) == NULL) { + if (liftoff_layer_needs_composition(layers[i])) { composite(drm_fd, &composition_fb, &fbs[i], i * 100, i * 100); } diff --git a/include/libliftoff.h b/include/libliftoff.h index 697056a..15e745e 100644 --- a/include/libliftoff.h +++ b/include/libliftoff.h @@ -2,6 +2,7 @@ #define LIFTOFF_H #include +#include #include #include #include @@ -56,8 +57,8 @@ uint32_t liftoff_plane_get_id(struct liftoff_plane *plane); /** * Build a layer to plane mapping and append the plane configuration to `req`. * - * Callers are expected to commit `req` afterwards and can read the layer to - * plane mapping with `liftoff_layer_get_plane`. + * 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. * @@ -88,6 +89,14 @@ void liftoff_output_destroy(struct liftoff_output *output); */ void liftoff_output_set_composition_layer(struct liftoff_output *output, struct liftoff_layer *layer); +/** + * Check whether this output needs composition. + * + * An output doesn't need composition if all visible layers could be mapped to a + * plane. In other words, if an output needs composition, at least one layer + * will return true when `liftoff_layer_needs_composition` is called. + */ +bool liftoff_output_needs_composition(struct liftoff_output *output); /** * Create a new layer on an output. @@ -124,6 +133,13 @@ int liftoff_layer_set_property(struct liftoff_layer *layer, const char *name, * needs to be displayed (e.g. the buffer cannot be imported in KMS). */ void liftoff_layer_set_fb_composited(struct liftoff_layer *layer); +/** + * Check whether this layer needs composition. + * + * A layer needs composition if it's visible and if it couldn't be mapped to a + * plane. + */ +bool liftoff_layer_needs_composition(struct liftoff_layer *layer); /** * Retrieve the plane mapped to this layer. * diff --git a/layer.c b/layer.c index 210ca42..c3ef0cf 100644 --- a/layer.c +++ b/layer.c @@ -106,6 +106,14 @@ struct liftoff_plane *liftoff_layer_get_plane(struct liftoff_layer *layer) return layer->plane; } +bool liftoff_layer_needs_composition(struct liftoff_layer *layer) +{ + if (!layer_is_visible(layer)) { + return false; + } + return layer->plane == NULL; +} + void layer_get_rect(struct liftoff_layer *layer, struct liftoff_rect *rect) { struct liftoff_layer_property *x_prop, *y_prop, *w_prop, *h_prop; diff --git a/output.c b/output.c index 5c4f62f..1cd1745 100644 --- a/output.c +++ b/output.c @@ -55,6 +55,19 @@ void liftoff_output_set_composition_layer(struct liftoff_output *output, output->composition_layer = layer; } +bool liftoff_output_needs_composition(struct liftoff_output *output) +{ + struct liftoff_layer *layer; + + liftoff_list_for_each(layer, &output->layers, link) { + if (liftoff_layer_needs_composition(layer)) { + return true; + } + } + + return false; +} + void output_log_layers(struct liftoff_output *output) { struct liftoff_layer *layer; size_t i; diff --git a/test/test_alloc.c b/test/test_alloc.c index 5d22ffc..7120843 100644 --- a/test/test_alloc.c +++ b/test/test_alloc.c @@ -606,6 +606,19 @@ static struct test_case tests[] = { }, }; +static bool test_needs_composition(struct test_layer *test_layers) +{ + size_t i; + + for (i = 0; test_layers[i].width > 0; i++) { + if (test_layers[i].result == NULL) { + return true; + } + } + + return false; +} + static void run_test(struct test_layer *test_layers) { size_t i, j; @@ -696,6 +709,9 @@ static void run_test(struct test_layer *test_layers) } assert(ok); + assert(test_needs_composition(test_layers) == + liftoff_output_needs_composition(output)); + liftoff_output_destroy(output); liftoff_device_destroy(device); close(drm_fd); diff --git a/test/test_prop.c b/test/test_prop.c index 59320c0..fbdf92c 100644 --- a/test/test_prop.c +++ b/test/test_prop.c @@ -157,6 +157,7 @@ static int test_ignore_alpha(void) ret = drmModeAtomicCommit(drm_fd, req, 0, NULL); assert(ret == 0); assert(liftoff_mock_plane_get_layer(mock_plane) == NULL); + assert(!liftoff_layer_needs_composition(layer)); drmModeAtomicFree(req); liftoff_device_destroy(device);