summaryrefslogtreecommitdiff
path: root/src/drmmode_display.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drmmode_display.c')
-rw-r--r--src/drmmode_display.c89
1 files changed, 78 insertions, 11 deletions
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);