Create drmmode_wait_vblank helper

Allows cleaning up the code considerably.

(Ported from radeon commit 99f1d7a474af3683fe1a66f50c0bb8935478ff0a)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Michel Dänzer
2017-08-18 15:12:35 +09:00
committed by Michel Dänzer
parent 24b2718992
commit fd5b78b7ed
6 changed files with 85 additions and 128 deletions

View File

@@ -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;

View File

@@ -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_ */

View File

@@ -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;

View File

@@ -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);

View File

@@ -189,6 +189,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
@@ -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;
uint32_t seq;
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_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;

View File

@@ -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