On Fri, Nov 25, 2016 at 4:41 AM, Michel Dänzer <michel at daenzer.net> wrote: > From: Michel Dänzer <michel.daenzer at amd.com> > > (Ported from radeon commits 1106b2f773ad0611c729b27f4c192a26b43ef1e7 > and 5fea5ef2f07eee4a0f94baab427010b936f1d4b4) > > v2: > * Squash in radeon fix for TearFree regression > * Remove preprocessor guards for compatibility with libdrm < 2.4.72 > (Emil Velikov) > > Signed-off-by: Michel Dänzer <michel.daenzer at amd.com> Reviewed-by: Alex Deucher <alexander.deucher at amd.com> > --- > src/amdgpu_dri2.c | 3 +- > src/amdgpu_kms.c | 18 +++++------ > src/amdgpu_present.c | 5 +-- > src/amdgpu_probe.h | 1 + > src/drmmode_display.c | 89 ++++++++++++++++++++++++++++++++++++++++++++------- > src/drmmode_display.h | 13 +++++++- > 6 files changed, 104 insertions(+), 25 deletions(-) > > diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c > index 31ac3f3..c3a112d 100644 > --- a/src/amdgpu_dri2.c > +++ b/src/amdgpu_dri2.c > @@ -563,7 +563,8 @@ amdgpu_dri2_schedule_flip(xf86CrtcPtr crtc, ClientPtr client, > AMDGPU_DRM_QUEUE_ID_DEFAULT, flip_info, > ref_crtc_hw_id, > amdgpu_dri2_flip_event_handler, > - amdgpu_dri2_flip_event_abort, FLIP_VSYNC)) { > + amdgpu_dri2_flip_event_abort, FLIP_VSYNC, > + target_msc - amdgpu_get_msc_delta(draw, crtc))) { > info->drmmode.dri2_flipping = TRUE; > return TRUE; > } > diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c > index 319b572..cadd928 100644 > --- a/src/amdgpu_kms.c > +++ b/src/amdgpu_kms.c > @@ -701,9 +701,9 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent) > 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)) { > + if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, > + drmmode_crtc->scanout[scanout_id].fb_id, > + 0, drm_queue_seq, 0) != 0) { > xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", > __func__, strerror(errno)); > return; > @@ -949,8 +949,8 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, > xf86CrtcPtr xf86_crtc) > { > drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; > - ScrnInfoPtr scrn; > - AMDGPUEntPtr pAMDGPUEnt; > + ScrnInfoPtr scrn = xf86_crtc->scrn; > + AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); > uintptr_t drm_queue_seq; > unsigned scanout_id; > > @@ -961,7 +961,6 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, > if (!amdgpu_scanout_do_update(xf86_crtc, scanout_id)) > return; > > - scrn = xf86_crtc->scrn; > drm_queue_seq = amdgpu_drm_queue_alloc(xf86_crtc, > AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, > AMDGPU_DRM_QUEUE_ID_DEFAULT, > @@ -973,10 +972,9 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info, > return; > } > > - pAMDGPUEnt = AMDGPUEntPriv(scrn); > - 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)) { > + if (drmmode_page_flip_target_relative(pAMDGPUEnt, drmmode_crtc, > + drmmode_crtc->scanout[scanout_id].fb_id, > + 0, drm_queue_seq, 0) != 0) { > xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", > __func__, strerror(errno)); > return; > diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c > index dcb18da..3646190 100644 > --- a/src/amdgpu_present.c > +++ b/src/amdgpu_present.c > @@ -329,7 +329,8 @@ amdgpu_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, > pixmap, event_id, event, crtc_id, > amdgpu_present_flip_event, > amdgpu_present_flip_abort, > - sync_flip ? FLIP_VSYNC : FLIP_ASYNC); > + sync_flip ? FLIP_VSYNC : FLIP_ASYNC, > + target_msc); > if (!ret) > xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n"); > else > @@ -366,7 +367,7 @@ amdgpu_present_unflip(ScreenPtr screen, uint64_t event_id) > > if (amdgpu_do_pageflip(scrn, AMDGPU_DRM_QUEUE_CLIENT_DEFAULT, pixmap, > event_id, event, -1, amdgpu_present_flip_event, > - amdgpu_present_flip_abort, FLIP_VSYNC)) > + amdgpu_present_flip_abort, FLIP_VSYNC, 0)) > return; > > modeset: > diff --git a/src/amdgpu_probe.h b/src/amdgpu_probe.h > index 1ec1299..0302d02 100644 > --- a/src/amdgpu_probe.h > +++ b/src/amdgpu_probe.h > @@ -56,6 +56,7 @@ extern DriverRec AMDGPU; > > typedef struct { > Bool HasCRTC2; /* All cards except original Radeon */ > + Bool has_page_flip_target; > > amdgpu_device_handle pDev; > > diff --git a/src/drmmode_display.c b/src/drmmode_display.c > index a75cc5c..8cedc5f 100644 > --- a/src/drmmode_display.c > +++ b/src/drmmode_display.c > @@ -2132,6 +2132,59 @@ static void drm_wakeup_handler(pointer data, int err, pointer p) > } > #endif > > +static Bool drmmode_probe_page_flip_target(AMDGPUEntPtr pAMDGPUEnt) > +{ > + uint64_t cap_value; > + > + return drmGetCap(pAMDGPUEnt->fd, DRM_CAP_PAGE_FLIP_TARGET, > + &cap_value) == 0 && cap_value != 0; > +} > + > +static int > +drmmode_page_flip(AMDGPUEntPtr pAMDGPUEnt, drmmode_crtc_private_ptr drmmode_crtc, > + int fb_id, uint32_t flags, uintptr_t drm_queue_seq) > +{ > + flags |= DRM_MODE_PAGE_FLIP_EVENT; > + return drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id, > + fb_id, flags, (void*)drm_queue_seq); > +} > + > +int > +drmmode_page_flip_target_absolute(AMDGPUEntPtr pAMDGPUEnt, > + drmmode_crtc_private_ptr drmmode_crtc, > + int fb_id, uint32_t flags, > + uintptr_t drm_queue_seq, uint32_t target_msc) > +{ > + if (pAMDGPUEnt->has_page_flip_target) { > + flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE; > + return drmModePageFlipTarget(pAMDGPUEnt->fd, > + drmmode_crtc->mode_crtc->crtc_id, > + fb_id, flags, (void*)drm_queue_seq, > + target_msc); > + } > + > + return drmmode_page_flip(pAMDGPUEnt, drmmode_crtc, fb_id, flags, > + drm_queue_seq); > +} > + > +int > +drmmode_page_flip_target_relative(AMDGPUEntPtr pAMDGPUEnt, > + drmmode_crtc_private_ptr drmmode_crtc, > + int fb_id, uint32_t flags, > + uintptr_t drm_queue_seq, uint32_t target_msc) > +{ > + if (pAMDGPUEnt->has_page_flip_target) { > + flags |= DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_PAGE_FLIP_TARGET_RELATIVE; > + return drmModePageFlipTarget(pAMDGPUEnt->fd, > + drmmode_crtc->mode_crtc->crtc_id, > + fb_id, flags, (void*)drm_queue_seq, > + target_msc); > + } > + > + return drmmode_page_flip(pAMDGPUEnt, drmmode_crtc, fb_id, flags, > + drm_queue_seq); > +} > + > Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) > { > AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(pScrn); > @@ -2198,6 +2251,8 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) > drmmode->event_context.vblank_handler = amdgpu_drm_queue_handler; > drmmode->event_context.page_flip_handler = amdgpu_drm_queue_handler; > > + pAMDGPUEnt->has_page_flip_target = drmmode_probe_page_flip_target(pAMDGPUEnt); > + > drmModeFreeResources(mode_res); > return TRUE; > } > @@ -2535,7 +2590,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > PixmapPtr new_front, uint64_t id, void *data, > int ref_crtc_hw_id, amdgpu_drm_handler_proc handler, > amdgpu_drm_abort_proc abort, > - enum drmmode_flip_sync flip_sync) > + enum drmmode_flip_sync flip_sync, > + uint32_t target_msc) > { > AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn); > xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); > @@ -2543,7 +2599,7 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; > drmmode_ptr drmmode = drmmode_crtc->drmmode; > int i; > - uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT; > + uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; > drmmode_flipdata_ptr flipdata; > uintptr_t drm_queue_seq = 0; > uint32_t new_front_handle; > @@ -2585,9 +2641,6 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > flipdata->handler = handler; > flipdata->abort = abort; > > - if (flip_sync == FLIP_ASYNC) > - flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC; > - > for (i = 0; i < config->num_crtc; i++) { > crtc = config->crtc[i]; > > @@ -2613,13 +2666,23 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > goto error; > } > > - if (drmModePageFlip(pAMDGPUEnt->fd, drmmode_crtc->mode_crtc->crtc_id, > - drmmode->fb_id, flip_flags, > - (void*)drm_queue_seq)) { > - xf86DrvMsg(scrn->scrnIndex, X_WARNING, > - "flip queue failed: %s\n", strerror(errno)); > - goto error; > + if (drmmode_crtc->hw_id == ref_crtc_hw_id) { > + if (drmmode_page_flip_target_absolute(pAMDGPUEnt, > + drmmode_crtc, > + drmmode->fb_id, > + flip_flags, > + drm_queue_seq, > + target_msc) != 0) > + goto flip_error; > + } else { > + if (drmmode_page_flip_target_relative(pAMDGPUEnt, > + drmmode_crtc, > + drmmode->fb_id, > + flip_flags, > + drm_queue_seq, 0) != 0) > + goto flip_error; > } > + > drmmode_crtc->flip_pending = TRUE; > drm_queue_seq = 0; > } > @@ -2627,6 +2690,10 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > if (flipdata->flip_count > 0) > return TRUE; > > +flip_error: > + xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed: %s\n", > + strerror(errno)); > + > error: > if (flipdata && flipdata->flip_count <= 1) { > drmModeRmFB(pAMDGPUEnt->fd, drmmode->fb_id); > diff --git a/src/drmmode_display.h b/src/drmmode_display.h > index 2c4a869..639b3fb 100644 > --- a/src/drmmode_display.h > +++ b/src/drmmode_display.h > @@ -130,6 +130,16 @@ enum drmmode_flip_sync { > }; > > > +extern int drmmode_page_flip_target_absolute(AMDGPUEntPtr pAMDGPUEnt, > + drmmode_crtc_private_ptr drmmode_crtc, > + int fb_id, uint32_t flags, > + uintptr_t drm_queue_seq, > + uint32_t target_msc); > +extern int drmmode_page_flip_target_relative(AMDGPUEntPtr pAMDGPUEnt, > + drmmode_crtc_private_ptr drmmode_crtc, > + int fb_id, uint32_t flags, > + uintptr_t drm_queue_seq, > + uint32_t target_msc); > extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp); > extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode); > extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode); > @@ -153,7 +163,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, > PixmapPtr new_front, uint64_t id, void *data, > int ref_crtc_hw_id, amdgpu_drm_handler_proc handler, > amdgpu_drm_abort_proc abort, > - enum drmmode_flip_sync flip_sync); > + enum drmmode_flip_sync flip_sync, > + uint32_t target_msc); > int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc); > int drmmode_get_current_ust(int drm_fd, CARD64 * ust); > > -- > 2.10.2 > > _______________________________________________ > amd-gfx mailing list > amd-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/amd-gfx