From 94fdaa5d41ecc33f48bec6d2094e67f533a0e5de Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 3 Oct 2013 13:15:53 +0000 Subject: Fix crash starting game engine on linux Issue was caused by bug in mesa #54080 which makes glXQueryDrawable fail with GLXBadDrawable for any request with direct context. Worked around by temporary overriding X error handling when getting old interval value and disablingintervals extension if this query fails. Also added check for glXSwapIntervalEXT which is apparently NULL here with GLX_EXT_swap_control=1. --- intern/ghost/intern/GHOST_WindowX11.cpp | 61 +++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 25c74a0a6cb..3e6e1cd1a94 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -65,6 +65,14 @@ typedef struct { long input_mode; } MotifWmHints; +// Workaround for MESA bug #54080 +// https://bugs.freedesktop.org/show_bug.cgi?id=54080() +#define SWAP_INTERVALS_WORKAROUND + +#ifdef SWAP_INTERVALS_WORKAROUND +static bool g_swap_interwal_disabled = false; +#endif // SWAP_INTERVALS_WORKAROUND + #define MWM_HINTS_DECORATIONS (1L << 1) @@ -1519,18 +1527,67 @@ endFullScreen() const GHOST_TSuccess GHOST_WindowX11:: setSwapInterval(int interval) { - if (!GLX_EXT_swap_control) + if (!GLX_EXT_swap_control || !glXSwapIntervalEXT +#ifdef SWAP_INTERVALS_WORKAROUND + || g_swap_interwal_disabled +#endif // SWAP_INTERVALS_WORKAROUND + ) + { return GHOST_kFailure; + } glXSwapIntervalEXT(m_display, m_window, interval); return GHOST_kSuccess; } +#ifdef SWAP_INTERVALS_WORKAROUND +static int QueryDrawable_ApplicationErrorHandler(Display *display, XErrorEvent *theEvent) +{ + fprintf(stderr, "Ignoring Xlib error: error code %d request code %d\n", + theEvent->error_code, theEvent->request_code); + if (!g_swap_interwal_disabled) { + fprintf(stderr, "Disabling SWAP INTERVALS extension\n"); + g_swap_interwal_disabled = true; + } + return 0; +} + +static int QueryDrawable_ApplicationIOErrorHandler(Display *display) +{ + fprintf(stderr, "Ignoring Xlib error: error IO\n"); + if (!g_swap_interwal_disabled) { + fprintf(stderr, "Disabling SWAP INTERVALS extension\n"); + g_swap_interwal_disabled = true; + } + return 0; +} +#endif // SWAP_INTERVALS_WORKAROUND + int GHOST_WindowX11:: getSwapInterval() { if (GLX_EXT_swap_control) { - unsigned int value; +#ifdef SWAP_INTERVALS_WORKAROUND + /* XXX: Current MESA driver will give GLXBadDrawable for all + * the glXQueryDrawable requests with direct contexts. + * + * To prevent crashes and unexpected behaviors, we will + * disable swap interwals extension if query fails here. + * (because if we will override interval without having + * old value we couldn't restore it properly). + */ + XErrorHandler old_handler = XSetErrorHandler(QueryDrawable_ApplicationErrorHandler); + XIOErrorHandler old_handler_io = XSetIOErrorHandler(QueryDrawable_ApplicationIOErrorHandler); +#endif // SWAP_INTERVALS_WORKAROUND + + unsigned int value = 0; glXQueryDrawable(m_display, m_window, GLX_SWAP_INTERVAL_EXT, &value); + +#ifdef SWAP_INTERVALS_WORKAROUND + /* Restore handler */ + (void) XSetErrorHandler(old_handler); + (void) XSetIOErrorHandler(old_handler_io); +#endif // SWAP_INTERVALS_WORKAROUND + return (int)value; } return 0; -- cgit v1.2.3