Since *_dri.so binaries compiled before dri_interface.h was used (it is currently only used in my private tree) expect mode to be at offset N, but a libGL.so compiled with dri_interface.h has it at offset N+12. Basically, by having the *_dri.so access anything outside the __DRIContextRec part it is impossible to add any fields to __DRIContextRec. Oops.
I did a bit of research, and this bug only exists in DRI CVS. The exposure is limited to our binary snapshots. Attached if a patch that fixes the problem. I am able to detect the bad libGL version in __driUtilCreateNewScreen. When version 20031201 is detected, the driver will refuse to load. That prevents weird crashes when a broken libGL is used with a fixed driver. I don't see a way to fix things to other way around. If a fixed libGL is used with a broken driver, it will just inexplicably crash.
There is a way to work around problems like this in the future. Each *_dri.so can export a new symbol, something like __driDesiredAPIVersion, that contains the highest version the driver wants to use. If this symbol already existed, libGL could do the following to reject broken drivers:
const unsigned *desired_version =
(const unsigned *) dlsym(handle, "__driDesiredAPIVersion");
if ( *desired_version == 20031201 ) {
ErrorMessageF("Driver uses broken API. Upgrade.");
Xfree(driver);
dlclose(handle);
return NULL;
}This also provides a mechanism to deprecate the "old" DRI API. The attached patch does not include any __driDesiredAPIVersion stuff.
Comments & opinions are welcome, as always.
Index: lib/GL/dri/dri_util.c
===================================================================
RCS file: /cvs/dri/xc/xc/lib/GL/dri/dri_util.c,v
retrieving revision 1.29
diff -u -d -r1.29 dri_util.c
--- a/lib/GL/dri/dri_util.c 3 Mar 2004 21:57:59 -0000 1.29
+++ b/lib/GL/dri/dri_util.c 26 Mar 2004 02:05:28 -0000
@@ -433,9 +433,9 @@
return GL_FALSE;
}
#else
- if ( driCompareGLXAPIVersion( 20031201 ) >= 0 ) {
+ if ( driCompareGLXAPIVersion( 20040317 ) >= 0 ) {
#endif /* DRI_NEW_INTERFACE_ONLY */
- modes = gc->mode;
+ modes = gc->driContext.mode;
#ifndef DRI_NEW_INTERFACE_ONLY
}
else {
@@ -1108,6 +1108,14 @@
__DRIscreenPrivate *psp;
+ if ( internal_api_version == 20031201 ) {
+ fprintf( stderr, "libGL error: libGL version 20031201 has critical "
+ "binary compatilibity bugs.\nlibGL error: You must upgrade "
+ "to use direct-rendering!\n" );
+ return NULL;
+ }
+
+
window_exists = (PFNGLXWINDOWEXISTSPROC)
glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
Index: lib/GL/glx/glxclient.h
===================================================================
RCS file: /cvs/dri/xc/xc/lib/GL/glx/glxclient.h,v
retrieving revision 1.48
diff -u -d -r1.48 glxclient.h
--- a/lib/GL/glx/glxclient.h 3 Mar 2004 21:58:00 -0000 1.48
+++ b/lib/GL/glx/glxclient.h 26 Mar 2004 02:05:28 -0000
@@ -316,6 +316,13 @@
*/
Bool (*unbindContext2)(Display *dpy, int scrn, GLXDrawable draw,
GLXDrawable read, GLXContext gc);
+
+ /**
+ * Pointer to the mode used to create this context.
+ *
+ * \since Internal API version 20040317.
+ */
+ const __GLcontextModes * mode;
};
/**
@@ -810,16 +817,6 @@
* drivers should NEVER use this data or even care that it exists.
*/
void * client_state_private;
-
-#ifdef GLX_DIRECT_RENDERING
- /**
- * Pointer to the mode used to create this context. This field replaces
- * the \c vid and \c fbconfigID fields.
- *
- * \since Internal API version 20031201.
- */
- const __GLcontextModes * mode;
-#endif /* GLX_DIRECT_RENDERING */
};
#define __glXSetError(gc,code) \
Index: lib/GL/glx/glxcmds.c
===================================================================
RCS file: /cvs/dri/xc/xc/lib/GL/glx/glxcmds.c,v
retrieving revision 1.77
diff -u -d -r1.77 glxcmds.c
--- a/lib/GL/glx/glxcmds.c 3 Mar 2004 21:58:00 -0000 1.77
+++ b/lib/GL/glx/glxcmds.c 26 Mar 2004 02:05:28 -0000
@@ -583,7 +583,7 @@
gc->screen = mode->screen;
gc->vid = mode->visualID;
gc->fbconfigID = mode->fbconfigID;
- gc->mode = mode;
+ gc->driContext.mode = mode;
}
}
}
@@ -3298,8 +3298,11 @@
* deprecated GLX_NV_vertex_array_range & GLX_MESA_agp_offset
* interfaces.
* 20031201 - Added support for the first round of DRI interface changes.
+ * Do NOT test against this version! It has binary
+ * compatibility bugs, use 20040317 instead.
+ * 20040317 - Added the 'mode' field to __DRIcontextRec.
*/
- return 20031201;
+ return 20040317;
}
