Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in / Register
X
xf86-video-intel
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 194
    • Issues 194
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • xorg
  • driver
  • xf86-video-intel
  • Issues
  • #206

Closed
Open
Opened Jan 15, 2021 by iamahuman@iamahuman

Revert to SW cursor when XRandR transformation enlarges beyond HW cursor

XRandR scaling may change the cursor size as well, which the driver did not correctly handle.

When cursor.size (current cursor) grows beyond cursor.max_size (HW cursor size), __sna_get_cursor proceeds to copy the cursor into the preallocated cursor buffer anyway, resulting in a buffer overrun.

Fix this by using the opportunity in sna_cursors_reload (CRTC config reload) to detect changes in transformed cursor size;

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 874292bc..fb46ea1b 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -6223,6 +6223,12 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
 	} else
 		size = sna->cursor.size;
 
+	if (size > sna->cursor.max_size) {
+		__DBG(("%s: refusing to create cursor of size=%d, max=%d\n",
+		       __FUNCTION__, size, sna->cursor.max_size));
+		return NULL;
+	}
+
 	if (crtc->transform_in_use) {
 		RRTransformPtr T = NULL;
 		struct pixman_vector v;
@@ -6828,6 +6834,26 @@ transformable_cursor(struct sna *sna, CursorPtr cursor)
 	return true;
 }
 
+static bool __sna_cursor_possible(struct sna *sna, CursorPtr cursor)
+{
+	assert(cursor);
+	assert(sna->cursor.size == __cursor_size(cursor->bits->width, cursor->bits->height));
+
+	if (sna->cursor.size > sna->cursor.max_size) {
+		DBG(("%s: cursor size=%d too large, max %d: using sw cursor\n",
+		     __FUNCTION__, sna->cursor.size, sna->cursor.max_size));
+		return false;
+	}
+
+	if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) {
+		DBG(("%s: RandR active [%d] and non-transformable cursor: using sw cursor\n",
+		     __FUNCTION__, sna->mode.rr_active));
+		return false;
+	}
+
+	return true;
+}
+
 static Bool
 sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
 {
@@ -6850,15 +6876,8 @@ sna_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
 
 	sna->cursor.size =
 		__cursor_size(cursor->bits->width, cursor->bits->height);
-	if (sna->cursor.size > sna->cursor.max_size) {
-		DBG(("%s: cursor size=%d too large, max %d: using sw cursor\n",
-		     __FUNCTION__, sna->cursor.size, sna->cursor.max_size));
-		return FALSE;
-	}
-
-	if (sna->mode.rr_active && !transformable_cursor(sna, cursor)) {
-		DBG(("%s: RandR active [%d] and non-transformable cursor: using sw cursor\n",
-		     __FUNCTION__, sna->mode.rr_active));
+	if (!__sna_cursor_possible(sna, cursor)) {
+		DBG(("%s: cursor too large, using sw cursor\n", __FUNCTION__));
 		return FALSE;
 	}
 
@@ -7003,10 +7022,19 @@ static void
 sna_cursors_reload(struct sna *sna)
 {
 	DBG(("%s: active?=%d\n", __FUNCTION__, sna->cursor.active));
-	if (sna->cursor.active)
+	if (sna->cursor.active) {
+		if (sna->cursor.ref &&
+		    !__sna_cursor_possible(sna, sna->cursor.ref)) {
+			DBG(("%s: CRTC change incompatible with hw cursors, disabling\n", __FUNCTION__));
+			sna->cursor.disable = true;
+			restore_swcursor(sna);
+			return;
+		}
+
 		sna_set_cursor_position(sna->scrn,
 					sna->cursor.last_x,
 					sna->cursor.last_y);
+	}
 }
 
 static void
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: xorg/driver/xf86-video-intel#206