[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