mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-11-16 19:47:55 +01:00
Rename library to liftoff
Let's make these planes useful!
This commit is contained in:
parent
c4a8afb39b
commit
caac9bc87f
11 changed files with 213 additions and 210 deletions
|
@ -1,10 +1,10 @@
|
|||
# libhwc
|
||||
# libliftoff
|
||||
|
||||
Lightweight hardware composer library for libdrm.
|
||||
|
||||
libhwc eases the use of KMS planes from userspace without standing in your way.
|
||||
Users create "virtual planes" called layers, set KMS properties on them, and
|
||||
libhwc will allocate planes for these layers if possible.
|
||||
libliftoff eases the use of KMS planes from userspace without standing in your
|
||||
way. Users create "virtual planes" called layers, set KMS properties on them,
|
||||
and libliftoff will allocate planes for these layers if possible.
|
||||
|
||||
## Building
|
||||
|
||||
|
|
108
display.c
108
display.c
|
@ -8,10 +8,10 @@
|
|||
#include <unistd.h>
|
||||
#include "private.h"
|
||||
|
||||
static int guess_plane_zpos_from_type(struct hwc_display *display,
|
||||
static int guess_plane_zpos_from_type(struct liftoff_display *display,
|
||||
uint32_t plane_id, uint32_t type)
|
||||
{
|
||||
struct hwc_plane *primary;
|
||||
struct liftoff_plane *primary;
|
||||
|
||||
/* From far to close to the eye: primary, overlay, cursor. Unless
|
||||
* the overlay ID < primary ID. */
|
||||
|
@ -21,10 +21,11 @@ static int guess_plane_zpos_from_type(struct hwc_display *display,
|
|||
case DRM_PLANE_TYPE_CURSOR:
|
||||
return 2;
|
||||
case DRM_PLANE_TYPE_OVERLAY:
|
||||
if (hwc_list_empty(&display->planes)) {
|
||||
if (liftoff_list_empty(&display->planes)) {
|
||||
return 0; /* No primary plane, shouldn't happen */
|
||||
}
|
||||
primary = hwc_container_of(display->planes.next, primary, link);
|
||||
primary = liftoff_container_of(display->planes.next,
|
||||
primary, link);
|
||||
if (plane_id < primary->id) {
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -34,14 +35,15 @@ static int guess_plane_zpos_from_type(struct hwc_display *display,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct hwc_plane *plane_create(struct hwc_display *display, uint32_t id)
|
||||
static struct liftoff_plane *plane_create(struct liftoff_display *display,
|
||||
uint32_t id)
|
||||
{
|
||||
struct hwc_plane *plane, *cur;
|
||||
struct liftoff_plane *plane, *cur;
|
||||
drmModePlane *drm_plane;
|
||||
drmModeObjectProperties *drm_props;
|
||||
uint32_t i;
|
||||
drmModePropertyRes *drm_prop;
|
||||
struct hwc_plane_property *prop;
|
||||
struct liftoff_plane_property *prop;
|
||||
uint64_t value;
|
||||
bool has_type = false, has_zpos = false;
|
||||
|
||||
|
@ -64,7 +66,7 @@ static struct hwc_plane *plane_create(struct hwc_display *display, uint32_t id)
|
|||
return NULL;
|
||||
}
|
||||
plane->props = calloc(drm_props->count_props,
|
||||
sizeof(struct hwc_plane_property));
|
||||
sizeof(struct liftoff_plane_property));
|
||||
if (plane->props == NULL) {
|
||||
drmModeFreeObjectProperties(drm_props);
|
||||
return NULL;
|
||||
|
@ -108,34 +110,34 @@ static struct hwc_plane *plane_create(struct hwc_display *display, uint32_t id)
|
|||
* far from the primary planes, then planes closer and closer to the
|
||||
* primary plane. */
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
|
||||
hwc_list_insert(&display->planes, &plane->link);
|
||||
liftoff_list_insert(&display->planes, &plane->link);
|
||||
} else {
|
||||
hwc_list_for_each(cur, &display->planes, link) {
|
||||
liftoff_list_for_each(cur, &display->planes, link) {
|
||||
if (cur->type != DRM_PLANE_TYPE_PRIMARY &&
|
||||
plane->zpos >= cur->zpos) {
|
||||
hwc_list_insert(cur->link.prev, &plane->link);
|
||||
liftoff_list_insert(cur->link.prev, &plane->link);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (plane->link.next == NULL) { /* not inserted */
|
||||
hwc_list_insert(display->planes.prev, &plane->link);
|
||||
liftoff_list_insert(display->planes.prev, &plane->link);
|
||||
}
|
||||
}
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
static void plane_destroy(struct hwc_plane *plane)
|
||||
static void plane_destroy(struct liftoff_plane *plane)
|
||||
{
|
||||
hwc_list_remove(&plane->link);
|
||||
liftoff_list_remove(&plane->link);
|
||||
free(plane->props);
|
||||
free(plane);
|
||||
}
|
||||
|
||||
struct hwc_display *hwc_display_create(int drm_fd)
|
||||
struct liftoff_display *liftoff_display_create(int drm_fd)
|
||||
{
|
||||
struct hwc_display *display;
|
||||
struct liftoff_display *display;
|
||||
drmModeRes *drm_res;
|
||||
drmModePlaneRes *drm_plane_res;
|
||||
uint32_t i;
|
||||
|
@ -146,23 +148,23 @@ struct hwc_display *hwc_display_create(int drm_fd)
|
|||
}
|
||||
display->drm_fd = dup(drm_fd);
|
||||
if (display->drm_fd < 0) {
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hwc_list_init(&display->planes);
|
||||
hwc_list_init(&display->outputs);
|
||||
liftoff_list_init(&display->planes);
|
||||
liftoff_list_init(&display->outputs);
|
||||
|
||||
drm_res = drmModeGetResources(drm_fd);
|
||||
if (drm_res == NULL) {
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display->crtcs = malloc(drm_res->count_crtcs * sizeof(uint32_t));
|
||||
if (display->crtcs == NULL) {
|
||||
drmModeFreeResources(drm_res);
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
display->crtcs_len = drm_res->count_crtcs;
|
||||
|
@ -174,13 +176,13 @@ struct hwc_display *hwc_display_create(int drm_fd)
|
|||
/* TODO: allow users to choose which layers to hand over */
|
||||
drm_plane_res = drmModeGetPlaneResources(drm_fd);
|
||||
if (drm_plane_res == NULL) {
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < drm_plane_res->count_planes; i++) {
|
||||
if (plane_create(display, drm_plane_res->planes[i]) == NULL) {
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
@ -189,20 +191,20 @@ struct hwc_display *hwc_display_create(int drm_fd)
|
|||
return display;
|
||||
}
|
||||
|
||||
void hwc_display_destroy(struct hwc_display *display)
|
||||
void liftoff_display_destroy(struct liftoff_display *display)
|
||||
{
|
||||
struct hwc_plane *plane, *tmp;
|
||||
struct liftoff_plane *plane, *tmp;
|
||||
|
||||
close(display->drm_fd);
|
||||
hwc_list_for_each_safe(plane, tmp, &display->planes, link) {
|
||||
liftoff_list_for_each_safe(plane, tmp, &display->planes, link) {
|
||||
plane_destroy(plane);
|
||||
}
|
||||
free(display->crtcs);
|
||||
free(display);
|
||||
}
|
||||
|
||||
static struct hwc_plane_property *plane_get_property(struct hwc_plane *plane,
|
||||
const char *name)
|
||||
static struct liftoff_plane_property *plane_get_property(struct liftoff_plane *plane,
|
||||
const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -214,8 +216,8 @@ static struct hwc_plane_property *plane_get_property(struct hwc_plane *plane,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool plane_set_prop(struct hwc_plane *plane, drmModeAtomicReq *req,
|
||||
struct hwc_plane_property *prop, uint64_t value)
|
||||
static bool plane_set_prop(struct liftoff_plane *plane, drmModeAtomicReq *req,
|
||||
struct liftoff_plane_property *prop, uint64_t value)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
@ -229,13 +231,13 @@ static bool plane_set_prop(struct hwc_plane *plane, drmModeAtomicReq *req,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool plane_apply(struct hwc_plane *plane, struct hwc_layer *layer,
|
||||
static bool plane_apply(struct liftoff_plane *plane, struct liftoff_layer *layer,
|
||||
drmModeAtomicReq *req, bool *compatible)
|
||||
{
|
||||
int cursor;
|
||||
size_t i;
|
||||
struct hwc_layer_property *layer_prop;
|
||||
struct hwc_plane_property *plane_prop;
|
||||
struct liftoff_layer_property *layer_prop;
|
||||
struct liftoff_plane_property *plane_prop;
|
||||
|
||||
*compatible = true;
|
||||
cursor = drmModeAtomicGetCursor(req);
|
||||
|
@ -287,31 +289,31 @@ struct plane_alloc {
|
|||
drmModeAtomicReq *req;
|
||||
size_t planes_len;
|
||||
|
||||
struct hwc_layer **best;
|
||||
struct liftoff_layer **best;
|
||||
int best_score;
|
||||
};
|
||||
|
||||
/* Transient data, arguments for each step */
|
||||
struct plane_data {
|
||||
struct hwc_list *plane_link; /* hwc_plane.link */
|
||||
struct liftoff_list *plane_link; /* liftoff_plane.link */
|
||||
size_t plane_idx;
|
||||
|
||||
struct hwc_layer **alloc; /* only items up to plane_idx are valid */
|
||||
struct liftoff_layer **alloc; /* only items up to plane_idx are valid */
|
||||
int score;
|
||||
int last_plane_zpos, last_layer_zpos;
|
||||
};
|
||||
|
||||
bool output_choose_layers(struct hwc_output *output, struct plane_alloc *alloc,
|
||||
bool output_choose_layers(struct liftoff_output *output, struct plane_alloc *alloc,
|
||||
struct plane_data *data)
|
||||
{
|
||||
struct hwc_display *display;
|
||||
struct hwc_plane *plane;
|
||||
struct hwc_layer *layer;
|
||||
struct liftoff_display *display;
|
||||
struct liftoff_plane *plane;
|
||||
struct liftoff_layer *layer;
|
||||
int cursor, ret;
|
||||
size_t remaining_planes, i;
|
||||
bool found, compatible;
|
||||
struct plane_data next_data;
|
||||
struct hwc_layer_property *zpos_prop;
|
||||
struct liftoff_layer_property *zpos_prop;
|
||||
|
||||
display = output->display;
|
||||
|
||||
|
@ -320,11 +322,11 @@ bool output_choose_layers(struct hwc_output *output, struct plane_alloc *alloc,
|
|||
/* We found a better allocation */
|
||||
alloc->best_score = data->score;
|
||||
memcpy(alloc->best, data->alloc,
|
||||
alloc->planes_len * sizeof(struct hwc_layer *));
|
||||
alloc->planes_len * sizeof(struct liftoff_layer *));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
plane = hwc_container_of(data->plane_link, plane, link);
|
||||
plane = liftoff_container_of(data->plane_link, plane, link);
|
||||
|
||||
/* These don't change depending on the layer we choose */
|
||||
next_data.plane_link = data->plane_link->next;
|
||||
|
@ -350,7 +352,7 @@ bool output_choose_layers(struct hwc_output *output, struct plane_alloc *alloc,
|
|||
fprintf(stderr, "Performing allocation for plane %d (%zu/%zu)\n",
|
||||
plane->id, data->plane_idx + 1, alloc->planes_len);
|
||||
|
||||
hwc_list_for_each(layer, &output->layers, link) {
|
||||
liftoff_list_for_each(layer, &output->layers, link) {
|
||||
if (layer->plane != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
@ -447,11 +449,11 @@ skip:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
||||
bool liftoff_display_apply(struct liftoff_display *display, drmModeAtomicReq *req)
|
||||
{
|
||||
struct hwc_output *output;
|
||||
struct hwc_plane *plane;
|
||||
struct hwc_layer *layer;
|
||||
struct liftoff_output *output;
|
||||
struct liftoff_plane *plane;
|
||||
struct liftoff_layer *layer;
|
||||
struct plane_alloc alloc;
|
||||
struct plane_data data;
|
||||
size_t i;
|
||||
|
@ -459,7 +461,7 @@ bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
|||
|
||||
/* Unset all existing plane and layer mappings.
|
||||
TODO: incremental updates keeping old configuration if possible */
|
||||
hwc_list_for_each(plane, &display->planes, link) {
|
||||
liftoff_list_for_each(plane, &display->planes, link) {
|
||||
if (plane->layer != NULL) {
|
||||
plane->layer->plane = NULL;
|
||||
plane->layer = NULL;
|
||||
|
@ -468,7 +470,7 @@ bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
|||
|
||||
/* Disable all planes. Do it before building mappings to make sure not
|
||||
to hit bandwidth limits because too many planes are enabled. */
|
||||
hwc_list_for_each(plane, &display->planes, link) {
|
||||
liftoff_list_for_each(plane, &display->planes, link) {
|
||||
if (plane->layer == NULL) {
|
||||
fprintf(stderr, "Disabling plane %d\n", plane->id);
|
||||
if (!plane_apply(plane, NULL, req, &compatible)) {
|
||||
|
@ -479,7 +481,7 @@ bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
|||
}
|
||||
|
||||
alloc.req = req;
|
||||
alloc.planes_len = hwc_list_length(&display->planes);
|
||||
alloc.planes_len = liftoff_list_length(&display->planes);
|
||||
|
||||
data.alloc = malloc(alloc.planes_len * sizeof(*data.alloc));
|
||||
alloc.best = malloc(alloc.planes_len * sizeof(*alloc.best));
|
||||
|
@ -493,7 +495,7 @@ bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
|||
* issues? Also: be fair when mapping planes to outputs, don't give all
|
||||
* planes to a single output. Also: don't treat each output separately,
|
||||
* allocate planes for all outputs at once. */
|
||||
hwc_list_for_each(output, &display->outputs, link) {
|
||||
liftoff_list_for_each(output, &display->outputs, link) {
|
||||
/* 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
|
||||
|
@ -515,7 +517,7 @@ bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
|||
|
||||
/* Apply the best allocation */
|
||||
i = 0;
|
||||
hwc_list_for_each(plane, &display->planes, link) {
|
||||
liftoff_list_for_each(plane, &display->planes, link) {
|
||||
layer = alloc.best[i];
|
||||
i++;
|
||||
if (layer == NULL) {
|
||||
|
|
62
example.c
62
example.c
|
@ -1,6 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <fcntl.h>
|
||||
#include <libhwc.h>
|
||||
#include <libliftoff.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
@ -97,13 +97,13 @@ static const uint32_t colors[] = {
|
|||
0xFFFFFF00, /* yellow */
|
||||
};
|
||||
|
||||
static struct hwc_layer *add_layer(int drm_fd, struct hwc_output *output,
|
||||
int x, int y, int width, int height,
|
||||
bool with_alpha)
|
||||
static struct liftoff_layer *add_layer(int drm_fd, struct liftoff_output *output,
|
||||
int x, int y, int width, int height,
|
||||
bool with_alpha)
|
||||
{
|
||||
static size_t color_idx = 0;
|
||||
uint32_t fb_id;
|
||||
struct hwc_layer *layer;
|
||||
struct liftoff_layer *layer;
|
||||
|
||||
fb_id = create_argb_fb(drm_fd, width, height, colors[color_idx],
|
||||
with_alpha);
|
||||
|
@ -114,16 +114,16 @@ static struct hwc_layer *add_layer(int drm_fd, struct hwc_output *output,
|
|||
printf("Created FB %d with size %dx%d\n", fb_id, width, height);
|
||||
color_idx = (color_idx + 1) % (sizeof(colors) / sizeof(colors[0]));
|
||||
|
||||
layer = hwc_layer_create(output);
|
||||
hwc_layer_set_property(layer, "FB_ID", fb_id);
|
||||
hwc_layer_set_property(layer, "CRTC_X", x);
|
||||
hwc_layer_set_property(layer, "CRTC_Y", y);
|
||||
hwc_layer_set_property(layer, "CRTC_W", width);
|
||||
hwc_layer_set_property(layer, "CRTC_H", height);
|
||||
hwc_layer_set_property(layer, "SRC_X", 0);
|
||||
hwc_layer_set_property(layer, "SRC_Y", 0);
|
||||
hwc_layer_set_property(layer, "SRC_W", width << 16);
|
||||
hwc_layer_set_property(layer, "SRC_H", height << 16);
|
||||
layer = liftoff_layer_create(output);
|
||||
liftoff_layer_set_property(layer, "FB_ID", fb_id);
|
||||
liftoff_layer_set_property(layer, "CRTC_X", x);
|
||||
liftoff_layer_set_property(layer, "CRTC_Y", y);
|
||||
liftoff_layer_set_property(layer, "CRTC_W", width);
|
||||
liftoff_layer_set_property(layer, "CRTC_H", height);
|
||||
liftoff_layer_set_property(layer, "SRC_X", 0);
|
||||
liftoff_layer_set_property(layer, "SRC_Y", 0);
|
||||
liftoff_layer_set_property(layer, "SRC_W", width << 16);
|
||||
liftoff_layer_set_property(layer, "SRC_H", height << 16);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
@ -131,12 +131,12 @@ static struct hwc_layer *add_layer(int drm_fd, struct hwc_output *output,
|
|||
int main(int argc, char *argv[])
|
||||
{
|
||||
int drm_fd;
|
||||
struct hwc_display *display;
|
||||
struct liftoff_display *display;
|
||||
drmModeRes *drm_res;
|
||||
drmModeCrtc *crtc;
|
||||
drmModeConnector *connector;
|
||||
struct hwc_output *output;
|
||||
struct hwc_layer *layers[4];
|
||||
struct liftoff_output *output;
|
||||
struct liftoff_layer *layers[4];
|
||||
drmModeAtomicReq *req;
|
||||
int ret;
|
||||
size_t i;
|
||||
|
@ -156,16 +156,16 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
display = hwc_display_create(drm_fd);
|
||||
display = liftoff_display_create(drm_fd);
|
||||
if (display == NULL) {
|
||||
perror("hwc_display_create");
|
||||
perror("liftoff_display_create");
|
||||
return 1;
|
||||
}
|
||||
|
||||
drm_res = drmModeGetResources(drm_fd);
|
||||
connector = pick_connector(drm_fd, drm_res);
|
||||
crtc = pick_crtc(drm_fd, drm_res, connector);
|
||||
output = hwc_output_create(display, crtc->crtc_id);
|
||||
output = liftoff_output_create(display, crtc->crtc_id);
|
||||
drmModeFreeResources(drm_res);
|
||||
|
||||
if (connector == NULL) {
|
||||
|
@ -186,14 +186,14 @@ int main(int argc, char *argv[])
|
|||
layers[2] = add_layer(drm_fd, output, 300, 300, 128, 128, false);
|
||||
layers[3] = add_layer(drm_fd, output, 400, 400, 128, 128, true);
|
||||
|
||||
hwc_layer_set_property(layers[0], "zpos", 0);
|
||||
hwc_layer_set_property(layers[1], "zpos", 1);
|
||||
hwc_layer_set_property(layers[2], "zpos", 2);
|
||||
hwc_layer_set_property(layers[3], "zpos", 3);
|
||||
liftoff_layer_set_property(layers[0], "zpos", 0);
|
||||
liftoff_layer_set_property(layers[1], "zpos", 1);
|
||||
liftoff_layer_set_property(layers[2], "zpos", 2);
|
||||
liftoff_layer_set_property(layers[3], "zpos", 3);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
if (!hwc_display_apply(display, req)) {
|
||||
perror("hwc_display_commit");
|
||||
if (!liftoff_display_apply(display, req)) {
|
||||
perror("liftoff_display_commit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -205,18 +205,18 @@ int main(int argc, char *argv[])
|
|||
|
||||
for (i = 0; i < sizeof(layers) / sizeof(layers[0]); i++) {
|
||||
printf("Layer %zu got assigned to plane %u\n", i,
|
||||
hwc_layer_get_plane_id(layers[i]));
|
||||
liftoff_layer_get_plane_id(layers[i]));
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
|
||||
drmModeAtomicFree(req);
|
||||
for (i = 0; i < sizeof(layers) / sizeof(layers[0]); i++) {
|
||||
hwc_layer_destroy(layers[i]);
|
||||
liftoff_layer_destroy(layers[i]);
|
||||
}
|
||||
hwc_output_destroy(output);
|
||||
liftoff_output_destroy(output);
|
||||
drmModeFreeCrtc(crtc);
|
||||
drmModeFreeConnector(connector);
|
||||
hwc_display_destroy(display);
|
||||
liftoff_display_destroy(display);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef HWC_H
|
||||
#define HWC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
/**
|
||||
* Initialize libhwc for a DRM node. The node is expected to have
|
||||
* DRM_CLIENT_CAP_UNIVERSAL_PLANES and DRM_CLIENT_CAP_ATOMIC enabled.
|
||||
*/
|
||||
struct hwc_display *hwc_display_create(int drm_fd);
|
||||
void hwc_display_destroy(struct hwc_display *display);
|
||||
/**
|
||||
* 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 `hwc_layer_get_plane_id`.
|
||||
*/
|
||||
bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req);
|
||||
|
||||
/**
|
||||
* Make the display manage a CRTC's planes. The returned output allows callers
|
||||
* to attach layers.
|
||||
*/
|
||||
struct hwc_output *hwc_output_create(struct hwc_display *display,
|
||||
uint32_t crtc_id);
|
||||
void hwc_output_destroy(struct hwc_output *output);
|
||||
|
||||
/**
|
||||
* Create a new layer on an output.
|
||||
*/
|
||||
struct hwc_layer *hwc_layer_create(struct hwc_output *output);
|
||||
void hwc_layer_destroy(struct hwc_layer *layer);
|
||||
/**
|
||||
* Set a property on the layer. Any plane property can be set. If none of the
|
||||
* planes support the property, the layer won't be mapped to any plane.
|
||||
*/
|
||||
void hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
||||
uint64_t value);
|
||||
/**
|
||||
* Retrieve the plane mapped to this layer. Zero is returned if no plane is
|
||||
* mapped.
|
||||
*/
|
||||
uint32_t hwc_layer_get_plane_id(struct hwc_layer *layer);
|
||||
|
||||
#endif
|
48
include/libliftoff.h
Normal file
48
include/libliftoff.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#ifndef LIFTOFF_H
|
||||
#define LIFTOFF_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
/**
|
||||
* Initialize libliftoff for a DRM node. The node is expected to have
|
||||
* DRM_CLIENT_CAP_UNIVERSAL_PLANES and DRM_CLIENT_CAP_ATOMIC enabled.
|
||||
*/
|
||||
struct liftoff_display *liftoff_display_create(int drm_fd);
|
||||
void liftoff_display_destroy(struct liftoff_display *display);
|
||||
/**
|
||||
* 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_id`.
|
||||
*/
|
||||
bool liftoff_display_apply(struct liftoff_display *display,
|
||||
drmModeAtomicReq *req);
|
||||
|
||||
/**
|
||||
* Make the display manage a CRTC's planes. The returned output allows callers
|
||||
* to attach layers.
|
||||
*/
|
||||
struct liftoff_output *liftoff_output_create(struct liftoff_display *display,
|
||||
uint32_t crtc_id);
|
||||
void liftoff_output_destroy(struct liftoff_output *output);
|
||||
|
||||
/**
|
||||
* Create a new layer on an output.
|
||||
*/
|
||||
struct liftoff_layer *liftoff_layer_create(struct liftoff_output *output);
|
||||
void liftoff_layer_destroy(struct liftoff_layer *layer);
|
||||
/**
|
||||
* Set a property on the layer. Any plane property can be set. If none of the
|
||||
* planes support the property, the layer won't be mapped to any plane.
|
||||
*/
|
||||
void liftoff_layer_set_property(struct liftoff_layer *layer, const char *name,
|
||||
uint64_t value);
|
||||
/**
|
||||
* Retrieve the plane mapped to this layer. Zero is returned if no plane is
|
||||
* mapped.
|
||||
*/
|
||||
uint32_t liftoff_layer_get_plane_id(struct liftoff_layer *layer);
|
||||
|
||||
#endif
|
|
@ -4,31 +4,31 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct hwc_list {
|
||||
struct hwc_list *prev;
|
||||
struct hwc_list *next;
|
||||
struct liftoff_list {
|
||||
struct liftoff_list *prev;
|
||||
struct liftoff_list *next;
|
||||
};
|
||||
|
||||
void hwc_list_init(struct hwc_list *list);
|
||||
void hwc_list_insert(struct hwc_list *list, struct hwc_list *elm);
|
||||
void hwc_list_remove(struct hwc_list *elm);
|
||||
size_t hwc_list_length(const struct hwc_list *list);
|
||||
bool hwc_list_empty(const struct hwc_list *list);
|
||||
void liftoff_list_init(struct liftoff_list *list);
|
||||
void liftoff_list_insert(struct liftoff_list *list, struct liftoff_list *elm);
|
||||
void liftoff_list_remove(struct liftoff_list *elm);
|
||||
size_t liftoff_list_length(const struct liftoff_list *list);
|
||||
bool liftoff_list_empty(const struct liftoff_list *list);
|
||||
|
||||
#define hwc_container_of(ptr, sample, member) \
|
||||
#define liftoff_container_of(ptr, sample, member) \
|
||||
(__typeof__(sample))((char *)(ptr) - \
|
||||
offsetof(__typeof__(*sample), member))
|
||||
|
||||
#define hwc_list_for_each(pos, head, member) \
|
||||
for (pos = hwc_container_of((head)->next, pos, member); \
|
||||
#define liftoff_list_for_each(pos, head, member) \
|
||||
for (pos = liftoff_container_of((head)->next, pos, member); \
|
||||
&pos->member != (head); \
|
||||
pos = hwc_container_of(pos->member.next, pos, member))
|
||||
pos = liftoff_container_of(pos->member.next, pos, member))
|
||||
|
||||
#define hwc_list_for_each_safe(pos, tmp, head, member) \
|
||||
for (pos = hwc_container_of((head)->next, pos, member), \
|
||||
tmp = hwc_container_of(pos->member.next, tmp, member); \
|
||||
#define liftoff_list_for_each_safe(pos, tmp, head, member) \
|
||||
for (pos = liftoff_container_of((head)->next, pos, member), \
|
||||
tmp = liftoff_container_of(pos->member.next, tmp, member); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = hwc_container_of(pos->member.next, tmp, member))
|
||||
tmp = liftoff_container_of(pos->member.next, tmp, member))
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
|
||||
#include "libhwc.h"
|
||||
#include "libliftoff.h"
|
||||
#include "list.h"
|
||||
|
||||
struct hwc_display {
|
||||
struct liftoff_display {
|
||||
int drm_fd;
|
||||
|
||||
struct hwc_list planes; /* hwc_plane.link */
|
||||
struct hwc_list outputs; /* hwc_output.link */
|
||||
struct liftoff_list planes; /* liftoff_plane.link */
|
||||
struct liftoff_list outputs; /* liftoff_output.link */
|
||||
|
||||
uint32_t *crtcs;
|
||||
size_t crtcs_len;
|
||||
};
|
||||
|
||||
struct hwc_output {
|
||||
struct hwc_display *display;
|
||||
struct liftoff_output {
|
||||
struct liftoff_display *display;
|
||||
uint32_t crtc_id;
|
||||
size_t crtc_index;
|
||||
struct hwc_list link; /* hwc_display.outputs */
|
||||
struct liftoff_list link; /* liftoff_display.outputs */
|
||||
|
||||
struct hwc_list layers; /* hwc_layer.link */
|
||||
struct liftoff_list layers; /* liftoff_layer.link */
|
||||
};
|
||||
|
||||
struct hwc_layer {
|
||||
struct hwc_output *output;
|
||||
struct hwc_list link; /* hwc_output.layers */
|
||||
struct liftoff_layer {
|
||||
struct liftoff_output *output;
|
||||
struct liftoff_list link; /* liftoff_output.layers */
|
||||
|
||||
struct hwc_layer_property *props;
|
||||
struct liftoff_layer_property *props;
|
||||
size_t props_len;
|
||||
|
||||
struct hwc_plane *plane;
|
||||
struct liftoff_plane *plane;
|
||||
};
|
||||
|
||||
struct hwc_layer_property {
|
||||
struct liftoff_layer_property {
|
||||
char name[DRM_PROP_NAME_LEN];
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
struct hwc_plane {
|
||||
struct liftoff_plane {
|
||||
uint32_t id;
|
||||
uint32_t possible_crtcs;
|
||||
uint32_t type;
|
||||
int zpos; /* greater values mean closer to the eye */
|
||||
/* TODO: formats */
|
||||
struct hwc_list link; /* hwc_display.planes */
|
||||
struct liftoff_list link; /* liftoff_display.planes */
|
||||
|
||||
struct hwc_plane_property *props;
|
||||
struct liftoff_plane_property *props;
|
||||
size_t props_len;
|
||||
|
||||
struct hwc_layer *layer;
|
||||
struct liftoff_layer *layer;
|
||||
};
|
||||
|
||||
struct hwc_plane_property {
|
||||
struct liftoff_plane_property {
|
||||
char name[DRM_PROP_NAME_LEN];
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct hwc_layer_property *layer_get_property(struct hwc_layer *layer,
|
||||
const char *name);
|
||||
struct liftoff_layer_property *layer_get_property(struct liftoff_layer *layer,
|
||||
const char *name);
|
||||
|
||||
#endif
|
||||
|
|
26
layer.c
26
layer.c
|
@ -3,28 +3,28 @@
|
|||
#include <string.h>
|
||||
#include "private.h"
|
||||
|
||||
struct hwc_layer *hwc_layer_create(struct hwc_output *output)
|
||||
struct liftoff_layer *liftoff_layer_create(struct liftoff_output *output)
|
||||
{
|
||||
struct hwc_layer *layer;
|
||||
struct liftoff_layer *layer;
|
||||
|
||||
layer = calloc(1, sizeof(*layer));
|
||||
if (layer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
layer->output = output;
|
||||
hwc_list_insert(output->layers.prev, &layer->link);
|
||||
liftoff_list_insert(output->layers.prev, &layer->link);
|
||||
return layer;
|
||||
}
|
||||
|
||||
void hwc_layer_destroy(struct hwc_layer *layer)
|
||||
void liftoff_layer_destroy(struct liftoff_layer *layer)
|
||||
{
|
||||
free(layer->props);
|
||||
hwc_list_remove(&layer->link);
|
||||
liftoff_list_remove(&layer->link);
|
||||
free(layer);
|
||||
}
|
||||
|
||||
struct hwc_layer_property *layer_get_property(struct hwc_layer *layer,
|
||||
const char *name)
|
||||
struct liftoff_layer_property *layer_get_property(struct liftoff_layer *layer,
|
||||
const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
|
@ -36,11 +36,11 @@ struct hwc_layer_property *layer_get_property(struct hwc_layer *layer,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
||||
uint64_t value)
|
||||
void liftoff_layer_set_property(struct liftoff_layer *layer, const char *name,
|
||||
uint64_t value)
|
||||
{
|
||||
struct hwc_layer_property *props;
|
||||
struct hwc_layer_property *prop;
|
||||
struct liftoff_layer_property *props;
|
||||
struct liftoff_layer_property *prop;
|
||||
|
||||
/* TODO: better error handling */
|
||||
if (strcmp(name, "CRTC_ID") == 0) {
|
||||
|
@ -51,7 +51,7 @@ void hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
|||
prop = layer_get_property(layer, name);
|
||||
if (prop == NULL) {
|
||||
props = realloc(layer->props, (layer->props_len + 1)
|
||||
* sizeof(struct hwc_layer_property));
|
||||
* sizeof(struct liftoff_layer_property));
|
||||
if (props == NULL) {
|
||||
perror("realloc");
|
||||
return;
|
||||
|
@ -67,7 +67,7 @@ void hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
|||
prop->value = value;
|
||||
}
|
||||
|
||||
uint32_t hwc_layer_get_plane_id(struct hwc_layer *layer)
|
||||
uint32_t liftoff_layer_get_plane_id(struct liftoff_layer *layer)
|
||||
{
|
||||
if (layer->plane == NULL) {
|
||||
return 0;
|
||||
|
|
12
list.c
12
list.c
|
@ -1,12 +1,12 @@
|
|||
#include "list.h"
|
||||
|
||||
void hwc_list_init(struct hwc_list *list)
|
||||
void liftoff_list_init(struct liftoff_list *list)
|
||||
{
|
||||
list->prev = list;
|
||||
list->next = list;
|
||||
}
|
||||
|
||||
void hwc_list_insert(struct hwc_list *list, struct hwc_list *elm)
|
||||
void liftoff_list_insert(struct liftoff_list *list, struct liftoff_list *elm)
|
||||
{
|
||||
elm->prev = list;
|
||||
elm->next = list->next;
|
||||
|
@ -14,7 +14,7 @@ void hwc_list_insert(struct hwc_list *list, struct hwc_list *elm)
|
|||
elm->next->prev = elm;
|
||||
}
|
||||
|
||||
void hwc_list_remove(struct hwc_list *elm)
|
||||
void liftoff_list_remove(struct liftoff_list *elm)
|
||||
{
|
||||
elm->prev->next = elm->next;
|
||||
elm->next->prev = elm->prev;
|
||||
|
@ -22,9 +22,9 @@ void hwc_list_remove(struct hwc_list *elm)
|
|||
elm->prev = NULL;
|
||||
}
|
||||
|
||||
size_t hwc_list_length(const struct hwc_list *list)
|
||||
size_t liftoff_list_length(const struct liftoff_list *list)
|
||||
{
|
||||
struct hwc_list *e;
|
||||
struct liftoff_list *e;
|
||||
size_t count;
|
||||
|
||||
count = 0;
|
||||
|
@ -37,7 +37,7 @@ size_t hwc_list_length(const struct hwc_list *list)
|
|||
return count;
|
||||
}
|
||||
|
||||
bool hwc_list_empty(const struct hwc_list *list)
|
||||
bool liftoff_list_empty(const struct liftoff_list *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
|
24
meson.build
24
meson.build
|
@ -1,5 +1,5 @@
|
|||
project(
|
||||
'hwc',
|
||||
'liftoff',
|
||||
'c',
|
||||
version: '0.0.0',
|
||||
license: 'MIT',
|
||||
|
@ -18,13 +18,13 @@ add_project_arguments(cc.get_supported_arguments([
|
|||
'-Wno-unused-parameter',
|
||||
]), language: 'c')
|
||||
|
||||
hwc_inc = include_directories('include')
|
||||
liftoff_inc = include_directories('include')
|
||||
|
||||
drm = dependency('libdrm')
|
||||
|
||||
hwc_deps = [drm]
|
||||
liftoff_deps = [drm]
|
||||
|
||||
hwc_lib = library(
|
||||
liftoff_lib = library(
|
||||
meson.project_name(),
|
||||
files(
|
||||
'display.c',
|
||||
|
@ -32,27 +32,27 @@ hwc_lib = library(
|
|||
'list.c',
|
||||
'output.c',
|
||||
),
|
||||
include_directories: hwc_inc,
|
||||
include_directories: liftoff_inc,
|
||||
version: meson.project_version(),
|
||||
dependencies: hwc_deps,
|
||||
dependencies: liftoff_deps,
|
||||
install: true,
|
||||
)
|
||||
|
||||
hwc = declare_dependency(
|
||||
link_with: hwc_lib,
|
||||
include_directories: hwc_inc,
|
||||
dependencies: hwc_deps,
|
||||
liftoff = declare_dependency(
|
||||
link_with: liftoff_lib,
|
||||
include_directories: liftoff_inc,
|
||||
dependencies: liftoff_deps,
|
||||
)
|
||||
|
||||
executable(
|
||||
'example',
|
||||
files('example.c'),
|
||||
dependencies: [hwc],
|
||||
dependencies: [liftoff],
|
||||
)
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
pkgconfig.generate(
|
||||
libraries: hwc_lib,
|
||||
libraries: liftoff_lib,
|
||||
version: meson.project_version(),
|
||||
filebase: meson.project_name(),
|
||||
name: meson.project_name(),
|
||||
|
|
14
output.c
14
output.c
|
@ -3,10 +3,10 @@
|
|||
#include <sys/types.h>
|
||||
#include "private.h"
|
||||
|
||||
struct hwc_output *hwc_output_create(struct hwc_display *display,
|
||||
uint32_t crtc_id)
|
||||
struct liftoff_output *liftoff_output_create(struct liftoff_display *display,
|
||||
uint32_t crtc_id)
|
||||
{
|
||||
struct hwc_output *output;
|
||||
struct liftoff_output *output;
|
||||
ssize_t crtc_index;
|
||||
size_t i;
|
||||
|
||||
|
@ -28,13 +28,13 @@ struct hwc_output *hwc_output_create(struct hwc_display *display,
|
|||
output->display = display;
|
||||
output->crtc_id = crtc_id;
|
||||
output->crtc_index = crtc_index;
|
||||
hwc_list_init(&output->layers);
|
||||
hwc_list_insert(&display->outputs, &output->link);
|
||||
liftoff_list_init(&output->layers);
|
||||
liftoff_list_insert(&display->outputs, &output->link);
|
||||
return output;
|
||||
}
|
||||
|
||||
void hwc_output_destroy(struct hwc_output *output)
|
||||
void liftoff_output_destroy(struct liftoff_output *output)
|
||||
{
|
||||
hwc_list_remove(&output->link);
|
||||
liftoff_list_remove(&output->link);
|
||||
free(output);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue