mirror of
https://gitlab.freedesktop.org/emersion/libliftoff.git
synced 2024-11-16 19:47:55 +01:00
Initial experiments
This commit is contained in:
commit
9fe471dd6b
11 changed files with 769 additions and 0 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
max_line_length = 80
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/build
|
||||
*.log
|
231
display.c
Normal file
231
display.c
Normal file
|
@ -0,0 +1,231 @@
|
|||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "private.h"
|
||||
|
||||
static bool plane_init(struct hwc_plane *plane, struct hwc_display *display,
|
||||
int32_t id)
|
||||
{
|
||||
drmModePlane *drm_plane;
|
||||
drmModeObjectProperties *drm_props;
|
||||
uint32_t i;
|
||||
drmModePropertyRes *drm_prop;
|
||||
struct hwc_plane_property *prop;
|
||||
|
||||
drm_plane = drmModeGetPlane(display->drm_fd, id);
|
||||
if (drm_plane == NULL) {
|
||||
return false;
|
||||
}
|
||||
plane->id = drm_plane->plane_id;
|
||||
plane->possible_crtcs = drm_plane->possible_crtcs;
|
||||
drmModeFreePlane(drm_plane);
|
||||
|
||||
drm_props = drmModeObjectGetProperties(display->drm_fd, id,
|
||||
DRM_MODE_OBJECT_PLANE);
|
||||
if (drm_props == NULL) {
|
||||
return false;
|
||||
}
|
||||
plane->props = calloc(drm_props->count_props,
|
||||
sizeof(struct hwc_plane_property));
|
||||
if (plane->props == NULL) {
|
||||
drmModeFreeObjectProperties(drm_props);
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < drm_props->count_props; i++) {
|
||||
drm_prop = drmModeGetProperty(display->drm_fd,
|
||||
drm_props->props[i]);
|
||||
if (drm_prop == NULL) {
|
||||
drmModeFreeObjectProperties(drm_props);
|
||||
return false;
|
||||
}
|
||||
prop = &plane->props[i];
|
||||
memcpy(prop->name, drm_prop->name, sizeof(prop->name));
|
||||
prop->id = drm_prop->prop_id;
|
||||
drmModeFreeProperty(drm_prop);
|
||||
plane->props_len++;
|
||||
}
|
||||
drmModeFreeObjectProperties(drm_props);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void plane_finish(struct hwc_plane *plane)
|
||||
{
|
||||
free(plane->props);
|
||||
}
|
||||
|
||||
struct hwc_display *hwc_display_create(int drm_fd)
|
||||
{
|
||||
struct hwc_display *display;
|
||||
drmModePlaneRes *drm_plane_res;
|
||||
uint32_t i;
|
||||
|
||||
display = calloc(1, sizeof(*display));
|
||||
if (display == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
display->drm_fd = dup(drm_fd);
|
||||
if (display->drm_fd < 0) {
|
||||
hwc_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hwc_list_init(&display->outputs);
|
||||
|
||||
/* 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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display->planes = calloc(drm_plane_res->count_planes,
|
||||
sizeof(struct hwc_plane));
|
||||
if (display->planes == NULL) {
|
||||
hwc_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < drm_plane_res->count_planes; i++) {
|
||||
if (!plane_init(&display->planes[i], display,
|
||||
drm_plane_res->planes[i])) {
|
||||
hwc_display_destroy(display);
|
||||
return NULL;
|
||||
}
|
||||
display->planes_len++;
|
||||
}
|
||||
drmModeFreePlaneResources(drm_plane_res);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
void hwc_display_destroy(struct hwc_display *display)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
close(display->drm_fd);
|
||||
for (i = 0; i < display->planes_len; i++) {
|
||||
plane_finish(&display->planes[i]);
|
||||
}
|
||||
free(display->planes);
|
||||
free(display);
|
||||
}
|
||||
|
||||
struct hwc_plane_property *plane_get_property(struct hwc_plane *plane,
|
||||
const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < plane->props_len; i++) {
|
||||
if (strcmp(plane->props[i].name, name) == 0) {
|
||||
return &plane->props[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool layer_apply(struct hwc_layer *layer, struct hwc_plane *plane,
|
||||
drmModeAtomicReq *req)
|
||||
{
|
||||
size_t i;
|
||||
int ret;
|
||||
struct hwc_layer_property *layer_prop;
|
||||
struct hwc_plane_property *plane_prop;
|
||||
|
||||
/* TODO: disable planes that aren't used */
|
||||
|
||||
fprintf(stderr, " Setting CRTC_ID = %"PRIu32"\n",
|
||||
layer->output->crtc_id);
|
||||
plane_prop = plane_get_property(plane, "CRTC_ID");
|
||||
ret = drmModeAtomicAddProperty(req, plane->id, plane_prop->id,
|
||||
layer->output->crtc_id);
|
||||
if (ret < 0) {
|
||||
perror("drmModeAtomicAddProperty");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < layer->props_len; i++) {
|
||||
layer_prop = &layer->props[i];
|
||||
plane_prop = plane_get_property(plane, layer_prop->name);
|
||||
if (plane_prop == NULL) {
|
||||
fprintf(stderr, "failed to find property %s\n",
|
||||
layer_prop->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(stderr, " Setting %s = %"PRIu64"\n", layer_prop->name,
|
||||
layer_prop->value);
|
||||
ret = drmModeAtomicAddProperty(req, plane->id,
|
||||
plane_prop->id,
|
||||
layer_prop->value);
|
||||
if (ret < 0) {
|
||||
perror("drmModeAtomicAddProperty");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool layer_choose_plane(struct hwc_layer *layer, drmModeAtomicReq *req)
|
||||
{
|
||||
struct hwc_display *display;
|
||||
int cursor;
|
||||
struct hwc_plane *plane;
|
||||
size_t i;
|
||||
int ret;
|
||||
|
||||
display = layer->output->display;
|
||||
cursor = drmModeAtomicGetCursor(req);
|
||||
|
||||
for (i = 0; i < display->planes_len; i++) {
|
||||
plane = &display->planes[i];
|
||||
|
||||
fprintf(stderr, "Trying to apply layer %p with plane %d...\n",
|
||||
(void *)layer, plane->id);
|
||||
if (!layer_apply(layer, plane, req)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = drmModeAtomicCommit(display->drm_fd, req,
|
||||
DRM_MODE_ATOMIC_TEST_ONLY, NULL);
|
||||
if (ret == 0) {
|
||||
fprintf(stderr, "Success\n");
|
||||
layer->plane = plane;
|
||||
return true;
|
||||
} else if (-ret != EINVAL && -ret != ERANGE) {
|
||||
perror("drmModeAtomicCommit");
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Failure\n");
|
||||
drmModeAtomicSetCursor(req, cursor);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req)
|
||||
{
|
||||
int cursor;
|
||||
struct hwc_output *output;
|
||||
struct hwc_layer *layer;
|
||||
|
||||
cursor = drmModeAtomicGetCursor(req);
|
||||
|
||||
hwc_list_for_each(output, &display->outputs, link) {
|
||||
hwc_list_for_each(layer, &output->layers, link) {
|
||||
if (!layer_choose_plane(layer, req)) {
|
||||
fprintf(stderr,
|
||||
"Failed to find plane for layer %p\n",
|
||||
(void *)layer);
|
||||
drmModeAtomicSetCursor(req, cursor);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
212
example.c
Normal file
212
example.c
Normal file
|
@ -0,0 +1,212 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <fcntl.h>
|
||||
#include <libhwc.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
static drmModeConnector *pick_connector(int drm_fd, drmModeRes *drm_res)
|
||||
{
|
||||
int i;
|
||||
drmModeConnector *connector;
|
||||
|
||||
for (i = 0; i < drm_res->count_connectors; i++) {
|
||||
connector = drmModeGetConnector(drm_fd, drm_res->connectors[i]);
|
||||
if (connector->connection == DRM_MODE_CONNECTED) {
|
||||
return connector;
|
||||
}
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static drmModeCrtc *pick_crtc(int drm_fd, drmModeRes *drm_res,
|
||||
drmModeConnector *connector)
|
||||
{
|
||||
drmModeEncoder *enc;
|
||||
uint32_t crtc_id;
|
||||
|
||||
/* TODO: don't blindly use current CRTC */
|
||||
enc = drmModeGetEncoder(drm_fd, connector->encoder_id);
|
||||
crtc_id = enc->crtc_id;
|
||||
drmModeFreeEncoder(enc);
|
||||
|
||||
return drmModeGetCrtc(drm_fd, crtc_id);
|
||||
}
|
||||
|
||||
static uint32_t create_argb_fb(int drm_fd, uint32_t width, uint32_t height,
|
||||
uint32_t color, bool with_alpha)
|
||||
{
|
||||
int ret;
|
||||
uint32_t fb_id;
|
||||
uint32_t *data;
|
||||
size_t i;
|
||||
|
||||
struct drm_mode_create_dumb create = {
|
||||
.width = width,
|
||||
.height = height,
|
||||
.bpp = 32,
|
||||
.flags = 0,
|
||||
};
|
||||
ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t fmt = with_alpha ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
|
||||
uint32_t handles[4] = { create.handle };
|
||||
uint32_t strides[4] = { create.pitch };
|
||||
uint32_t offsets[4] = { 0 };
|
||||
ret = drmModeAddFB2(drm_fd, width, height, fmt, handles, strides,
|
||||
offsets, &fb_id, 0);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_mode_map_dumb map = { .handle = create.handle };
|
||||
ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = mmap(0, create.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm_fd,
|
||||
map.offset);
|
||||
if (data == MAP_FAILED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < create.size / sizeof(uint32_t); i++) {
|
||||
data[i] = color;
|
||||
}
|
||||
|
||||
munmap(data, create.size);
|
||||
return fb_id;
|
||||
}
|
||||
|
||||
/* ARGB */
|
||||
static const uint32_t colors[] = {0xFFFF0000, 0xFF00FF00, 0xFF0000FF};
|
||||
|
||||
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 size_t color_idx = 0;
|
||||
uint32_t fb_id;
|
||||
struct hwc_layer *layer;
|
||||
|
||||
fb_id = create_argb_fb(drm_fd, width, height, colors[color_idx],
|
||||
with_alpha);
|
||||
if (fb_id == 0) {
|
||||
fprintf(stderr, "failed to create framebuffer\n");
|
||||
return NULL;
|
||||
}
|
||||
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);
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int drm_fd;
|
||||
struct hwc_display *display;
|
||||
drmModeRes *drm_res;
|
||||
drmModeCrtc *crtc;
|
||||
drmModeConnector *connector;
|
||||
struct hwc_output *output;
|
||||
struct hwc_layer *layers[3];
|
||||
drmModeAtomicReq *req;
|
||||
int ret;
|
||||
|
||||
drm_fd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC);
|
||||
if (drm_fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) < 0) {
|
||||
perror("drmSetClientCap(UNIVERSAL_PLANES)");
|
||||
return 1;
|
||||
}
|
||||
if (drmSetClientCap(drm_fd, DRM_CLIENT_CAP_ATOMIC, 1) < 0) {
|
||||
perror("drmSetClientCap(ATOMIC)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
display = hwc_display_create(drm_fd);
|
||||
if (display == NULL) {
|
||||
perror("hwc_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);
|
||||
drmModeFreeResources(drm_res);
|
||||
|
||||
if (connector == NULL) {
|
||||
fprintf(stderr, "no connector found\n");
|
||||
return 1;
|
||||
}
|
||||
if (crtc == NULL || !crtc->mode_valid) {
|
||||
fprintf(stderr, "no CRTC found\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Using connector %d, CRTC %d\n", connector->connector_id,
|
||||
crtc->crtc_id);
|
||||
|
||||
layers[0] = add_layer(drm_fd, output, 0, 0, crtc->mode.hdisplay,
|
||||
crtc->mode.vdisplay, false);
|
||||
layers[1] = add_layer(drm_fd, output, 50, 50, 256, 256, true);
|
||||
layers[2] = add_layer(drm_fd, output, 500, 500, 128, 128, false);
|
||||
|
||||
req = drmModeAtomicAlloc();
|
||||
if (!hwc_display_apply(display, req)) {
|
||||
perror("hwc_display_commit");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = drmModeAtomicCommit(drm_fd, req, DRM_MODE_ATOMIC_NONBLOCK, NULL);
|
||||
if (ret < 0) {
|
||||
perror("drmModeAtomicCommit");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("Layer 0 got assigned to plane %u\n",
|
||||
hwc_layer_get_plane_id(layers[0]));
|
||||
printf("Layer 1 got assigned to plane %u\n",
|
||||
hwc_layer_get_plane_id(layers[1]));
|
||||
printf("Layer 2 got assigned to plane %u\n",
|
||||
hwc_layer_get_plane_id(layers[2]));
|
||||
|
||||
sleep(1);
|
||||
|
||||
drmModeAtomicFree(req);
|
||||
hwc_layer_destroy(layers[0]);
|
||||
hwc_layer_destroy(layers[1]);
|
||||
hwc_layer_destroy(layers[2]);
|
||||
hwc_output_destroy(output);
|
||||
drmModeFreeCrtc(crtc);
|
||||
drmModeFreeConnector(connector);
|
||||
hwc_display_destroy(display);
|
||||
return 0;
|
||||
}
|
23
include/libhwc.h
Normal file
23
include/libhwc.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#ifndef HWC_H
|
||||
#define HWC_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
struct hwc_display *hwc_display_create(int drm_fd);
|
||||
void hwc_display_destroy(struct hwc_display *display);
|
||||
bool hwc_display_apply(struct hwc_display *display, drmModeAtomicReq *req);
|
||||
|
||||
struct hwc_output *hwc_output_create(struct hwc_display *display,
|
||||
uint32_t crtc_id);
|
||||
void hwc_output_destroy(struct hwc_output *output);
|
||||
|
||||
struct hwc_layer *hwc_layer_create(struct hwc_output *output);
|
||||
void hwc_layer_destroy(struct hwc_layer *layer);
|
||||
void hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
||||
uint64_t value);
|
||||
uint32_t hwc_layer_get_plane_id(struct hwc_layer *layer);
|
||||
|
||||
#endif
|
34
include/list.h
Normal file
34
include/list.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct hwc_list {
|
||||
struct hwc_list *prev;
|
||||
struct hwc_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);
|
||||
|
||||
#define hwc_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); \
|
||||
&pos->member != (head); \
|
||||
pos = hwc_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); \
|
||||
&pos->member != (head); \
|
||||
pos = tmp, \
|
||||
tmp = hwc_container_of(pos->member.next, tmp, member))
|
||||
|
||||
#endif
|
53
include/private.h
Normal file
53
include/private.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
|
||||
#include "libhwc.h"
|
||||
#include "list.h"
|
||||
|
||||
struct hwc_display {
|
||||
int drm_fd;
|
||||
|
||||
struct hwc_plane *planes;
|
||||
size_t planes_len;
|
||||
|
||||
struct hwc_list outputs; /* hwc_output.link */
|
||||
};
|
||||
|
||||
struct hwc_output {
|
||||
struct hwc_display *display;
|
||||
uint32_t crtc_id;
|
||||
struct hwc_list link; /* hwc_display.outputs */
|
||||
|
||||
struct hwc_list layers; /* hwc_layer.link */
|
||||
};
|
||||
|
||||
struct hwc_layer {
|
||||
struct hwc_output *output;
|
||||
struct hwc_list link; /* hwc_output.layers */
|
||||
|
||||
struct hwc_layer_property *props;
|
||||
size_t props_len;
|
||||
|
||||
struct hwc_plane *plane;
|
||||
};
|
||||
|
||||
struct hwc_layer_property {
|
||||
char name[DRM_PROP_NAME_LEN];
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
struct hwc_plane {
|
||||
uint32_t id;
|
||||
uint32_t possible_crtcs;
|
||||
/* TODO: formats */
|
||||
|
||||
struct hwc_plane_property *props;
|
||||
size_t props_len;
|
||||
};
|
||||
|
||||
struct hwc_plane_property {
|
||||
char name[DRM_PROP_NAME_LEN];
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
#endif
|
76
layer.c
Normal file
76
layer.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "private.h"
|
||||
|
||||
struct hwc_layer *hwc_layer_create(struct hwc_output *output)
|
||||
{
|
||||
struct hwc_layer *layer;
|
||||
|
||||
layer = calloc(1, sizeof(*layer));
|
||||
if (layer == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
layer->output = output;
|
||||
hwc_list_insert(output->layers.prev, &layer->link);
|
||||
return layer;
|
||||
}
|
||||
|
||||
void hwc_layer_destroy(struct hwc_layer *layer)
|
||||
{
|
||||
free(layer->props);
|
||||
hwc_list_remove(&layer->link);
|
||||
free(layer);
|
||||
}
|
||||
|
||||
struct hwc_layer_property *layer_get_property(struct hwc_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 hwc_layer_set_property(struct hwc_layer *layer, const char *name,
|
||||
uint64_t value)
|
||||
{
|
||||
struct hwc_layer_property *props;
|
||||
struct hwc_layer_property *prop;
|
||||
|
||||
/* TODO: better error handling */
|
||||
if (strcmp(name, "CRTC_ID") == 0) {
|
||||
fprintf(stderr, "refusing to set a layer's CRTC_ID\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prop = layer_get_property(layer, name);
|
||||
if (prop == NULL) {
|
||||
props = realloc(layer->props, (layer->props_len + 1)
|
||||
* sizeof(struct hwc_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 hwc_layer_get_plane_id(struct hwc_layer *layer)
|
||||
{
|
||||
if (layer->plane == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return layer->plane->id;
|
||||
}
|
43
list.c
Normal file
43
list.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "list.h"
|
||||
|
||||
void hwc_list_init(struct hwc_list *list)
|
||||
{
|
||||
list->prev = list;
|
||||
list->next = list;
|
||||
}
|
||||
|
||||
void hwc_list_insert(struct hwc_list *list, struct hwc_list *elm)
|
||||
{
|
||||
elm->prev = list;
|
||||
elm->next = list->next;
|
||||
list->next = elm;
|
||||
elm->next->prev = elm;
|
||||
}
|
||||
|
||||
void hwc_list_remove(struct hwc_list *elm)
|
||||
{
|
||||
elm->prev->next = elm->next;
|
||||
elm->next->prev = elm->prev;
|
||||
elm->next = NULL;
|
||||
elm->prev = NULL;
|
||||
}
|
||||
|
||||
size_t hwc_list_length(const struct hwc_list *list)
|
||||
{
|
||||
struct hwc_list *e;
|
||||
size_t count;
|
||||
|
||||
count = 0;
|
||||
e = list->next;
|
||||
while (e != list) {
|
||||
e = e->next;
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool hwc_list_empty(const struct hwc_list *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
60
meson.build
Normal file
60
meson.build
Normal file
|
@ -0,0 +1,60 @@
|
|||
project(
|
||||
'hwc',
|
||||
'c',
|
||||
version: '0.0.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=0.47.0',
|
||||
default_options: [
|
||||
'c_std=c99',
|
||||
'warning_level=3',
|
||||
'werror=true',
|
||||
],
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
|
||||
add_project_arguments(cc.get_supported_arguments([
|
||||
'-Wno-missing-braces',
|
||||
'-Wno-unused-parameter',
|
||||
]), language: 'c')
|
||||
|
||||
hwc_inc = include_directories('include')
|
||||
|
||||
drm = dependency('libdrm')
|
||||
|
||||
hwc_deps = [drm]
|
||||
|
||||
hwc_lib = library(
|
||||
meson.project_name(),
|
||||
files(
|
||||
'display.c',
|
||||
'layer.c',
|
||||
'list.c',
|
||||
'output.c',
|
||||
),
|
||||
include_directories: hwc_inc,
|
||||
version: meson.project_version(),
|
||||
dependencies: hwc_deps,
|
||||
install: true,
|
||||
)
|
||||
|
||||
hwc = declare_dependency(
|
||||
link_with: hwc_lib,
|
||||
include_directories: hwc_inc,
|
||||
dependencies: hwc_deps,
|
||||
)
|
||||
|
||||
executable(
|
||||
'example',
|
||||
files('example.c'),
|
||||
dependencies: [hwc],
|
||||
)
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
pkgconfig.generate(
|
||||
libraries: hwc_lib,
|
||||
version: meson.project_version(),
|
||||
filebase: meson.project_name(),
|
||||
name: meson.project_name(),
|
||||
description: 'Hardware composer library',
|
||||
)
|
25
output.c
Normal file
25
output.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "private.h"
|
||||
|
||||
struct hwc_output *hwc_output_create(struct hwc_display *display,
|
||||
uint32_t crtc_id)
|
||||
{
|
||||
struct hwc_output *output;
|
||||
|
||||
output = calloc(1, sizeof(*output));
|
||||
if (output == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
output->display = display;
|
||||
output->crtc_id = crtc_id;
|
||||
hwc_list_init(&output->layers);
|
||||
hwc_list_insert(&display->outputs, &output->link);
|
||||
return output;
|
||||
}
|
||||
|
||||
void hwc_output_destroy(struct hwc_output *output)
|
||||
{
|
||||
hwc_list_remove(&output->link);
|
||||
free(output);
|
||||
}
|
Loading…
Reference in a new issue