[PATCH xf86-video-amdgpu 6/6] Allow toggling TearFree at runtime via output property

Alex Deucher alexdeucher at gmail.com
Thu Mar 2 14:31:55 UTC 2017


On Thu, Mar 2, 2017 at 4:18 AM, Michel Dänzer <michel at daenzer.net> wrote:
> From: Michel Dänzer <michel.daenzer at amd.com>
>
> Option "TearFree" now sets the default value of the output property.
> See the manpage update for details.
>
> TearFree is now enabled by default for outputs using rotation or other
> RandR transforms, and for RandR 1.4 slave outputs.
>
> (Ported from radeon commit 58cd1600057e41aade0106d4acf78e23eac6e44f)
>
> Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>

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

> ---
>  man/amdgpu.man        |  15 +++--
>  src/amdgpu_dri2.c     |  34 +++++++++--
>  src/amdgpu_drv.h      |   2 +-
>  src/amdgpu_kms.c      |  57 ++++++++++--------
>  src/drmmode_display.c | 162 +++++++++++++++++++++++++++++++++++++++++++++-----
>  src/drmmode_display.h |   2 +
>  6 files changed, 221 insertions(+), 51 deletions(-)
>
> diff --git a/man/amdgpu.man b/man/amdgpu.man
> index 0e5c291d..53bd768a 100644
> --- a/man/amdgpu.man
> +++ b/man/amdgpu.man
> @@ -73,10 +73,17 @@ Enable DRI2 page flipping.  The default is
>  .B on.
>  .TP
>  .BI "Option \*qTearFree\*q \*q" boolean \*q
> -Enable tearing prevention using the hardware page flipping mechanism. Requires allocating two
> -separate scanout buffers for each CRTC. Enabling this option currently disables Option
> -\*qEnablePageFlip\*q. The default is
> -.B off.
> +Set the default value of the per-output 'TearFree' property, which controls
> +tearing prevention using the hardware page flipping mechanism. TearFree is
> +on for any CRTC associated with one or more outputs with TearFree on. Two
> +separate scanout buffers need to be allocated for each CRTC with TearFree
> +on. While TearFree is on for any CRTC, it currently prevents clients from using
> +DRI page flipping. If this option is set, the default value of the property is
> +'on' or 'off' accordingly. If this option isn't set, the default value of the
> +property is
> +.B auto,
> +which means that TearFree is on for outputs with rotation or other RandR
> +transforms, and for RandR 1.4 slave outputs, otherwise off.
>  .TP
>  .BI "Option \*qAccelMethod\*q \*q" string \*q
>  Setting this option to
> diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
> index a83d2177..8dde2930 100644
> --- a/src/amdgpu_dri2.c
> +++ b/src/amdgpu_dri2.c
> @@ -51,6 +51,7 @@
>  #include "amdgpu_list.h"
>
>  #include <xf86Priv.h>
> +#include <X11/extensions/dpmsconst.h>
>
>  #if DRI2INFOREC_VERSION >= 9
>  #define USE_DRI2_PRIME
> @@ -637,13 +638,34 @@ can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
>          DRI2BufferPtr front, DRI2BufferPtr back)
>  {
>         AMDGPUInfoPtr info = AMDGPUPTR(pScrn);
> +       xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
> +       int num_crtcs_on;
> +       int i;
> +
> +       if (draw->type != DRAWABLE_WINDOW ||
> +           !info->allowPageFlip ||
> +           info->hwcursor_disabled ||
> +           info->drmmode.present_flipping ||
> +           !pScrn->vtSema ||
> +           !DRI2CanFlip(draw))
> +               return FALSE;
> +
> +       for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
> +               xf86CrtcPtr crtc = config->crtc[i];
> +               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +               if (!crtc->enabled)
> +                       continue;
> +
> +               if (!drmmode_crtc || drmmode_crtc->rotate.bo ||
> +                       drmmode_crtc->scanout[0].bo)
> +                       return FALSE;
> +
> +               if (drmmode_crtc->pending_dpms_mode == DPMSModeOn)
> +                       num_crtcs_on++;
> +       }
>
> -       return draw->type == DRAWABLE_WINDOW &&
> -           info->allowPageFlip &&
> -           !info->hwcursor_disabled &&
> -           !info->drmmode.present_flipping &&
> -           pScrn->vtSema &&
> -           DRI2CanFlip(draw) && can_exchange(pScrn, draw, front, back);
> +       return num_crtcs_on > 0 && can_exchange(pScrn, draw, front, back);
>  }
>
>  static void
> diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
> index 3a24fa73..2aaafe43 100644
> --- a/src/amdgpu_drv.h
> +++ b/src/amdgpu_drv.h
> @@ -221,7 +221,7 @@ typedef struct {
>         Bool use_glamor;
>         Bool force_accel;
>         Bool shadow_primary;
> -       Bool tear_free;
> +       int tear_free;
>
>         /* general */
>         OptionInfoPtr Options;
> diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
> index 10a68fbd..bafcb9bb 100644
> --- a/src/amdgpu_kms.c
> +++ b/src/amdgpu_kms.c
> @@ -575,7 +575,6 @@ 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;
> @@ -583,7 +582,7 @@ amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
>
>         xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) {
>                 if (dirty->src == scanoutpix && dirty->slave_dst ==
> -                   drmmode_crtc->scanout[scanout_id ^ info->tear_free].pixmap) {
> +                   drmmode_crtc->scanout[scanout_id ^ drmmode_crtc->tear_free].pixmap) {
>                         RegionPtr region;
>
>                         if (master_has_sync_shared_pixmap(scrn, dirty))
> @@ -593,7 +592,7 @@ amdgpu_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id)
>                         if (RegionNil(region))
>                                 goto destroy;
>
> -                       if (info->tear_free) {
> +                       if (drmmode_crtc->tear_free) {
>                                 RegionTranslate(region, crtc->x, crtc->y);
>                                 amdgpu_sync_scanout_pixmaps(crtc, region, scanout_id);
>                                 amdgpu_glamor_flush(scrn);
> @@ -730,7 +729,6 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
>  static void
>  amdgpu_dirty_update(ScrnInfoPtr scrn)
>  {
> -       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>         ScreenPtr screen = scrn->pScreen;
>         PixmapDirtyUpdatePtr ent;
>         RegionPtr region;
> @@ -751,7 +749,13 @@ amdgpu_dirty_update(ScrnInfoPtr scrn)
>                         region = dirty_region(region_ent);
>
>                         if (RegionNotEmpty(region)) {
> -                               if (info->tear_free)
> +                               xf86CrtcPtr crtc = amdgpu_prime_dirty_to_crtc(ent);
> +                               drmmode_crtc_private_ptr drmmode_crtc = NULL;
> +
> +                               if (crtc)
> +                                       drmmode_crtc = crtc->driver_private;
> +
> +                               if (drmmode_crtc && drmmode_crtc->tear_free)
>                                         amdgpu_prime_scanout_flip(ent);
>                                 else
>                                         amdgpu_prime_scanout_update(ent);
> @@ -779,7 +783,6 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
>         RegionPtr pRegion = DamageRegion(drmmode_crtc->scanout_damage);
>         ScrnInfoPtr scrn = xf86_crtc->scrn;
>         ScreenPtr pScreen = scrn->pScreen;
> -       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>         DrawablePtr pDraw;
>         BoxRec extents;
>
> @@ -796,7 +799,7 @@ amdgpu_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
>         if (!amdgpu_scanout_extents_intersect(xf86_crtc, &extents))
>                 return FALSE;
>
> -       if (info->tear_free) {
> +       if (drmmode_crtc->tear_free) {
>                 amdgpu_sync_scanout_pixmaps(xf86_crtc, pRegion, scanout_id);
>                 RegionCopy(&drmmode_crtc->scanout_last_region, pRegion);
>         }
> @@ -1014,14 +1017,17 @@ static void AMDGPUBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
>         if (!amdgpu_is_gpu_screen(pScreen))
>         {
>                 for (c = 0; c < xf86_config->num_crtc; c++) {
> -                       if (info->tear_free)
> -                               amdgpu_scanout_flip(pScreen, info, xf86_config->crtc[c]);
> +                       xf86CrtcPtr crtc = xf86_config->crtc[c];
> +                       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +                       if (drmmode_crtc->tear_free)
> +                               amdgpu_scanout_flip(pScreen, info, crtc);
>                         else if (info->shadow_primary
>  #if XF86_CRTC_VERSION >= 4
> -                                        || xf86_config->crtc[c]->driverIsPerformingTransform
> +                                || crtc->driverIsPerformingTransform
>  #endif
>                                 )
> -                               amdgpu_scanout_update(xf86_config->crtc[c]);
> +                               amdgpu_scanout_update(crtc);
>                 }
>         }
>
> @@ -1265,6 +1271,7 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
>         AMDGPUInfoPtr info;
>         AMDGPUEntPtr pAMDGPUEnt;
>         struct amdgpu_gpu_info gpu_info;
> +       MessageType from;
>         DevUnion *pPriv;
>         Gamma zeros = { 0.0, 0.0, 0.0 };
>         int cpp;
> @@ -1359,12 +1366,14 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
>         }
>
>         if (info->use_glamor) {
> -               info->tear_free = xf86ReturnOptValBool(info->Options,
> -                                                      OPTION_TEAR_FREE, FALSE);
> +               from = X_DEFAULT;
>
> -               if (info->tear_free)
> -                       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
> -                                  "TearFree enabled\n");
> +               info->tear_free = 2;
> +               if (xf86GetOptValBool(info->Options, OPTION_TEAR_FREE,
> +                                     &info->tear_free))
> +                       from = X_CONFIG;
> +               xf86DrvMsg(pScrn->scrnIndex, from, "TearFree property default: %s\n",
> +                          info->tear_free == 2 ? "auto" : (info->tear_free ? "on" : "off"));
>
>                 info->shadow_primary =
>                         xf86ReturnOptValBool(info->Options, OPTION_SHADOW_PRIMARY, FALSE);
> @@ -1378,14 +1387,14 @@ Bool AMDGPUPreInit_KMS(ScrnInfoPtr pScrn, int flags)
>         info->allowPageFlip = xf86ReturnOptValBool(info->Options,
>                                                    OPTION_PAGE_FLIP,
>                                                    TRUE);
> -       if (sw_cursor || info->tear_free || info->shadow_primary) {
> -                   xf86DrvMsg(pScrn->scrnIndex,
> -                              info->allowPageFlip ? X_WARNING : X_DEFAULT,
> -                              "KMS Pageflipping: disabled%s\n",
> -                              info->allowPageFlip ?
> -                              (sw_cursor ? " because of SWcursor" :
> -                               " because of ShadowPrimary/TearFree") : "");
> -                   info->allowPageFlip = FALSE;
> +       if (sw_cursor || info->shadow_primary) {
> +               xf86DrvMsg(pScrn->scrnIndex,
> +                          info->allowPageFlip ? X_WARNING : X_DEFAULT,
> +                          "KMS Pageflipping: disabled%s\n",
> +                          info->allowPageFlip ?
> +                          (sw_cursor ? " because of SWcursor" :
> +                           " because of ShadowPrimary") : "");
> +               info->allowPageFlip = FALSE;
>         } else {
>                 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
>                            "KMS Pageflipping: %sabled\n",
> diff --git a/src/drmmode_display.c b/src/drmmode_display.c
> index 303848f3..40439dd2 100644
> --- a/src/drmmode_display.c
> +++ b/src/drmmode_display.c
> @@ -587,6 +587,34 @@ drmmode_can_use_hw_cursor(xf86CrtcPtr crtc)
>         return TRUE;
>  }
>
> +static void
> +drmmode_crtc_update_tear_free(xf86CrtcPtr crtc)
> +{
> +       AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
> +       xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
> +       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +       int i;
> +
> +       drmmode_crtc->tear_free = FALSE;
> +
> +       for (i = 0; i < xf86_config->num_output; i++) {
> +               xf86OutputPtr output = xf86_config->output[i];
> +               drmmode_output_private_ptr drmmode_output = output->driver_private;
> +
> +               if (output->crtc != crtc)
> +                       continue;
> +
> +               if (drmmode_output->tear_free == 1 ||
> +                   (drmmode_output->tear_free == 2 &&
> +                    (amdgpu_is_gpu_screen(crtc->scrn->pScreen) ||
> +                     info->shadow_primary ||
> +                     crtc->transformPresent || crtc->rotation != RR_Rotate_0))) {
> +                       drmmode_crtc->tear_free = TRUE;
> +                       return;
> +               }
> +       }
> +}
> +
>  #if XF86_CRTC_VERSION >= 4
>
>  #if XF86_CRTC_VERSION < 7
> @@ -621,24 +649,86 @@ drmmode_handle_transform(xf86CrtcPtr crtc)
>
>  #endif
>
> +#ifdef AMDGPU_PIXMAP_SHARING
> +
> +static void
> +drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
> +                                 unsigned scanout_id, int *fb_id, int *x,
> +                                 int *y)
> +{
> +       ScrnInfoPtr scrn = crtc->scrn;
> +       ScreenPtr screen = scrn->pScreen;
> +       drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> +
> +       if (drmmode_crtc->tear_free &&
> +           !drmmode_crtc->scanout[1].pixmap) {
> +               RegionPtr region;
> +               BoxPtr box;
> +
> +               drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
> +                                           mode->HDisplay,
> +                                           mode->VDisplay);
> +               region = &drmmode_crtc->scanout_last_region;
> +               RegionUninit(region);
> +               region->data = NULL;
> +               box = RegionExtents(region);
> +               box->x1 = crtc->x;
> +               box->y1 = crtc->y;
> +               box->x2 = crtc->x + mode->HDisplay;
> +               box->y2 = crtc->y + mode->VDisplay;
> +       }
> +
> +       if (scanout_id != drmmode_crtc->scanout_id) {
> +               PixmapDirtyUpdatePtr dirty = NULL;
> +
> +               xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list,
> +                                        ent) {
> +                       if (dirty->src == crtc->randr_crtc->scanout_pixmap &&
> +                           dirty->slave_dst ==
> +                           drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) {
> +                               dirty->slave_dst =
> +                                       drmmode_crtc->scanout[scanout_id].pixmap;
> +                               break;
> +                       }
> +               }
> +
> +               if (!drmmode_crtc->tear_free) {
> +                       GCPtr gc = GetScratchGC(scrn->depth, screen);
> +
> +                       ValidateGC(&drmmode_crtc->scanout[0].pixmap->drawable, gc);
> +                       gc->ops->CopyArea(&drmmode_crtc->scanout[1].pixmap->drawable,
> +                                         &drmmode_crtc->scanout[0].pixmap->drawable,
> +                                         gc, 0, 0, mode->HDisplay, mode->VDisplay,
> +                                         0, 0);
> +                       FreeScratchGC(gc);
> +                       amdgpu_glamor_finish(scrn);
> +               }
> +       }
> +
> +       *fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
> +       *x = *y = 0;
> +       drmmode_crtc->scanout_id = scanout_id;
> +}
> +
> +#endif /* AMDGPU_PIXMAP_SHARING */
> +
>  static void
>  drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode,
>                             unsigned scanout_id, int *fb_id, int *x, int *y)
>  {
>         ScrnInfoPtr scrn = crtc->scrn;
>         ScreenPtr screen = scrn->pScreen;
> -       AMDGPUInfoPtr info = AMDGPUPTR(scrn);
>         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
>
>         drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[0],
>                                     mode->HDisplay, mode->VDisplay);
> -       if (info->tear_free) {
> +       if (drmmode_crtc->tear_free) {
>                 drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
>                                             mode->HDisplay, mode->VDisplay);
>         }
>
>         if (drmmode_crtc->scanout[0].pixmap &&
> -           (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
> +           (!drmmode_crtc->tear_free || drmmode_crtc->scanout[1].pixmap)) {
>                 RegionPtr region;
>                 BoxPtr box;
>
> @@ -678,7 +768,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
>         AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn);
>         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
>         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
> -       unsigned scanout_id = drmmode_crtc->scanout_id ^ info->tear_free;
> +       unsigned scanout_id = 0;
>         drmmode_ptr drmmode = drmmode_crtc->drmmode;
>         int saved_x, saved_y;
>         Rotation saved_rotation;
> @@ -722,6 +812,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
>                 if (!drmmode_handle_transform(crtc))
>                         goto done;
>
> +               drmmode_crtc_update_tear_free(crtc);
> +               if (drmmode_crtc->tear_free)
> +                       scanout_id = drmmode_crtc->scanout_id;
> +
>                 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
>                                        crtc->gamma_blue, crtc->gamma_size);
>
> @@ -730,8 +824,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
>                 fb_id = drmmode->fb_id;
>  #ifdef AMDGPU_PIXMAP_SHARING
>                 if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
> -                       fb_id = drmmode_crtc->scanout[scanout_id].fb_id;
> -                       x = y = 0;
> +                       drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id,
> +                                                         &fb_id, &x, &y);
>                 } else
>  #endif
>                 if (drmmode_crtc->rotate.fb_id) {
> @@ -739,7 +833,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
>                         x = y = 0;
>
>                 } else if (!amdgpu_is_gpu_screen(pScreen) &&
> -                          (info->tear_free ||
> +                          (drmmode_crtc->tear_free ||
>  #if XF86_CRTC_VERSION >= 4
>                             crtc->driverIsPerformingTransform ||
>  #endif
> @@ -828,6 +922,10 @@ done:
>
>                 if (fb_id != drmmode_crtc->scanout[scanout_id].fb_id)
>                         drmmode_crtc_scanout_free(drmmode_crtc);
> +               else if (!drmmode_crtc->tear_free) {
> +                       drmmode_crtc_scanout_destroy(drmmode,
> +                                                    &drmmode_crtc->scanout[1]);
> +               }
>         }
>
>         return ret;
> @@ -1086,7 +1184,6 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>  {
>         drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
>         unsigned scanout_id = drmmode_crtc->scanout_id;
> -       AMDGPUInfoPtr info = AMDGPUPTR(crtc->scrn);
>         ScreenPtr screen = crtc->scrn->pScreen;
>         PixmapDirtyUpdatePtr dirty;
>
> @@ -1107,7 +1204,7 @@ static Bool drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
>                                          ppix->drawable.height))
>                 return FALSE;
>
> -       if (info->tear_free &&
> +       if (drmmode_crtc->tear_free &&
>             !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1],
>                                          ppix->drawable.width,
>                                          ppix->drawable.height)) {
> @@ -1354,14 +1451,15 @@ static Bool drmmode_property_ignore(drmModePropertyPtr prop)
>
>  static void drmmode_output_create_resources(xf86OutputPtr output)
>  {
> +       AMDGPUInfoPtr info = AMDGPUPTR(output->scrn);
>         drmmode_output_private_ptr drmmode_output = output->driver_private;
>         drmModeConnectorPtr mode_output = drmmode_output->mode_output;
>         AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(output->scrn);
> -       drmModePropertyPtr drmmode_prop;
> +       drmModePropertyPtr drmmode_prop, tearfree_prop;
>         int i, j, err;
>
>         drmmode_output->props =
> -           calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
> +               calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec));
>         if (!drmmode_output->props)
>                 return;
>
> @@ -1379,6 +1477,23 @@ static void drmmode_output_create_resources(xf86OutputPtr output)
>                 j++;
>         }
>
> +       /* Userspace-only property for TearFree */
> +       tearfree_prop = calloc(1, sizeof(*tearfree_prop));
> +       tearfree_prop->flags = DRM_MODE_PROP_ENUM;
> +       strncpy(tearfree_prop->name, "TearFree", 8);
> +       tearfree_prop->count_enums = 3;
> +       tearfree_prop->enums = calloc(tearfree_prop->count_enums,
> +                                     sizeof(*tearfree_prop->enums));
> +       strncpy(tearfree_prop->enums[0].name, "off", 3);
> +       strncpy(tearfree_prop->enums[1].name, "on", 2);
> +       tearfree_prop->enums[1].value = 1;
> +       strncpy(tearfree_prop->enums[2].name, "auto", 4);
> +       tearfree_prop->enums[2].value = 2;
> +       drmmode_output->props[j].mode_prop = tearfree_prop;
> +       drmmode_output->props[j].value = info->tear_free;
> +       drmmode_output->tear_free = info->tear_free;
> +       drmmode_output->num_props++;
> +
>         for (i = 0; i < drmmode_output->num_props; i++) {
>                 drmmode_prop_ptr p = &drmmode_output->props[i];
>                 drmmode_prop = p->mode_prop;
> @@ -1504,11 +1619,26 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property,
>                         /* search for matching name string, then set its value down */
>                         for (j = 0; j < p->mode_prop->count_enums; j++) {
>                                 if (!strcmp(p->mode_prop->enums[j].name, name)) {
> -                                       drmModeConnectorSetProperty(pAMDGPUEnt->fd,
> -                                                                   drmmode_output->output_id,
> -                                                                   p->mode_prop->prop_id,
> -                                                                   p->mode_prop->enums
> -                                                                   [j].value);
> +                                       if (i == (drmmode_output->num_props - 1)) {
> +                                               if (drmmode_output->tear_free != j) {
> +                                                       xf86CrtcPtr crtc = output->crtc;
> +
> +                                                       drmmode_output->tear_free = j;
> +                                                       if (crtc) {
> +                                                               drmmode_set_mode_major(crtc,
> +                                                                                      &crtc->mode,
> +                                                                                      crtc->rotation,
> +                                                                                      crtc->x,
> +                                                                                      crtc->y);
> +                                                       }
> +                                               }
> +                                       } else {
> +                                               drmModeConnectorSetProperty(pAMDGPUEnt->fd,
> +                                                                           drmmode_output->output_id,
> +                                                                           p->mode_prop->prop_id,
> +                                                                           p->mode_prop->enums[j].value);
> +                                       }
> +
>                                         return TRUE;
>                                 }
>                         }
> diff --git a/src/drmmode_display.h b/src/drmmode_display.h
> index e9967a26..fa15a4f7 100644
> --- a/src/drmmode_display.h
> +++ b/src/drmmode_display.h
> @@ -85,6 +85,7 @@ typedef struct {
>         RegionRec scanout_last_region;
>         unsigned scanout_id;
>         Bool scanout_update_pending;
> +       Bool tear_free;
>         int dpms_mode;
>         /* For when a flip is pending when DPMS off requested */
>         int pending_dpms_mode;
> @@ -117,6 +118,7 @@ typedef struct {
>         drmmode_prop_ptr props;
>         int enc_mask;
>         int enc_clone_mask;
> +       int tear_free;
>  } drmmode_output_private_rec, *drmmode_output_private_ptr;
>
>
> --
> 2.11.0
>
> _______________________________________________
> 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