Hi,
I found a cursor hotspot regression in vmwgfx while testing Slax
with Linux 7.2.9.
Environment:
- VirtualBox 7.1.10, VMSVGA, 3D acceleration disabled
- Debian 13 userspace
- xserver-xorg-core 21.1.16
- xf86-video-vmware 13.4.0
- Hardware cursors enabled through normal driver autodetection
Resize cursors appear displaced from the pointer position. For
example, a horizontal resize cursor with hotspot (13, 6) is drawn
13 pixels to the right and 6 pixels below the expected position.
The theme file and XFixesGetCursorImage both report the correct
hotspot (13, 6), but VirtualBox's VMSVGA diagnostics report (0, 0).
Code inspection points to the GB_ONLY branch introduced by:
eef295a85082 ("drm/vmwgfx: Restore Guest-Backed only cursor plane support")
In vmw_cursor_plane_atomic_update(), this branch passes only
vps->base.hotspot_x/y to vmw_send_define_cursor_cmd().
However, xf86-video-vmware supplies the hotspot through
DRM_VMW_CURSOR_BYPASS, which stores it in
vps->cursor.legacy.hotspot_x/y.
The position calculation adds both hotspot components, and the
LEGACY and MOB image paths also include both. Only the GB_ONLY
image path omits the legacy component.
The attached patch uses the same combined hotspot for the GB_ONLY
image and its position. It fixes the displacement in our VM.
Additional tests with custom cursors, bypassing the cursor theme
and window manager, confirmed that hotspots (13,6), (6,13), (9,9)
and (7,11) reach the virtual hardware correctly with the fix.
For completeness, this setup also encounters the separately
reported zero SVGA_REG_CURSOR_MAX_DIMENSION issue:
https://patchew.org/linux/[email protected]/
To make hardware cursors visible for these tests, our kernel also
has a local workaround that retains a 64px limit specifically for
GB_ONLY when that register returns zero. MOB validation is unchanged.
Could you review the hotspot fix and consider applying it upstream?
I can provide further diagnostics if helpful.
Thanks,
Tomas M
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c
@@ -803,6 +803,10 @@
return;
}
+ /* Include legacy Xorg cursor-bypass offsets in the image and position. */
+ hotspot_x = vps->cursor.legacy.hotspot_x + new_state->hotspot_x;
+ hotspot_y = vps->cursor.legacy.hotspot_y + new_state->hotspot_y;
+
switch (vps->cursor.update_type) {
case VMW_CURSOR_UPDATE_LEGACY:
vmw_cursor_plane_update_legacy(dev_priv, vps);
@@ -816,8 +820,7 @@
vmw_send_define_cursor_cmd(dev_priv, bo->map.virtual,
vps->base.crtc_w,
vps->base.crtc_h,
- vps->base.hotspot_x,
- vps->base.hotspot_y);
+ hotspot_x, hotspot_y);
break;
case VMW_CURSOR_UPDATE_NONE:
/* do nothing */
@@ -829,9 +832,6 @@
*/
cursor_x = new_state->crtc_x + du->set_gui_x;
cursor_y = new_state->crtc_y + du->set_gui_y;
-
- hotspot_x = vps->cursor.legacy.hotspot_x + new_state->hotspot_x;
- hotspot_y = vps->cursor.legacy.hotspot_y + new_state->hotspot_y;
vmw_cursor_update_position(dev_priv, true, cursor_x + hotspot_x,
cursor_y + hotspot_y);
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c
@@ -748,6 +748,10 @@
u32 cursor_max_dim =
vmw_read(vmw, SVGA_REG_CURSOR_MAX_DIMENSION);
+ /* Older hosts lack the MOB cursor limit register; retain the 64px limit. */
+ if (!cursor_max_dim && update_type == VMW_CURSOR_UPDATE_GB_ONLY)
+ cursor_max_dim = VMW_CURSOR_SNOOP_WIDTH;
+
if (new_state->crtc_w > cursor_max_dim ||
new_state->crtc_h > cursor_max_dim) {
drm_warn(&vmw->drm,