[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