From: Michel Dänzer <michel.daen...@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.daen...@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

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to