diff --git a/alloc.c b/alloc.c index 20a8065..377f663 100644 --- a/alloc.c +++ b/alloc.c @@ -125,7 +125,7 @@ plane_step_init_next(struct alloc_step *step, struct alloc_step *prev, zpos_prop = NULL; if (layer != NULL) { - zpos_prop = layer_get_property(layer, "zpos"); + zpos_prop = layer_get_property(layer, LIFTOFF_PROP_ZPOS); } if (zpos_prop != NULL && plane->type != DRM_PLANE_TYPE_PRIMARY) { step->last_layer_zpos = zpos_prop->value; @@ -168,7 +168,7 @@ has_composited_layer_over(struct liftoff_output *output, struct liftoff_layer *other_layer; struct liftoff_layer_property *zpos_prop, *other_zpos_prop; - zpos_prop = layer_get_property(layer, "zpos"); + zpos_prop = layer_get_property(layer, LIFTOFF_PROP_ZPOS); if (zpos_prop == NULL) { return false; } @@ -178,7 +178,8 @@ has_composited_layer_over(struct liftoff_output *output, continue; } - other_zpos_prop = layer_get_property(other_layer, "zpos"); + other_zpos_prop = layer_get_property(other_layer, + LIFTOFF_PROP_ZPOS); if (other_zpos_prop == NULL) { continue; } @@ -201,7 +202,7 @@ has_allocated_layer_over(struct liftoff_output *output, struct alloc_step *step, struct liftoff_layer *other_layer; struct liftoff_layer_property *zpos_prop, *other_zpos_prop; - zpos_prop = layer_get_property(layer, "zpos"); + zpos_prop = layer_get_property(layer, LIFTOFF_PROP_ZPOS); if (zpos_prop == NULL) { return false; } @@ -221,7 +222,8 @@ has_allocated_layer_over(struct liftoff_output *output, struct alloc_step *step, continue; } - other_zpos_prop = layer_get_property(other_layer, "zpos"); + other_zpos_prop = layer_get_property(other_layer, + LIFTOFF_PROP_ZPOS); if (other_zpos_prop == NULL) { continue; } @@ -284,7 +286,7 @@ check_layer_plane_compatible(struct alloc_step *step, return false; } - zpos_prop = layer_get_property(layer, "zpos"); + zpos_prop = layer_get_property(layer, LIFTOFF_PROP_ZPOS); if (zpos_prop != NULL) { if ((int)zpos_prop->value > step->last_layer_zpos && has_allocated_layer_over(output, step, layer)) { diff --git a/device.c b/device.c index df6425b..8ed4491 100644 --- a/device.c +++ b/device.c @@ -111,3 +111,36 @@ device_test_commit(struct liftoff_device *device, drmModeAtomicReq *req, return ret; } + +ssize_t +core_property_index(const char *name) +{ + if (strcmp(name, "FB_ID") == 0) { + return LIFTOFF_PROP_FB_ID; + } else if (strcmp(name, "CRTC_ID") == 0) { + return LIFTOFF_PROP_CRTC_ID; + } else if (strcmp(name, "CRTC_X") == 0) { + return LIFTOFF_PROP_CRTC_X; + } else if (strcmp(name, "CRTC_Y") == 0) { + return LIFTOFF_PROP_CRTC_Y; + } else if (strcmp(name, "CRTC_W") == 0) { + return LIFTOFF_PROP_CRTC_W; + } else if (strcmp(name, "CRTC_H") == 0) { + return LIFTOFF_PROP_CRTC_H; + } else if (strcmp(name, "SRC_X") == 0) { + return LIFTOFF_PROP_SRC_X; + } else if (strcmp(name, "SRC_Y") == 0) { + return LIFTOFF_PROP_SRC_Y; + } else if (strcmp(name, "SRC_W") == 0) { + return LIFTOFF_PROP_SRC_W; + } else if (strcmp(name, "SRC_H") == 0) { + return LIFTOFF_PROP_SRC_H; + } else if (strcmp(name, "zpos") == 0) { + return LIFTOFF_PROP_ZPOS; + } else if (strcmp(name, "alpha") == 0) { + return LIFTOFF_PROP_ALPHA; + } else if (strcmp(name, "rotation") == 0) { + return LIFTOFF_PROP_ROTATION; + } + return -1; +} diff --git a/include/private.h b/include/private.h index 4b237d0..7c030f0 100644 --- a/include/private.h +++ b/include/private.h @@ -2,6 +2,7 @@ #define PRIVATE_H #include +#include #include "list.h" #include "log.h" @@ -9,6 +10,28 @@ * given number of page-flips */ #define LIFTOFF_PRIORITY_PERIOD 60 +/** + * List of well-known KMS properties. + * + * Keep core_property_index in sync. + */ +enum liftoff_core_property { + LIFTOFF_PROP_FB_ID, + LIFTOFF_PROP_CRTC_ID, + LIFTOFF_PROP_CRTC_X, + LIFTOFF_PROP_CRTC_Y, + LIFTOFF_PROP_CRTC_W, + LIFTOFF_PROP_CRTC_H, + LIFTOFF_PROP_SRC_X, + LIFTOFF_PROP_SRC_Y, + LIFTOFF_PROP_SRC_W, + LIFTOFF_PROP_SRC_H, + LIFTOFF_PROP_ZPOS, + LIFTOFF_PROP_ALPHA, + LIFTOFF_PROP_ROTATION, + LIFTOFF_PROP_LAST, /* keep last */ +}; + struct liftoff_device { int drm_fd; @@ -43,6 +66,7 @@ struct liftoff_layer { struct liftoff_layer_property *props; size_t props_len; + ssize_t core_props[LIFTOFF_PROP_LAST]; bool force_composition; /* FB needs to be composited */ @@ -56,6 +80,7 @@ struct liftoff_layer { struct liftoff_layer_property { char name[DRM_PROP_NAME_LEN]; uint64_t value, prev_value; + ssize_t core_index; }; struct liftoff_plane { @@ -68,6 +93,7 @@ struct liftoff_plane { struct liftoff_plane_property *props; size_t props_len; + struct liftoff_plane_property *core_props[LIFTOFF_PROP_LAST]; struct liftoff_layer *layer; }; @@ -87,7 +113,7 @@ device_test_commit(struct liftoff_device *device, drmModeAtomicReq *req, uint32_t flags); struct liftoff_layer_property * -layer_get_property(struct liftoff_layer *layer, const char *name); +layer_get_property(struct liftoff_layer *layer, enum liftoff_core_property prop); void layer_get_rect(struct liftoff_layer *layer, struct liftoff_rect *rect); @@ -114,4 +140,7 @@ plane_apply(struct liftoff_plane *plane, struct liftoff_layer *layer, void output_log_layers(struct liftoff_output *output); +ssize_t +core_property_index(const char *name); + #endif diff --git a/layer.c b/layer.c index 3825780..989835f 100644 --- a/layer.c +++ b/layer.c @@ -7,6 +7,7 @@ struct liftoff_layer * liftoff_layer_create(struct liftoff_output *output) { struct liftoff_layer *layer; + size_t i; layer = calloc(1, sizeof(*layer)); if (layer == NULL) { @@ -14,6 +15,9 @@ liftoff_layer_create(struct liftoff_output *output) return NULL; } layer->output = output; + for (i = 0; i < LIFTOFF_PROP_LAST; i++) { + layer->core_props[i] = -1; + } liftoff_list_insert(output->layers.prev, &layer->link); output->layers_changed = true; return layer; @@ -39,16 +43,14 @@ liftoff_layer_destroy(struct liftoff_layer *layer) } struct liftoff_layer_property * -layer_get_property(struct liftoff_layer *layer, const char *name) +layer_get_property(struct liftoff_layer *layer, enum liftoff_core_property prop) { - size_t i; + ssize_t i; - for (i = 0; i < layer->props_len; i++) { - if (strcmp(layer->props[i].name, name) == 0) { - return &layer->props[i]; - } - } - return NULL; + i = layer->core_props[prop]; + if (i < 0) + return NULL; + return &layer->props[i]; } int @@ -57,6 +59,8 @@ liftoff_layer_set_property(struct liftoff_layer *layer, const char *name, { struct liftoff_layer_property *props; struct liftoff_layer_property *prop; + ssize_t core_prop_idx; + size_t i; if (strcmp(name, "CRTC_ID") == 0) { liftoff_log(LIFTOFF_ERROR, @@ -64,7 +68,19 @@ liftoff_layer_set_property(struct liftoff_layer *layer, const char *name, return -EINVAL; } - prop = layer_get_property(layer, name); + prop = NULL; + core_prop_idx = core_property_index(name); + if (core_prop_idx >= 0) { + prop = layer_get_property(layer, core_prop_idx); + } else { + for (i = 0; i < layer->props_len; i++) { + if (strcmp(layer->props[i].name, name) == 0) { + prop = &layer->props[i]; + break; + } + } + } + if (prop == NULL) { props = realloc(layer->props, (layer->props_len + 1) * sizeof(struct liftoff_layer_property)); @@ -75,11 +91,17 @@ liftoff_layer_set_property(struct liftoff_layer *layer, const char *name, layer->props = props; layer->props_len++; - prop = &layer->props[layer->props_len - 1]; + i = layer->props_len - 1; + prop = &layer->props[i]; memset(prop, 0, sizeof(*prop)); strncpy(prop->name, name, sizeof(prop->name) - 1); + prop->core_index = core_prop_idx; layer->changed = true; + + if (core_prop_idx >= 0) { + layer->core_props[core_prop_idx] = i; + } } prop->value = value; @@ -125,10 +147,10 @@ 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"); + x_prop = layer_get_property(layer, LIFTOFF_PROP_CRTC_X); + y_prop = layer_get_property(layer, LIFTOFF_PROP_CRTC_Y); + w_prop = layer_get_property(layer, LIFTOFF_PROP_CRTC_W); + h_prop = layer_get_property(layer, LIFTOFF_PROP_CRTC_H); rect->x = x_prop != NULL ? x_prop->value : 0; rect->y = y_prop != NULL ? y_prop->value : 0; @@ -178,7 +200,7 @@ layer_update_priority(struct liftoff_layer *layer, bool make_current) struct liftoff_layer_property *prop; /* TODO: also bump priority when updating other properties */ - prop = layer_get_property(layer, "FB_ID"); + prop = layer_get_property(layer, LIFTOFF_PROP_FB_ID); if (prop != NULL && prop->prev_value != prop->value) { layer->pending_priority++; } @@ -195,7 +217,7 @@ layer_has_fb(struct liftoff_layer *layer) { struct liftoff_layer_property *fb_id_prop; - fb_id_prop = layer_get_property(layer, "FB_ID"); + fb_id_prop = layer_get_property(layer, LIFTOFF_PROP_FB_ID); return fb_id_prop != NULL && fb_id_prop->value != 0; } @@ -204,7 +226,7 @@ layer_is_visible(struct liftoff_layer *layer) { struct liftoff_layer_property *alpha_prop; - alpha_prop = layer_get_property(layer, "alpha"); + alpha_prop = layer_get_property(layer, LIFTOFF_PROP_ALPHA); if (alpha_prop != NULL && alpha_prop->value == 0) { return false; /* fully transparent */ } diff --git a/plane.c b/plane.c index 25a7034..fd4832d 100644 --- a/plane.c +++ b/plane.c @@ -43,6 +43,7 @@ liftoff_plane_create(struct liftoff_device *device, uint32_t id) struct liftoff_plane_property *prop; uint64_t value; bool has_type = false, has_zpos = false; + ssize_t core_prop_idx; liftoff_list_for_each(plane, &device->planes, link) { if (plane->id == id) { @@ -103,6 +104,11 @@ liftoff_plane_create(struct liftoff_device *device, uint32_t id) plane->zpos = value; has_zpos = true; } + + core_prop_idx = core_property_index(prop->name); + if (core_prop_idx >= 0) { + plane->core_props[core_prop_idx] = prop; + } } drmModeFreeObjectProperties(drm_props); @@ -159,12 +165,16 @@ liftoff_plane_get_id(struct liftoff_plane *plane) } static struct liftoff_plane_property * -plane_get_property(struct liftoff_plane *plane, const char *name) +plane_get_property(struct liftoff_plane *plane, + const struct liftoff_layer_property *layer_prop) { size_t i; + if (layer_prop->core_index >= 0) + return plane->core_props[layer_prop->core_index]; + for (i = 0; i < plane->props_len; i++) { - if (strcmp(plane->props[i].name, name) == 0) { + if (strcmp(plane->props[i].name, layer_prop->name) == 0) { return &plane->props[i]; } } @@ -188,16 +198,16 @@ plane_set_prop(struct liftoff_plane *plane, drmModeAtomicReq *req, } static int -set_plane_prop_str(struct liftoff_plane *plane, drmModeAtomicReq *req, - const char *name, uint64_t value) +set_plane_core_prop(struct liftoff_plane *plane, drmModeAtomicReq *req, + enum liftoff_core_property core_prop, uint64_t value) { struct liftoff_plane_property *prop; - prop = plane_get_property(plane, name); + prop = plane->core_props[core_prop]; if (prop == NULL) { liftoff_log(LIFTOFF_DEBUG, - "plane %"PRIu32" is missing the %s property", - plane->id, name); + "plane %"PRIu32" is missing core property %d", + plane->id, core_prop); return -EINVAL; } @@ -216,33 +226,34 @@ plane_apply(struct liftoff_plane *plane, struct liftoff_layer *layer, cursor = drmModeAtomicGetCursor(req); if (layer == NULL) { - ret = set_plane_prop_str(plane, req, "FB_ID", 0); + ret = set_plane_core_prop(plane, req, LIFTOFF_PROP_FB_ID, 0); if (ret != 0) { return ret; } - return set_plane_prop_str(plane, req, "CRTC_ID", 0); + return set_plane_core_prop(plane, req, LIFTOFF_PROP_CRTC_ID, 0); } - ret = set_plane_prop_str(plane, req, "CRTC_ID", layer->output->crtc_id); + ret = set_plane_core_prop(plane, req, LIFTOFF_PROP_CRTC_ID, + layer->output->crtc_id); if (ret != 0) { return ret; } for (i = 0; i < layer->props_len; i++) { layer_prop = &layer->props[i]; - if (strcmp(layer_prop->name, "zpos") == 0) { + if (layer_prop->core_index == LIFTOFF_PROP_ZPOS) { /* We don't yet support setting the zpos property. We * only use it (read-only) during plane allocation. */ continue; } - plane_prop = plane_get_property(plane, layer_prop->name); + plane_prop = plane_get_property(plane, layer_prop); if (plane_prop == NULL) { - if (strcmp(layer_prop->name, "alpha") == 0 && + if (layer_prop->core_index == LIFTOFF_PROP_ALPHA && layer_prop->value == 0xFFFF) { continue; /* Layer is completely opaque */ } - if (strcmp(layer_prop->name, "rotation") == 0 && + if (layer_prop->core_index == LIFTOFF_PROP_ROTATION && layer_prop->value == DRM_MODE_ROTATE_0) { continue; /* Layer isn't rotated */ }