xf86-video-amdgpu: Branch 'master' - 3 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Fri Nov 16 15:52:35 UTC 2018
src/amdgpu_dri2.c | 4 -
src/amdgpu_drm_queue.c | 110 ++++++++++++++++++++++++++++---------------------
src/amdgpu_drm_queue.h | 3 -
src/amdgpu_kms.c | 10 ++--
src/amdgpu_present.c | 3 -
src/drmmode_display.c | 3 -
6 files changed, 78 insertions(+), 55 deletions(-)
New commits:
commit 51ba6dddee40c3688d4c7b12eabeab516ed153b7
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Fri Nov 9 11:00:04 2018 +0100
Move deferred vblank events to separate drm_vblank_deferred list
It was still possible for nested xorg_list_for_each_entry_safe loops
to occur over the drm_vblank_signalled list, which could mess up that
list. Moving deferred events to a separate list allows processing the
drm_vblank_signalled list without xorg_list_for_each_entry_safe.
v2:
* Refactor drm_handle_vblank_signalled helper function, less code
duplication => better readability (Alex Deucher)
Bugzilla: https://bugs.freedesktop.org/108600
Acked-by: Alex Deucher <alexander.deucher at amd.com>
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 808941b..56d593d 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -56,6 +56,7 @@ static int amdgpu_drm_queue_refcnt;
static struct xorg_list amdgpu_drm_queue;
static struct xorg_list amdgpu_drm_flip_signalled;
static struct xorg_list amdgpu_drm_vblank_signalled;
+static struct xorg_list amdgpu_drm_vblank_deferred;
static uintptr_t amdgpu_drm_queue_seq;
@@ -112,6 +113,31 @@ amdgpu_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
}
/*
+ * Handle signalled vblank events. If we're waiting for a flip event,
+ * put events for that CRTC in the vblank_deferred list.
+ */
+static void
+amdgpu_drm_handle_vblank_signalled(void)
+{
+ drmmode_crtc_private_ptr drmmode_crtc;
+ struct amdgpu_drm_queue_entry *e;
+
+ while (!xorg_list_is_empty(&amdgpu_drm_vblank_signalled)) {
+ e = xorg_list_first_entry(&amdgpu_drm_vblank_signalled,
+ struct amdgpu_drm_queue_entry, list);
+ drmmode_crtc = e->crtc->driver_private;
+
+ if (drmmode_crtc->wait_flip_nesting_level == 0) {
+ amdgpu_drm_queue_handle_one(e);
+ continue;
+ }
+
+ xorg_list_del(&e->list);
+ xorg_list_append(&e->list, &amdgpu_drm_vblank_deferred);
+ }
+}
+
+/*
* Handle deferred DRM vblank events
*
* This function must be called after amdgpu_drm_wait_pending_flip, once
@@ -127,12 +153,18 @@ amdgpu_drm_queue_handle_deferred(xf86CrtcPtr crtc)
--drmmode_crtc->wait_flip_nesting_level > 0)
return;
- xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_signalled, list) {
- drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
+ /* Put previously deferred vblank events for this CRTC back in the
+ * signalled queue
+ */
+ xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_deferred, list) {
+ if (e->crtc != crtc)
+ continue;
- if (drmmode_crtc->wait_flip_nesting_level == 0)
- amdgpu_drm_queue_handle_one(e);
+ xorg_list_del(&e->list);
+ xorg_list_append(&e->list, &amdgpu_drm_vblank_signalled);
}
+
+ amdgpu_drm_handle_vblank_signalled();
}
/*
@@ -205,6 +237,13 @@ amdgpu_drm_abort_entry(uintptr_t seq)
}
}
+ xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_deferred, list) {
+ if (e->seq == seq) {
+ amdgpu_drm_abort_one(e);
+ return;
+ }
+ }
+
xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
if (e->seq == seq) {
amdgpu_drm_abort_one(e);
@@ -235,7 +274,7 @@ amdgpu_drm_abort_id(uint64_t id)
int
amdgpu_drm_handle_event(int fd, drmEventContext *event_context)
{
- struct amdgpu_drm_queue_entry *e, *tmp;
+ struct amdgpu_drm_queue_entry *e;
int r;
r = drmHandleEvent(fd, event_context);
@@ -246,12 +285,7 @@ amdgpu_drm_handle_event(int fd, drmEventContext *event_context)
amdgpu_drm_queue_handle_one(e);
}
- xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_vblank_signalled, list) {
- drmmode_crtc_private_ptr drmmode_crtc = e->crtc->driver_private;
-
- if (drmmode_crtc->wait_flip_nesting_level == 0)
- amdgpu_drm_queue_handle_one(e);
- }
+ amdgpu_drm_handle_vblank_signalled();
return r;
}
@@ -298,6 +332,7 @@ amdgpu_drm_queue_init(ScrnInfoPtr scrn)
xorg_list_init(&amdgpu_drm_queue);
xorg_list_init(&amdgpu_drm_flip_signalled);
xorg_list_init(&amdgpu_drm_vblank_signalled);
+ xorg_list_init(&amdgpu_drm_vblank_deferred);
}
/*
commit e2c7369cae65069aa93eed1c0b678f975ce5c274
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Mon Nov 5 19:02:31 2018 +0100
Explicitly keep track of whether a DRM event is for a flip or not
When an async flip is performed, and TearFree is enabled on the CRTC
used for timing, we schedule a vblank event for completing the page
flip. The DRM event queuing code treated this event like a vblank event,
but it needs to be treated like a page flip event.
Acked-by: Alex Deucher <alexander.deucher at amd.com>
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index 96b2d17..ff1b94a 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -981,7 +981,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
wait_info, amdgpu_dri2_frame_event_handler,
- amdgpu_dri2_frame_event_abort);
+ amdgpu_dri2_frame_event_abort, FALSE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue event entry failed.\n");
@@ -1121,7 +1121,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
swap_info, amdgpu_dri2_frame_event_handler,
- amdgpu_dri2_frame_event_abort);
+ amdgpu_dri2_frame_event_abort, FALSE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue entry failed.\n");
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 4b51d46..808941b 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -48,6 +48,7 @@ struct amdgpu_drm_queue_entry {
xf86CrtcPtr crtc;
amdgpu_drm_handler_proc handler;
amdgpu_drm_abort_proc abort;
+ Bool is_flip;
unsigned int frame;
};
@@ -86,8 +87,8 @@ amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
}
static void
-amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
- unsigned int sec, unsigned int usec, void *user_ptr)
+amdgpu_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
{
uintptr_t seq = (uintptr_t)user_ptr;
struct amdgpu_drm_queue_entry *e, *tmp;
@@ -102,35 +103,15 @@ amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
xorg_list_del(&e->list);
e->usec = (uint64_t)sec * 1000000 + usec;
e->frame = frame;
- xorg_list_append(&e->list, signalled);
+ xorg_list_append(&e->list, e->is_flip ?
+ &amdgpu_drm_flip_signalled :
+ &amdgpu_drm_vblank_signalled);
break;
}
}
}
/*
- * Signal a DRM page flip event
- */
-static void
-amdgpu_drm_page_flip_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *user_ptr)
-{
- amdgpu_drm_queue_handler(&amdgpu_drm_flip_signalled, frame, sec, usec,
- user_ptr);
-}
-
-/*
- * Signal a DRM vblank event
- */
-static void
-amdgpu_drm_vblank_handler(int fd, unsigned int frame, unsigned int sec,
- unsigned int usec, void *user_ptr)
-{
- amdgpu_drm_queue_handler(&amdgpu_drm_vblank_signalled, frame, sec, usec,
- user_ptr);
-}
-
-/*
* Handle deferred DRM vblank events
*
* This function must be called after amdgpu_drm_wait_pending_flip, once
@@ -162,7 +143,8 @@ uintptr_t
amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
uint64_t id, void *data,
amdgpu_drm_handler_proc handler,
- amdgpu_drm_abort_proc abort)
+ amdgpu_drm_abort_proc abort,
+ Bool is_flip)
{
struct amdgpu_drm_queue_entry *e;
@@ -180,6 +162,7 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
e->data = data;
e->handler = handler;
e->abort = abort;
+ e->is_flip = is_flip;
xorg_list_append(&e->list, &amdgpu_drm_queue);
@@ -306,8 +289,8 @@ amdgpu_drm_queue_init(ScrnInfoPtr scrn)
drmmode_ptr drmmode = &info->drmmode;
drmmode->event_context.version = 2;
- drmmode->event_context.vblank_handler = amdgpu_drm_vblank_handler;
- drmmode->event_context.page_flip_handler = amdgpu_drm_page_flip_handler;
+ drmmode->event_context.vblank_handler = amdgpu_drm_queue_handler;
+ drmmode->event_context.page_flip_handler = amdgpu_drm_queue_handler;
if (amdgpu_drm_queue_refcnt++)
return;
diff --git a/src/amdgpu_drm_queue.h b/src/amdgpu_drm_queue.h
index 4e7c8f4..72ab036 100644
--- a/src/amdgpu_drm_queue.h
+++ b/src/amdgpu_drm_queue.h
@@ -46,7 +46,8 @@ void amdgpu_drm_queue_handle_deferred(xf86CrtcPtr crtc);
uintptr_t amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
uint64_t id, void *data,
amdgpu_drm_handler_proc handler,
- amdgpu_drm_abort_proc abort);
+ amdgpu_drm_abort_proc abort,
+ Bool is_flip);
void amdgpu_drm_abort_client(ClientPtr client);
void amdgpu_drm_abort_entry(uintptr_t seq);
void amdgpu_drm_abort_id(uint64_t id);
diff --git a/src/amdgpu_kms.c b/src/amdgpu_kms.c
index 5a5fee2..2622409 100644
--- a/src/amdgpu_kms.c
+++ b/src/amdgpu_kms.c
@@ -664,7 +664,8 @@ amdgpu_prime_scanout_update(PixmapDirtyUpdatePtr dirty)
AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
AMDGPU_DRM_QUEUE_ID_DEFAULT, NULL,
amdgpu_prime_scanout_update_handler,
- amdgpu_prime_scanout_update_abort);
+ amdgpu_prime_scanout_update_abort,
+ FALSE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"amdgpu_drm_queue_alloc failed for PRIME update\n");
@@ -712,7 +713,7 @@ amdgpu_prime_scanout_flip(PixmapDirtyUpdatePtr ent)
AMDGPU_DRM_QUEUE_ID_DEFAULT,
NULL,
amdgpu_scanout_flip_handler,
- amdgpu_scanout_flip_abort);
+ amdgpu_scanout_flip_abort, TRUE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM event queue entry failed for PRIME flip.\n");
@@ -940,7 +941,8 @@ amdgpu_scanout_update(xf86CrtcPtr xf86_crtc)
AMDGPU_DRM_QUEUE_ID_DEFAULT,
drmmode_crtc,
amdgpu_scanout_update_handler,
- amdgpu_scanout_update_abort);
+ amdgpu_scanout_update_abort,
+ FALSE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"amdgpu_drm_queue_alloc failed for scanout update\n");
@@ -989,7 +991,7 @@ amdgpu_scanout_flip(ScreenPtr pScreen, AMDGPUInfoPtr info,
AMDGPU_DRM_QUEUE_ID_DEFAULT,
NULL,
amdgpu_scanout_flip_handler,
- amdgpu_scanout_flip_abort);
+ amdgpu_scanout_flip_abort, TRUE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM event queue entry failed.\n");
diff --git a/src/amdgpu_present.c b/src/amdgpu_present.c
index eabe0f3..f9e07a5 100644
--- a/src/amdgpu_present.c
+++ b/src/amdgpu_present.c
@@ -157,7 +157,8 @@ amdgpu_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
AMDGPU_DRM_QUEUE_CLIENT_DEFAULT,
event_id, event,
amdgpu_present_vblank_handler,
- amdgpu_present_vblank_abort);
+ amdgpu_present_vblank_abort,
+ FALSE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
free(event);
return BadAlloc;
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 871a645..23c7349 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -3973,7 +3973,8 @@ Bool amdgpu_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
drm_queue_seq = amdgpu_drm_queue_alloc(crtc, client, id,
flipdata,
drmmode_flip_handler,
- drmmode_flip_abort);
+ drmmode_flip_abort,
+ TRUE);
if (drm_queue_seq == AMDGPU_DRM_QUEUE_ERROR) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"Allocating DRM queue event entry failed.\n");
commit eda571222f5a6be47f8897e82d85199bb9d95251
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Mon Nov 5 18:07:54 2018 +0100
Use drm_abort_one in drm_queue_handler
At this point, we've already established that e->handler is NULL, no
need to check again in drm_queue_handle_one. This also makes it clearer
what's happening.
Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
diff --git a/src/amdgpu_drm_queue.c b/src/amdgpu_drm_queue.c
index 0353562..4b51d46 100644
--- a/src/amdgpu_drm_queue.c
+++ b/src/amdgpu_drm_queue.c
@@ -72,6 +72,19 @@ amdgpu_drm_queue_handle_one(struct amdgpu_drm_queue_entry *e)
free(e);
}
+/*
+ * Abort one queued DRM entry, removing it
+ * from the list, calling the abort function and
+ * freeing the memory
+ */
+static void
+amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
+{
+ xorg_list_del(&e->list);
+ e->abort(e->crtc, e->data);
+ free(e);
+}
+
static void
amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
unsigned int sec, unsigned int usec, void *user_ptr)
@@ -82,7 +95,7 @@ amdgpu_drm_queue_handler(struct xorg_list *signalled, unsigned int frame,
xorg_list_for_each_entry_safe(e, tmp, &amdgpu_drm_queue, list) {
if (e->seq == seq) {
if (!e->handler) {
- amdgpu_drm_queue_handle_one(e);
+ amdgpu_drm_abort_one(e);
break;
}
@@ -174,19 +187,6 @@ amdgpu_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client,
}
/*
- * Abort one queued DRM entry, removing it
- * from the list, calling the abort function and
- * freeing the memory
- */
-static void
-amdgpu_drm_abort_one(struct amdgpu_drm_queue_entry *e)
-{
- xorg_list_del(&e->list);
- e->abort(e->crtc, e->data);
- free(e);
-}
-
-/*
* Abort drm queue entries for a client
*
* NOTE: This keeps the entries in the list until the DRM event arrives,
More information about the xorg-commit
mailing list