summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drm-lease-manager/drm-lease.h2
-rw-r--r--drm-lease-manager/lease-config.c32
-rw-r--r--drm-lease-manager/lease-manager.c54
-rw-r--r--drm-lease-manager/test/lease-config-test.c38
-rw-r--r--drm-lease-manager/test/lease-manager-test.c71
5 files changed, 188 insertions, 9 deletions
diff --git a/drm-lease-manager/drm-lease.h b/drm-lease-manager/drm-lease.h
index 84fa942..5670fa8 100644
--- a/drm-lease-manager/drm-lease.h
+++ b/drm-lease-manager/drm-lease.h
@@ -26,6 +26,8 @@ struct lease_handle {
struct connector_config {
char *name;
bool optional;
+ int nplanes;
+ uint32_t *planes;
};
struct lease_config {
diff --git a/drm-lease-manager/lease-config.c b/drm-lease-manager/lease-config.c
index b3f35a1..aaba6b6 100644
--- a/drm-lease-manager/lease-config.c
+++ b/drm-lease-manager/lease-config.c
@@ -23,6 +23,26 @@
#define CONFIG_ERROR(x, ...) ERROR_LOG("%s: " x, filename, ##__VA_ARGS__)
+static bool populate_connector_planes(struct connector_config *config,
+ toml_array_t *planes)
+{
+ config->nplanes = toml_array_nelem(planes);
+ config->planes = calloc(config->nplanes, sizeof(uint32_t));
+ if (!config->planes) {
+ DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
+ return false;
+ }
+
+ for (int j = 0; j < config->nplanes; j++) {
+ toml_datum_t plane = toml_int_at(planes, j);
+ if (!plane.ok) {
+ return false;
+ }
+ config->planes[j] = plane.u.i;
+ }
+ return true;
+}
+
static bool populate_connector_config(struct lease_config *config,
toml_table_t *global_table,
toml_array_t *conns)
@@ -55,6 +75,14 @@ static bool populate_connector_config(struct lease_config *config,
toml_bool_in(conn_config_data, "optional");
if (optional.ok)
config->connectors[i].optional = optional.u.b;
+
+ toml_array_t *planes =
+ toml_array_in(conn_config_data, "planes");
+ if (planes && !populate_connector_planes(conn_config, planes)) {
+ ERROR_LOG("Invalid plane id for connector: %s\n",
+ conn_config->name);
+ return false;
+ }
}
return true;
}
@@ -128,8 +156,10 @@ void release_config(int num_leases, struct lease_config *config)
for (int i = 0; i < num_leases; i++) {
struct lease_config *c = &config[i];
free(c->lease_name);
- for (int j = 0; j < c->nconnectors; j++)
+ for (int j = 0; j < c->nconnectors; j++) {
free(c->connectors[j].name);
+ free(c->connectors[j].planes);
+ }
free(c->connectors);
}
free(config);
diff --git a/drm-lease-manager/lease-manager.c b/drm-lease-manager/lease-manager.c
index 3834631..885ca29 100644
--- a/drm-lease-manager/lease-manager.c
+++ b/drm-lease-manager/lease-manager.c
@@ -216,17 +216,48 @@ static bool drm_find_connector(struct lm *lm, char *name, uint32_t *id)
return false;
}
-static bool lease_add_planes(struct lm *lm, struct lease *lease, int crtc_index)
+static void config_get_planes(struct lm *lm,
+ const struct connector_config *config,
+ int *nplanes, uint32_t **planes)
{
- for (uint32_t i = 0; i < lm->drm_plane_resource->count_planes; i++) {
- uint32_t plane_id = lm->drm_plane_resource->planes[i];
+ if (config && config->planes) {
+ *nplanes = config->nplanes;
+ *planes = config->planes;
+ } else {
+ *nplanes = (int)lm->drm_plane_resource->count_planes;
+ *planes = lm->drm_plane_resource->planes;
+ }
+}
+
+static bool lease_add_planes(struct lm *lm, struct lease *lease,
+ uint32_t crtc_index,
+ const struct connector_config *con_config)
+{
+ int nplanes;
+ uint32_t *planes;
+ uint32_t crtc_mask = (1 << crtc_index);
+
+ /* Only allow shared planes when plane list is explicitly set */
+ bool allow_shared = con_config && con_config->planes;
+
+ config_get_planes(lm, con_config, &nplanes, &planes);
+
+ for (int i = 0; i < nplanes; i++) {
+ uint32_t plane_id = planes[i];
drmModePlanePtr plane = drmModeGetPlane(lm->drm_fd, plane_id);
- assert(plane);
+ if (!plane) {
+ ERROR_LOG(
+ "Unknown plane id %d configured in lease: %s\n",
+ plane_id, lease->base.name);
+ return false;
+ }
- // Exclude planes that can be used with multiple CRTCs for now
- if (plane->possible_crtcs == (1u << crtc_index)) {
- lease->object_ids[lease->nobject_ids++] = plane_id;
+ if (plane->possible_crtcs & crtc_mask) {
+ bool shared_plane = plane->possible_crtcs != crtc_mask;
+ if (allow_shared || !shared_plane)
+ lease->object_ids[lease->nobject_ids++] =
+ plane_id;
}
drmModeFreePlane(plane);
}
@@ -404,7 +435,7 @@ static struct lease *lease_create(struct lm *lm,
goto err;
}
- if (!lease_add_planes(lm, lease, crtc_index))
+ if (!lease_add_planes(lm, lease, crtc_index, con_config))
goto err;
uint32_t crtc_id = lm->drm_resource->crtcs[crtc_index];
@@ -487,6 +518,13 @@ static struct lm *drm_device_get_resources(const char *device)
goto err;
}
+ /* Enable universal planes so that ALL planes, even primary and cursor
+ * planes can be assigned from lease configurations. */
+ if (drmSetClientCap(lm->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1)) {
+ DEBUG_LOG("drmSetClientCap failed\n");
+ goto err;
+ }
+
lm->drm_resource = drmModeGetResources(lm->drm_fd);
if (!lm->drm_resource) {
ERROR_LOG("Invalid DRM device(%s)\n", device);
diff --git a/drm-lease-manager/test/lease-config-test.c b/drm-lease-manager/test/lease-config-test.c
index 65bd32a..0dc171f 100644
--- a/drm-lease-manager/test/lease-config-test.c
+++ b/drm-lease-manager/test/lease-config-test.c
@@ -74,6 +74,43 @@ START_TEST(parse_leases)
}
END_TEST
+START_TEST(connector_config)
+{
+ ck_assert_ptr_ne(config_file, NULL);
+
+ char test_data[] = "[[lease]]\n"
+ "name = \"lease 1\"\n"
+ "connectors = [\"1\", \"b\",\"gamma\" ]\n"
+ "[b]\n"
+ "optional = true\n"
+ "planes = [1, 4, 3]\n";
+
+ write(config_fd, test_data, sizeof(test_data));
+
+ struct lease_config *config = NULL;
+ int nconfigs = parse_config(config_file, &config);
+
+ ck_assert_int_eq(nconfigs, 1);
+ ck_assert_ptr_ne(config, NULL);
+
+ ck_assert_str_eq(config[0].lease_name, "lease 1");
+ ck_assert_int_eq(config[0].nconnectors, 3);
+ ck_assert_str_eq(config[0].connectors[0].name, "1");
+ ck_assert_str_eq(config[0].connectors[1].name, "b");
+ ck_assert_str_eq(config[0].connectors[2].name, "gamma");
+
+ ck_assert(!config[0].connectors[0].optional);
+ ck_assert(config[0].connectors[1].optional);
+ ck_assert(!config[0].connectors[2].optional);
+
+ ck_assert_int_eq(config[0].connectors[1].nplanes, 3);
+ ck_assert_int_eq(config[0].connectors[1].planes[0], 1);
+ ck_assert_int_eq(config[0].connectors[1].planes[1], 4);
+ ck_assert_int_eq(config[0].connectors[1].planes[2], 3);
+
+ release_config(nconfigs, config);
+}
+END_TEST
static void add_parse_tests(Suite *s)
{
TCase *tc = tcase_create("Config file parsing tests");
@@ -81,6 +118,7 @@ static void add_parse_tests(Suite *s)
tcase_add_checked_fixture(tc, test_setup, test_shutdown);
tcase_add_test(tc, parse_leases);
+ tcase_add_test(tc, connector_config);
suite_add_tcase(s, tc);
}
diff --git a/drm-lease-manager/test/lease-manager-test.c b/drm-lease-manager/test/lease-manager-test.c
index b32cd05..fa87815 100644
--- a/drm-lease-manager/test/lease-manager-test.c
+++ b/drm-lease-manager/test/lease-manager-test.c
@@ -61,6 +61,7 @@ FAKE_VOID_FUNC(drmModeFreeEncoder, drmModeEncoderPtr);
FAKE_VALUE_FUNC(int, drmModeCreateLease, int, const uint32_t *, int, int,
uint32_t *);
FAKE_VALUE_FUNC(int, drmModeRevokeLease, int, uint32_t);
+FAKE_VALUE_FUNC(int, drmSetClientCap, int, uint64_t, uint64_t);
/************** Test fixutre functions *************************/
struct lm *g_lm = NULL;
@@ -90,6 +91,8 @@ static void test_setup(void)
drmModeGetEncoder_fake.custom_fake = get_encoder;
drmModeCreateLease_fake.custom_fake = create_lease;
+ drmSetClientCap_fake.return_val = 0;
+
ck_assert_msg(g_lm == NULL,
"Lease manager context not clear at start of test");
}
@@ -524,6 +527,73 @@ START_TEST(named_connector_config)
}
END_TEST
+/* config plane sharing */
+/* Test details: Add overlay planes to leases. Some planes are shared between
+ * multiple CRTCs. These planes are explicitly assigned to a
+ * connector. Expected results: The leases contain all of the unique planes for
+ * each CRTC. Shared planes are also included as defined by the lease
+ * configuration.
+ */
+START_TEST(config_plane_sharing)
+{
+
+ int out_cnt = 2, plane_cnt = 3, lease_cnt = 2;
+
+ ck_assert_int_eq(
+ setup_drm_test_device(out_cnt, out_cnt, out_cnt, plane_cnt), true);
+
+ drmModeConnector connectors[] = {
+ CONNECTOR_FULL(CONNECTOR_ID(0), ENCODER_ID(0), &ENCODER_ID(0), 1,
+ DRM_MODE_CONNECTOR_HDMIA, 1),
+ CONNECTOR_FULL(CONNECTOR_ID(1), ENCODER_ID(1), &ENCODER_ID(1), 1,
+ DRM_MODE_CONNECTOR_VGA, 3),
+ };
+
+ drmModeEncoder encoders[] = {
+ ENCODER(ENCODER_ID(0), CRTC_ID(0), 0x1),
+ ENCODER(ENCODER_ID(1), CRTC_ID(1), 0x2),
+ };
+
+ drmModePlane planes[] = {
+ PLANE(PLANE_ID(0), 0x2),
+ PLANE(PLANE_ID(1), 0x1),
+ PLANE(PLANE_ID(2), 0x3),
+ };
+
+ setup_test_device_layout(connectors, encoders, planes);
+
+ struct lease_config lconfig[] = {
+ [0] =
+ {
+ .lease_name = "Lease Config Test 1",
+ .nconnectors = 1,
+ .connectors =
+ (struct connector_config[]){
+ {.name = "HDMI-A-1",
+ .nplanes = 2,
+ .planes = (uint32_t[]){PLANE_ID(1), PLANE_ID(2)}},
+ },
+ },
+ [1] =
+ {
+ .lease_name = "Lease Config Test 2",
+ .nconnectors = 1,
+ .connectors =
+ (struct connector_config[]){
+ {.name = "VGA-3"},
+ },
+ },
+ };
+
+ struct lease_handle **handles = create_leases(lease_cnt, lconfig);
+
+ CHECK_LEASE_OBJECTS(handles[0], PLANE_ID(1), PLANE_ID(2), CRTC_ID(0),
+ CONNECTOR_ID(0));
+ CHECK_LEASE_OBJECTS(handles[1], PLANE_ID(0), CRTC_ID(1),
+ CONNECTOR_ID(1));
+}
+END_TEST
+
static void add_lease_config_tests(Suite *s)
{
TCase *tc = tcase_create("Lease configuration");
@@ -533,6 +603,7 @@ static void add_lease_config_tests(Suite *s)
tcase_add_test(tc, multiple_connector_lease);
tcase_add_test(tc, single_failed_lease);
tcase_add_test(tc, named_connector_config);
+ tcase_add_test(tc, config_plane_sharing);
suite_add_tcase(s, tc);
}