[PATCH 1/4] drm/vmwgfx: Add support for CursorMob and CursorBypass 4
Zack Rusin
zackr at vmware.com
Wed Jul 14 04:14:14 UTC 2021
From: Martin Krastev <krastevm at vmware.com>
* Add support for CursorMob
* Add support for CursorBypass 4
Reviewed-by: Zack Rusin <zackr at vmware.com>
Signed-off-by: Martin Krastev <krastevm at vmware.com>
Signed-off-by: Zack Rusin <zackr at vmware.com>
---
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 45 +++++++++++++++-
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 +++
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 79 +++++++++++++++++++++++++++--
3 files changed, 125 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 086dc75e7b42..7d8cc2f6b04e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2009-2016 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -301,8 +301,12 @@ static void vmw_print_capabilities2(uint32_t capabilities2)
DRM_INFO(" Grow oTable.\n");
if (capabilities2 & SVGA_CAP2_INTRA_SURFACE_COPY)
DRM_INFO(" IntraSurface copy.\n");
+ if (capabilities2 & SVGA_CAP2_CURSOR_MOB)
+ DRM_INFO(" Cursor Mob.\n");
if (capabilities2 & SVGA_CAP2_DX3)
DRM_INFO(" DX3.\n");
+ if (capabilities2 & SVGA_CAP2_EXTRA_REGS)
+ DRM_INFO(" Extra Regs.\n");
}
static void vmw_print_capabilities(uint32_t capabilities)
@@ -505,6 +509,7 @@ static int vmw_request_device_late(struct vmw_private *dev_priv)
static int vmw_request_device(struct vmw_private *dev_priv)
{
int ret;
+ size_t i;
ret = vmw_device_init(dev_priv);
if (unlikely(ret != 0)) {
@@ -526,6 +531,37 @@ static int vmw_request_device(struct vmw_private *dev_priv)
if (unlikely(ret != 0))
goto out_no_query_bo;
+ /* Set up mobs for cursor updates */
+ if (dev_priv->has_mob && dev_priv->capabilities2 & SVGA_CAP2_CURSOR_MOB) {
+ const uint32_t cursor_max_dim = vmw_read(dev_priv, SVGA_REG_CURSOR_MAX_DIMENSION);
+
+ for (i = 0; i < ARRAY_SIZE(dev_priv->cursor_mob); i++) {
+ struct ttm_buffer_object **const bo = &dev_priv->cursor_mob[i];
+
+ ret = vmw_bo_create_kernel(dev_priv,
+ cursor_max_dim * cursor_max_dim * sizeof(u32) + sizeof(SVGAGBCursorHeader),
+ &vmw_mob_placement, bo);
+
+ if (ret != 0) {
+ DRM_ERROR("Unable to create CursorMob array.\n");
+ break;
+ }
+
+ BUG_ON((*bo)->resource->mem_type != VMW_PL_MOB);
+
+ /* Fence the mob creation so we are guarateed to have the mob */
+ ret = ttm_bo_reserve(*bo, false, true, NULL);
+ BUG_ON(ret);
+
+ vmw_bo_fence_single(*bo, NULL);
+
+ ttm_bo_unreserve(*bo);
+
+ DRM_INFO("Using CursorMob mobid %lu, max dimension %u\n",
+ (*bo)->resource->start, cursor_max_dim);
+ }
+ }
+
return 0;
out_no_query_bo:
@@ -556,6 +592,8 @@ static int vmw_request_device(struct vmw_private *dev_priv)
*/
static void vmw_release_device_early(struct vmw_private *dev_priv)
{
+ size_t i;
+
/*
* Previous destructions should've released
* the pinned bo.
@@ -570,6 +608,11 @@ static void vmw_release_device_early(struct vmw_private *dev_priv)
if (dev_priv->has_mob) {
struct ttm_resource_manager *man;
+ for (i = 0; i < ARRAY_SIZE(dev_priv->cursor_mob); i++) {
+ if (dev_priv->cursor_mob[i] != NULL)
+ ttm_bo_put(dev_priv->cursor_mob[i]);
+ }
+
man = ttm_manager_type(&dev_priv->bdev, VMW_PL_MOB);
ttm_resource_manager_evict_all(&dev_priv->bdev, man);
vmw_otables_takedown(dev_priv);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 356f82c26f59..46bf54f6169a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -642,6 +642,12 @@ struct vmw_private {
u8 mksstat_kern_top_timer[MKSSTAT_CAPACITY];
atomic_t mksstat_kern_pids[MKSSTAT_CAPACITY];
#endif
+
+ /*
+ * CursorMob buffer objects
+ */
+ struct ttm_buffer_object *cursor_mob[2];
+ atomic_t cursor_mob_idx;
};
static inline struct vmw_surface *vmw_res_to_srf(struct vmw_resource *res)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 2ddf4932d62c..8d7844354774 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -53,6 +53,10 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
* Display Unit Cursor functions
*/
+static int vmw_cursor_update_mob(struct vmw_private *dev_priv,
+ u32 *image, u32 width, u32 height,
+ u32 hotspotX, u32 hotspotY);
+
static int vmw_cursor_update_image(struct vmw_private *dev_priv,
u32 *image, u32 width, u32 height,
u32 hotspotX, u32 hotspotY)
@@ -67,6 +71,10 @@ static int vmw_cursor_update_image(struct vmw_private *dev_priv,
if (!image)
return -EINVAL;
+ if (dev_priv->cursor_mob[ARRAY_SIZE(dev_priv->cursor_mob) - 1] != NULL)
+ return vmw_cursor_update_mob(dev_priv, image, width, height,
+ hotspotX, hotspotY);
+
cmd = VMW_CMD_RESERVE(dev_priv, cmd_size);
if (unlikely(cmd == NULL))
return -ENOMEM;
@@ -87,6 +95,62 @@ static int vmw_cursor_update_image(struct vmw_private *dev_priv,
return 0;
}
+static int vmw_cursor_update_mob(struct vmw_private *dev_priv,
+ u32 *image, u32 width, u32 height,
+ u32 hotspotX, u32 hotspotY)
+{
+ SVGAGBCursorHeader *header;
+ SVGAGBAlphaCursorHeader *alpha_header;
+ const u32 image_size = width * height * sizeof(*image);
+ const u32 mob_size = sizeof(*header) + image_size;
+
+ struct ttm_buffer_object *bo;
+ struct ttm_bo_kmap_obj map;
+ bool dummy;
+ int ret;
+
+ bo = dev_priv->cursor_mob[atomic_inc_return(&dev_priv->cursor_mob_idx) %
+ ARRAY_SIZE(dev_priv->cursor_mob)];
+ BUG_ON(bo == NULL);
+
+ ret = ttm_bo_reserve(bo, true, false, NULL);
+
+ if (unlikely(ret != 0)) {
+ DRM_ERROR("reserve failed\n");
+ return -EINVAL;
+ }
+
+ ret = ttm_bo_kmap(bo, 0, vmw_num_pages(mob_size), &map);
+
+ if (unlikely(ret != 0))
+ goto err_map;
+
+ header = (SVGAGBCursorHeader *)ttm_kmap_obj_virtual(&map, &dummy);
+ alpha_header = &header->header.alphaHeader;
+
+ header->type = SVGA_ALPHA_CURSOR;
+ header->sizeInBytes = image_size;
+
+ alpha_header->hotspotX = hotspotX;
+ alpha_header->hotspotY = hotspotY;
+ alpha_header->width = width;
+ alpha_header->height = height;
+
+ memcpy(header + 1, image, image_size);
+
+ ttm_bo_kunmap(&map);
+ ttm_bo_unreserve(bo);
+
+ vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, bo->resource->start);
+
+ return 0;
+
+err_map:
+ ttm_bo_unreserve(bo);
+
+ return ret;
+}
+
static int vmw_cursor_update_bo(struct vmw_private *dev_priv,
struct vmw_buffer_object *bo,
u32 width, u32 height,
@@ -127,11 +191,18 @@ static int vmw_cursor_update_bo(struct vmw_private *dev_priv,
static void vmw_cursor_update_position(struct vmw_private *dev_priv,
bool show, int x, int y)
{
+ const uint32_t svga_cursor_on = show ? SVGA_CURSOR_ON_SHOW
+ : SVGA_CURSOR_ON_HIDE;
uint32_t count;
spin_lock(&dev_priv->cursor_lock);
- if (vmw_is_cursor_bypass3_enabled(dev_priv)) {
- vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, show ? 1 : 0);
+ if (dev_priv->capabilities2 & SVGA_CAP2_EXTRA_REGS) {
+ vmw_write(dev_priv, SVGA_REG_CURSOR4_X, x);
+ vmw_write(dev_priv, SVGA_REG_CURSOR4_Y, y);
+ vmw_write(dev_priv, SVGA_REG_CURSOR4_ON, svga_cursor_on);
+ vmw_write(dev_priv, SVGA_REG_CURSOR4_SUBMIT, TRUE);
+ } else if (vmw_is_cursor_bypass3_enabled(dev_priv)) {
+ vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, svga_cursor_on);
vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_X, x);
vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_Y, y);
count = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CURSOR_COUNT);
@@ -139,7 +210,7 @@ static void vmw_cursor_update_position(struct vmw_private *dev_priv,
} else {
vmw_write(dev_priv, SVGA_REG_CURSOR_X, x);
vmw_write(dev_priv, SVGA_REG_CURSOR_Y, y);
- vmw_write(dev_priv, SVGA_REG_CURSOR_ON, show ? 1 : 0);
+ vmw_write(dev_priv, SVGA_REG_CURSOR_ON, svga_cursor_on);
}
spin_unlock(&dev_priv->cursor_lock);
}
--
2.30.2
More information about the dri-devel
mailing list