summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2017-08-18 15:12:35 +0900
committerMichel Dänzer <michel@daenzer.net>2017-08-22 18:32:34 +0900
commitfd5b78b7edff2021111bca37642b8b508f0c3328 (patch)
treeb9763edf0538c30775849936aa3a6809fefd49eb
parent24b2718992e4bbc859c07e5b29b571f53314045d (diff)
Create drmmode_wait_vblank helper
Allows cleaning up the code considerably. (Ported from radeon commit 99f1d7a474af3683fe1a66f50c0bb8935478ff0a) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r--src/amdgpu_dri2.c97
-rw-r--r--src/amdgpu_drv.h2
-rw-r--r--src/amdgpu_kms.c23
-rw-r--r--src/amdgpu_present.c23
-rw-r--r--src/drmmode_display.c63
-rw-r--r--src/drmmode_display.h5
6 files changed, 85 insertions, 128 deletions
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 52fac03..bf85dfa 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -778,20 +778,6 @@ cleanup:
amdgpu_dri2_frame_event_abort(crtc, event_data);
}
-drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc)
-{
- drmVBlankSeqType type = 0;
- int crtc_id = drmmode_get_crtc_id(crtc);
-
- if (crtc_id == 1)
- type |= DRM_VBLANK_SECONDARY;
- else if (crtc_id > 1)
- type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
- DRM_VBLANK_HIGH_CRTC_MASK;
-
- return type;
-}
-
/*
* This function should be called on a disabled CRTC only (i.e., CRTC
* in DPMS-off state). It will calculate the delay necessary to reach
@@ -971,13 +957,11 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
{
ScreenPtr screen = draw->pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
DRI2FrameEventPtr wait_info = NULL;
uintptr_t drm_queue_seq = 0;
xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
uint32_t msc_delta;
- drmVBlank vbl;
- int ret;
+ uint32_t seq;
CARD64 current_msc;
/* Truncate to match kernel interfaces; means occasional overflow
@@ -1016,17 +1000,13 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
}
/* Get current count */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"get vblank counter failed: %s\n", strerror(errno));
goto out_complete;
}
- current_msc = vbl.reply.sequence + msc_delta;
+ current_msc = seq + msc_delta;
current_msc &= 0xffffffff;
drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
@@ -1053,12 +1033,9 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
*/
if (current_msc >= target_msc)
target_msc = current_msc;
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
- vbl.request.sequence = target_msc - msc_delta;
- vbl.request.signal = drm_queue_seq;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT,
+ target_msc - msc_delta, drm_queue_seq, NULL,
+ NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"get vblank counter failed: %s\n",
strerror(errno));
@@ -1073,11 +1050,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
* If we get here, target_msc has already passed or we don't have one,
* so we queue an event that will satisfy the divisor/remainder equation.
*/
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
-
- vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder - msc_delta;
+ target_msc = current_msc - (current_msc % divisor) + remainder - msc_delta;
/*
* If calculated remainder is larger than requested remainder,
@@ -1086,11 +1059,10 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
* that will happen.
*/
if ((current_msc % divisor) >= remainder)
- vbl.request.sequence += divisor;
+ target_msc += divisor;
- vbl.request.signal = drm_queue_seq;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT,
+ target_msc, drm_queue_seq, NULL, NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"get vblank counter failed: %s\n", strerror(errno));
goto out_complete;
@@ -1134,14 +1106,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
{
ScreenPtr screen = draw->pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
uint32_t msc_delta;
- drmVBlank vbl;
- int ret, flip = 0;
+ drmVBlankSeqType type;
+ uint32_t seq;
+ int flip = 0;
DRI2FrameEventPtr swap_info = NULL;
uintptr_t drm_queue_seq;
- CARD64 current_msc;
+ CARD64 current_msc, event_msc;
BoxRec box;
RegionRec region;
@@ -1204,18 +1176,14 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
}
/* Get current count */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, NULL, &seq)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"first get vblank counter failed: %s\n",
strerror(errno));
goto blit_fallback;
}
- current_msc = vbl.reply.sequence + msc_delta;
+ current_msc = seq + msc_delta;
current_msc &= 0xffffffff;
/* Flips need to be submitted one frame before */
@@ -1237,14 +1205,13 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
* the swap.
*/
if (divisor == 0 || current_msc < *target_msc) {
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
/* If non-pageflipping, but blitting/exchanging, we need to use
* DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
* on.
*/
if (flip == 0)
- vbl.request.type |= DRM_VBLANK_NEXTONMISS;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
+ type |= DRM_VBLANK_NEXTONMISS;
/* If target_msc already reached or passed, set it to
* current_msc to ensure we return a reasonable value back
@@ -1253,17 +1220,15 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
if (current_msc >= *target_msc)
*target_msc = current_msc;
- vbl.request.sequence = *target_msc - msc_delta;
- vbl.request.signal = drm_queue_seq;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, type, *target_msc - msc_delta,
+ drm_queue_seq, NULL, &seq)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"divisor 0 get vblank counter failed: %s\n",
strerror(errno));
goto blit_fallback;
}
- *target_msc = vbl.reply.sequence + flip + msc_delta;
+ *target_msc = seq + flip + msc_delta;
*target_msc &= 0xffffffff;
swap_info->frame = *target_msc;
@@ -1275,13 +1240,11 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
* and we need to queue an event that will satisfy the divisor/remainder
* equation.
*/
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
+ type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
if (flip == 0)
- vbl.request.type |= DRM_VBLANK_NEXTONMISS;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
+ type |= DRM_VBLANK_NEXTONMISS;
- vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder - msc_delta;
+ event_msc = current_msc - (current_msc % divisor) + remainder - msc_delta;
/*
* If the calculated deadline vbl.request.sequence is smaller than
@@ -1294,15 +1257,13 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
* into account, as well as a potential DRM_VBLANK_NEXTONMISS delay
* if we are blitting/exchanging instead of flipping.
*/
- if (vbl.request.sequence <= current_msc)
- vbl.request.sequence += divisor;
+ if (event_msc <= current_msc)
+ event_msc += divisor;
/* Account for 1 frame extra pageflip delay if flip > 0 */
- vbl.request.sequence -= flip;
+ event_msc -= flip;
- vbl.request.signal = drm_queue_seq;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, type, event_msc, drm_queue_seq, NULL, &seq)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"final get vblank counter failed: %s\n",
strerror(errno));
@@ -1310,7 +1271,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
}
/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
- *target_msc = vbl.reply.sequence + flip + msc_delta;
+ *target_msc = seq + flip + msc_delta;
*target_msc &= 0xffffffff;
swap_info->frame = *target_msc;
diff --git a/src/amdgpu_drv.h b/src/amdgpu_drv.h
index 9e088e7..da71ce8 100644
--- a/src/amdgpu_drv.h
+++ b/src/amdgpu_drv.h
@@ -363,6 +363,4 @@ extern xf86CrtcPtr amdgpu_pick_best_crtc(ScrnInfoPtr pScrn,
extern AMDGPUEntPtr AMDGPUEntPriv(ScrnInfoPtr pScrn);
-drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc);
-
#endif /* _AMDGPU_DRV_H_ */
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 20a552b..3e21125 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -624,11 +624,9 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
{
ScreenPtr screen = dirty->slave_dst->drawable.pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
xf86CrtcPtr xf86_crtc = amdgpu_prime_dirty_to_crtc(dirty);
drmmode_crtc_private_ptr drmmode_crtc;
uintptr_t drm_queue_seq;
- drmVBlank vbl;
if (!xf86_crtc || !xf86_crtc->enabled)
return;
@@ -650,13 +648,10 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
return;
}
- vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
- vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
- vbl.request.sequence = 1;
- vbl.request.signal = drm_queue_seq;
- if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
+ if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+ 1, drm_queue_seq, NULL, NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "drmWaitVBlank failed for PRIME update: %s\n",
+ "drmmode_wait_vblank failed for PRIME update: %s\n",
strerror(errno));
amdgpu_drm_abort_entry(drm_queue_seq);
return;
@@ -915,8 +910,6 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
uintptr_t drm_queue_seq;
ScrnInfoPtr scrn;
- AMDGPUEntPtr pAMDGPUEnt;
- drmVBlank vbl;
DamagePtr pDamage;
RegionPtr pRegion;
BoxRec extents;
@@ -953,14 +946,10 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
return;
}
- pAMDGPUEnt = AMDGPUEntPriv(scrn);
- vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
- vbl.request.type |= amdgpu_populate_vbl_request_type(xf86_crtc);
- vbl.request.sequence = 1;
- vbl.request.signal = drm_queue_seq;
- if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl)) {
+ if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+ 1, drm_queue_seq, NULL, NULL)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "drmWaitVBlank failed for scanout update: %s\n",
+ "drmmode_wait_vblank failed for scanout update: %s\n",
strerror(errno));
amdgpu_drm_abort_entry(drm_queue_seq);
return;
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index 7769e1f..b6792f3 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -55,16 +55,6 @@ struct amdgpu_present_vblank_event {
Bool unflip;
};
-static uint32_t crtc_select(int crtc_id)
-{
- if (crtc_id > 1)
- return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
- else if (crtc_id > 0)
- return DRM_VBLANK_SECONDARY;
- else
- return 0;
-}
-
static RRCrtcPtr
amdgpu_present_get_crtc(WindowPtr window)
{
@@ -155,13 +145,8 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
{
xf86CrtcPtr xf86_crtc = crtc->devPrivate;
ScreenPtr screen = crtc->pScreen;
- ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
- int crtc_id = drmmode_get_crtc_id(xf86_crtc);
struct amdgpu_present_vblank_event *event;
uintptr_t drm_queue_seq;
- drmVBlank vbl;
- int ret;
event = calloc(sizeof(struct amdgpu_present_vblank_event), 1);
if (!event)
@@ -177,12 +162,10 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
return BadAlloc;
}
- vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id);
- vbl.request.sequence = msc;
- vbl.request.signal = drm_queue_seq;
for (;;) {
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (!ret)
+ if (drmmode_wait_vblank(xf86_crtc,
+ DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT, msc,
+ drm_queue_seq, NULL, NULL))
break;
if (errno != EBUSY || !amdgpu_present_flush_drm_events(screen)) {
amdgpu_drm_abort_entry(drm_queue_seq);
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 93f6d27..1a805b8 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -190,6 +190,41 @@ drmmode_ConvertToKMode(ScrnInfoPtr scrn,
}
/*
+ * Utility helper for drmWaitVBlank
+ */
+Bool
+drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
+ uint32_t target_seq, unsigned long signal, uint64_t *ust,
+ uint32_t *result_seq)
+{
+ int crtc_id = drmmode_get_crtc_id(crtc);
+ ScrnInfoPtr scrn = crtc->scrn;
+ AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
+ drmVBlank vbl;
+
+ if (crtc_id == 1)
+ type |= DRM_VBLANK_SECONDARY;
+ else if (crtc_id > 1)
+ type |= (crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT) &
+ DRM_VBLANK_HIGH_CRTC_MASK;
+
+ vbl.request.type = type;
+ vbl.request.sequence = target_seq;
+ vbl.request.signal = signal;
+
+ if (drmWaitVBlank(pAMDGPUEnt->fd, &vbl) != 0)
+ return FALSE;
+
+ if (ust)
+ *ust = (uint64_t)vbl.reply.tval_sec * 1000000 +
+ vbl.reply.tval_usec;
+ if (result_seq)
+ *result_seq = vbl.reply.sequence;
+
+ return TRUE;
+}
+
+/*
* Retrieves present time in microseconds that is compatible
* with units used by vblank timestamps. Depending on the kernel
* version and DRM kernel module configuration, the vblank
@@ -219,23 +254,15 @@ int drmmode_get_current_ust(int drm_fd, CARD64 * ust)
int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
{
ScrnInfoPtr scrn = crtc->scrn;
- AMDGPUEntPtr pAMDGPUEnt = AMDGPUEntPriv(scrn);
- drmVBlank vbl;
- int ret;
-
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
+ uint32_t seq;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret) {
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, ust, &seq)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"get vblank counter failed: %s\n", strerror(errno));
- return ret;
+ return -1;
}
- *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
- *msc = vbl.reply.sequence;
+ *msc = seq;
return Success;
}
@@ -252,7 +279,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
drmmode_crtc->pending_dpms_mode = mode;
if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) {
- drmVBlank vbl;
+ uint32_t seq;
/* Wait for any pending flip to finish */
if (drmmode_crtc->flip_pending)
@@ -262,20 +289,14 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
* On->Off transition: record the last vblank time,
* sequence number and frame period.
*/
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
- ret = drmWaitVBlank(pAMDGPUEnt->fd, &vbl);
- if (ret)
+ if (!drmmode_wait_vblank(crtc, DRM_VBLANK_RELATIVE, 0, 0, &ust,
+ &seq))
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s cannot get last vblank counter\n",
__func__);
else {
- CARD64 seq = (CARD64) vbl.reply.sequence;
CARD64 nominal_frame_rate, pix_in_frame;
- ust = ((CARD64) vbl.reply.tval_sec * 1000000) +
- vbl.reply.tval_usec;
drmmode_crtc->dpms_last_ust = ust;
drmmode_crtc->dpms_last_seq = seq;
nominal_frame_rate = crtc->mode.Clock;
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index bece0ce..ba7ec68 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -216,4 +216,9 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
int drmmode_get_current_ust(int drm_fd, CARD64 * ust);
+Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type,
+ uint32_t target_seq, unsigned long signal,
+ uint64_t *ust, uint32_t *result_seq);
+
+
#endif