Commit 8fbf9d92 authored by Thomas Hellstrom's avatar Thomas Hellstrom

drm/vmwgfx: Implement the cursor_set2 callback v2

Fixes native drm clients like Fedora 23 Wayland which now appears to
be able to use cursor hotspots without strange cursor offsets.
Also fixes a couple of ignored error paths.

Since the core drm cursor hotspot is incompatible with the legacy vmwgfx
hotspot (the core drm hotspot is reset when the drm_mode_cursor ioctl
is used), we need to keep track of both and add them when the device
hotspot is set. We assume that either is always zero.
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarSinclair Yeh <syeh@vmware.com>
parent 99f9be4c
...@@ -1233,6 +1233,7 @@ static void vmw_master_drop(struct drm_device *dev, ...@@ -1233,6 +1233,7 @@ static void vmw_master_drop(struct drm_device *dev,
vmw_fp->locked_master = drm_master_get(file_priv->master); vmw_fp->locked_master = drm_master_get(file_priv->master);
ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile); ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
vmw_kms_legacy_hotspot_clear(dev_priv);
if (unlikely((ret != 0))) { if (unlikely((ret != 0))) {
DRM_ERROR("Unable to lock TTM at VT switch.\n"); DRM_ERROR("Unable to lock TTM at VT switch.\n");
drm_master_put(&vmw_fp->locked_master); drm_master_put(&vmw_fp->locked_master);
......
...@@ -925,6 +925,7 @@ int vmw_kms_present(struct vmw_private *dev_priv, ...@@ -925,6 +925,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
uint32_t num_clips); uint32_t num_clips);
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv); struct drm_file *file_priv);
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv);
int vmw_dumb_create(struct drm_file *file_priv, int vmw_dumb_create(struct drm_file *file_priv,
struct drm_device *dev, struct drm_device *dev,
......
...@@ -133,13 +133,19 @@ void vmw_cursor_update_position(struct vmw_private *dev_priv, ...@@ -133,13 +133,19 @@ void vmw_cursor_update_position(struct vmw_private *dev_priv,
vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT); vmw_mmio_write(++count, fifo_mem + SVGA_FIFO_CURSOR_COUNT);
} }
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height) /*
* vmw_du_crtc_cursor_set2 - Driver cursor_set2 callback.
*/
int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height,
int32_t hot_x, int32_t hot_y)
{ {
struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct vmw_private *dev_priv = vmw_priv(crtc->dev);
struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
struct vmw_surface *surface = NULL; struct vmw_surface *surface = NULL;
struct vmw_dma_buffer *dmabuf = NULL; struct vmw_dma_buffer *dmabuf = NULL;
s32 hotspot_x, hotspot_y;
int ret; int ret;
/* /*
...@@ -151,6 +157,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -151,6 +157,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
*/ */
drm_modeset_unlock_crtc(crtc); drm_modeset_unlock_crtc(crtc);
drm_modeset_lock_all(dev_priv->dev); drm_modeset_lock_all(dev_priv->dev);
hotspot_x = hot_x + du->hotspot_x;
hotspot_y = hot_y + du->hotspot_y;
/* A lot of the code assumes this */ /* A lot of the code assumes this */
if (handle && (width != 64 || height != 64)) { if (handle && (width != 64 || height != 64)) {
...@@ -187,31 +195,34 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, ...@@ -187,31 +195,34 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
vmw_dmabuf_unreference(&du->cursor_dmabuf); vmw_dmabuf_unreference(&du->cursor_dmabuf);
/* setup new image */ /* setup new image */
ret = 0;
if (surface) { if (surface) {
/* vmw_user_surface_lookup takes one reference */ /* vmw_user_surface_lookup takes one reference */
du->cursor_surface = surface; du->cursor_surface = surface;
du->cursor_surface->snooper.crtc = crtc; du->cursor_surface->snooper.crtc = crtc;
du->cursor_age = du->cursor_surface->snooper.age; du->cursor_age = du->cursor_surface->snooper.age;
vmw_cursor_update_image(dev_priv, surface->snooper.image, ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
64, 64, du->hotspot_x, du->hotspot_y); 64, 64, hotspot_x, hotspot_y);
} else if (dmabuf) { } else if (dmabuf) {
/* vmw_user_surface_lookup takes one reference */ /* vmw_user_surface_lookup takes one reference */
du->cursor_dmabuf = dmabuf; du->cursor_dmabuf = dmabuf;
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height, ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
du->hotspot_x, du->hotspot_y); hotspot_x, hotspot_y);
} else { } else {
vmw_cursor_update_position(dev_priv, false, 0, 0); vmw_cursor_update_position(dev_priv, false, 0, 0);
ret = 0;
goto out; goto out;
} }
if (!ret) {
vmw_cursor_update_position(dev_priv, true, vmw_cursor_update_position(dev_priv, true,
du->cursor_x + du->hotspot_x, du->cursor_x + hotspot_x,
du->cursor_y + du->hotspot_y); du->cursor_y + hotspot_y);
du->core_hotspot_x = hot_x;
du->core_hotspot_y = hot_y;
}
ret = 0;
out: out:
drm_modeset_unlock_all(dev_priv->dev); drm_modeset_unlock_all(dev_priv->dev);
drm_modeset_lock_crtc(crtc, crtc->cursor); drm_modeset_lock_crtc(crtc, crtc->cursor);
...@@ -239,8 +250,10 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) ...@@ -239,8 +250,10 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
drm_modeset_lock_all(dev_priv->dev); drm_modeset_lock_all(dev_priv->dev);
vmw_cursor_update_position(dev_priv, shown, vmw_cursor_update_position(dev_priv, shown,
du->cursor_x + du->hotspot_x, du->cursor_x + du->hotspot_x +
du->cursor_y + du->hotspot_y); du->core_hotspot_x,
du->cursor_y + du->hotspot_y +
du->core_hotspot_y);
drm_modeset_unlock_all(dev_priv->dev); drm_modeset_unlock_all(dev_priv->dev);
drm_modeset_lock_crtc(crtc, crtc->cursor); drm_modeset_lock_crtc(crtc, crtc->cursor);
...@@ -334,6 +347,29 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, ...@@ -334,6 +347,29 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
ttm_bo_unreserve(bo); ttm_bo_unreserve(bo);
} }
/**
* vmw_kms_legacy_hotspot_clear - Clear legacy hotspots
*
* @dev_priv: Pointer to the device private struct.
*
* Clears all legacy hotspots.
*/
void vmw_kms_legacy_hotspot_clear(struct vmw_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
struct vmw_display_unit *du;
struct drm_crtc *crtc;
drm_modeset_lock_all(dev);
drm_for_each_crtc(crtc, dev) {
du = vmw_crtc_to_du(crtc);
du->hotspot_x = 0;
du->hotspot_y = 0;
}
drm_modeset_unlock_all(dev);
}
void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
{ {
struct drm_device *dev = dev_priv->dev; struct drm_device *dev = dev_priv->dev;
...@@ -351,7 +387,9 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) ...@@ -351,7 +387,9 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
du->cursor_age = du->cursor_surface->snooper.age; du->cursor_age = du->cursor_surface->snooper.age;
vmw_cursor_update_image(dev_priv, vmw_cursor_update_image(dev_priv,
du->cursor_surface->snooper.image, du->cursor_surface->snooper.image,
64, 64, du->hotspot_x, du->hotspot_y); 64, 64,
du->hotspot_x + du->core_hotspot_x,
du->hotspot_y + du->core_hotspot_y);
} }
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
......
...@@ -159,6 +159,8 @@ struct vmw_display_unit { ...@@ -159,6 +159,8 @@ struct vmw_display_unit {
int hotspot_x; int hotspot_x;
int hotspot_y; int hotspot_y;
s32 core_hotspot_x;
s32 core_hotspot_y;
unsigned unit; unsigned unit;
...@@ -193,8 +195,9 @@ void vmw_du_crtc_restore(struct drm_crtc *crtc); ...@@ -193,8 +195,9 @@ void vmw_du_crtc_restore(struct drm_crtc *crtc);
void vmw_du_crtc_gamma_set(struct drm_crtc *crtc, void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
u16 *r, u16 *g, u16 *b, u16 *r, u16 *g, u16 *b,
uint32_t start, uint32_t size); uint32_t start, uint32_t size);
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, int vmw_du_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
uint32_t handle, uint32_t width, uint32_t height); uint32_t handle, uint32_t width, uint32_t height,
int32_t hot_x, int32_t hot_y);
int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
int vmw_du_connector_dpms(struct drm_connector *connector, int mode); int vmw_du_connector_dpms(struct drm_connector *connector, int mode);
void vmw_du_connector_save(struct drm_connector *connector); void vmw_du_connector_save(struct drm_connector *connector);
......
...@@ -297,7 +297,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) ...@@ -297,7 +297,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
static struct drm_crtc_funcs vmw_legacy_crtc_funcs = { static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.save = vmw_du_crtc_save, .save = vmw_du_crtc_save,
.restore = vmw_du_crtc_restore, .restore = vmw_du_crtc_restore,
.cursor_set = vmw_du_crtc_cursor_set, .cursor_set2 = vmw_du_crtc_cursor_set2,
.cursor_move = vmw_du_crtc_cursor_move, .cursor_move = vmw_du_crtc_cursor_move,
.gamma_set = vmw_du_crtc_gamma_set, .gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_ldu_crtc_destroy, .destroy = vmw_ldu_crtc_destroy,
......
...@@ -533,7 +533,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, ...@@ -533,7 +533,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
.save = vmw_du_crtc_save, .save = vmw_du_crtc_save,
.restore = vmw_du_crtc_restore, .restore = vmw_du_crtc_restore,
.cursor_set = vmw_du_crtc_cursor_set, .cursor_set2 = vmw_du_crtc_cursor_set2,
.cursor_move = vmw_du_crtc_cursor_move, .cursor_move = vmw_du_crtc_cursor_move,
.gamma_set = vmw_du_crtc_gamma_set, .gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_sou_crtc_destroy, .destroy = vmw_sou_crtc_destroy,
......
...@@ -1043,7 +1043,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, ...@@ -1043,7 +1043,7 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
static struct drm_crtc_funcs vmw_stdu_crtc_funcs = { static struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
.save = vmw_du_crtc_save, .save = vmw_du_crtc_save,
.restore = vmw_du_crtc_restore, .restore = vmw_du_crtc_restore,
.cursor_set = vmw_du_crtc_cursor_set, .cursor_set2 = vmw_du_crtc_cursor_set2,
.cursor_move = vmw_du_crtc_cursor_move, .cursor_move = vmw_du_crtc_cursor_move,
.gamma_set = vmw_du_crtc_gamma_set, .gamma_set = vmw_du_crtc_gamma_set,
.destroy = vmw_stdu_crtc_destroy, .destroy = vmw_stdu_crtc_destroy,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment