Force add a primary plane to lease
[src/drm-lease-manager.git] / drm-lease-manager / lease-manager.c
index 3834631..7147078 100644 (file)
@@ -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];
@@ -473,9 +504,12 @@ err:
        return -1;
 }
 
-static struct lm *drm_device_get_resources(const char *device)
+static struct lm *drm_device_get_resources(const char *device,
+                                          bool universal_plane)
 {
        struct lm *lm = calloc(1, sizeof(struct lm));
+       uint64_t value = 0;
+
        if (!lm) {
                DEBUG_LOG("Memory allocation failed: %s\n", strerror(errno));
                return NULL;
@@ -487,6 +521,20 @@ static struct lm *drm_device_get_resources(const char *device)
                goto err;
        }
 
+       /* When -u option set at args. Enable universal planes so that ALL
+          planes, even primary and cursor planes can be assigned from lease
+          configurations. */
+       if (universal_plane == true) {
+               DEBUG_LOG("Enable universal plean mode.\n");
+               value = 1;
+       }
+
+       if (drmSetClientCap(lm->drm_fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES,
+                           value)) {
+               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);
@@ -494,6 +542,13 @@ static struct lm *drm_device_get_resources(const char *device)
                goto err;
        }
 
+       if (lm->drm_resource->count_connectors <= 0 ||
+           lm->drm_resource->count_crtcs <= 0 ||
+           lm->drm_resource->count_encoders <= 0) {
+               DEBUG_LOG("Insufficient DRM resources on device(%s)\n", device);
+               goto err;
+       }
+
        lm->drm_plane_resource = drmModeGetPlaneResources(lm->drm_fd);
        if (!lm->drm_plane_resource) {
                DEBUG_LOG("drmModeGetPlaneResources failed: %s\n",
@@ -532,20 +587,20 @@ err:
        return NULL;
 }
 
-static struct lm *drm_find_drm_device(const char *device)
+static struct lm *drm_find_drm_device(const char *device, bool universal_plane)
 {
        drmDevicePtr devices[64];
        int ndevs;
        struct lm *lm = NULL;
 
        if (device)
-               return drm_device_get_resources(device);
+               return drm_device_get_resources(device, universal_plane);
 
        ndevs = drmGetDevices2(0, devices, 64);
 
        for (int i = 0; i < ndevs; i++) {
                lm = drm_device_get_resources(
-                   devices[i]->nodes[DRM_NODE_PRIMARY]);
+                   devices[i]->nodes[DRM_NODE_PRIMARY], universal_plane);
                if (lm)
                        break;
        }
@@ -581,10 +636,11 @@ static int lm_create_leases(struct lm *lm, int num_leases,
 }
 
 struct lm *lm_create_with_config(const char *device, int num_leases,
-                                struct lease_config *configs)
+                                struct lease_config *configs,
+                                bool universal_plane)
 {
        struct lease_config *default_configs = NULL;
-       struct lm *lm = drm_find_drm_device(device);
+       struct lm *lm = drm_find_drm_device(device, universal_plane);
 
        if (!lm) {
                ERROR_LOG("No available DRM device found\n");
@@ -613,7 +669,7 @@ struct lm *lm_create_with_config(const char *device, int num_leases,
 
 struct lm *lm_create(const char *device)
 {
-       return lm_create_with_config(device, 0, NULL);
+       return lm_create_with_config(device, 0, NULL, false);
 }
 
 void lm_destroy(struct lm *lm)