[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