summaryrefslogtreecommitdiff
path: root/src/amdgpu_dri2.c
diff options
context:
space:
mode:
authorMichel Dänzer <michel.daenzer@amd.com>2015-06-01 17:32:56 +0900
committerMichel Dänzer <michel@daenzer.net>2015-06-08 17:04:02 +0900
commit9a554a683b970660b467566cf05b921393705a20 (patch)
tree5783e5a2c49a090beb748d9bc6bdd88fc78ea723 /src/amdgpu_dri2.c
parente6164ad340f65ff8ee6f6a6934302591af875a43 (diff)
DRI2: Use helper functions for DRM event queue management
This is mostly in preparation for Present support, but it also simplifies the DRI2 specific code a little. (Cherry picked from radeon commit 6c3a721cde9317233072b573f9502348dcd21b16) Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src/amdgpu_dri2.c')
-rw-r--r--src/amdgpu_dri2.c271
1 files changed, 98 insertions, 173 deletions
diff --git a/src/amdgpu_dri2.c b/src/amdgpu_dri2.c
index c139dec..95db216 100644
--- a/src/amdgpu_dri2.c
+++ b/src/amdgpu_dri2.c
@@ -49,6 +49,8 @@
#include "amdgpu_list.h"
+#include <xf86Priv.h>
+
#if DRI2INFOREC_VERSION >= 9
#define USE_DRI2_PRIME
#endif
@@ -370,65 +372,20 @@ typedef struct _DRI2FrameEvent {
XID drawable_id;
ClientPtr client;
enum DRI2FrameEventType type;
- int frame;
+ unsigned frame;
xf86CrtcPtr crtc;
+ OsTimerPtr timer;
+ struct amdgpu_drm_queue_entry *drm_queue;
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
void *event_data;
DRI2BufferPtr front;
DRI2BufferPtr back;
-
- Bool valid;
-
- struct xorg_list link;
} DRI2FrameEventRec, *DRI2FrameEventPtr;
-typedef struct _DRI2ClientEvents {
- struct xorg_list reference_list;
-} DRI2ClientEventsRec, *DRI2ClientEventsPtr;
-
-#if HAS_DEVPRIVATEKEYREC
-
static int DRI2InfoCnt;
-static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec;
-#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec)
-
-#else
-
-static int DRI2ClientEventsPrivateKeyIndex;
-DevPrivateKey DRI2ClientEventsPrivateKey = &DRI2ClientEventsPrivateKeyIndex;
-
-#endif /* HAS_DEVPRIVATEKEYREC */
-
-#define GetDRI2ClientEvents(pClient) ((DRI2ClientEventsPtr) \
- dixLookupPrivate(&(pClient)->devPrivates, DRI2ClientEventsPrivateKey))
-
-static int ListAddDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return BadAlloc;
- }
-
- xorg_list_add(entry, &pClientPriv->reference_list);
- return 0;
-}
-
-static void ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return;
- }
- xorg_list_del(entry);
-}
-
static void amdgpu_dri2_ref_buffer(BufferPtr buffer)
{
struct dri2_buffer_priv *private = buffer->driverPrivate;
@@ -448,30 +405,13 @@ static void
amdgpu_dri2_client_state_changed(CallbackListPtr * ClientStateCallback,
pointer data, pointer calldata)
{
- DRI2ClientEventsPtr pClientEventsPriv;
- DRI2FrameEventPtr ref;
NewClientInfoRec *clientinfo = calldata;
ClientPtr pClient = clientinfo->client;
- pClientEventsPriv = GetDRI2ClientEvents(pClient);
switch (pClient->clientState) {
- case ClientStateInitial:
- xorg_list_init(&pClientEventsPriv->reference_list);
- break;
- case ClientStateRunning:
- break;
-
case ClientStateRetained:
case ClientStateGone:
- if (pClientEventsPriv) {
- xorg_list_for_each_entry(ref,
- &pClientEventsPriv->
- reference_list, link) {
- ref->valid = FALSE;
- amdgpu_dri2_unref_buffer(ref->front);
- amdgpu_dri2_unref_buffer(ref->back);
- }
- }
+ amdgpu_drm_abort_client(pClient);
break;
default:
break;
@@ -497,37 +437,42 @@ xf86CrtcPtr amdgpu_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
return NULL;
}
-void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+static void
+amdgpu_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ free(event_data);
+}
+
+static void
+amdgpu_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+ void *event_data)
{
DRI2FrameEventPtr flip = event_data;
+ unsigned tv_sec, tv_usec;
DrawablePtr drawable;
ScreenPtr screen;
- ScrnInfoPtr scrn;
int status;
PixmapPtr pixmap;
status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
M_ANY, DixWriteAccess);
- if (status != Success) {
- free(flip);
- return;
- }
- if (!flip->crtc) {
- free(flip);
- return;
- }
- frame += amdgpu_get_interpolated_vblanks(flip->crtc);
+ if (status != Success)
+ goto abort;
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+ if (!flip->crtc)
+ goto abort;
+ frame += amdgpu_get_interpolated_vblanks(flip->crtc);
+ screen = scrn->pScreen;
pixmap = screen->GetScreenPixmap(screen);
xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, AMDGPU_LOGLEVEL_DEBUG,
"%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
__func__, __LINE__, flip, pixmap->drawable.width,
pixmap->devKind, pixmap->devKind / 4);
+ tv_sec = usec / 1000000;
+ tv_usec = usec % 1000000;
+
/* We assume our flips arrive in order, so we don't check the frame */
switch (flip->type) {
case DRI2_SWAP:
@@ -537,7 +482,7 @@ void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
*/
if ((frame < flip->frame) && (flip->frame - frame < 5)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
+ "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
__func__, frame, flip->frame);
/* All-Zero values signal failure of (msc, ust) timestamping to client. */
frame = tv_sec = tv_usec = 0;
@@ -554,7 +499,8 @@ void amdgpu_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
break;
}
- free(flip);
+abort:
+ amdgpu_dri2_flip_event_abort(scrn, event_data);
}
static Bool
@@ -589,7 +535,10 @@ amdgpu_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
back_priv = back->driverPrivate;
bo = amdgpu_get_pixmap_bo(back_priv->pixmap);
- return amdgpu_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
+ return amdgpu_do_pageflip(scrn, client, bo, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+ flip_info, ref_crtc_hw_id,
+ amdgpu_dri2_flip_event_handler,
+ amdgpu_dri2_flip_event_abort);
}
static Bool update_front(DrawablePtr draw, DRI2BufferPtr front)
@@ -719,31 +668,36 @@ amdgpu_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front,
DamageRegionProcessPending(&front_priv->pixmap->drawable);
}
-void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+static void amdgpu_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ DRI2FrameEventPtr event = event_data;
+
+ TimerCancel(event->timer);
+ TimerFree(event->timer);
+ amdgpu_dri2_unref_buffer(event->front);
+ amdgpu_dri2_unref_buffer(event->back);
+ free(event);
+}
+
+static void amdgpu_dri2_frame_event_handler(ScrnInfoPtr scrn, uint32_t seq,
+ uint64_t usec, void *event_data)
{
DRI2FrameEventPtr event = event_data;
DrawablePtr drawable;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
int status;
int swap_type;
BoxRec box;
RegionRec region;
- if (!event->valid)
+ if (!event->crtc)
goto cleanup;
status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
M_ANY, DixWriteAccess);
if (status != Success)
goto cleanup;
- if (!event->crtc)
- goto cleanup;
- frame += amdgpu_get_interpolated_vblanks(event->crtc);
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+ seq += amdgpu_get_interpolated_vblanks(event->crtc);
switch (event->type) {
case DRI2_FLIP:
@@ -778,14 +732,14 @@ void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
swap_type = DRI2_BLIT_COMPLETE;
}
- DRI2SwapComplete(event->client, drawable, frame, tv_sec,
- tv_usec, swap_type, event->event_complete,
+ DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000, swap_type, event->event_complete,
event->event_data);
break;
case DRI2_WAITMSC:
- DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec,
- tv_usec);
+ DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000);
break;
default:
/* Unknown type */
@@ -795,12 +749,7 @@ void amdgpu_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
}
cleanup:
- if (event->valid) {
- amdgpu_dri2_unref_buffer(event->front);
- amdgpu_dri2_unref_buffer(event->back);
- ListDelDRI2ClientEvents(event->client, &event->link);
- }
- free(event);
+ amdgpu_dri2_frame_event_abort(scrn, event_data);
}
drmVBlankSeqType amdgpu_populate_vbl_request_type(xf86CrtcPtr crtc)
@@ -972,17 +921,13 @@ static
CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
{
DRI2FrameEventPtr event_info = (DRI2FrameEventPtr) data;
- DrawablePtr drawable;
- ScreenPtr screen;
+ xf86CrtcPtr crtc = event_info->crtc;
ScrnInfoPtr scrn;
AMDGPUInfoPtr info;
- int status;
CARD64 drm_now;
int ret;
- unsigned int tv_sec, tv_usec;
CARD64 delta_t, delta_seq, frame;
drmmode_crtc_private_ptr drmmode_crtc;
- TimerFree(timer);
/*
* This is emulated event, so its time is current time, which we
@@ -993,29 +938,26 @@ CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
*/
if (!event_info->crtc) {
ErrorF("%s no crtc\n", __func__);
- amdgpu_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ amdgpu_drm_abort_entry(event_info->drm_queue);
+ else
+ amdgpu_dri2_frame_event_abort(NULL, data);
return 0;
}
- status =
- dixLookupDrawable(&drawable, event_info->drawable_id, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- ErrorF("%s cannot lookup drawable\n", __func__);
- amdgpu_dri2_frame_event_handler(0, 0, 0, data);
- return 0;
- }
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+
+ scrn = crtc->scrn;
info = AMDGPUPTR(scrn);
ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s cannot get current time\n", __func__);
- amdgpu_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ amdgpu_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
+ event_info->drm_queue);
+ else
+ amdgpu_dri2_frame_event_handler(scrn, 0, 0, data);
return 0;
}
- tv_sec = (unsigned int)(drm_now / 1000000);
- tv_usec = (unsigned int)(drm_now - (CARD64) tv_sec * 1000000);
/*
* calculate the frame number from current time
* that would come from CRTC if it were running
@@ -1025,21 +967,22 @@ CARD32 amdgpu_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
delta_seq /= 1000000;
frame = (CARD64) drmmode_crtc->dpms_last_seq + delta_seq;
- frame &= 0xffffffff;
- amdgpu_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec,
- data);
+ if (event_info->drm_queue)
+ amdgpu_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
+ drm_now % 1000000, event_info->drm_queue);
+ else
+ amdgpu_dri2_frame_event_handler(scrn, frame, drm_now, data);
return 0;
}
static
-void amdgpu_dri2_schedule_event(CARD32 delay, pointer arg)
+void amdgpu_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
{
- OsTimerPtr timer;
-
- timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event, arg);
+ event_info->timer = TimerSet(NULL, 0, delay, amdgpu_dri2_deferred_event,
+ event_info);
if (delay == 0) {
CARD32 now = GetTimeInMillis();
- amdgpu_dri2_deferred_event(timer, now, arg);
+ amdgpu_dri2_deferred_event(event_info->timer, now, event_info);
}
}
@@ -1057,6 +1000,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
AMDGPUInfoPtr info = AMDGPUPTR(scrn);
DRI2FrameEventPtr wait_info = NULL;
+ struct amdgpu_drm_queue_entry *wait = NULL;
xf86CrtcPtr crtc = amdgpu_dri2_drawable_crtc(draw, TRUE);
drmVBlank vbl;
int ret;
@@ -1079,17 +1023,8 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
wait_info->drawable_id = draw->id;
wait_info->client = client;
wait_info->type = DRI2_WAITMSC;
- wait_info->valid = TRUE;
wait_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &wait_info->link)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(wait_info);
- wait_info = NULL;
- goto out_complete;
- }
-
/*
* CRTC is in DPMS off state, calculate wait time from current time,
* target_msc and last vblank time/sequence when CRTC was turned off
@@ -1118,6 +1053,16 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
vbl.reply.sequence + amdgpu_get_interpolated_vblanks(crtc);
current_msc &= 0xffffffff;
+ wait = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+ wait_info, amdgpu_dri2_frame_event_handler,
+ amdgpu_dri2_frame_event_abort);
+ if (!wait) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM queue event entry failed.\n");
+ goto out_complete;
+ }
+ wait_info->drm_queue = wait;
+
/*
* If divisor is zero, or current_msc is smaller than target_msc,
* we just need to make sure target_msc passes before waking up the
@@ -1136,7 +1081,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
vbl.request.type |= amdgpu_populate_vbl_request_type(crtc);
vbl.request.sequence = target_msc;
vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1169,7 +1114,7 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
vbl.request.sequence += divisor;
vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1182,11 +1127,8 @@ static int amdgpu_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
return TRUE;
out_complete:
- if (wait_info) {
- ListDelDRI2ClientEvents(wait_info->client, &wait_info->link);
- free(wait_info);
- }
- DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+ if (wait_info)
+ amdgpu_dri2_deferred_event(NULL, 0, wait_info);
return TRUE;
}
@@ -1223,6 +1165,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
drmVBlank vbl;
int ret, flip = 0;
DRI2FrameEventPtr swap_info = NULL;
+ struct amdgpu_drm_queue_entry *swap;
CARD64 current_msc;
BoxRec box;
RegionRec region;
@@ -1255,15 +1198,17 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
swap_info->event_data = data;
swap_info->front = front;
swap_info->back = back;
- swap_info->valid = TRUE;
swap_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &swap_info->link)) {
+
+ swap = amdgpu_drm_queue_alloc(scrn, client, AMDGPU_DRM_QUEUE_ID_DEFAULT,
+ swap_info, amdgpu_dri2_frame_event_handler,
+ amdgpu_dri2_frame_event_abort);
+ if (!swap) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(swap_info);
- swap_info = NULL;
+ "Allocating DRM queue entry failed.\n");
goto blit_fallback;
}
+ swap_info->drm_queue = swap;
/*
* CRTC is in DPMS off state, fallback to blit, but calculate
@@ -1331,7 +1276,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
vbl.request.sequence = *target_msc;
vbl.request.sequence -= amdgpu_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1378,7 +1323,7 @@ static int amdgpu_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
/* Account for 1 frame extra pageflip delay if flip > 0 */
vbl.request.sequence -= flip;
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1472,26 +1417,6 @@ Bool amdgpu_dri2_screen_init(ScreenPtr pScreen)
driverNames[0] = driverNames[1] = dri2_info.driverName;
if (DRI2InfoCnt == 0) {
-#if HAS_DIXREGISTERPRIVATEKEY
- if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey,
- PRIVATE_CLIENT,
- sizeof(DRI2ClientEventsRec)))
- {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "DRI2 registering "
- "private key to client failed\n");
- return FALSE;
- }
-#else
- if (!dixRequestPrivate(DRI2ClientEventsPrivateKey,
- sizeof(DRI2ClientEventsRec))) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- "DRI2 requesting "
- "private key to client failed\n");
- return FALSE;
- }
-#endif
-
AddCallback(&ClientStateCallback,
amdgpu_dri2_client_state_changed, 0);
}