summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2021-02-13 14:44:08 +0200
committerVille Syrjälä <ville.syrjala@linux.intel.com>2023-02-01 15:36:56 +0200
commitc14994713b87eef67037903f40819793d5959d10 (patch)
treed6a05f3ac410bf409c90618368018b6c143e1f89
parent31486f40f8e8f8923ca0799aea84b58799754564 (diff)
downloadxorg-driver-xf86-video-intel-c14994713b87eef67037903f40819793d5959d10.tar.gz
sna: Fix async flips
We need to wait for flip events even when doing async flips, otherwise the kernel will just hand us -EBUSY if we try to flip too fast. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
-rw-r--r--src/sna/sna.h1
-rw-r--r--src/sna/sna_display.c20
-rw-r--r--src/sna/sna_dri2.c7
-rw-r--r--src/sna/sna_present.c61
4 files changed, 41 insertions, 48 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index f2bc1896..29d08a9b 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -491,6 +491,7 @@ typedef void (*sna_flip_handler_t)(struct drm_event_vblank *e,
extern bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo);
extern int sna_page_flip(struct sna *sna,
struct kgem_bo *bo,
+ bool async,
sna_flip_handler_t handler,
void *data);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 874292bc..a26f4906 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -7143,6 +7143,7 @@ bool sna_needs_page_flip(struct sna *sna, struct kgem_bo *bo)
int
sna_page_flip(struct sna *sna,
struct kgem_bo *bo,
+ bool async,
sna_flip_handler_t handler,
void *data)
{
@@ -7162,7 +7163,7 @@ sna_page_flip(struct sna *sna,
assert(!sna->mode.hidden);
assert(sna->scrn->vtSema);
- if ((sna->flags & (data ? SNA_HAS_FLIP : SNA_HAS_ASYNC_FLIP)) == 0)
+ if ((sna->flags & (async ? SNA_HAS_ASYNC_FLIP : SNA_HAS_FLIP)) == 0)
return 0;
kgem_bo_submit(&sna->kgem, bo);
@@ -7186,7 +7187,7 @@ sna_page_flip(struct sna *sna,
assert(crtc->flip_bo == NULL);
assert_crtc_fb(sna, crtc);
- if (data == NULL && crtc->bo == bo)
+ if (async && crtc->bo == bo)
goto next_crtc;
arg.crtc_id = __sna_crtc_id(crtc);
@@ -7224,7 +7225,7 @@ update_scanout:
crtc->bo = kgem_bo_reference(bo);
crtc->bo->active_scanout++;
- if (data == NULL)
+ if (async)
goto next_crtc;
/* queue a flip in order to send the event */
@@ -7235,13 +7236,10 @@ update_scanout:
/* Only the reference crtc will finally deliver its page flip
* completion event. All other crtc's events will be discarded.
*/
- if (data) {
- arg.user_data = (uintptr_t)crtc;
- arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
- } else {
- arg.user_data = 0;
- arg.flags = DRM_MODE_PAGE_FLIP_ASYNC;
- }
+ arg.user_data = (uintptr_t)crtc;
+ arg.flags = DRM_MODE_PAGE_FLIP_EVENT;
+ if (async)
+ arg.flags |= DRM_MODE_PAGE_FLIP_ASYNC;
arg.reserved = 0;
retry_flip:
@@ -7281,7 +7279,7 @@ retry_flip:
error:
xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
"page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n",
- __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), data ? "synchronous": "asynchronous");
+ __sna_crtc_id(crtc), __sna_crtc_pipe(crtc), async ? "asynchronous": "synchronous");
if (count || crtc->bo == bo)
sna_mode_restore(sna);
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 4ee76627..4361af71 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -1963,8 +1963,8 @@ sna_dri2_flip(struct sna_dri2_event *info)
}
assert(!info->queued);
- if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler,
- info->type == FLIP_ASYNC ? NULL : info))
+ if (!sna_page_flip(info->sna, bo, info->type == FLIP_ASYNC,
+ sna_dri2_flip_handler, info))
return false;
DBG(("%s: queued flip=%p\n", __FUNCTION__, info->type == FLIP_ASYNC ? NULL : info));
@@ -2855,7 +2855,8 @@ sna_dri2_flip_continue(struct sna_dri2_event *info)
return false;
assert(!info->queued);
- if (!sna_page_flip(info->sna, bo, sna_dri2_flip_handler, info))
+ if (!sna_page_flip(info->sna, bo, false,
+ sna_dri2_flip_handler, info))
return false;
DBG(("%s: queued flip=%p\n", __FUNCTION__, info));
diff --git a/src/sna/sna_present.c b/src/sna/sna_present.c
index 6bb7b927..b86dc97e 100644
--- a/src/sna/sna_present.c
+++ b/src/sna/sna_present.c
@@ -675,34 +675,6 @@ sna_present_check_flip(RRCrtcPtr crtc,
return TRUE;
}
-static Bool
-flip__async(struct sna *sna,
- RRCrtcPtr crtc,
- uint64_t event_id,
- uint64_t target_msc,
- struct kgem_bo *bo)
-{
- DBG(("%s(pipe=%d, event=%lld, handle=%d)\n",
- __FUNCTION__,
- pipe_from_crtc(crtc),
- (long long)event_id,
- bo->handle));
-
- if (!sna_page_flip(sna, bo, NULL, NULL)) {
- DBG(("%s: async pageflip failed\n", __FUNCTION__));
- present_info.capabilities &= ~PresentCapabilityAsync;
- return FALSE;
- }
-
- DBG(("%s: pipe=%d tv=%ld.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
- pipe_from_crtc(crtc),
- (long)(gettime_ust64() / 1000000), (int)(gettime_ust64() % 1000000),
- crtc ? (long long)sna_crtc_last_swap(crtc->devPrivate)->msc : 0LL,
- (long long)target_msc, (long long)event_id));
- present_event_notify(event_id, gettime_ust64(), target_msc);
- return TRUE;
-}
-
static void
present_flip_handler(struct drm_event_vblank *event, void *data)
{
@@ -748,11 +720,12 @@ present_flip_handler(struct drm_event_vblank *event, void *data)
}
static Bool
-flip(struct sna *sna,
- RRCrtcPtr crtc,
- uint64_t event_id,
- uint64_t target_msc,
- struct kgem_bo *bo)
+do_flip(struct sna *sna,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ struct kgem_bo *bo,
+ bool async)
{
struct sna_present_event *info;
@@ -774,7 +747,7 @@ flip(struct sna *sna,
info->target_msc = target_msc;
info->active = false;
- if (!sna_page_flip(sna, bo, present_flip_handler, info)) {
+ if (!sna_page_flip(sna, bo, async, present_flip_handler, info)) {
DBG(("%s: pageflip failed\n", __FUNCTION__));
info_free(info);
return FALSE;
@@ -784,6 +757,26 @@ flip(struct sna *sna,
return TRUE;
}
+static Bool
+flip__async(struct sna *sna,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ struct kgem_bo *bo)
+{
+ return do_flip(sna, crtc, event_id, target_msc, bo, true);
+}
+
+static Bool
+flip(struct sna *sna,
+ RRCrtcPtr crtc,
+ uint64_t event_id,
+ uint64_t target_msc,
+ struct kgem_bo *bo)
+{
+ return do_flip(sna, crtc, event_id, target_msc, bo, false);
+}
+
static struct kgem_bo *
get_flip_bo(PixmapPtr pixmap)
{