Hi all, This patch removes the following errors when remote-displaying on an XFree86 server : X Error of failed request: 145 Major opcode of failed request: 137 (XFree86-DGA) Minor opcode of failed request: 0 (XDGAQueryVersion) Serial number of failed request: 185 Current serial number in output stream: 185 What is happening is that the X server reports that the DGA2 extension is supported but sends us back an X error as soon as we want to use it (for security reasons). I will try to send a patch to XFree this week-end to try to convince them that it would be best if they would report the extension to not exist rather than to send an error. Anyway, the attached patch adds X error handling to both the XVideo and DGA2 cases. Changelog: - prevent X errors when remote displaying on XFree X servers Lionel PS for Alexandre: we once discussed how we could 'streamline' this X error handling (ie to prevent doing the same kind of code at three different locations in the Wine code). Did you progress on this issue or not ? -- Lionel Ulmer - http://www.bbrox.org/
Index: dlls/x11drv/dga2.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/dga2.c,v retrieving revision 1.7 diff -u -r1.7 dga2.c --- dlls/x11drv/dga2.c 2001/11/30 23:14:18 1.7 +++ dlls/x11drv/dga2.c 2002/01/18 16:46:10 @@ -44,9 +44,17 @@ info->dwWidth, info->dwHeight, info->dwBPP, info->wRefreshRate); } +static int XDGA2ErrorFlag; +static int XDGA2ErrorHandler(Display *dpy, XErrorEvent *event) +{ + XDGA2ErrorFlag = 1; + return 0; +} + void X11DRV_XF86DGA2_Init(void) { int nmodes, major, minor, i; + int (*WineXHandler)(Display *, XErrorEvent *); if (xf86dga2_modes) return; /* already initialized? */ @@ -55,23 +63,45 @@ if (!usedga) return; + /* First query the existence of the extension */ if (!TSXDGAQueryExtension(gdi_display, &dga_event, &dga_error)) return; - if (!TSXDGAQueryVersion(gdi_display, &major, &minor)) return; + /* For some dumb reasons, all the following code needs to be put in a 'X11 error handler' + critical section */ + wine_tsx11_lock(); + XDGA2ErrorFlag = 0; + XSync( gdi_display, 0 ); + WineXHandler = XSetErrorHandler(XDGA2ErrorHandler); + XSync( gdi_display, 0 ); + + if (!XDGAQueryVersion(gdi_display, &major, &minor)) goto error_handling; + XSync( gdi_display, 0 ); + if (XDGA2ErrorFlag == 1) goto error_handling; if (major < 2) return; /* only bother with DGA 2+ */ /* test that it works */ - if (!TSXDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) { + if (!XDGAOpenFramebuffer(gdi_display, DefaultScreen(gdi_display))) { WARN("disabling XF86DGA2 (insufficient permissions?)\n"); - return; + goto error_handling; } - TSXDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display)); + XSync( gdi_display, 0 ); + if (XDGA2ErrorFlag == 1) goto error_handling; + XDGACloseFramebuffer(gdi_display, DefaultScreen(gdi_display)); + XSync( gdi_display, 0 ); + if (XDGA2ErrorFlag == 1) goto error_handling; /* retrieve modes */ modes = TSXDGAQueryModes(gdi_display, DefaultScreen(gdi_display), &nmodes); - if (!modes) return; - + if (!modes) goto error_handling; + XSync( gdi_display, 0 ); + if (XDGA2ErrorFlag == 1) goto error_handling; + + /* And go back to 'normal' mode */ + XSync( gdi_display, 0 ); + XSetErrorHandler(WineXHandler); + wine_tsx11_unlock(); + TRACE("DGA modes: count=%d\n", nmodes); xf86dga2_mode_count = nmodes+1; @@ -85,6 +115,13 @@ convert_mode(&modes[i], &xf86dga2_modes[i+1]); TRACE("Enabling XF86DGA2 mode\n"); + return; + + error_handling: + XSync( gdi_display, 0 ); + XSetErrorHandler(WineXHandler); + wine_tsx11_unlock(); + return; } void X11DRV_XF86DGA2_Cleanup(void) Index: dlls/x11drv/xvidmode.c =================================================================== RCS file: /home/wine/wine/dlls/x11drv/xvidmode.c,v retrieving revision 1.12 diff -u -r1.12 xvidmode.c --- dlls/x11drv/xvidmode.c 2001/10/21 15:02:01 1.12 +++ dlls/x11drv/xvidmode.c 2002/01/18 16:46:10 @@ -79,9 +79,17 @@ info->dwAlphaBitMask = 0; } +static int XVideoErrorFlag; +static int XVideoErrorHandler(Display *dpy, XErrorEvent *event) +{ + XVideoErrorFlag = 1; + return 0; +} + void X11DRV_XF86VM_Init(void) { int nmodes, i; + int (*WineXHandler)(Display *, XErrorEvent *); if (xf86vm_major) return; /* already initialized? */ @@ -92,26 +100,41 @@ /* see if XVidMode is available */ if (!TSXF86VidModeQueryExtension(gdi_display, &xf86vm_event, &xf86vm_error)) return; - if (!TSXF86VidModeQueryVersion(gdi_display, &xf86vm_major, &xf86vm_minor)) return; + /* For some dumb reasons, all the following code needs to be put in a 'X11 error handler' + critical section */ + wine_tsx11_lock(); + XVideoErrorFlag = 0; + XSync( gdi_display, 0 ); + WineXHandler = XSetErrorHandler(XVideoErrorHandler); + XSync( gdi_display, 0 ); + if (!XF86VidModeQueryVersion(gdi_display, &xf86vm_major, &xf86vm_minor)) goto error_handling; + XSync( gdi_display, 0 ); + if (XVideoErrorFlag == 1) goto error_handling; #ifdef X_XF86VidModeSetGammaRamp if (xf86vm_major > 2 || (xf86vm_major == 2 && xf86vm_minor >= 1)) { - wine_tsx11_lock(); XF86VidModeGetGammaRampSize(gdi_display, DefaultScreen(gdi_display), &xf86vm_gammaramp_size); - wine_tsx11_unlock(); - if (xf86vm_gammaramp_size == 256) xf86vm_use_gammaramp = TRUE; } #endif /* retrieve modes */ - if (!TSXF86VidModeGetAllModeLines(gdi_display, DefaultScreen(gdi_display), &nmodes, - &modes)) - return; + if (!XF86VidModeGetAllModeLines(gdi_display, DefaultScreen(gdi_display), &nmodes, + &modes)) goto error_handling; + /* And leave the crit. section */ + XSync( gdi_display, 0 ); + XSetErrorHandler(WineXHandler); + wine_tsx11_unlock(); + if (XVideoErrorFlag == 1) + { + /* This means an error occured... */ + return; + } + TRACE("XVidMode modes: count=%d\n", nmodes); xf86vm_mode_count = nmodes; @@ -122,6 +145,12 @@ convert_modeinfo(modes[i], &xf86vm_modes[i]); TRACE("Enabling XVidMode\n"); + return; + + error_handling: + XSync(gdi_display, 0); + XSetErrorHandler(WineXHandler); + wine_tsx11_unlock(); } void X11DRV_XF86VM_Cleanup(void)