diff options
-rw-r--r-- | drm-lease-manager/drm-lease.h | 2 | ||||
-rw-r--r-- | drm-lease-manager/lease-config.c | 32 | ||||
-rw-r--r-- | drm-lease-manager/lease-manager.c | 54 | ||||
-rw-r--r-- | drm-lease-manager/test/lease-config-test.c | 38 | ||||
-rw-r--r-- | drm-lease-manager/test/lease-manager-test.c | 71 |
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); } |