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);
}
goto err;
}
- int nconnectors = config->cnames > 0 ? config->cnames : config->ncids;
+ int nconnectors =
+ config->nconnectors > 0 ? config->nconnectors : config->ncids;
int nobjects = lm->drm_plane_resource->count_planes +
nconnectors * DRM_OBJECTS_PER_CONNECTOR;
for (int i = 0; i < nconnectors; i++) {
uint32_t cid;
+ struct connector_config *con_config = NULL;
+
+ if (config->nconnectors > 0)
+ con_config = &config->connectors[i];
+
+ if (con_config) {
+ char *connector_name = con_config->name;
+ bool optional = con_config->optional;
+
+ bool found =
+ drm_find_connector(lm, connector_name, &cid);
- if (config->cnames > 0) {
- char *connector_name = config->connector_names[i];
+ bool missing_mandatory = !found && !optional;
+ bool missing_optional = !found && optional;
- if (!drm_find_connector(lm, connector_name, &cid)) {
+ if (missing_mandatory) {
+ ERROR_LOG("Lease: %s, "
+ "mandatory connector %s not found\n",
+ config->lease_name, connector_name);
+ goto err;
+ } else if (missing_optional) {
WARN_LOG("Lease: %s, "
"unknown DRM connector: %s\n",
config->lease_name, connector_name);
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];
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);
return NULL;
}
+static struct lm *drm_find_drm_device(const char *device)
+{
+ drmDevicePtr devices[64];
+ int ndevs;
+ struct lm *lm = NULL;
+
+ if (device)
+ return drm_device_get_resources(device);
+
+ ndevs = drmGetDevices2(0, devices, 64);
+
+ for (int i = 0; i < ndevs; i++) {
+ lm = drm_device_get_resources(
+ devices[i]->nodes[DRM_NODE_PRIMARY]);
+ if (lm)
+ break;
+ }
+
+ drmFreeDevices(devices, ndevs);
+
+ return lm;
+}
+
static int lm_create_leases(struct lm *lm, int num_leases,
const struct lease_config *configs)
{
struct lease_config *configs)
{
struct lease_config *default_configs = NULL;
- struct lm *lm = drm_device_get_resources(device);
+ struct lm *lm = drm_find_drm_device(device);
- if (!lm)
+ if (!lm) {
+ ERROR_LOG("No available DRM device found\n");
return NULL;
+ }
if (configs == NULL || num_leases == 0) {
num_leases = create_default_lease_configs(lm, &default_configs);