Some fixes for dumb X errors :-)

Lionel Ulmer lionel.ulmer at free.fr
Fri Jan 18 12:39:02 CST 2002


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/
-------------- next part --------------
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)


More information about the wine-patches mailing list