diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-09-20 08:56:02 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-09-20 08:56:02 +0100 |
commit | f0fbead9f24009c4d9900f28d4e5b3c07a93f560 (patch) | |
tree | aeebafc16e3a14405e1cd95f9efe92b097ce9e07 | |
parent | b45dbdbd446108745b39b305303b457f5e876989 (diff) |
sna/present: Prime the msc cache on first query
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna.h | 1 | ||||
-rw-r--r-- | src/sna/sna_present.c | 64 |
2 files changed, 58 insertions, 7 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index c4978cbc..fb5c0074 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -385,6 +385,7 @@ struct sna { #if HAVE_PRESENT struct list vblank_queue; uint64_t unflip; + void *freed_info; #endif } present; diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c index f5d15154..cfff0f14 100644 --- a/src/sna/sna_present.c +++ b/src/sna/sna_present.c @@ -58,6 +58,29 @@ to_present_event(uintptr_t data) return (struct sna_present_event *)(data & ~3); } +static struct sna_present_event *info_alloc(struct sna *sna) +{ + struct sna_present_event *info; + + info = sna->present.freed_info; + if (info) { + sna->present.freed_info = NULL; + return info; + } + + return malloc(sizeof(struct sna_present_event) + sizeof(uint64_t)); +} + +static void info_free(struct sna_present_event *info) +{ + struct sna *sna = info->sna; + + if (sna->present.freed_info) + free(sna->present.freed_info); + + sna->present.freed_info = info; +} + static inline bool msc_before(uint64_t msc, uint64_t target) { return (int64_t)(msc - target) < 0; @@ -141,7 +164,7 @@ static void vblank_complete(struct sna_present_event *info, if (info->n_event_id > 1) free(info->event_id); list_del(&info->link); - free(info); + info_free(info); } static uint32_t msc_to_delay(xf86CrtcPtr crtc, uint64_t target) @@ -354,8 +377,34 @@ sna_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) vbl.request.type = DRM_VBLANK_RELATIVE; vbl.request.sequence = 0; if (sna_wait_vblank(sna, &vbl, sna_crtc_pipe(crtc->devPrivate)) == 0) { + struct sna_present_event *info; + *ust = ust64(vbl.reply.tval_sec, vbl.reply.tval_usec); *msc = sna_crtc_record_vblank(crtc->devPrivate, &vbl); + + info = info_alloc(sna); + if (info) { + info->crtc = crtc->devPrivate; + info->sna = sna; + info->target_msc = *msc + 1; + info->event_id = (uint64_t *)(info + 1); + info->n_event_id = 0; + + vbl.request.type = + DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; + vbl.request.sequence = info->target_msc; + vbl.request.signal = (uintptr_t)MARK_PRESENT(info); + + if (sna_wait_vblank(info->sna, &vbl, + sna_crtc_pipe(info->crtc)) == 0) { + list_add(&info->link, + &sna->present.vblank_queue); + info->queued = true; + sna_crtc_set_vblank(info->crtc); + info->crtc = mark_crtc(info->crtc); + } else + info_free(info); + } } else { const struct ust_msc *swap; last: @@ -433,7 +482,8 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) unmask_crtc(tmp->crtc) == crtc->devPrivate) { uint64_t *events = tmp->event_id; - if (is_power_of_two(tmp->n_event_id)) { + if (tmp->n_event_id && + is_power_of_two(tmp->n_event_id)) { events = malloc(2*sizeof(uint64_t)*tmp->n_event_id); if (events == NULL) return BadAlloc; @@ -458,7 +508,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) } } - info = malloc(sizeof(struct sna_present_event) + sizeof(uint64_t)); + info = info_alloc(sna); if (info == NULL) return BadAlloc; @@ -473,7 +523,7 @@ sna_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) if (!sna_present_queue(info, swap->msc)) { list_del(&info->link); - free(info); + info_free(info); return BadAlloc; } @@ -661,7 +711,7 @@ present_flip_handler(struct drm_event_vblank *event, void *data) info->sna->present.unflip); info->sna->present.unflip = 0; } - free(info); + info_free(info); } static Bool @@ -679,7 +729,7 @@ flip(struct sna *sna, (long long)event_id, bo->handle)); - info = malloc(sizeof(struct sna_present_event)+sizeof(uint64_t)); + info = info_alloc(sna); if (info == NULL) return FALSE; @@ -693,7 +743,7 @@ flip(struct sna *sna, if (!sna_page_flip(sna, bo, present_flip_handler, info)) { DBG(("%s: pageflip failed\n", __FUNCTION__)); - free(info); + info_free(info); return FALSE; } |