[PATCH v2 xf86-video-ati 1/2] Only copy from screen pixmap to shared pixmap on demand for slave scanout

Deucher, Alexander Alexander.Deucher at amd.com
Thu Sep 1 13:49:11 UTC 2016


> -----Original Message-----
> From: amd-gfx [mailto:amd-gfx-bounces at lists.freedesktop.org] On Behalf
> Of Michel Dänzer
> Sent: Thursday, September 01, 2016 3:46 AM
> To: amd-gfx at lists.freedesktop.org
> Subject: [PATCH v2 xf86-video-ati 1/2] Only copy from screen pixmap to
> shared pixmap on demand for slave scanout
> 
> From: Michel Dänzer <michel.daenzer at amd.com>
> 
> Only copy once for each time we update the corresponding scanout pixmap.
> This can significantly reduce the bandwidth usage when there are
> frequent updates to the screen pixmap.
> 
> This initial implementation only works when both the master and slave
> screens use this driver.
> 
> v2:
> * Reduce churn in radeon_prime_scanout_update_handler
> * Clear the correct damage in radeon_dirty_update
> 
> Reviewed-by: Alex Deucher <alexander.deucher at amd.com> [v1]
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

Reviewed-by: Alex Deucher <alexander.deucher at amd.com>

> ---
>  src/radeon_kms.c | 82
> +++++++++++++++++++++++++++++++++++++++++++++++---------
>  1 file changed, 69 insertions(+), 13 deletions(-)
> 
> diff --git a/src/radeon_kms.c b/src/radeon_kms.c
> index 51f320c..711e84a 100644
> --- a/src/radeon_kms.c
> +++ b/src/radeon_kms.c
> @@ -440,6 +440,9 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty,
> RegionPtr region)
>  {
>  	ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->src-
> >drawable.pScreen);
> 
> +	if (RegionNil(region))
> +		goto out;
> +
>  	if (dirty->slave_dst->master_pixmap)
>  	    DamageRegionAppend(&dirty->slave_dst->drawable, region);
> 
> @@ -453,6 +456,7 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty,
> RegionPtr region)
>  	if (dirty->slave_dst->master_pixmap)
>  	    DamageRegionProcessPending(&dirty->slave_dst->drawable);
> 
> +out:
>  	DamageEmpty(dirty->damage);
>  }
> 
> @@ -465,6 +469,39 @@ radeon_prime_scanout_update_abort(xf86CrtcPtr
> crtc, void *event_data)
>  }
> 
>  void
> +radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty)
> +{
> +    ScreenPtr master_screen = dirty->src->master_pixmap-
> >drawable.pScreen;
> +    PixmapDirtyUpdatePtr ent;
> +    RegionPtr region;
> +
> +    xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent)
> {
> +	if (ent->slave_dst != dirty->src)
> +	    continue;
> +
> +	region = dirty_region(ent);
> +	redisplay_dirty(ent, region);
> +	RegionDestroy(region);
> +    }
> +}
> +
> +static Bool
> +master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr
> dirty)
> +{
> +    ScrnInfoPtr master_scrn = xf86ScreenToScrn(dirty->src->master_pixmap-
> >drawable.pScreen);
> +
> +    return master_scrn->driverName == scrn->driverName;
> +}
> +
> +static Bool
> +slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr
> dirty)
> +{
> +    ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst-
> >drawable.pScreen);
> +
> +    return slave_scrn->driverName == scrn->driverName;
> +}
> +
> +void
>  radeon_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame,
> uint64_t usec,
>  				    void *event_data)
>  {
> @@ -477,8 +514,12 @@
> 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) {
> -	    RegionPtr region = dirty_region(dirty);
> +	    RegionPtr region;
> 
> +	    if (master_has_sync_shared_pixmap(scrn, dirty))
> +		radeon_sync_shared_pixmap(dirty);
> +
> +	    region = dirty_region(dirty);
>  	    redisplay_dirty(dirty, region);
>  	    RegionDestroy(region);
>  	    break;
> @@ -542,26 +583,41 @@
> radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
>  }
> 
>  static void
> -radeon_dirty_update(ScreenPtr screen)
> +radeon_dirty_update(ScrnInfoPtr scrn)
>  {
> +	ScreenPtr screen = scrn->pScreen;
>  	PixmapDirtyUpdatePtr ent;
> -
> -	if (xorg_list_is_empty(&screen->pixmap_dirty_list))
> -		return;
> +	RegionPtr region;
> 
>  	xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
> -		RegionPtr region = dirty_region(ent);
> +		if (screen->isGPU) {
> +			PixmapDirtyUpdatePtr region_ent = ent;
> +
> +			if (master_has_sync_shared_pixmap(scrn, ent)) {
> +				ScreenPtr master_screen = ent->src-
> >master_pixmap->drawable.pScreen;
> 
> -		if (RegionNotEmpty(region)) {
> -			if (screen->isGPU)
> +				xorg_list_for_each_entry(region_ent,
> &master_screen->pixmap_dirty_list, ent) {
> +					if (region_ent->slave_dst == ent-
> >src)
> +						break;
> +				}
> +			}
> +
> +			region = dirty_region(region_ent);
> +
> +			if (RegionNotEmpty(region))
>  				radeon_prime_scanout_update(ent);
>  			else
> -				redisplay_dirty(ent, region);
> +				DamageEmpty(region_ent->damage);
> +
> +			RegionDestroy(region);
>  		} else {
> -			DamageEmpty(ent->damage);
> -		}
> +			if (slave_has_sync_shared_pixmap(scrn, ent))
> +				continue;
> 
> -		RegionDestroy(region);
> +			region = dirty_region(ent);
> +			redisplay_dirty(ent, region);
> +			RegionDestroy(region);
> +		}
>  	}
>  }
>  #endif
> @@ -861,7 +917,7 @@ static void
> RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
>      radeon_cs_flush_indirect(pScrn);
> 
>  #ifdef RADEON_PIXMAP_SHARING
> -    radeon_dirty_update(pScreen);
> +    radeon_dirty_update(pScrn);
>  #endif
>  }
> 
> --
> 2.9.3
> 
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx


More information about the amd-gfx mailing list