mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-12-26 21:59:18 +01:00
e9433997d9
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
106 lines
2.5 KiB
C
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;
|
|
}
|