From 1a7aee77bf63bae2c3cf511d200e4350ab236201 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 31 Jan 2016 09:05:52 +0000 Subject: [PATCH] sna/dri2: Restore signalling on Window destruction This effectively reverts commit 5c735befdcc40f94bd740be9fc0df54ad53aa174 Author: Chris Wilson Date: Wed Jan 6 10:00:19 2016 +0000 sna/dri2: Ignore pending SwapComplete events when the window is destroyed but in order to do so, we have to use a RESTYPE on the Window in order for our destruction event to be run before the DRI2DrawableGone (we rely on adding our resource after and so being run before!) to work around the dri2 core bug: diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 6a3391d..7223c9b 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -420,6 +420,9 @@ DRI2DrawableGone(void *p, XID id) (*pDraw->pScreen->DestroyPixmap)(pPriv->redirectpixmap); } + if (pPriv->blockedClient) + AttendClient(pPriv->blockedClient); + free(pPriv); return Success; References: https://bugs.freedesktop.org/show_bug.cgi?id=93844 Signed-off-by: Chris Wilson --- src/sna/sna.h | 2 -- src/sna/sna_accel.c | 1 - src/sna/sna_dri2.c | 38 +++++++++++++++++++++++++++++--------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 3c19aa5..7491b4a 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -574,7 +574,6 @@ void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_vblank *event) void sna_dri2_vblank_handler(struct drm_event_vblank *event); void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo); void sna_dri2_decouple_window(WindowPtr win); -void sna_dri2_destroy_window(WindowPtr win); void sna_dri2_close(struct sna *sna, ScreenPtr pScreen); #else static inline bool sna_dri2_open(struct sna *sna, ScreenPtr pScreen) { return false; } @@ -582,7 +581,6 @@ static inline void sna_dri2_page_flip_handler(struct sna *sna, struct drm_event_ static inline void sna_dri2_vblank_handler(struct drm_event_vblank *event) { } static inline void sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo) { } static inline void sna_dri2_decouple_window(WindowPtr win) { } -static inline void sna_dri2_destroy_window(WindowPtr win) { } static inline void sna_dri2_close(struct sna *sna, ScreenPtr pScreen) { } #endif diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 71a6207..2db7f37 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -17914,7 +17914,6 @@ sna_destroy_window(WindowPtr win) { DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id)); sna_video_destroy_window(win); - sna_dri2_destroy_window(win); return TRUE; } diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 045b12d..cb72ba5 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -62,6 +62,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #error DRI2 version supported by the Xserver is too old #endif +static RESTYPE sna_dri2_window_type; +static int sna_dri2_server_generation; + static inline struct kgem_bo *ref(struct kgem_bo *bo) { return kgem_bo_reference(bo); @@ -1512,8 +1515,14 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc) priv = dri2_window((WindowPtr)draw); if (priv == NULL) { + /* Note that we want to add our private resource late, so + * that we can be run before the DRI2DrawableGone in order + * to wake up the blocked client before DRI2 frees its own + * private struct. + */ priv = malloc(sizeof(*priv)); - if (priv != NULL) { + if (priv != NULL && + AddResource(draw->id, sna_dri2_window_type, draw)) { priv->front = NULL; priv->crtc = crtc; priv->msc_delta = 0; @@ -1521,7 +1530,8 @@ draw_current_msc(DrawablePtr draw, xf86CrtcPtr crtc, uint64_t msc) priv->scanout = -1; list_init(&priv->cache); dri2_window_attach((WindowPtr)draw, priv); - } + } else + free(priv); } else { if (priv->crtc != crtc) { const struct ust_msc *last = sna_crtc_last_swap(priv->crtc); @@ -1817,15 +1827,13 @@ void sna_dri2_decouple_window(WindowPtr win) priv->scanout = -1; } -void sna_dri2_destroy_window(WindowPtr win) +static int +sna_dri2_window_gone(void *data, XID id) { - struct dri2_window *priv; + WindowPtr win = data; + struct dri2_window *priv = dri2_window(win); struct sna *sna; - priv = dri2_window(win); - if (priv == NULL) - return; - DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.id)); sna = to_sna_from_drawable(&win->drawable); @@ -1846,16 +1854,19 @@ void sna_dri2_destroy_window(WindowPtr win) __FUNCTION__, info->signal, info->pending.bo ? info->pending.bo->handle : 0)); assert(info->draw == &win->drawable); + if (info->signal) + frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE); if (info->pending.bo) { assert(info->pending.bo->active_scanout > 0); info->pending.bo->active_scanout--; + info->signal = true; + frame_swap_complete(info, DRI2_EXCHANGE_COMPLETE); kgem_bo_destroy(&sna->kgem, info->pending.bo); info->pending.bo = NULL; } - info->signal = false; info->draw = NULL; info->keepalive = 1; assert(!info->signal); @@ -1883,6 +1894,8 @@ void sna_dri2_destroy_window(WindowPtr win) } free(priv); + + return Success; } static void @@ -3650,6 +3663,13 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen) return false; } + if (serverGeneration != sna_dri2_server_generation) { + sna_dri2_server_generation = serverGeneration; + sna_dri2_window_type = + CreateNewResourceType(sna_dri2_window_gone, + "DRI2 Window"); + } + memset(&info, '\0', sizeof(info)); info.fd = sna->kgem.fd; info.driverName = dri_driver_name(sna); -- 2.7.0