Commit 92f59ac4 authored by Michael Banack's avatar Michael Banack Committed by Zack Rusin

drm/vmwgfx: Support cursor surfaces with mob cursor

Add support for cursor surfaces when using mob cursors.
Signed-off-by: default avatarMichael Banack <banackm@vmware.com>
Signed-off-by: default avatarZack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221022040236.616490-9-zack@kde.org
parent 40f9e40b
...@@ -85,7 +85,7 @@ static void vmw_send_define_cursor_cmd(struct vmw_private *dev_priv, ...@@ -85,7 +85,7 @@ static void vmw_send_define_cursor_cmd(struct vmw_private *dev_priv,
other fallible KMS-atomic resources at prepare_fb */ other fallible KMS-atomic resources at prepare_fb */
cmd = VMW_CMD_RESERVE(dev_priv, cmd_size); cmd = VMW_CMD_RESERVE(dev_priv, cmd_size);
if (unlikely(cmd == NULL)) if (unlikely(!cmd))
return; return;
memset(cmd, 0, sizeof(*cmd)); memset(cmd, 0, sizeof(*cmd));
...@@ -117,7 +117,7 @@ static void vmw_cursor_update_image(struct vmw_private *dev_priv, ...@@ -117,7 +117,7 @@ static void vmw_cursor_update_image(struct vmw_private *dev_priv,
u32 *image, u32 width, u32 height, u32 *image, u32 width, u32 height,
u32 hotspotX, u32 hotspotY) u32 hotspotX, u32 hotspotY)
{ {
if (vps->cursor.bo != NULL) if (vps->cursor.bo)
vmw_cursor_write_mobid(dev_priv, vps); vmw_cursor_write_mobid(dev_priv, vps);
else else
vmw_send_define_cursor_cmd(dev_priv, image, width, height, vmw_send_define_cursor_cmd(dev_priv, image, width, height,
...@@ -197,7 +197,7 @@ static bool vmw_du_cursor_plane_mob_has_changed(struct vmw_plane_state *old_vps, ...@@ -197,7 +197,7 @@ static bool vmw_du_cursor_plane_mob_has_changed(struct vmw_plane_state *old_vps,
u32 size; u32 size;
// If either of them aren't using CursorMobs, assume changed. // If either of them aren't using CursorMobs, assume changed.
if (old_vps->cursor.bo == NULL || new_vps->cursor.bo == NULL) if (!old_vps->cursor.bo || !new_vps->cursor.bo)
return true; return true;
// If either of them failed to map, assume changed. // If either of them failed to map, assume changed.
...@@ -222,7 +222,7 @@ static bool vmw_du_cursor_plane_mob_has_changed(struct vmw_plane_state *old_vps, ...@@ -222,7 +222,7 @@ static bool vmw_du_cursor_plane_mob_has_changed(struct vmw_plane_state *old_vps,
static void vmw_du_destroy_cursor_mob(struct ttm_buffer_object **bo) static void vmw_du_destroy_cursor_mob(struct ttm_buffer_object **bo)
{ {
if (*bo == NULL) if (!(*bo))
return; return;
ttm_bo_unpin(*bo); ttm_bo_unpin(*bo);
...@@ -236,14 +236,14 @@ static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp, ...@@ -236,14 +236,14 @@ static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp,
{ {
u32 i; u32 i;
if (vps->cursor.bo == NULL) if (!vps->cursor.bo)
return; return;
vmw_du_cursor_plane_unmap_cm(vps); vmw_du_cursor_plane_unmap_cm(vps);
/* Look for a free slot to return this mob to the cache. */ /* Look for a free slot to return this mob to the cache. */
for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
if (vcp->cursor_mobs[i] == NULL) { if (!vcp->cursor_mobs[i]) {
vcp->cursor_mobs[i] = vps->cursor.bo; vcp->cursor_mobs[i] = vps->cursor.bo;
vps->cursor.bo = NULL; vps->cursor.bo = NULL;
return; return;
...@@ -285,7 +285,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, ...@@ -285,7 +285,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp,
vps->base.crtc_h > cursor_max_dim) vps->base.crtc_h > cursor_max_dim)
return -EINVAL; return -EINVAL;
if (vps->cursor.bo != NULL) { if (vps->cursor.bo) {
if (vps->cursor.bo->base.size >= size) if (vps->cursor.bo->base.size >= size)
return 0; return 0;
vmw_du_put_cursor_mob(vcp, vps); vmw_du_put_cursor_mob(vcp, vps);
...@@ -293,7 +293,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp, ...@@ -293,7 +293,7 @@ static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp,
/* Look for an unused mob in the cache. */ /* Look for an unused mob in the cache. */
for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) { for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
if (vcp->cursor_mobs[i] != NULL && if (vcp->cursor_mobs[i] &&
vcp->cursor_mobs[i]->base.size >= size) { vcp->cursor_mobs[i]->base.size >= size) {
vps->cursor.bo = vcp->cursor_mobs[i]; vps->cursor.bo = vcp->cursor_mobs[i];
vcp->cursor_mobs[i] = NULL; vcp->cursor_mobs[i] = NULL;
...@@ -371,7 +371,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf, ...@@ -371,7 +371,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
cmd = container_of(header, struct vmw_dma_cmd, header); cmd = container_of(header, struct vmw_dma_cmd, header);
/* No snooper installed */ /* No snooper installed, nothing to copy */
if (!srf->snooper.image) if (!srf->snooper.image)
return; return;
...@@ -471,7 +471,8 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) ...@@ -471,7 +471,8 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
du = vmw_crtc_to_du(crtc); du = vmw_crtc_to_du(crtc);
if (!du->cursor_surface || if (!du->cursor_surface ||
du->cursor_age == du->cursor_surface->snooper.age) du->cursor_age == du->cursor_surface->snooper.age ||
!du->cursor_surface->snooper.image)
continue; continue;
du->cursor_age = du->cursor_surface->snooper.age; du->cursor_age = du->cursor_surface->snooper.age;
...@@ -567,7 +568,7 @@ vmw_du_cursor_plane_map_cm(struct vmw_plane_state *vps) ...@@ -567,7 +568,7 @@ vmw_du_cursor_plane_map_cm(struct vmw_plane_state *vps)
u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h); u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);
struct ttm_buffer_object *bo = vps->cursor.bo; struct ttm_buffer_object *bo = vps->cursor.bo;
if (bo == NULL) if (!bo)
return -EINVAL; return -EINVAL;
if (bo->base.size < size) if (bo->base.size < size)
...@@ -619,7 +620,7 @@ vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps) ...@@ -619,7 +620,7 @@ vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps)
if (!vps->cursor.mapped) if (!vps->cursor.mapped)
return 0; return 0;
if (bo == NULL) if (!bo)
return 0; return 0;
ret = ttm_bo_reserve(bo, true, false, NULL); ret = ttm_bo_reserve(bo, true, false, NULL);
...@@ -651,7 +652,12 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, ...@@ -651,7 +652,12 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
bool dummy; bool dummy;
if (vps->bo != NULL && ttm_kmap_obj_virtual(&vps->bo->map, &dummy) != NULL) { if (vps->surf_mapped) {
vmw_bo_unmap(vps->surf->res.backup);
vps->surf_mapped = false;
}
if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) {
const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);
if (likely(ret == 0)) { if (likely(ret == 0)) {
...@@ -666,12 +672,12 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, ...@@ -666,12 +672,12 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
vmw_du_plane_unpin_surf(vps, false); vmw_du_plane_unpin_surf(vps, false);
if (vps->surf != NULL) { if (vps->surf) {
vmw_surface_unreference(&vps->surf); vmw_surface_unreference(&vps->surf);
vps->surf = NULL; vps->surf = NULL;
} }
if (vps->bo != NULL) { if (vps->bo) {
vmw_bo_unreference(&vps->bo); vmw_bo_unreference(&vps->bo);
vps->bo = NULL; vps->bo = NULL;
} }
...@@ -715,7 +721,7 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, ...@@ -715,7 +721,7 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
} }
} }
if (vps->surf == NULL && vps->bo != NULL) { if (!vps->surf && vps->bo) {
const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32); const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32);
/* /*
...@@ -737,9 +743,18 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, ...@@ -737,9 +743,18 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return -ENOMEM; return -ENOMEM;
} else if (vps->surf && !vps->bo && vps->surf->res.backup) {
ret = ttm_bo_reserve(&vps->surf->res.backup->base, true, false,
NULL);
if (unlikely(ret != 0))
return -ENOMEM;
vmw_bo_map_and_cache(vps->surf->res.backup);
ttm_bo_unreserve(&vps->surf->res.backup->base);
vps->surf_mapped = true;
} }
if (vps->surf != NULL || vps->bo != NULL) { if (vps->surf || vps->bo) {
vmw_du_get_cursor_mob(vcp, vps); vmw_du_get_cursor_mob(vcp, vps);
vmw_du_cursor_plane_map_cm(vps); vmw_du_cursor_plane_map_cm(vps);
} }
...@@ -776,18 +791,20 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, ...@@ -776,18 +791,20 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
du->cursor_surface = vps->surf; du->cursor_surface = vps->surf;
du->cursor_bo = vps->bo; du->cursor_bo = vps->bo;
if (vps->surf == NULL && vps->bo == NULL) { if (!vps->surf && !vps->bo) {
vmw_cursor_update_position(dev_priv, false, 0, 0); vmw_cursor_update_position(dev_priv, false, 0, 0);
return; return;
} }
if (vps->surf != NULL) { if (vps->surf) {
du->cursor_age = du->cursor_surface->snooper.age; du->cursor_age = du->cursor_surface->snooper.age;
image = vps->surf->snooper.image; image = vps->surf->snooper.image;
if (vps->surf_mapped)
image = vmw_bo_map_and_cache(vps->surf->res.backup);
} else } else
image = ttm_kmap_obj_virtual(&vps->bo->map, &dummy); image = ttm_kmap_obj_virtual(&vps->bo->map, &dummy);
if (vps->cursor.bo != NULL) if (vps->cursor.bo)
vmw_cursor_update_mob(dev_priv, vps, image, vmw_cursor_update_mob(dev_priv, vps, image,
new_state->crtc_w, new_state->crtc_w,
new_state->crtc_h, new_state->crtc_h,
...@@ -801,13 +818,13 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, ...@@ -801,13 +818,13 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
struct vmw_cursor_plane_state tmp = old_vps->cursor; struct vmw_cursor_plane_state tmp = old_vps->cursor;
old_vps->cursor = vps->cursor; old_vps->cursor = vps->cursor;
vps->cursor = tmp; vps->cursor = tmp;
} else if (image != NULL) } else if (image)
vmw_cursor_update_image(dev_priv, vps, image, vmw_cursor_update_image(dev_priv, vps, image,
new_state->crtc_w, new_state->crtc_w,
new_state->crtc_h, new_state->crtc_h,
hotspot_x, hotspot_y); hotspot_x, hotspot_y);
if (image != NULL && vps->bo != NULL) if (image && vps->bo)
atomic_dec(&vps->bo->base_mapped_count); atomic_dec(&vps->bo->base_mapped_count);
du->cursor_x = new_state->crtc_x + du->set_gui_x; du->cursor_x = new_state->crtc_x + du->set_gui_x;
...@@ -907,12 +924,16 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, ...@@ -907,12 +924,16 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
return -EINVAL; return -EINVAL;
} }
if (!vmw_framebuffer_to_vfb(fb)->bo) if (!vmw_framebuffer_to_vfb(fb)->bo) {
surface = vmw_framebuffer_to_vfbs(fb)->surface; surface = vmw_framebuffer_to_vfbs(fb)->surface;
if (surface && !surface->snooper.image) { WARN_ON(!surface);
DRM_ERROR("surface not suitable for cursor\n");
return -EINVAL; if (!surface ||
(!surface->snooper.image && !surface->res.backup)) {
DRM_ERROR("surface not suitable for cursor\n");
return -EINVAL;
}
} }
return 0; return 0;
...@@ -1075,10 +1096,10 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane) ...@@ -1075,10 +1096,10 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane)
memset(&vps->cursor, 0, sizeof(vps->cursor)); memset(&vps->cursor, 0, sizeof(vps->cursor));
/* Each ref counted resource needs to be acquired again */ /* Each ref counted resource needs to be acquired again */
if (vps->surf != NULL) if (vps->surf)
(void) vmw_surface_reference(vps->surf); (void) vmw_surface_reference(vps->surf);
if (vps->bo != NULL) if (vps->bo)
(void) vmw_bo_reference(vps->bo); (void) vmw_bo_reference(vps->bo);
state = &vps->base; state = &vps->base;
...@@ -2223,7 +2244,6 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data, ...@@ -2223,7 +2244,6 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
struct drm_crtc *crtc; struct drm_crtc *crtc;
int ret = 0; int ret = 0;
mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex);
if (arg->flags & DRM_VMW_CURSOR_BYPASS_ALL) { if (arg->flags & DRM_VMW_CURSOR_BYPASS_ALL) {
......
...@@ -301,6 +301,7 @@ struct vmw_plane_state { ...@@ -301,6 +301,7 @@ struct vmw_plane_state {
/* For CPU Blit */ /* For CPU Blit */
unsigned int cpp; unsigned int cpp;
bool surf_mapped;
struct vmw_cursor_plane_state cursor; struct vmw_cursor_plane_state cursor;
}; };
......
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