forked from Minki/linux
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: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com>
This commit is contained in:
parent
99f9be4c73
commit
8fbf9d92a7
@ -1233,6 +1233,7 @@ static void vmw_master_drop(struct drm_device *dev,
|
||||
|
||||
vmw_fp->locked_master = drm_master_get(file_priv->master);
|
||||
ret = ttm_vt_lock(&vmaster->lock, false, vmw_fp->tfile);
|
||||
vmw_kms_legacy_hotspot_clear(dev_priv);
|
||||
if (unlikely((ret != 0))) {
|
||||
DRM_ERROR("Unable to lock TTM at VT switch.\n");
|
||||
drm_master_put(&vmw_fp->locked_master);
|
||||
|
@ -925,6 +925,7 @@ int vmw_kms_present(struct vmw_private *dev_priv,
|
||||
uint32_t num_clips);
|
||||
int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
|
||||
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,
|
||||
struct drm_device *dev,
|
||||
|
@ -133,13 +133,19 @@ void vmw_cursor_update_position(struct vmw_private *dev_priv,
|
||||
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_display_unit *du = vmw_crtc_to_du(crtc);
|
||||
struct vmw_surface *surface = NULL;
|
||||
struct vmw_dma_buffer *dmabuf = NULL;
|
||||
s32 hotspot_x, hotspot_y;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -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_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 */
|
||||
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,
|
||||
vmw_dmabuf_unreference(&du->cursor_dmabuf);
|
||||
|
||||
/* setup new image */
|
||||
ret = 0;
|
||||
if (surface) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_surface = surface;
|
||||
|
||||
du->cursor_surface->snooper.crtc = crtc;
|
||||
du->cursor_age = du->cursor_surface->snooper.age;
|
||||
vmw_cursor_update_image(dev_priv, surface->snooper.image,
|
||||
64, 64, du->hotspot_x, du->hotspot_y);
|
||||
ret = vmw_cursor_update_image(dev_priv, surface->snooper.image,
|
||||
64, 64, hotspot_x, hotspot_y);
|
||||
} else if (dmabuf) {
|
||||
/* vmw_user_surface_lookup takes one reference */
|
||||
du->cursor_dmabuf = dmabuf;
|
||||
|
||||
ret = vmw_cursor_update_dmabuf(dev_priv, dmabuf, width, height,
|
||||
du->hotspot_x, du->hotspot_y);
|
||||
hotspot_x, hotspot_y);
|
||||
} else {
|
||||
vmw_cursor_update_position(dev_priv, false, 0, 0);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
vmw_cursor_update_position(dev_priv, true,
|
||||
du->cursor_x + du->hotspot_x,
|
||||
du->cursor_y + du->hotspot_y);
|
||||
if (!ret) {
|
||||
vmw_cursor_update_position(dev_priv, true,
|
||||
du->cursor_x + hotspot_x,
|
||||
du->cursor_y + hotspot_y);
|
||||
du->core_hotspot_x = hot_x;
|
||||
du->core_hotspot_y = hot_y;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
drm_modeset_unlock_all(dev_priv->dev);
|
||||
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)
|
||||
drm_modeset_lock_all(dev_priv->dev);
|
||||
|
||||
vmw_cursor_update_position(dev_priv, shown,
|
||||
du->cursor_x + du->hotspot_x,
|
||||
du->cursor_y + du->hotspot_y);
|
||||
du->cursor_x + du->hotspot_x +
|
||||
du->core_hotspot_x,
|
||||
du->cursor_y + du->hotspot_y +
|
||||
du->core_hotspot_y);
|
||||
|
||||
drm_modeset_unlock_all(dev_priv->dev);
|
||||
drm_modeset_lock_crtc(crtc, crtc->cursor);
|
||||
@ -334,6 +347,29 @@ err_unreserve:
|
||||
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)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
@ -351,7 +387,9 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
|
||||
du->cursor_age = du->cursor_surface->snooper.age;
|
||||
vmw_cursor_update_image(dev_priv,
|
||||
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);
|
||||
|
@ -159,6 +159,8 @@ struct vmw_display_unit {
|
||||
|
||||
int hotspot_x;
|
||||
int hotspot_y;
|
||||
s32 core_hotspot_x;
|
||||
s32 core_hotspot_y;
|
||||
|
||||
unsigned unit;
|
||||
|
||||
@ -193,8 +195,9 @@ void vmw_du_crtc_restore(struct drm_crtc *crtc);
|
||||
void vmw_du_crtc_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *r, u16 *g, u16 *b,
|
||||
uint32_t start, uint32_t size);
|
||||
int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
|
||||
uint32_t handle, uint32_t width, uint32_t height);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
static struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
|
||||
.save = vmw_du_crtc_save,
|
||||
.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,
|
||||
.gamma_set = vmw_du_crtc_gamma_set,
|
||||
.destroy = vmw_ldu_crtc_destroy,
|
||||
|
@ -533,7 +533,7 @@ out_no_fence:
|
||||
static struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
|
||||
.save = vmw_du_crtc_save,
|
||||
.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,
|
||||
.gamma_set = vmw_du_crtc_gamma_set,
|
||||
.destroy = vmw_sou_crtc_destroy,
|
||||
|
@ -1043,7 +1043,7 @@ out_finish:
|
||||
static struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
|
||||
.save = vmw_du_crtc_save,
|
||||
.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,
|
||||
.gamma_set = vmw_du_crtc_gamma_set,
|
||||
.destroy = vmw_stdu_crtc_destroy,
|
||||
|
Loading…
Reference in New Issue
Block a user