xf86-video-amdgpu: Branch 'master'

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Oct 29 09:58:11 UTC 2018


 src/drmmode_display.c |   91 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 60 insertions(+), 31 deletions(-)

New commits:
commit ad6dfb0124860cf67730bde85867f81d9258c84d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Oct 19 11:02:41 2018 +0200

    Detect and fix up non-premultiplied cursor data
    
    X server >= 1.18 already had code for this, but it only caught cases
    where some pixels have 0 for alpha and non-0 for a non-alpha component.
    Turns out some apps (e.g. the Civilization VI game) use
    non-premultiplied cursor data which doesn't have such pixels, but can
    still result in visual artifacts.
    
    This uses the method suggested by Kamil in
    https://bugs.freedesktop.org/92309#c19: check for pixels where any
    colour component value is larger than the alpha value, which isn't
    possible with premultiplied alpha.
    
    There can still be non-premultiplied data which won't be caught by this,
    but that should result in slightly incorrect colours and/or blending at
    the worst, not wildly incorrect colours such as shown in the bug report
    below.
    
    v2:
    * Disable the check with current xserver Git master, which already does
      the same check now.
    
    Bugzilla: https://bugs.freedesktop.org/108355
    Suggested-by: Kamil Páral <kamil.paral at gmail.com>
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index ec45d57..34b3d87 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -1500,49 +1500,65 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height,
 
 #endif
 
-static uint32_t
-drmmode_cursor_gamma_passthrough(xf86CrtcPtr crtc, uint32_t argb)
-{
-	uint32_t alpha = argb >> 24;
-
-	if (!alpha)
-		return 0;
-
-	return argb;
-}
-
-static uint32_t
-drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb)
+static Bool
+drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool premultiplied,
+		     Bool apply_gamma)
 {
-	uint32_t alpha = argb >> 24;
+	uint32_t alpha = *argb >> 24;
 	uint32_t rgb[3];
 	int i;
 
-	if (!alpha)
-		return 0;
+	if (premultiplied) {
+#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 20, 99, 0, 0)
+		if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24))
+			/* Doesn't look like premultiplied alpha */
+			return FALSE;
+#endif
+
+		if (!apply_gamma)
+			return TRUE;
+	}
 
-	/* Un-premultiply alpha */
+	if (!alpha) {
+		*argb = 0;
+		return TRUE;
+	}
+
+	/* Extract RGB */
 	for (i = 0; i < 3; i++)
-		rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha;
+		rgb[i] = (*argb >> (i * 8)) & 0xff;
 
-	/* Apply gamma correction and pre-multiply alpha */
-	rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff;
-	rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff;
-	rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff;
+	if (premultiplied) {
+		/* Un-premultiply alpha */
+		for (i = 0; i < 3; i++)
+			rgb[i] = rgb[i] * 0xff / alpha;
+	}
 
-	return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+	if (apply_gamma) {
+		rgb[0] = crtc->gamma_blue[rgb[0]] >> 8;
+		rgb[1] = crtc->gamma_green[rgb[1]] >> 8;
+		rgb[2] = crtc->gamma_red[rgb[2]] >> 8;
+	}
+
+	/* Premultiply alpha */
+	for (i = 0; i < 3; i++)
+		rgb[i] = rgb[i] * alpha / 0xff;
+
+	*argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
+	return TRUE;
 }
 
 static void drmmode_do_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image, uint32_t *ptr)
 {
 	ScrnInfoPtr pScrn = crtc->scrn;
 	AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
-	uint32_t (*cursor_gamma)(xf86CrtcPtr crtc, uint32_t argb) =
-		drmmode_cursor_gamma;
+	Bool premultiplied = TRUE;
+	Bool apply_gamma = TRUE;
+	uint32_t argb;
 
 	if ((crtc->scrn->depth != 24 && crtc->scrn->depth != 32) ||
 	    drmmode_cm_enabled(&info->drmmode))
-		cursor_gamma = drmmode_cursor_gamma_passthrough;
+		apply_gamma = FALSE;
 
 #if XF86_CRTC_VERSION < 7
 	if (crtc->driverIsPerformingTransform) {
@@ -1550,15 +1566,20 @@ static void drmmode_do_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image, uint32_
 		int dstx, dsty;
 		int srcoffset;
 
+retry_transform:
 		for (dsty = 0; dsty < cursor_h; dsty++) {
 			for (dstx = 0; dstx < cursor_w; dstx++) {
 				srcoffset = drmmode_cursor_src_offset(crtc->rotation,
 								      cursor_w,
 								      cursor_h,
 								      dstx, dsty);
-
-				ptr[dsty * info->cursor_w + dstx] =
-					cpu_to_le32(cursor_gamma(crtc, image[srcoffset]));
+				argb = image[srcoffset];
+				if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
+							  apply_gamma)) {
+					premultiplied = FALSE;
+					goto retry_transform;
+				}
+				ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb);
 			}
 		}
 	} else
@@ -1567,8 +1588,16 @@ static void drmmode_do_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image, uint32_
 		uint32_t cursor_size = info->cursor_w * info->cursor_h;
 		int i;
 
-		for (i = 0; i < cursor_size; i++)
-			ptr[i] = cpu_to_le32(cursor_gamma(crtc, image[i]));
+retry:
+		for (i = 0; i < cursor_size; i++) {
+			argb = image[i];
+			if (!drmmode_cursor_pixel(crtc, &argb, premultiplied,
+						  apply_gamma)) {
+				premultiplied = FALSE;
+				goto retry;
+			}
+			ptr[i] = cpu_to_le32(argb);
+		}
 	}
 }
 


More information about the xorg-commit mailing list