From: Michel Dänzer <michel.daenzer@xxxxxxx> This further reduces the PCIe bandwidth usage. Signed-off-by: Michel Dänzer <michel.daenzer at amd.com> --- src/radeon_kms.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 11 deletions(-) diff --git a/src/radeon_kms.c b/src/radeon_kms.c index adf56fd..e353d66 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -382,23 +382,76 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) } #ifdef RADEON_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); + } 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 pScrn = 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 radeon_cs_flush_indirect(pScrn); - DamageRegionProcessPending(&dirty->slave_dst->drawable); - RegionUninit(&pixregion); + if (dirty->slave_dst->master_pixmap) + DamageRegionProcessPending(&dirty->slave_dst->drawable); DamageEmpty(dirty->damage); } @@ -424,7 +477,10 @@ radeon_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; } } @@ -488,20 +544,24 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) static void radeon_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) radeon_prime_scanout_update(ent); else - redisplay_dirty(ent); + redisplay_dirty(ent, region); + } else { + DamageEmpty(ent->damage); } + + RegionDestroy(region); } } #endif -- 2.9.3