diff options
author | Francisco Jerez <currojerez@riseup.net> | 2010-10-13 18:45:04 +0200 |
---|---|---|
committer | Francisco Jerez <currojerez@riseup.net> | 2010-10-22 15:33:07 +0200 |
commit | a685a5c3be12f3e95a6ec1140af115e7ef28fcaa (patch) | |
tree | 2682e07ea1dbabc145df154f73c5682318e217f6 | |
parent | eb83c830c87bce345748edef3b50660246143db7 (diff) | |
download | xorg-driver-xf86-video-nouveau-a685a5c3be12f3e95a6ec1140af115e7ef28fcaa.tar.gz |
dri2: Implement the ScheduleWaitMSC/GetMSC hooks.
Signed-off-by: Francisco Jerez <currojerez@riseup.net>
-rw-r--r-- | src/nouveau_dri2.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index 7fdfa9c..c8d5c57 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -116,7 +116,8 @@ nouveau_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion, struct nouveau_dri2_vblank_state { enum { - SWAP + SWAP, + WAIT } action; ClientPtr client; @@ -308,6 +309,66 @@ fail: return FALSE; } +static Bool +nouveau_dri2_schedule_wait(ClientPtr client, DrawablePtr draw, + CARD64 target_msc, CARD64 divisor, CARD64 remainder) +{ + struct nouveau_dri2_vblank_state *s; + CARD64 current_msc; + int ret; + + if (!can_sync_to_vblank(draw)) + return FALSE; + + /* Initialize a vblank structure */ + s = malloc(sizeof(*s)); + if (!s) + return FALSE; + + *s = (struct nouveau_dri2_vblank_state) { WAIT, client, draw->id }; + + /* Get current sequence */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, + ¤t_msc, NULL, NULL); + if (ret) + goto fail; + + /* Calculate a wait target if we don't have one */ + if (current_msc > target_msc && divisor) + target_msc = current_msc + divisor + - (current_msc - remainder) % divisor; + + /* Request a vblank event */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_ABSOLUTE | + DRM_VBLANK_EVENT, + max(current_msc, target_msc), + NULL, NULL, s); + if (ret) + goto fail; + + DRI2BlockClient(client, draw); + return TRUE; +fail: + free(s); + return FALSE; +} + +static Bool +nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) +{ + int ret; + + if (!can_sync_to_vblank(draw)) + return FALSE; + + /* Get current sequence */ + ret = nouveau_wait_vblank(draw, DRM_VBLANK_RELATIVE, 0, msc, ust, NULL); + if (ret) + return FALSE; + + return TRUE; +} + void nouveau_dri2_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, @@ -326,6 +387,11 @@ nouveau_dri2_vblank_handler(int fd, unsigned int frame, case SWAP: nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s); break; + + case WAIT: + DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec); + free(s); + break; } } @@ -349,6 +415,8 @@ nouveau_dri2_init(ScreenPtr pScreen) dri2.DestroyBuffer = nouveau_dri2_destroy_buffer; dri2.CopyRegion = nouveau_dri2_copy_region; dri2.ScheduleSwap = nouveau_dri2_schedule_swap; + dri2.ScheduleWaitMSC = nouveau_dri2_schedule_wait; + dri2.GetMSC = nouveau_dri2_get_msc; return DRI2ScreenInit(pScreen, &dri2); } |