[PATCH xf86-video-amdgpu 07/12] Track damage accurately for RandR 1.4 slave scanout

Michel Dänzer michel at daenzer.net
Thu Sep 8 10:02:40 UTC 2016


From: Michel Dänzer <michel.daenzer at amd.com>

This further reduces the PCIe bandwidth usage.

(Ported from radeon commit b0867063abb197b9134166706d99fcbe5f204bb5,
 plus leak fix from 5a57005178fc13b6f7e513458ca6dae72a3e5783)

Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
---
 src/amdgpu_kms.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 11 deletions(-)

diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index aaaee1a..0342ef8 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -304,23 +304,77 @@ static Bool AMDGPUCreateScreenResources_KMS(ScreenPtr pScreen)
 }
 
 #ifdef AMDGPU_PIXMAP_SHARING
+static RegionPtr
+dirty_region(PixmapDirtyUpdatePtr dirty)
+{
+	RegionPtr damageregion = DamageRegion(dirty->damage);
+	RegionPtr dstregion;
+
+#ifdef HAS_DIRTYTRACKING_ROTATION
+	if (dirty->rotation != RR_Rotate_0) {
+		BoxPtr boxes = RegionRects(damageregion);
+		int nboxes = RegionNumRects(damageregion);
+		xRectanglePtr rects = malloc(nboxes * sizeof(*rects));
+		int dst_w = dirty->slave_dst->drawable.width;
+		int dst_h = dirty->slave_dst->drawable.height;
+		int nrects = 0;
+		BoxRec box;
+		int i;
+
+		for (i = 0; i < nboxes; i++) {
+			box.x1 = boxes[i].x1;
+			box.x2 = boxes[i].x2;
+			box.y1 = boxes[i].y1;
+			box.y2 = boxes[i].y2;
+			pixman_f_transform_bounds(&dirty->f_inverse, &box);
+
+			box.x1 = max(box.x1, 0);
+			box.y1 = max(box.y1, 0);
+			box.x2 = min(box.x2, dst_w);
+			box.y2 = min(box.y2, dst_h);
+			if (box.x1 >= box.x2 || box.y1 >= box.y2)
+				continue;
+
+			rects[nrects].x = box.x1;
+			rects[nrects].y = box.y1;
+			rects[nrects].width = box.x2 - box.x1;
+			rects[nrects].height = box.y2 - box.y1;
+			nrects++;
+		}
+		dstregion = RegionFromRects(nrects, rects, CT_UNSORTED);
+		free(rects);
+	} else
+#endif
+	{
+		RegionRec pixregion;
+
+		dstregion = RegionDuplicate(damageregion);
+		RegionTranslate(dstregion, -dirty->x, -dirty->y);
+		PixmapRegionInit(&pixregion, dirty->slave_dst);
+		RegionIntersect(dstregion, dstregion, &pixregion);
+		RegionUninit(&pixregion);
+	}
+
+	return dstregion;
+}
+
 static void
-redisplay_dirty(PixmapDirtyUpdatePtr dirty)
+redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region)
 {
 	ScrnInfoPtr scrn = xf86ScreenToScrn(dirty->src->drawable.pScreen);
-	RegionRec pixregion;
 
-	PixmapRegionInit(&pixregion, dirty->slave_dst);
-	DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+	if (dirty->slave_dst->master_pixmap)
+		DamageRegionAppend(&dirty->slave_dst->drawable, region);
+
 #ifdef HAS_DIRTYTRACKING_ROTATION
 	PixmapSyncDirtyHelper(dirty);
 #else
-	PixmapSyncDirtyHelper(dirty, &pixregion);
+	PixmapSyncDirtyHelper(dirty, region);
 #endif
 
 	amdgpu_glamor_flush(scrn);
-	DamageRegionProcessPending(&dirty->slave_dst->drawable);
-	RegionUninit(&pixregion);
+	if (dirty->slave_dst->master_pixmap)
+		DamageRegionProcessPending(&dirty->slave_dst->drawable);
 
 	DamageEmpty(dirty->damage);
 }
@@ -346,7 +400,10 @@ amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t u
 	xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
 		if (dirty->src == scanoutpix &&
 		    dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
-			redisplay_dirty(dirty);
+			RegionPtr region = dirty_region(dirty);
+
+			redisplay_dirty(dirty, region);
+			RegionDestroy(region);
 			break;
 		}
 	}
@@ -410,20 +467,24 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
 
 static void amdgpu_dirty_update(ScreenPtr screen)
 {
-	RegionPtr region;
 	PixmapDirtyUpdatePtr ent;
 
 	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
 		return;
 
 	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
-		region = DamageRegion(ent->damage);
+		RegionPtr region = dirty_region(ent);
+
 		if (RegionNotEmpty(region)) {
 			if (screen->isGPU)
 				amdgpu_prime_scanout_update(ent);
 			else
-				redisplay_dirty(ent);
+				redisplay_dirty(ent, region);
+		} else {
+			DamageEmpty(ent->damage);
 		}
+
+		RegionDestroy(region);
 	}
 }
 #endif
-- 
2.9.3



More information about the amd-gfx mailing list