drm: Add a STEREO_3D capability to the SET_CLIENT_CAP ioctl
authorDamien Lespiau <damien.lespiau@intel.com>
Wed, 25 Sep 2013 15:45:22 +0000 (16:45 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 1 Oct 2013 05:45:27 +0000 (07:45 +0200)
This capability allows user space to control the delivery of modes with
the 3D flags set. This is to not play games with current user space
users not knowing anything about stereo 3D flags and that could try
to set a mode with one or several of those bits set.

So, the plan is to remove the stereo modes from the list of modes we
give to DRM clients by default, and let them through if we are being
told otherwise.

stereo_allowed is bound to the drm_file structure to make it a
per-client setting, not a global one.

v2: Replace clearing 3D flags by discarding the stereo modes now that
    they are regular modes.
v3: SET_CAP -> SET_CLIENT_CAP rename (Chris Wilson)

Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
Acked-by: Dave Airlie <airlied@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_ioctl.c
include/drm/drmP.h
include/uapi/drm/drm.h

index e79577cb46650a306ccc16eed00c9847d525fd91..454ac8a6381cf590c7d2eff615df38c659c19a2a 100644 (file)
@@ -1581,6 +1581,19 @@ out:
        return ret;
 }
 
+static bool drm_mode_expose_to_userspace(const struct drm_display_mode *mode,
+                                        const struct drm_file *file_priv)
+{
+       /*
+        * If user-space hasn't configured the driver to expose the stereo 3D
+        * modes, don't expose them.
+        */
+       if (!file_priv->stereo_allowed && drm_mode_is_stereo(mode))
+               return false;
+
+       return true;
+}
+
 /**
  * drm_mode_getconnector - get connector configuration
  * @dev: drm device for the ioctl
@@ -1646,7 +1659,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 
        /* delayed so we get modes regardless of pre-fill_modes state */
        list_for_each_entry(mode, &connector->modes, head)
-               mode_count++;
+               if (drm_mode_expose_to_userspace(mode, file_priv))
+                       mode_count++;
 
        out_resp->connector_id = connector->base.id;
        out_resp->connector_type = connector->connector_type;
@@ -1668,6 +1682,9 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
                copied = 0;
                mode_ptr = (struct drm_mode_modeinfo __user *)(unsigned long)out_resp->modes_ptr;
                list_for_each_entry(mode, &connector->modes, head) {
+                       if (!drm_mode_expose_to_userspace(mode, file_priv))
+                               continue;
+
                        drm_crtc_convert_to_umode(&u_mode, mode);
                        if (copy_to_user(mode_ptr + copied,
                                         &u_mode, sizeof(u_mode))) {
index 15da4124ee12bb9ca1eaa5859b262bedd1e0d0b3..dffc836144cc96266a616902aa457b46c0ef1b33 100644 (file)
@@ -308,7 +308,19 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 int
 drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
 {
-       return -EINVAL;
+       struct drm_set_client_cap *req = data;
+
+       switch (req->capability) {
+       case DRM_CLIENT_CAP_STEREO_3D:
+               if (req->value > 1)
+                       return -EINVAL;
+               file_priv->stereo_allowed = req->value;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
 /**
index dbc86b06a7245dac5e37848e97a7e145b5a47796..c65f496ad6b63dd1c8c22f289dfaf5b77a0c7048 100644 (file)
@@ -433,6 +433,9 @@ struct drm_file {
        struct drm_master *master; /* master this node is currently associated with
                                      N.B. not always minor->master */
 
+       /* true when the client has asked us to expose stereo 3D mode flags */
+       bool stereo_allowed;
+
        /**
         * fbs - List of framebuffers associated with this file.
         *
index 526baed365ff29843aeb710a8286734ce697f71a..9b24d65fed72b9d06843cba89ebeeabff07fb71f 100644 (file)
@@ -627,6 +627,15 @@ struct drm_get_cap {
        __u64 value;
 };
 
+/**
+ * DRM_CLIENT_CAP_STEREO_3D
+ *
+ * if set to 1, the DRM core will expose the stereo 3D capabilities of the
+ * monitor by advertising the supported 3D layouts in the flags of struct
+ * drm_mode_modeinfo.
+ */
+#define DRM_CLIENT_CAP_STEREO_3D       1
+
 /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
 struct drm_set_client_cap {
        __u64 capability;