From 61ceefe17fe9e6ffbaaad0e216b2bd37fd39f47d Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Thu, 8 Sep 2016 17:15:03 +0900 Subject: Track damage accurately for RandR 1.4 slave scanout This further reduces the PCIe bandwidth usage. (Ported from radeon commit b0867063abb197b9134166706d99fcbe5f204bb5, plus leak fix from 5a57005178fc13b6f7e513458ca6dae72a3e5783) Reviewed-by: Alex Deucher --- 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 -- cgit v1.2.3