> -----Original Message-----
> From: amd-gfx [mailto:[email protected]] On Behalf
> Of Michel Dänzer
> Sent: Thursday, September 08, 2016 6:03 AM
> To: [email protected]
> Subject: [PATCH xf86-video-amdgpu 12/12] Make TearFree effective with
> PRIME slave scanout
> 
> From: Michel Dänzer <[email protected]>
> 
> TearFree can now prevent tearing with any possible display
> configuration.
> 
> Note that there may still be inter-GPU tearing if the primary GPU uses
> a different driver.
> 
> (Ported from radeon commit 38797a33117222dadbc89e5f21ed8cd5deef9bea)
> 
> Signed-off-by: Michel Dänzer <[email protected]>

Series is:
Reviewed-by: Alex Deucher <[email protected]>

> ---
>  src/amdgpu_kms.c      | 112
> ++++++++++++++++++++++++++++++++++++++++++++++----
>  src/drmmode_display.c |  33 ++++++++++++---
>  src/drmmode_display.h |   1 +
>  3 files changed, 133 insertions(+), 13 deletions(-)
> 
> diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
> index 88b0be0..a159c84 100644
> --- a/src/amdgpu_kms.c
> +++ b/src/amdgpu_kms.c
> @@ -507,31 +507,56 @@ slave_has_sync_shared_pixmap(ScrnInfoPtr scrn,
> PixmapDirtyUpdatePtr dirty)
>       return slave_scrn->driverName == scrn->driverName;
>  }
> 
> -void
> -amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame,
> uint64_t usec,
> -                                 void *event_data)
> +static Bool
> +amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
>  {
>       ScrnInfoPtr scrn = crtc->scrn;
>       ScreenPtr screen = scrn->pScreen;
> +     AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
>       PixmapPtr scanoutpix = crtc->randr_crtc->scanout_pixmap;
>       PixmapDirtyUpdatePtr dirty;
> +     Bool ret = FALSE;
> 
>       xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
> -             if (dirty->src == scanoutpix &&
> -                 dirty->slave_dst == drmmode_crtc->scanout[0].pixmap) {
> +             if (dirty->src == scanoutpix && dirty->slave_dst ==
> +                 drmmode_crtc->scanout[scanout_id ^ info-
> >tear_free].pixmap) {
>                       RegionPtr region;
> 
>                       if (master_has_sync_shared_pixmap(scrn, dirty))
>                               amdgpu_sync_shared_pixmap(dirty);
> 
>                       region = dirty_region(dirty);
> +                     if (RegionNil(region))
> +                             goto destroy;
> +
> +                     if (info->tear_free) {
> +                             RegionTranslate(region, crtc->x, crtc->y);
> +                             amdgpu_sync_scanout_pixmaps(crtc, region,
> scanout_id);
> +                             amdgpu_glamor_flush(scrn);
> +                             RegionCopy(&drmmode_crtc-
> >scanout_last_region, region);
> +                             RegionTranslate(region, -crtc->x, -crtc->y);
> +                             dirty->slave_dst = drmmode_crtc-
> >scanout[scanout_id].pixmap;
> +                     }
> +
>                       redisplay_dirty(dirty, region);
> +                     ret = TRUE;
> +             destroy:
>                       RegionDestroy(region);
>                       break;
>               }
>       }
> 
> +     return ret;
> +}
> +
> +void
> +amdgpu_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame,
> uint64_t usec,
> +                                  void *event_data)
> +{
> +     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +     amdgpu_prime_scanout_do_update(crtc, 0);
>       drmmode_crtc->scanout_update_pending = FALSE;
>  }
> 
> @@ -590,8 +615,75 @@
> amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
>  }
> 
>  static void
> +amdgpu_prime_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data)
> +{
> +     drmmode_crtc_private_ptr drmmode_crtc = event_data;
> +
> +     drmmode_crtc->scanout_update_pending = FALSE;
> +     drmmode_clear_pending_flip(crtc);
> +}
> +
> +static void
> +amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
> +{
> +     ScreenPtr screen = ent->slave_dst->drawable.pScreen;
> +     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
> +     AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
> +     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
> +     xf86CrtcPtr crtc = NULL;
> +     drmmode_crtc_private_ptr drmmode_crtc = NULL;
> +     uintptr_t drm_queue_seq;
> +     unsigned scanout_id;
> +     int c;
> +
> +     /* Find the CRTC which is scanning out from this slave pixmap */
> +     for (c = 0; c < xf86_config->num_crtc; c++) {
> +             crtc = xf86_config->crtc[c];
> +             drmmode_crtc = crtc->driver_private;
> +             scanout_id = drmmode_crtc->scanout_id;
> +             if (drmmode_crtc->scanout[scanout_id].pixmap == ent-
> >slave_dst)
> +                     break;
> +     }
> +
> +     if (c == xf86_config->num_crtc ||
> +         !crtc->enabled ||
> +         drmmode_crtc->scanout_update_pending ||
> +         !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap ||
> +         drmmode_crtc->pending_dpms_mode != DPMSModeOn)
> +             return;
> +
> +     scanout_id = drmmode_crtc->scanout_id ^ 1;
> +     if (!amdgpu_prime_scanout_do_update(crtc, scanout_id))
> +             return;
> +
> +     drm_queue_seq = amdgpu_drm_queue_alloc(crtc,
> +
> AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
> +
> AMDGPU_DRM_QUEUE_ID_DEFAULT,
> +                                            drmmode_crtc, NULL,
> +
> amdgpu_prime_scanout_flip_abort);
> +     if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
> +             xf86DrvMsg(scrn->scrnIndex, X_WARNING,
> +                        "Allocating DRM event queue entry failed for PRIME
> flip.\n");
> +             return;
> +     }
> +
> +     if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc-
> >mode_crtc->crtc_id,
> +                         drmmode_crtc->scanout[scanout_id].fb_id,
> +                         DRM_MODE_PAGE_FLIP_EVENT,
> (void*)drm_queue_seq)) {
> +             xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue
> failed in %s: %s\n",
> +                        __func__, strerror(errno));
> +             return;
> +     }
> +
> +     drmmode_crtc->scanout_id = scanout_id;
> +     drmmode_crtc->scanout_update_pending = TRUE;
> +     drmmode_crtc->flip_pending = TRUE;
> +}
> +
> +static void
>  amdgpu_dirty_update(ScrnInfoPtr scrn)
>  {
> +     AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>       ScreenPtr screen = scrn->pScreen;
>       PixmapDirtyUpdatePtr ent;
>       RegionPtr region;
> @@ -611,10 +703,14 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
> 
>                       region = dirty_region(region_ent);
> 
> -                     if (RegionNotEmpty(region))
> -                             amdgpu_prime_scanout_update(ent);
> -                     else
> +                     if (RegionNotEmpty(region)) {
> +                             if (info->tear_free)
> +                                     amdgpu_prime_scanout_flip(ent);
> +                             else
> +
>       amdgpu_prime_scanout_update(ent);
> +                     } else {
>                               DamageEmpty(region_ent->damage);
> +                     }
> 
>                       RegionDestroy(region);
>               } else {
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 1e4622d..31aa1db 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -467,10 +467,19 @@ drmmode_crtc_scanout_destroy(drmmode_ptr
> drmmode,
>  static void
>  drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc)
>  {
> -     drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> -                                  &drmmode_crtc->scanout[0]);
> -     drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> -                                  &drmmode_crtc->scanout[1]);
> +     if (drmmode_crtc->flip_pending) {
> +             drmmode_crtc->scanout_destroy[0] = drmmode_crtc-
> >scanout[0];
> +             drmmode_crtc->scanout[0].pixmap = NULL;
> +             drmmode_crtc->scanout[0].bo = NULL;
> +             drmmode_crtc->scanout_destroy[1] = drmmode_crtc-
> >scanout[1];
> +             drmmode_crtc->scanout[1].pixmap = NULL;
> +             drmmode_crtc->scanout[1].bo = NULL;
> +     } else {
> +             drmmode_crtc_scanout_destroy(drmmode_crtc-
> >drmmode,
> +                                          &drmmode_crtc->scanout[0]);
> +             drmmode_crtc_scanout_destroy(drmmode_crtc-
> >drmmode,
> +                                          &drmmode_crtc->scanout[1]);
> +     }
> 
>       if (drmmode_crtc->scanout_damage) {
>               DamageDestroy(drmmode_crtc->scanout_damage);
> @@ -1062,11 +1071,12 @@ drmmode_crtc_gamma_set(xf86CrtcPtr crtc,
> uint16_t * red, uint16_t * green,
>  static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>  {
>       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +     AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
> 
>       if (!ppix) {
>               if (crtc->randr_crtc->scanout_pixmap)
>                       PixmapStopDirtyTracking(crtc->randr_crtc-
> >scanout_pixmap,
> -                                             drmmode_crtc-
> >scanout[0].pixmap);
> +                                             drmmode_crtc-
> >scanout[drmmode_crtc->scanout_id].pixmap);
>               drmmode_crtc_scanout_free(drmmode_crtc);
>               return TRUE;
>       }
> @@ -1076,6 +1086,14 @@ static Bool
> drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>                                        ppix->drawable.height))
>               return FALSE;
> 
> +     if (info->tear_free &&
> +         !drmmode_crtc_scanout_create(crtc, &drmmode_crtc-
> >scanout[1],
> +                                      ppix->drawable.width,
> +                                      ppix->drawable.height)) {
> +             drmmode_crtc_scanout_free(drmmode_crtc);
> +             return FALSE;
> +     }
> +
>  #ifdef HAS_DIRTYTRACKING_ROTATION
>       PixmapStartDirtyTracking(ppix, drmmode_crtc->scanout[0].pixmap,
>                                0, 0, 0, 0, RR_Rotate_0);
> @@ -2010,6 +2028,11 @@ drmmode_clear_pending_flip(xf86CrtcPtr crtc)
> 
>               drmmode_crtc_dpms(crtc, drmmode_crtc-
> >pending_dpms_mode);
>       }
> +
> +     drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> +                                  &drmmode_crtc->scanout_destroy[0]);
> +     drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
> +                                  &drmmode_crtc->scanout_destroy[1]);
>  }
> 
>  static void
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index 6c5542c..4973bc2 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -84,6 +84,7 @@ typedef struct {
>       struct amdgpu_buffer *cursor_buffer;
>       struct drmmode_scanout rotate;
>       struct drmmode_scanout scanout[2];
> +     struct drmmode_scanout scanout_destroy[2];
>       DamagePtr scanout_damage;
>       RegionRec scanout_last_region;
>       unsigned scanout_id;
> --
> 2.9.3
> 
> _______________________________________________
> amd-gfx mailing list
> [email protected]
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
_______________________________________________
amd-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to