From c3a14b2a4d39915b60caa5323a7ce647c809f311 Mon Sep 17 00:00:00 2001 From: Alban Browaeys Date: Tue, 24 Aug 2010 14:52:50 +0200 Subject: [PATCH] radeon: vblank when client gone event version. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based upon a detailed explanation from Oldřich Jedlička and comments from Christopher James Halse Rogers. on http://lists.x.org/archives/xorg-driver-ati/2010-August/016780.html . --- src/radeon_dri2.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 102 insertions(+), 0 deletions(-) diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index a0ed085..25dd7fe 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -37,6 +37,7 @@ #include "radeon.h" #include "radeon_dri2.h" #include "radeon_version.h" +#include "list.h" #ifdef RADEON_DRI2 @@ -346,8 +347,82 @@ typedef struct _DRI2FrameEvent { void *event_data; DRI2BufferPtr front; DRI2BufferPtr back; + + Bool valid; + + struct list link; } DRI2FrameEventRec, *DRI2FrameEventPtr; +typedef struct _DRI2ClientEvents { + struct list reference_list; +} DRI2ClientEventsRec, *DRI2ClientEventsPtr; + + +static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec; +#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec) + +#define GetDRI2ClientEvents(_pClient) (DRI2ClientEventsPtr) \ + dixLookupPrivate(&(_pClient)->devPrivates, DRI2ClientEventsPrivateKey) + + +static int +ListAddDRI2ClientEvents(ClientPtr client, struct list *entry) +{ + DRI2ClientEventsPtr pClientPriv; + pClientPriv = GetDRI2ClientEvents(client); + + if (!pClientPriv) { + return BadAlloc; + } + + list_add(entry, &pClientPriv->reference_list); + return 0; +} + + +static void +ListDelDRI2ClientEvents(ClientPtr client, struct list *entry) +{ + DRI2ClientEventsPtr pClientPriv; + pClientPriv = GetDRI2ClientEvents(client); + + if (!pClientPriv) { + return; + } + list_del(entry); +} + + +static void +radeon_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: + list_init(&pClientEventsPriv->reference_list); + break; + case ClientStateRunning: + break; + + case ClientStateRetained: + case ClientStateGone: + if (pClientEventsPriv) { + list_for_each_entry(ref, &pClientEventsPriv->reference_list, link) { + ref->valid = FALSE; + } + } + break; + default: + break; + } +} + void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data) { @@ -360,6 +435,11 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, BoxRec box; RegionRec region; + if (!event->valid) { + free(event); + return; + } + status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, M_ANY, DixWriteAccess); if (status != Success) { @@ -394,6 +474,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, break; } + ListDelDRI2ClientEvents(event->client, &event->link); free(event); } @@ -489,6 +570,12 @@ static int radeon_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; + if (ListAddDRI2ClientEvents(client, &wait_info->link)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "add events to client private failed.\n"); + goto out_complete; + } /* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; @@ -628,6 +715,12 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, swap_info->event_data = data; swap_info->front = front; swap_info->back = back; + swap_info->valid = TRUE; + if (ListAddDRI2ClientEvents(client, &swap_info->link)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "add events to client private failed.\n"); + goto blit_fallback; + } /* Get current count */ vbl.request.type = DRM_VBLANK_RELATIVE; @@ -810,6 +903,12 @@ radeon_dri2_screen_init(ScreenPtr pScreen) } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for sync extension\n"); } + + if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey, PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 registering private key to client failed\n"); + return FALSE; + } + AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0); #endif info->dri2.enabled = DRI2ScreenInit(pScreen, &dri2_info); @@ -821,6 +920,9 @@ void radeon_dri2_close_screen(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); +#if DRI2INFOREC_VERSION >= 4 + DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0); +#endif DRI2CloseScreen(pScreen); drmFree(info->dri2.device_name); } -- 1.7.1