libliftoff/layer.c
Simon Ser e9433997d9
Add liftoff_output_set_composition_layer
This lets the library user define a layer where composition will happen. At the
moment there can be at most one composition layer per output, on the primary
plane. It should be possible to remove these restrictions in the future if
desirable.

The composition layer will be put on a plane if and only if composition is
needed.

The compositor needs to know where composited layers will be blended to resolve
zpos conflicts.

Closes: https://github.com/emersion/libliftoff/issues/9
2019-10-11 14:31:17 +03:00

106 lines
2.5 KiB
C

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "private.h"
struct liftoff_layer *liftoff_layer_create(struct liftoff_output *output)
{
struct liftoff_layer *layer;
layer = calloc(1, sizeof(*layer));
if (layer == NULL) {
return NULL;
}
layer->output = output;
liftoff_list_insert(output->layers.prev, &layer->link);
return layer;
}
void liftoff_layer_destroy(struct liftoff_layer *layer)
{
if (layer->output->composition_layer == layer) {
layer->output->composition_layer = NULL;
}
free(layer->props);
liftoff_list_remove(&layer->link);
free(layer);
}
struct liftoff_layer_property *layer_get_property(struct liftoff_layer *layer,
const char *name)
{
size_t i;
for (i = 0; i < layer->props_len; i++) {
if (strcmp(layer->props[i].name, name) == 0) {
return &layer->props[i];
}
}
return NULL;
}
void liftoff_layer_set_property(struct liftoff_layer *layer, const char *name,
uint64_t value)
{
struct liftoff_layer_property *props;
struct liftoff_layer_property *prop;
/* TODO: better error handling */
if (strcmp(name, "CRTC_ID") == 0) {
liftoff_log(LIFTOFF_ERROR,
"refusing to set a layer's CRTC_ID");
return;
}
prop = layer_get_property(layer, name);
if (prop == NULL) {
props = realloc(layer->props, (layer->props_len + 1)
* sizeof(struct liftoff_layer_property));
if (props == NULL) {
perror("realloc");
return;
}
layer->props = props;
layer->props_len++;
prop = &layer->props[layer->props_len - 1];
memset(prop, 0, sizeof(*prop));
strncpy(prop->name, name, sizeof(prop->name) - 1);
}
prop->value = value;
}
uint32_t liftoff_layer_get_plane_id(struct liftoff_layer *layer)
{
if (layer->plane == NULL) {
return 0;
}
return layer->plane->id;
}
void layer_get_rect(struct liftoff_layer *layer, struct liftoff_rect *rect)
{
struct liftoff_layer_property *x_prop, *y_prop, *w_prop, *h_prop;
x_prop = layer_get_property(layer, "CRTC_X");
y_prop = layer_get_property(layer, "CRTC_Y");
w_prop = layer_get_property(layer, "CRTC_W");
h_prop = layer_get_property(layer, "CRTC_H");
rect->x = x_prop != NULL ? x_prop->value : 0;
rect->y = y_prop != NULL ? y_prop->value : 0;
rect->width = w_prop != NULL ? w_prop->value : 0;
rect->height = h_prop != NULL ? h_prop->value : 0;
}
bool layer_intersects(struct liftoff_layer *a, struct liftoff_layer *b)
{
struct liftoff_rect ra, rb;
layer_get_rect(a, &ra);
layer_get_rect(b, &rb);
return ra.x < rb.x + rb.width && ra.y < rb.y + rb.height &&
ra.x + ra.width > rb.x && ra.y + ra.height > rb.y;
}