Userspace clients which wish to receive all DRM planes (primary and
cursor planes in addition to the traditional overlay planes) may set the
DRM_CLIENT_CAP_UNIVERSAL_PLANES capability.

v2: Hide behind drm.universal_planes module option [suggested by
    Daniel Vetter]

Signed-off-by: Matt Roper <matthew.d.roper at intel.com>
---
 drivers/gpu/drm/drm_crtc.c  | 20 +++++++++++++++-----
 drivers/gpu/drm/drm_ioctl.c |  7 +++++++
 drivers/gpu/drm/drm_stub.c  |  5 +++++
 include/drm/drmP.h          |  6 ++++++
 include/uapi/drm/drm.h      |  8 ++++++++
 5 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 18321fb..d8b7099 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1959,6 +1959,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void 
*data,
        struct drm_plane *plane;
        uint32_t __user *plane_ptr;
        int copied = 0, ret = 0;
+       unsigned num_planes;

        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
@@ -1966,17 +1967,26 @@ int drm_mode_getplane_res(struct drm_device *dev, void 
*data,
        drm_modeset_lock_all(dev);
        config = &dev->mode_config;

+       if (file_priv->universal_planes)
+               num_planes = config->num_total_plane;
+       else
+               num_planes = config->num_overlay_plane;
+
        /*
         * This ioctl is called twice, once to determine how much space is
         * needed, and the 2nd time to fill it.
         */
-       if (config->num_overlay_plane &&
-           (plane_resp->count_planes >= config->num_overlay_plane)) {
+       if (num_planes &&
+           (plane_resp->count_planes >= num_planes)) {
                plane_ptr = (uint32_t __user *)(unsigned 
long)plane_resp->plane_id_ptr;

                list_for_each_entry(plane, &config->plane_list, head) {
-                       /* Only advertise overlays to userspace for now. */
-                       if (plane->type != DRM_PLANE_TYPE_OVERLAY)
+                       /*
+                        * Unless userspace set the 'universal planes'
+                        * capability bit, only advertise overlays.
+                        */
+                       if (plane->type != DRM_PLANE_TYPE_OVERLAY &&
+                           !file_priv->universal_planes)
                                continue;

                        if (put_user(plane->base.id, plane_ptr + copied)) {
@@ -1986,7 +1996,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void 
*data,
                        copied++;
                }
        }
-       plane_resp->count_planes = config->num_overlay_plane;
+       plane_resp->count_planes = num_planes;

 out:
        drm_modeset_unlock_all(dev);
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index f4dc9b7..93a4204 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -328,6 +328,13 @@ drm_setclientcap(struct drm_device *dev, void *data, 
struct drm_file *file_priv)
                        return -EINVAL;
                file_priv->stereo_allowed = req->value;
                break;
+       case DRM_CLIENT_CAP_UNIVERSAL_PLANES:
+               if (!drm_universal_planes)
+                       return -EINVAL;
+               if (req->value > 1)
+                       return -EINVAL;
+               file_priv->universal_planes = req->value;
+               break;
        default:
                return -EINVAL;
        }
diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c
index fac6f98..4c24c3a 100644
--- a/drivers/gpu/drm/drm_stub.c
+++ b/drivers/gpu/drm/drm_stub.c
@@ -45,6 +45,10 @@ EXPORT_SYMBOL(drm_debug);
 unsigned int drm_rnodes = 0;   /* 1 to enable experimental render nodes API */
 EXPORT_SYMBOL(drm_rnodes);

+/* 1 to allow user space to request universal planes (experimental) */
+unsigned int drm_universal_planes = 0;
+EXPORT_SYMBOL(drm_universal_planes);
+
 unsigned int drm_vblank_offdelay = 5000;    /* Default to 5000 msecs. */
 EXPORT_SYMBOL(drm_vblank_offdelay);

@@ -68,6 +72,7 @@ MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic 
timestamps");

 module_param_named(debug, drm_debug, int, 0600);
 module_param_named(rnodes, drm_rnodes, int, 0600);
+module_param_named(universal_planes, drm_universal_planes, int, 0600);
 module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600);
 module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 
0600);
 module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 9e347fa..52d100c 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -409,6 +409,11 @@ struct drm_file {
        unsigned is_master :1;
        /* true when the client has asked us to expose stereo 3D mode flags */
        unsigned stereo_allowed :1;
+       /*
+        * true if client understands CRTC primary planes and cursor planes
+        * in the plane list
+        */
+       unsigned universal_planes:1;

        struct pid *pid;
        kuid_t uid;
@@ -1412,6 +1417,7 @@ extern void drm_put_dev(struct drm_device *dev);
 extern void drm_unplug_dev(struct drm_device *dev);
 extern unsigned int drm_debug;
 extern unsigned int drm_rnodes;
+extern unsigned int drm_universal_planes;

 extern unsigned int drm_vblank_offdelay;
 extern unsigned int drm_timestamp_precision;
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index ec6b259..9abbeb9 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -646,6 +646,14 @@ struct drm_get_cap {
  */
 #define DRM_CLIENT_CAP_STEREO_3D       1

+/**
+ * DRM_CLIENT_CAP_UNIVERSAL_PLANES
+ *
+ * If set to 1, the DRM core will expose all planes (overlay, primary, and
+ * cursor) to userspace.
+ */
+#define DRM_CLIENT_CAP_UNIVERSAL_PLANES  2
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
        __u64 capability;
-- 
1.8.5.1

Reply via email to