Add needs_composition APIs

Right now, compositors are expected to query liftoff_layer_get_plane_id to
decide whether a layer needs to be composited.

However there are cases where a layer has no plane, but still doesn't need
composition (e.g. when FB_ID is zero or when alpha is zero, in the future when
the layer is out of CRTC bounds etc).

Add a new API to make users' life simpler.

Closes: https://github.com/emersion/libliftoff/issues/54
This commit is contained in:
Simon Ser 2020-12-06 15:07:03 +01:00
parent 87e5dcfe72
commit 6321e7c5aa
7 changed files with 58 additions and 4 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -2,6 +2,7 @@
#define LIFTOFF_H
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <xf86drmMode.h>
@ -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.
*

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);