[PATCH] vmwgfx: Reinstate the update_layout ioctl
Thomas Hellstrom
thellstrom at vmware.com
Wed Nov 2 00:54:56 PDT 2011
Dave,
I saw the other two patches going into drm-fixes-staging, but this one
was not included.
It's pretty important because it fixes fighting when setting monitor
topology between gnome-settings-daemon and the vmware-user daemon.
Thanks
Thomas
On 10/25/2011 11:35 PM, Thomas Hellstrom wrote:
> We need to redefine a connector as "connected" if it matches a window
> in the host preferred GUI layout.
> Otherwise "smart" window managers would turn on Xorg outputs that we don't
> want to be on.
>
> This reinstates the update_layout and adds the following information to
> the modesetting system.
> a) Connection status<-> Equivalent to real hardware connection status
> b) Preferred mode<-> Equivalent to real hardware reading EDID
> c) Host window position<-> Equivalent to a real hardware scanout address
> dynamic register.
>
> It should be noted that there is no assumption here about what should be
> displayed and where. Only how to access the host windows.
>
> This also bumps minor to signal availability of the new IOCTL.
>
> Based on code originally written by Jakob Bornecrantz
>
> Signed-off-by: Thomas Hellstrom<thellstrom at vmware.com>
> ---
> drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 6 +++
> drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 ++-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 66 ++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 9 ++++-
> include/drm/vmwgfx_drm.h | 51 +++++++++++++--------------
> 5 files changed, 107 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> index b8eb8cd..0bc20c1 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
> @@ -103,6 +103,9 @@
> #define DRM_IOCTL_VMW_PRESENT_READBACK \
> DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_PRESENT_READBACK, \
> struct drm_vmw_present_readback_arg)
> +#define DRM_IOCTL_VMW_UPDATE_LAYOUT \
> + DRM_IOW(DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT, \
> + struct drm_vmw_update_layout_arg)
>
> /**
> * The core DRM version of this macro doesn't account for
> @@ -165,6 +168,9 @@ static struct drm_ioctl_desc vmw_ioctls[] = {
> VMW_IOCTL_DEF(VMW_PRESENT_READBACK,
> vmw_present_readback_ioctl,
> DRM_MASTER | DRM_AUTH | DRM_UNLOCKED),
> + VMW_IOCTL_DEF(VMW_UPDATE_LAYOUT,
> + vmw_kms_update_layout_ioctl,
> + DRM_MASTER | DRM_UNLOCKED),
> };
>
> static struct pci_device_id vmw_pci_id_list[] = {
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> index 30589d0..8cca91a 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
> @@ -40,9 +40,9 @@
> #include "ttm/ttm_module.h"
> #include "vmwgfx_fence.h"
>
> -#define VMWGFX_DRIVER_DATE "20111008"
> +#define VMWGFX_DRIVER_DATE "20111025"
> #define VMWGFX_DRIVER_MAJOR 2
> -#define VMWGFX_DRIVER_MINOR 2
> +#define VMWGFX_DRIVER_MINOR 3
> #define VMWGFX_DRIVER_PATCHLEVEL 0
> #define VMWGFX_FILE_PAGE_OFFSET 0x00100000
> #define VMWGFX_FIFO_STATIC_SIZE (1024*1024)
> @@ -633,6 +633,8 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
> struct drm_vmw_fence_rep __user *user_fence_rep,
> struct drm_vmw_rect *clips,
> uint32_t num_clips);
> +int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file_priv);
>
> /**
> * Overlay control - vmwgfx_overlay.c
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index 8b14dfd..f9a0f98 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -1517,6 +1517,8 @@ int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
> du->pref_width = rects[du->unit].w;
> du->pref_height = rects[du->unit].h;
> du->pref_active = true;
> + du->gui_x = rects[du->unit].x;
> + du->gui_y = rects[du->unit].y;
> } else {
> du->pref_width = 800;
> du->pref_height = 600;
> @@ -1572,12 +1574,14 @@ vmw_du_connector_detect(struct drm_connector *connector, bool force)
> uint32_t num_displays;
> struct drm_device *dev = connector->dev;
> struct vmw_private *dev_priv = vmw_priv(dev);
> + struct vmw_display_unit *du = vmw_connector_to_du(connector);
>
> mutex_lock(&dev_priv->hw_mutex);
> num_displays = vmw_read(dev_priv, SVGA_REG_NUM_DISPLAYS);
> mutex_unlock(&dev_priv->hw_mutex);
>
> - return ((vmw_connector_to_du(connector)->unit< num_displays) ?
> + return ((vmw_connector_to_du(connector)->unit< num_displays&&
> + du->pref_active) ?
> connector_status_connected : connector_status_disconnected);
> }
>
> @@ -1723,3 +1727,63 @@ int vmw_du_connector_set_property(struct drm_connector *connector,
> {
> return 0;
> }
> +
> +
> +int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *file_priv)
> +{
> + struct vmw_private *dev_priv = vmw_priv(dev);
> + struct drm_vmw_update_layout_arg *arg =
> + (struct drm_vmw_update_layout_arg *)data;
> + struct vmw_master *vmaster = vmw_master(file_priv->master);
> + void __user *user_rects;
> + struct drm_vmw_rect *rects;
> + unsigned rects_size;
> + int ret;
> + int i;
> + struct drm_mode_config *mode_config =&dev->mode_config;
> +
> + ret = ttm_read_lock(&vmaster->lock, true);
> + if (unlikely(ret != 0))
> + return ret;
> +
> + if (!arg->num_outputs) {
> + struct drm_vmw_rect def_rect = {0, 0, 800, 600};
> + vmw_du_update_layout(dev_priv, 1,&def_rect);
> + goto out_unlock;
> + }
> +
> + rects_size = arg->num_outputs * sizeof(struct drm_vmw_rect);
> + rects = kzalloc(rects_size, GFP_KERNEL);
> + if (unlikely(!rects)) {
> + ret = -ENOMEM;
> + goto out_unlock;
> + }
> +
> + user_rects = (void __user *)(unsigned long)arg->rects;
> + ret = copy_from_user(rects, user_rects, rects_size);
> + if (unlikely(ret != 0)) {
> + DRM_ERROR("Failed to get rects.\n");
> + ret = -EFAULT;
> + goto out_free;
> + }
> +
> + for (i = 0; i< arg->num_outputs; ++i) {
> + if (rects->x< 0 ||
> + rects->y< 0 ||
> + rects->x + rects->w> mode_config->max_width ||
> + rects->y + rects->h> mode_config->max_height) {
> + DRM_ERROR("Invalid GUI layout.\n");
> + ret = -EINVAL;
> + goto out_free;
> + }
> + }
> +
> + vmw_du_update_layout(dev_priv, arg->num_outputs, rects);
> +
> +out_free:
> + kfree(rects);
> +out_unlock:
> + ttm_read_unlock(&vmaster->lock);
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> index db0b901..815cf99 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
> @@ -96,6 +96,12 @@ struct vmw_display_unit {
> unsigned pref_height;
> bool pref_active;
> struct drm_display_mode *pref_mode;
> +
> + /*
> + * Gui positioning
> + */
> + int gui_x;
> + int gui_y;
> };
>
> #define vmw_crtc_to_du(x) \
> @@ -126,8 +132,7 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
> int vmw_du_connector_set_property(struct drm_connector *connector,
> struct drm_property *property,
> uint64_t val);
> -int vmw_du_update_layout(struct vmw_private *dev_priv, unsigned num,
> - struct drm_vmw_rect *rects);
> +
>
> /*
> * Legacy display unit functions - vmwgfx_ldu.c
> diff --git a/include/drm/vmwgfx_drm.h b/include/drm/vmwgfx_drm.h
> index cd7cd81..bcb0912 100644
> --- a/include/drm/vmwgfx_drm.h
> +++ b/include/drm/vmwgfx_drm.h
> @@ -54,7 +54,7 @@
> #define DRM_VMW_FENCE_EVENT 17
> #define DRM_VMW_PRESENT 18
> #define DRM_VMW_PRESENT_READBACK 19
> -
> +#define DRM_VMW_UPDATE_LAYOUT 20
>
> /*************************************************************************/
> /**
> @@ -552,31 +552,6 @@ struct drm_vmw_get_3d_cap_arg {
>
> /*************************************************************************/
> /**
> - * DRM_VMW_UPDATE_LAYOUT - Update layout
> - *
> - * Updates the preferred modes and connection status for connectors. The
> - * command conisits of one drm_vmw_update_layout_arg pointing out a array
> - * of num_outputs drm_vmw_rect's.
> - */
> -
> -/**
> - * struct drm_vmw_update_layout_arg
> - *
> - * @num_outputs: number of active
> - * @rects: pointer to array of drm_vmw_rect
> - *
> - * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
> - */
> -
> -struct drm_vmw_update_layout_arg {
> - uint32_t num_outputs;
> - uint32_t pad64;
> - uint64_t rects;
> -};
> -
> -
> -/*************************************************************************/
> -/**
> * DRM_VMW_FENCE_WAIT
> *
> * Waits for a fence object to signal. The wait is interruptible, so that
> @@ -788,4 +763,28 @@ struct drm_vmw_present_readback_arg {
> uint64_t clips_ptr;
> uint64_t fence_rep;
> };
> +
> +/*************************************************************************/
> +/**
> + * DRM_VMW_UPDATE_LAYOUT - Update layout
> + *
> + * Updates the preferred modes and connection status for connectors. The
> + * command consists of one drm_vmw_update_layout_arg pointing to an array
> + * of num_outputs drm_vmw_rect's.
> + */
> +
> +/**
> + * struct drm_vmw_update_layout_arg
> + *
> + * @num_outputs: number of active connectors
> + * @rects: pointer to array of drm_vmw_rect cast to an uint64_t
> + *
> + * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
> + */
> +struct drm_vmw_update_layout_arg {
> + uint32_t num_outputs;
> + uint32_t pad64;
> + uint64_t rects;
> +};
> +
> #endif
>
More information about the dri-devel
mailing list