xf86-video-ati: Branch 'master' - 3 commits

Michel Dänzer daenzer at kemper.freedesktop.org
Wed Mar 9 07:22:24 UTC 2016


 src/drmmode_display.c |  150 ++++++++++++++++++++++++++++++++++++++++++--------
 src/radeon_kms.c      |  123 +++++++++++++++++++++++++++++++----------
 2 files changed, 221 insertions(+), 52 deletions(-)

New commits:
commit 798c4fd16d339b1ad5fd729cc884be084c60e38b
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Fri Dec 25 18:57:42 2015 +0900

    Make Option "TearFree" effective for rotated/reflected outputs as well (v2)
    
    Support varies by xserver version:
    
    < 1.12:    No support for the driver handling rotation/reflection
    1.12-1.15: Support for driver handling rotation/reflection, but there's
               a bug preventing the HW cursor from being visible everywhere
               it should be on rotated outputs, so we can only support
               TearFree for reflection.
    >= 1.16:   While the bug above is still there (fixes pending review),
               the driver can force SW cursor for rotated outputs, so we
               can support TearFree for rotation as well.
    
    v2: Don't set crtc->driverIsPerformingTransform after xf86CrtcRotate if
        it wasn't set before. Fixes breaking rotation with TearFree disabled.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com> (v1)

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index cc71dd0..80fbbf6 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -617,6 +617,34 @@ radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
 	damage->damage.data = NULL;
 }
 
+#if XF86_CRTC_VERSION >= 4
+
+static Bool
+drmmode_handle_transform(xf86CrtcPtr crtc)
+{
+	RADEONInfoPtr info = RADEONPTR(crtc->scrn);
+	Bool ret;
+
+	crtc->driverIsPerformingTransform = info->tear_free &&
+		!crtc->transformPresent && crtc->rotation != RR_Rotate_0;
+
+	ret = xf86CrtcRotate(crtc);
+
+	crtc->driverIsPerformingTransform &= ret && crtc->transform_in_use;
+
+	return ret;
+}
+
+#else
+
+static Bool
+drmmode_handle_transform(xf86CrtcPtr crtc)
+{
+	return xf86CrtcRotate(crtc);
+}
+
+#endif
+
 static Bool
 drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     Rotation rotation, int x, int y)
@@ -694,9 +722,9 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			output_count++;
 		}
 
-		if (!xf86CrtcRotate(crtc)) {
+		if (!drmmode_handle_transform(crtc))
 			goto done;
-		}
+
 		crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
 				       crtc->gamma_blue, crtc->gamma_size);
 
@@ -718,7 +746,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 
 			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
 			drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
-		} else if (info->tear_free || info->shadow_primary) {
+		} else if (info->tear_free || info->shadow_primary ||
+			   crtc->driverIsPerformingTransform) {
 			for (i = 0; i < (info->tear_free ? 2 : 1); i++) {
 				drmmode_crtc_scanout_create(crtc,
 							    &drmmode_crtc->scanout[i],
@@ -744,8 +773,17 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 					pBox = RegionExtents(pRegion);
 					pBox->x1 = min(pBox->x1, x);
 					pBox->y1 = min(pBox->y1, y);
-					pBox->x2 = max(pBox->x2, x + mode->HDisplay);
-					pBox->y2 = max(pBox->y2, y + mode->VDisplay);
+
+					switch (crtc->rotation & 0xf) {
+					case RR_Rotate_90:
+					case RR_Rotate_270:
+						pBox->x2 = max(pBox->x2, x + mode->VDisplay);
+						pBox->y2 = max(pBox->y2, y + mode->HDisplay);
+						break;
+					default:
+						pBox->x2 = max(pBox->x2, x + mode->HDisplay);
+						pBox->y2 = max(pBox->y2, y + mode->VDisplay);
+					}
 				}
 			}
 
@@ -821,24 +859,89 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
 	drmmode_ptr drmmode = drmmode_crtc->drmmode;
 
+#if XF86_CRTC_VERSION >= 4
+	if (crtc->driverIsPerformingTransform) {
+		x += crtc->x;
+		y += crtc->y;
+		xf86CrtcTransformCursorPos(crtc, &x, &y);
+	}
+#endif
+
 	drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
 }
 
+#if XF86_CRTC_VERSION >= 4
+
+static int
+drmmode_cursor_src_offset(Rotation rotation, int width, int height,
+			  int x_dst, int y_dst)
+{
+	int t;
+
+	switch (rotation & 0xf) {
+	case RR_Rotate_90:
+		t = x_dst;
+		x_dst = height - y_dst - 1;
+		y_dst = t;
+		break;
+	case RR_Rotate_180:
+		x_dst = width - x_dst - 1;
+		y_dst = height - y_dst - 1;
+		break;
+	case RR_Rotate_270:
+		t = x_dst;
+		x_dst = y_dst;
+		y_dst = width - t - 1;
+		break;
+	}
+
+	if (rotation & RR_Reflect_X)
+		x_dst = width - x_dst - 1;
+	if (rotation & RR_Reflect_Y)
+		y_dst = height - y_dst - 1;
+
+	return y_dst * height + x_dst;
+}
+
+#endif
+
 static void
 drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
 {
 	ScrnInfoPtr pScrn = crtc->scrn;
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
-	int i;
 	uint32_t *ptr;
-	uint32_t cursor_size = info->cursor_w * info->cursor_h;
 
 	/* cursor should be mapped already */
 	ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
 
-	for (i = 0; i < cursor_size; i++)
-		ptr[i] = cpu_to_le32(image[i]);
+#if XF86_CRTC_VERSION >= 4
+	if (crtc->driverIsPerformingTransform) {
+		uint32_t cursor_w = info->cursor_w, cursor_h = info->cursor_h;
+		int dstx, dsty;
+		int srcoffset;
+
+		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(image[srcoffset]);
+			}
+		}
+	} else
+#endif
+	{
+		uint32_t cursor_size = info->cursor_w * info->cursor_h;
+		int i;
+
+		for (i = 0; i < cursor_size; i++)
+			ptr[i] = cpu_to_le32(image[i]);
+	}
 }
 
 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0)
@@ -849,6 +952,13 @@ static Bool drmmode_load_cursor_argb_check(xf86CrtcPtr crtc, CARD32 * image)
 	if (crtc->transformPresent)
 		return FALSE;
 
+	/* Xorg doesn't correctly handle cursor position transform in the
+	 * rotation case
+	 */
+	if (crtc->driverIsPerformingTransform &&
+	    (crtc->rotation & 0xf) != RR_Rotate_0)
+		return FALSE;
+
 	drmmode_load_cursor_argb(crtc, image);
 	return TRUE;
 }
@@ -2276,8 +2386,8 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
 			crtc->rotation = crtc->desiredRotation;
 			crtc->x = crtc->desiredX;
 			crtc->y = crtc->desiredY;
-			if (!xf86CrtcRotate(crtc))
-			    return FALSE;
+			if (!drmmode_handle_transform(crtc))
+				return FALSE;
 		}
 	}
 	return TRUE;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 44fe71e..8048c95 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -334,12 +334,22 @@ radeon_dirty_update(ScreenPtr screen)
 #endif
 
 static Bool
-radeon_scanout_extents_intersect(BoxPtr extents, int x, int y, int w, int h)
+radeon_scanout_extents_intersect(xf86CrtcPtr xf86_crtc, BoxPtr extents, int w,
+				 int h)
 {
-    extents->x1 = max(extents->x1 - x, 0);
-    extents->y1 = max(extents->y1 - y, 0);
-    extents->x2 = min(extents->x2 - x, w);
-    extents->y2 = min(extents->y2 - y, h);
+    extents->x1 = max(extents->x1 - xf86_crtc->x, 0);
+    extents->y1 = max(extents->y1 - xf86_crtc->y, 0);
+
+    switch (xf86_crtc->rotation & 0xf) {
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	extents->x2 = min(extents->x2 - xf86_crtc->x, h);
+	extents->y2 = min(extents->y2 - xf86_crtc->y, w);
+	break;
+    default:
+	extents->x2 = min(extents->x2 - xf86_crtc->x, w);
+	extents->y2 = min(extents->y2 - xf86_crtc->y, h);
+    }
 
     return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
 }
@@ -353,7 +363,6 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
     RegionPtr pRegion;
     DrawablePtr pDraw;
     ScreenPtr pScreen;
-    GCPtr gc;
     BoxRec extents;
     RADEONInfoPtr info;
     Bool force;
@@ -372,31 +381,87 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
 	return FALSE;
 
     pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
+    pScreen = pDraw->pScreen;
     extents = *RegionExtents(pRegion);
     RegionEmpty(pRegion);
-    if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
-					  pDraw->width, pDraw->height))
+    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width,
+					  pDraw->height))
 	return FALSE;
 
-    pScreen = pDraw->pScreen;
-    gc = GetScratchGC(pDraw->depth, pScreen);
     scrn = xf86_crtc->scrn;
     info = RADEONPTR(scrn);
     force = info->accel_state->force;
     info->accel_state->force = TRUE;
 
-    ValidateGC(pDraw, gc);
-    (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
-			 pDraw, gc,
-			 xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
-			 extents.x2 - extents.x1, extents.y2 - extents.y1,
-			 extents.x1, extents.y1);
-    FreeScratchGC(gc);
+    if (xf86_crtc->driverIsPerformingTransform) {
+	SourceValidateProcPtr SourceValidate = pScreen->SourceValidate;
+	PictFormatPtr format = PictureWindowFormat(pScreen->root);
+	int error;
+	PicturePtr src, dst;
+	XID include_inferiors = IncludeInferiors;
+
+	src = CreatePicture(None,
+			    &pScreen->root->drawable,
+			    format,
+			    CPSubwindowMode,
+			    &include_inferiors, serverClient, &error);
+	if (!src) {
+	    ErrorF("Failed to create source picture for transformed scanout "
+		   "update\n");
+	    goto out;
+	}
+
+	dst = CreatePicture(None, pDraw, format, 0L, NULL, serverClient, &error);
+	if (!dst) {
+	    ErrorF("Failed to create destination picture for transformed scanout "
+		   "update\n");
+	    goto out;
+	}
 
-    info->accel_state->force = force;
+	error = SetPictureTransform(src, &xf86_crtc->crtc_to_framebuffer);
+	if (error) {
+	    ErrorF("SetPictureTransform failed for transformed scanout "
+		   "update\n");
+	    goto out;
+	}
+
+	if (xf86_crtc->filter)
+	    SetPicturePictFilter(src, xf86_crtc->filter, xf86_crtc->params,
+				 xf86_crtc->nparams);
+
+	extents.x1 += xf86_crtc->x - (xf86_crtc->filter_width >> 1);
+	extents.x2 += xf86_crtc->x + (xf86_crtc->filter_width >> 1);
+	extents.y1 += xf86_crtc->y - (xf86_crtc->filter_height >> 1);
+	extents.y2 += xf86_crtc->y + (xf86_crtc->filter_height >> 1);
+	pixman_f_transform_bounds(&xf86_crtc->f_framebuffer_to_crtc, &extents);
+
+	pScreen->SourceValidate = NULL;
+	CompositePicture(PictOpSrc,
+			 src, NULL, dst,
+			 extents.x1, extents.y1, 0, 0, extents.x1,
+			 extents.y1, extents.x2 - extents.x1,
+			 extents.y2 - extents.y1);
+	pScreen->SourceValidate = SourceValidate;
+
+	FreePicture(src, None);
+	FreePicture(dst, None);
+    } else {
+	GCPtr gc = GetScratchGC(pDraw->depth, pScreen);
+
+	ValidateGC(pDraw, gc);
+	(*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->drawable,
+			     pDraw, gc,
+			     xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1,
+			     extents.x2 - extents.x1, extents.y2 - extents.y1,
+			     extents.x1, extents.y1);
+	FreeScratchGC(gc);
+    }
 
     radeon_cs_flush_indirect(scrn);
 
+ out:
+    info->accel_state->force = force;
+
     return TRUE;
 }
 
@@ -445,8 +510,8 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc)
 
     pDraw = &drmmode_crtc->scanout[0].pixmap->drawable;
     extents = *RegionExtents(pRegion);
-    if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
-					  pDraw->width, pDraw->height))
+    if (!radeon_scanout_extents_intersect(xf86_crtc, &extents, pDraw->width,
+					  pDraw->height))
 	return;
 
     scrn = xf86_crtc->scrn;
@@ -532,21 +597,19 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
     SCREEN_PTR(arg);
     ScrnInfoPtr    pScrn   = xf86ScreenToScrn(pScreen);
     RADEONInfoPtr  info    = RADEONPTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int c;
 
     pScreen->BlockHandler = info->BlockHandler;
     (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
     pScreen->BlockHandler = RADEONBlockHandler_KMS;
 
-    if (info->tear_free || info->shadow_primary) {
-	xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-	int c;
-
-	for (c = 0; c < xf86_config->num_crtc; c++) {
-	    if (info->tear_free)
-		radeon_scanout_flip(pScreen, info, xf86_config->crtc[c]);
-	    else
-		radeon_scanout_update(xf86_config->crtc[c]);
-	}
+    for (c = 0; c < xf86_config->num_crtc; c++) {
+	if (info->tear_free)
+	    radeon_scanout_flip(pScreen, info, xf86_config->crtc[c]);
+	else if (info->shadow_primary ||
+		 xf86_config->crtc[c]->driverIsPerformingTransform)
+	    radeon_scanout_update(xf86_config->crtc[c]);
     }
 
     radeon_cs_flush_indirect(pScrn);
commit eb611a2e4ecce7a1ab85fd72b9b78e3269311dd5
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Tue Feb 2 18:04:11 2016 +0900

    Consolidate pScreen usage in drmmode_set_mode_major
    
    We were already relying on pScrn->pScreen being non-NULL in some cases,
    which is supposedly always true ever since this function is no longer
    getting called from ScreenInit.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index c749127..cc71dd0 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -622,6 +622,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     Rotation rotation, int x, int y)
 {
 	ScrnInfoPtr pScrn = crtc->scrn;
+	ScreenPtr pScreen = pScrn->pScreen;
 	RADEONInfoPtr info = RADEONPTR(pScrn);
 	xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
 	drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@@ -681,8 +682,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 			goto done;
 		}
 
-		ScreenPtr pScreen = pScrn->pScreen;
-
 		for (i = 0; i < xf86_config->num_output; i++) {
 			xf86OutputPtr output = xf86_config->output[i];
 			drmmode_output_private_ptr drmmode_output;
@@ -777,8 +776,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		} else
 			ret = TRUE;
 
-		if (crtc->scrn->pScreen)
-			xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+		if (pScreen)
+			xf86CrtcSetScreenSubpixelOrder(pScreen);
 
 		drmmode_crtc->need_modeset = FALSE;
 
@@ -793,9 +792,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
 		}
 	}
 
-	if (pScrn->pScreen &&
-		!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
-		xf86_reload_cursors(pScrn->pScreen);
+	if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
+		xf86_reload_cursors(pScreen);
 
 done:
 	if (!ret) {
commit 06602171386e538081c298645fb7ca1a70fe80cc
Author: Michel Dänzer <michel.daenzer at amd.com>
Date:   Thu Feb 4 17:13:57 2016 +0900

    Remove check for XF86_CRTC_VERSION 3
    
    We require xserver >= 1.8, which was already at version 3.
    
    Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index f1ca02c..c749127 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -803,11 +803,9 @@ done:
 		crtc->y = saved_y;
 		crtc->rotation = saved_rotation;
 		crtc->mode = saved_mode;
-	}
-#if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
-	else
+	} else
 		crtc->active = TRUE;
-#endif
+
 	free(output_ids);
 
 	return ret;


More information about the xorg-commit mailing list