Hello,

this is hopefully the final version of the per-screen dynamic GLX
extensions patch. Major changes from the last version:

- per-screen data in __GLXscreenConfigs
- __DRIscreen has an opaque pointer back to the screenConfigs
- Bumped the internal libGL API version to 20030813
- __glXExtensionBitIsEnabled must be per-screen too
- requires two helper functions to find the __GLXscreenConfigs from
  either a GLXcontext or a display, screen pair
- Updated some comments in glxextensions.c

To test that the screen finding functions actually work as expected we
should test at least one of the SwapInverval-related extensions and one
of the FBConfig-related ones. Can someone point me to some simple test
cases. I remember some posts about glxgears with SwapInterval support.
Is that in Mesa CVS? It is a bit inconvenient for me to download a whole
mesa CVS tree through a modem connection. Ian, IIRC you made those
changes in glxgears. Could you send me only the updated glxgears source?

Regards,
  Felix

------------    __\|/__    ___     ___       -------------------------
 Felix       ___\_e -_/___/ __\___/ __\_____   You can do anything,
   Kühling  (_____\Ä/____/ /_____/ /________)  just not everything
 [EMAIL PROTECTED]       \___/   \___/   U        at the same time.
? dri/DONE
? dri/Makefile
? dri/drm/DONE
? dri/drm/Makefile
? glx/DONE
? glx/Makefile
? glx/glxextensions.patch
? glx/glxextensions2.patch
Index: dri/dri_glx.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/dri/dri_glx.c,v
retrieving revision 1.29.4.1
diff -u -r1.29.4.1 dri_glx.c
--- dri/dri_glx.c       26 May 2003 17:41:59 -0000      1.29.4.1
+++ dri/dri_glx.c       14 Aug 2003 16:31:27 -0000
@@ -230,8 +230,6 @@
             dlclose(handle);
             continue;
          }
-         driver->registerExtensionsFunc = (RegisterExtensionsFunc)
-            dlsym(handle, "__driRegisterExtensions");
          driver->handle = handle;
          /* put at head of linked list */
          driver->next = Drivers;
@@ -435,7 +433,6 @@
      * driver's "__driCreateScreen" function pointer.  That's the bootstrap
      * entrypoint for all DRI drivers.
      */
-    __glXRegisterExtensions();
     for (scrn = 0; scrn < numScreens; scrn++) {
         __DRIdriver *driver = driGetDriver(dpy, scrn);
         if (driver) {
@@ -451,71 +448,5 @@
 
     return (void *)pdpyp;
 }
-
-
-
-/*
-** Here we'll query the DRI driver for each screen and let each
-** driver register its GL extension functions.  We only have to
-** do this once.
-**
-** In older versions of libGL (prior to October 2002) we _always_
-** called this function during libGL start-up.  Now, we only call
-** it from glXGetProcAddress() as a last resort.
-**
-** Two key things changed along the way:
-** 1. _glapi_get_proc_address() now generates new dispatch stub functions
-**    anytime it gets an unknown "gl*" function name.  I.e. we always return
-**    a valid function address and later patch it up to use the correct
-**    dispatch offset.
-** 2. The GL API dispatch table is a fixed size (with plenty of extra slots).
-**    This means we don't have to register all new functions before we create
-**    the first dispatch table.
-*/
-void
-__glXRegisterExtensions(void)
-{
-#ifndef BUILT_IN_DRI_DRIVER
-   static GLboolean alreadyCalled = GL_FALSE;
-   int displayNum, maxDisplays;
-
-   if (alreadyCalled)
-      return;
-   alreadyCalled = GL_TRUE;
-
-   if (getenv("LIBGL_MULTIHEAD")) {
-      /* we'd like to always take this path but doing so causes a second
-       * or more of delay while the XOpenDisplay() function times out.
-       */
-      maxDisplays = 10;  /* infinity, really */
-   }
-   else {
-      /* just open the :0 display */
-      maxDisplays = 1;
-   }
-
-   for (displayNum = 0; displayNum < maxDisplays; displayNum++) {
-      char displayName[200];
-      Display *dpy;
-      snprintf(displayName, 199, ":%d.0", displayNum);
-      dpy = XOpenDisplay(displayName);
-      if (dpy) {
-         const int numScreens = ScreenCount(dpy);
-         int screenNum;
-         for (screenNum = 0; screenNum < numScreens; screenNum++) {
-            __DRIdriver *driver = driGetDriver(dpy, screenNum);
-            if (driver && driver->registerExtensionsFunc) {
-               (*driver->registerExtensionsFunc)();
-            }
-         }
-         XCloseDisplay(dpy);
-      }
-      else {
-         break;
-      }
-   }
-#endif
-}
-
 
 #endif /* GLX_DIRECT_RENDERING */
Index: dri/dri_util.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/dri/dri_util.c,v
retrieving revision 1.13
diff -u -r1.13 dri_util.c
--- dri/dri_util.c      21 May 2003 17:32:04 -0000      1.13
+++ dri/dri_util.c      14 Aug 2003 16:31:42 -0000
@@ -1031,6 +1031,7 @@
     if (!psp) {
        return NULL;
     }
+    psp->psc = psc;
     psp->fullscreen = NULL;
     psp->display = dpy;
     psp->myNum = scrn;
Index: dri/dri_util.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/dri/dri_util.h,v
retrieving revision 1.8
diff -u -r1.8 dri_util.h
--- dri/dri_util.h      21 May 2003 17:32:05 -0000      1.8
+++ dri/dri_util.h      14 Aug 2003 16:31:46 -0000
@@ -406,6 +406,11 @@
     */
     int numConfigs;
     __GLXvisualConfig *configs;
+
+    /*
+    ** Point back to the containing __DRIscreen
+    */
+    __DRIscreen *psc;
 };
 
 
Index: glx/glxclient.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/glx/glxclient.h,v
retrieving revision 1.28.2.1
diff -u -r1.28.2.1 glxclient.h
--- glx/glxclient.h     26 May 2003 17:41:59 -0000      1.28.2.1
+++ glx/glxclient.h     14 Aug 2003 16:31:54 -0000
@@ -167,6 +167,16 @@
     ** Added with internal API version "20030317".
     */
     int (*getMSC)( void *screenPrivate, int64_t *msc );
+
+    /*
+    ** Opaque pointer that points back to the containing __GLXscreenConfigs.
+    ** This data structure is shared with DRI drivers but __GLXscreenConfigs
+    ** is not. However, they are needed by some GLX functions called by DRI
+    ** drivers.
+    **
+    ** Added with internal API version "20030813".
+    */
+    void *screenConfigs;
 };
 
 /*
@@ -292,8 +302,6 @@
 typedef void *(*CreateScreenFunc)(Display *dpy, int scrn, __DRIscreen *psc,
                                   int numConfigs, __GLXvisualConfig *config);
 
-typedef void *(*RegisterExtensionsFunc)(void);
-
 /*
 ** We keep a linked list of these structures, one per DRI device driver.
 */
@@ -301,7 +309,6 @@
    const char *name;
    void *handle;
    CreateScreenFunc createScreenFunc;
-   RegisterExtensionsFunc registerExtensionsFunc;
    struct __DRIdriverRec *next;
 };
 
@@ -595,6 +602,11 @@
     ** Per screen direct rendering interface functions and data.
     */
     __DRIscreen driScreen;
+    /*
+    ** Per screen dynamic client GLX extensions
+    */
+    unsigned char direct_support[8];
+    GLboolean ext_list_first_time;
 #endif
 } __GLXscreenConfigs;
 
@@ -641,6 +653,8 @@
 #endif
 };
 
+__GLXscreenConfigs *__glXFindGLXScreenConfigs(Display *dpy, int scrn);
+
 void __glXFreeContext(__GLXcontext*);
 
 extern GLubyte *__glXFlushRenderBuffer(__GLXcontext*, GLubyte*);
@@ -650,15 +664,6 @@
 
 /* Initialize the GLX extension for dpy */
 extern __GLXdisplayPrivate *__glXInitialize(Display*);
-
-/* Query drivers for dynamically registered extensions */
-extern void __glXRegisterExtensions(void);
-
-/* Functions for extending the GLX API: */
-extern void *__glXRegisterGLXFunction(const char *funcName, void *funcAddr);
-extern void __glXRegisterGLXExtensionString(const char *extName);
-typedef void * (* PFNGLXREGISTERGLXFUNCTIONPROC) ( const char * funcName,
-                                                  void * funcAdd );
 
 /************************************************************************/
 
Index: glx/glxcmds.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/glx/glxcmds.c,v
retrieving revision 1.41.2.1
diff -u -r1.41.2.1 glxcmds.c
--- glx/glxcmds.c       26 May 2003 17:41:59 -0000      1.41.2.1
+++ glx/glxcmds.c       14 Aug 2003 16:32:24 -0000
@@ -104,6 +104,21 @@
 static const char __glXGLXClientVersion[] = "1.2";
 
 /****************************************************************************/
+
+static __GLXscreenConfigs *
+GetGLXScreenConfigs( GLXContext gc )
+{
+    __GLXscreenConfigs *psc = NULL;
+
+    if (gc != NULL) {
+       __GLXdisplayPrivate *priv = __glXInitialize(gc->currentDpy);
+       if (priv->screenConfigs)
+           psc = &priv->screenConfigs[gc->screen];
+    }
+
+    return psc;
+}
+
 /**
  * Get the write __DRIdrawable bound to the specificed GLXContext
  * 
@@ -1330,7 +1345,7 @@
                                                   screen, GLX_EXTENSIONS);
        }
 
-       psc->effectiveGLXexts = (char *) __glXGetUsableExtensions(psc->serverGLXexts);
+       psc->effectiveGLXexts = (char *) __glXGetUsableExtensions(psc, 
psc->serverGLXexts);
     }
 
     return psc->effectiveGLXexts;
@@ -1872,7 +1887,10 @@
    }
 
 #ifdef GLX_DIRECT_RENDERING
-   if ( gc->isDirect && __glXExtensionBitIsEnabled( SGI_swap_control_bit ) ) {
+   {
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
+   if ( gc->isDirect &&
+       __glXExtensionBitIsEnabled( psc, SGI_swap_control_bit ) ) {
       __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
       if ( pdraw != NULL ) {
@@ -1880,6 +1898,7 @@
         return 0;
       }
    }
+   }
 #endif
    dpy = gc->currentDpy;
    opcode = __glXSetupForCommand(dpy);
@@ -1913,6 +1932,7 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
    if ( pdraw == NULL ) {
@@ -1923,7 +1943,7 @@
       return GLX_BAD_VALUE;
    }
 
-   if ( __glXExtensionBitIsEnabled( MESA_swap_control_bit ) ) {
+   if ( __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) {
       pdraw->swap_interval = interval;
       return 0;
    }
@@ -1938,10 +1958,11 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
 
-   if ( pdraw && __glXExtensionBitIsEnabled( MESA_swap_control_bit ) ) {
+   if ( pdraw && __glXExtensionBitIsEnabled( psc, MESA_swap_control_bit ) ) {
       return pdraw->swap_interval;
    }
 #endif
@@ -1959,10 +1980,12 @@
    int   status = GLX_BAD_CONTEXT;
 #ifdef GLX_DIRECT_RENDERING
     GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw;
    __GLXdisplayPrivate *priv;
 
-   if ( (gc != NULL) && __glXExtensionBitIsEnabled( MESA_swap_frame_usage_bit ) ) {
+   if ( (gc != NULL) &&
+       __glXExtensionBitIsEnabled( psc, MESA_swap_frame_usage_bit ) ) {
       priv = __glXInitialize(gc->currentDpy);
       if (priv->driDisplay.private) {
         __GLXscreenConfigs *psc = &priv->screenConfigs[gc->screen];
@@ -1992,10 +2015,12 @@
    int   status = GLX_BAD_CONTEXT;
 #ifdef GLX_DIRECT_RENDERING
     GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw;
    __GLXdisplayPrivate *priv;
 
-   if ( (gc != NULL) && __glXExtensionBitIsEnabled( MESA_swap_frame_usage_bit ) ) {
+   if ( (gc != NULL) &&
+       __glXExtensionBitIsEnabled( psc, MESA_swap_frame_usage_bit ) ) {
       priv = __glXInitialize(gc->currentDpy);
       if (priv->driDisplay.private) {
         __GLXscreenConfigs *psc = &priv->screenConfigs[gc->screen];
@@ -2026,10 +2051,11 @@
    int   status = GLX_BAD_CONTEXT;
 #ifdef GLX_DIRECT_RENDERING
     GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
    if ( (pdraw != NULL ) && (pdraw->queryFrameTracking != NULL)
-       && __glXExtensionBitIsEnabled( MESA_swap_frame_usage_bit ) ) {
+       && __glXExtensionBitIsEnabled( psc, MESA_swap_frame_usage_bit ) ) {
       int64_t sbc, missedFrames;
       float   lastMissedUsage;
 
@@ -2053,10 +2079,11 @@
    int   status = GLX_BAD_CONTEXT;
 #ifdef GLX_DIRECT_RENDERING
     GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
    if ( (pdraw != NULL ) && (pdraw->queryFrameTracking != NULL)
-       && __glXExtensionBitIsEnabled( MESA_swap_frame_usage_bit ) ) {
+       && __glXExtensionBitIsEnabled( psc, MESA_swap_frame_usage_bit ) ) {
       float   usage;
 
       status = pdraw->queryFrameTracking( dpy, pdraw->private, sbc,
@@ -2085,10 +2112,10 @@
     */
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
-   
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
 
    if ( (gc != NULL) && gc->isDirect
-       && __glXExtensionBitIsEnabled( SGI_video_sync_bit ) ) {
+       && __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit ) ) {
       __GLXdisplayPrivate *priv = __glXInitialize(gc->currentDpy);
       if (priv->driDisplay.private) {
         __GLXscreenConfigs *psc = &priv->screenConfigs[gc->screen];
@@ -2112,13 +2139,14 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
    if ( divisor <= 0 || remainder < 0 )
      return GLX_BAD_VALUE;
 
    if (pdraw && pdraw->waitForMSC 
-       && __glXExtensionBitIsEnabled( SGI_video_sync_bit )) {
+       && __glXExtensionBitIsEnabled( psc, SGI_video_sync_bit )) {
       int       ret;
       int64_t   msc;
       int64_t   sbc;
@@ -2181,9 +2209,9 @@
     GLXPixmap xid = None;
     CARD8 opcode;
     __GLXFBConfig * fbconfig = (__GLXFBConfig *) config;
+    __GLXscreenConfigs *psc = __glXFindGLXScreenConfigs( dpy, fbconfig->screen );
 
-
-    if ( __glXExtensionBitIsEnabled( SGIX_fbconfig_bit ) ) {
+    if ( __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
        opcode = __glXSetupForCommand(dpy);
        if (!opcode) {
            return None;
@@ -2216,8 +2244,9 @@
     __GLXdisplayPrivate *priv;
 #endif
     __GLXFBConfig * fbconfig = (__GLXFBConfig *) config;
+    __GLXscreenConfigs *psc = __glXFindGLXScreenConfigs( dpy, fbconfig->screen );
 
-    if ( __glXExtensionBitIsEnabled( SGIX_fbconfig_bit ) ) {
+    if ( __glXExtensionBitIsEnabled( psc, SGIX_fbconfig_bit ) ) {
        if (!dpy || !fbconfig)
            return NULL;
 
@@ -2475,11 +2504,13 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw;
    __GLXdisplayPrivate *priv;
    int   ret;
 
-   if ( (gc != NULL) && __glXExtensionBitIsEnabled( OML_sync_control_bit ) ) {
+   if ( (gc != NULL) &&
+       __glXExtensionBitIsEnabled( psc, OML_sync_control_bit ) ) {
       priv = __glXInitialize(gc->currentDpy);
       if (priv->driDisplay.private) {
         __GLXscreenConfigs *psc = &priv->screenConfigs[gc->screen];
@@ -2598,6 +2629,7 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
 
    /* The OML_sync_control spec says these should "generate a GLX_BAD_VALUE
@@ -2610,7 +2642,7 @@
    if ( divisor > 0 && remainder >= divisor )
       return -1;
 
-   if (pdraw && __glXExtensionBitIsEnabled( OML_sync_control_bit )) {
+   if (pdraw && __glXExtensionBitIsEnabled( psc, OML_sync_control_bit )) {
       return (*pdraw->swapBuffersMSC)(dpy, pdraw->private, target_msc,
                                      divisor, remainder);
    }
@@ -2632,6 +2664,7 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
    int  ret;
 
@@ -2644,7 +2677,7 @@
       return False;
 
    if ( (pdraw != NULL) && (pdraw->waitForMSC != NULL)
-       && __glXExtensionBitIsEnabled( OML_sync_control_bit )) {
+       && __glXExtensionBitIsEnabled( psc, OML_sync_control_bit )) {
       ret = (*pdraw->waitForMSC)( dpy, pdraw->private, target_msc,
                                  divisor, remainder, msc, sbc );
 
@@ -2673,6 +2706,7 @@
 {
 #ifdef GLX_DIRECT_RENDERING
    GLXContext gc = __glXGetCurrentContext();
+   __GLXscreenConfigs *psc = GetGLXScreenConfigs( gc );
    __DRIdrawable *pdraw = GetDRIDrawable( gc );
    int  ret;
 
@@ -2683,7 +2717,7 @@
       return False;
 
    if ( (pdraw != NULL) && (pdraw->waitForSBC != NULL)
-       && __glXExtensionBitIsEnabled( OML_sync_control_bit )) {
+       && __glXExtensionBitIsEnabled( psc, OML_sync_control_bit )) {
       ret = (*pdraw->waitForSBC)( dpy, pdraw->private, target_sbc, msc, sbc );
 
       /* __glXGetUST returns zero on success and non-zero on failure.
@@ -2936,13 +2970,10 @@
    { "__glXInitialize", (GLvoid *) __glXInitialize, NULL },
    { "__glXFindDRIScreen", (GLvoid *) __glXFindDRIScreen, NULL },
    { "__glXGetInternalVersion", (GLvoid *) __glXGetInternalVersion, NULL },
-   { "__glXRegisterGLXExtensionString", (GLvoid *) __glXRegisterGLXExtensionString, 
NULL },
-   { "__glXRegisterGLXFunction", (GLvoid *) __glXRegisterGLXFunction, NULL },
    { "__glXWindowExists", (GLvoid *) __glXWindowExists, NULL },
 
-   { "__glXEnableExtension", (GLvoid *) __glXEnableExtension, NULL },
-   { "__glXDisableExtension", (GLvoid *) __glXDisableExtension, NULL },
-   { "__glXAddExtension", (GLvoid *) __glXAddExtension, NULL },
+   { "__glXScrEnableExtension", (GLvoid *) __glXScrEnableExtension, NULL },
+   { "__glXScrDisableExtension", (GLvoid *) __glXScrDisableExtension, NULL },
 
    { "__glXGetUST", (GLvoid *) __glXGetUST, NULL },
 
@@ -2950,85 +2981,11 @@
 };
 
 
-static struct name_address_pair *Dynamic_GLX_functions = NULL;
-
-
-/*
- * Drivers can call this function to append the name of a new GLX
- * extension string to __glXGLXClientExtensions.  Then, when the user
- * calls glXGetClientString() they'll see it listed.
- * This is a companion to __glXRegisterGLXFunction().
- */
-void
-__glXRegisterGLXExtensionString(const char *extName)
-{
-   __glXEnableExtension( extName, GL_TRUE );
-}
-
-
-/**
- * DRI drivers should call this function if they want to extend
- * the GLX API.  After registering a new GLX function, the user
- * can query and use it by calling \c glXGetProcAddress.
- * 
- * \param funcName name of new GLX function
- * \param funcAddr pointer to the function
- * \return Address of previously registered function with this name or NULL.
- * 
- * \sa __glXEnableExtension glXGetProcAddress
-  */
-void *
-__glXRegisterGLXFunction(const char *funcName, void *funcAddr)
-{
-   struct name_address_pair *ext;
-
-   assert(funcName);
-   assert(funcName[0] == 'g');
-   assert(funcName[1] == 'l');
-   assert(funcName[2] == 'X');
-
-   /* look if the function is already registered */
-   for (ext = Dynamic_GLX_functions; ext; ext = ext->Next) {
-      if (strcmp(ext->Name, funcName) == 0) {
-        /* It's up the caller to use this return value if he wants
-         * to chain-call or wrap the previously registered function.
-         */
-         void *prevAddr = ext->Address;
-        ext->Address = funcAddr;
-        return prevAddr;
-      }
-   }
-
-   /* add new function */
-   ext = Xmalloc(sizeof(struct name_address_pair));
-   if (!ext)
-      return NULL;
-   ext->Name = __glXstrdup(funcName);
-   if (!ext->Name) {
-      Xfree(ext);
-      return NULL;
-   }
-   ext->Address = funcAddr;
-   ext->Next = Dynamic_GLX_functions;
-   Dynamic_GLX_functions = ext;
-   return NULL;
-}
-
-
 static const GLvoid *
 get_glx_proc_address(const char *funcName, GLboolean dynamic_only)
 {
-   const struct name_address_pair *ext;
    GLuint i;
 
-   /* try dynamic functions */
-   for (ext = Dynamic_GLX_functions; ext; ext = ext->Next) {
-      if (strcmp(ext->Name, funcName) == 0) {
-        return ext->Address;
-      }
-   }
-
-   /* try static functions */
    if ( ! dynamic_only ) {     
       for (i = 0; GLX_functions[i].Name; i++) {
         if (strcmp(GLX_functions[i].Name, funcName) == 0)
@@ -3056,7 +3013,6 @@
        * dynamically added by a driver.  Call __glXRegisterExtensions()
        * to try to make that happen.
        */
-      __glXRegisterExtensions();
       f = (gl_function) get_glx_proc_address((const char *) procName, GL_TRUE);
       return f; /* may be NULL */
    }
@@ -3163,8 +3119,9 @@
      *            GLX_MESA_swap_frame_usage, GLX_OML_swap_method,
      *            GLX_{ARB,SGIS}_multisample, and
      *            GLX_SGIX_visual_select_group.
+     * 20030813 - Made support for dynamic extensions multi-head aware.
      */
-    return 20030317;
+    return 20030813;
 }
 
 
Index: glx/glxext.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/glx/glxext.c,v
retrieving revision 1.28
diff -u -r1.28 glxext.c
--- glx/glxext.c        13 May 2003 13:48:21 -0000      1.28
+++ glx/glxext.c        14 Aug 2003 16:32:37 -0000
@@ -771,22 +771,20 @@
        UnlockDisplay(dpy);
 
 #ifdef GLX_DIRECT_RENDERING
+        /* Initialize per screen dynamic client GLX extensions */
+       psc->ext_list_first_time = GL_TRUE;
        /* Initialize the direct rendering per screen data and functions */
        if (priv->driDisplay.private &&
                priv->driDisplay.createScreen &&
                priv->driDisplay.createScreen[i]) {
-           /* register glx extensions */
-            __DRIdriver *driver = driGetDriver(dpy, i);
-           if (driver && driver->registerExtensionsFunc)
-               (*driver->registerExtensionsFunc)();
            /* screen initialization (bootstrap the driver) */
-
            if ( (psc->old_configs == NULL)
                 && !FillInVisuals(psc) ) {
                FreeScreenConfigs(priv);
                return GL_FALSE;
            }
-                       
+
+           psc->driScreen.screenConfigs = (void *)psc;
            psc->driScreen.private =
                (*(priv->driDisplay.createScreen[i]))(dpy, i, &psc->driScreen,
                                                 psc->numOldConfigs,
@@ -1064,11 +1062,10 @@
 
 /************************************************************************/
 
-#ifdef GLX_DIRECT_RENDERING
-/* Return the DRI per screen structure */
-__DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn)
+/* Return the GLX per screen structure */
+__GLXscreenConfigs *__glXFindGLXScreenConfigs(Display *dpy, int scrn)
 {
-    __DRIscreen *pDRIScreen = NULL;
+    __GLXscreenConfigs *pGLXScreen = NULL;
     XExtDisplayInfo *info = __glXFindDisplay(dpy);
     XExtData **privList, *found;
     __GLXdisplayPrivate *dpyPriv;
@@ -1082,8 +1079,21 @@
 
     if (found) {
        dpyPriv = (__GLXdisplayPrivate *)found->private_data;
-       pDRIScreen = &dpyPriv->screenConfigs[scrn].driScreen;
+       pGLXScreen = &dpyPriv->screenConfigs[scrn];
     }
+
+    return pGLXScreen;
+}
+
+#ifdef GLX_DIRECT_RENDERING
+/* Return the DRI per screen structure */
+__DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn)
+{
+    __DRIscreen *pDRIScreen = NULL;
+    __GLXscreenConfigs *pGLXScreen = __glXFindGLXScreenConfigs(dpy, scrn);
+
+    if (pGLXScreen)
+       pDRIScreen = &pGLXScreen->driScreen;
 
     return pDRIScreen;
 }
Index: glx/glxextensions.c
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/glx/glxextensions.c,v
retrieving revision 1.3
diff -u -r1.3 glxextensions.c
--- glx/glxextensions.c 3 May 2003 05:19:30 -0000       1.3
+++ glx/glxextensions.c 14 Aug 2003 16:32:43 -0000
@@ -116,18 +116,22 @@
    { NULL }
 };
 
+/* global list of available extensions */
 static struct glx_extension  ext_list;
 static GLboolean ext_list_first_time = GL_TRUE;
-static GLuint next_bit = 0;
 
+/* global bit-fields of available extensions and their characteristics */
 static unsigned char client_support[8];
-static unsigned char direct_support[8];
 static unsigned char client_only[8];
 static unsigned char direct_only[8];
+/* extensions enabled by default on all screens */
+static unsigned char direct_support[8];
 
+/* client extensions string */
 static const char * __glXGLXClientExtensions = NULL;
 
 static void __glXExtensionsCtr( void );
+static void __glXExtensionsCtrScreen( __GLXscreenConfigs *psc );
 static void __glXProcessServerString( const char * server_string,
     unsigned char * server_support );
 
@@ -209,53 +213,49 @@
 
 
 /**
- * Enable a named GLX extension.
+ * Enable a named GLX extension on a given screen.
  * 
+ * \param psc   Pointer to GLX per-screen record.
  * \param name  Name of the extension to enable.
- * \param force_client  Enable client-side support also.  If this is set
- *                      to GL_TRUE, then the driver MUST supply function
- *                      entry-points via \c __glXRegisterGLXFunction.
- * \sa __glXRegisterGLXFunction, __glXDisableExtension
+ * \sa __glXDisableExtension
  */
 void
-__glXEnableExtension( const char * name, GLboolean force_client )
+__glXScrEnableExtension( __GLXscreenConfigs *psc, const char * name )
 {
-   if ( __glXGLXClientExtensions == NULL ) {
-      __glXExtensionsCtr();
-      set_glx_extension( name, strlen( name ), GL_TRUE, direct_support );
-      if ( force_client ) {
-        set_glx_extension( name, strlen( name ), GL_TRUE, client_support );
-      }
-   }
+   __glXExtensionsCtr();
+   __glXExtensionsCtrScreen(psc);
+   set_glx_extension( name, strlen( name ), GL_TRUE, psc->direct_support );
 }
 
 
 /**
- * Disable a named GLX extension.
+ * Disable a named GLX extension on a given screen.
  * 
+ * \param psc   Pointer to GLX per-screen record.
  * \param name  Name of the extension to disable.
  * \sa __glXEnableExtension
  */
 void
-__glXDisableExtension( const char * name )
+__glXScrDisableExtension( __GLXscreenConfigs *psc, const char * name )
 {
-   if ( __glXGLXClientExtensions == NULL ) {
-      __glXExtensionsCtr();
-      set_glx_extension( name, strlen( name ), GL_FALSE, direct_support );
-   }
+   __glXExtensionsCtr();
+   __glXExtensionsCtrScreen(psc);
+   set_glx_extension( name, strlen( name ), GL_FALSE, psc->direct_support );
 }
 
 
 /**
  * Add an extension to the global list of known GLX extensions.
  * 
- * \param enabled  Default state of the extension.
- * \param name     Text name of the extension.
- * \param version_major  Major GLX version that requires this extension.
- * \param version_minor  Minor GLX version that requires this extension.
- * \param bit      Bit number in the global table that is set if this
- *                 extension is enabled.
- * \param client_only_flag  Is this extension client-side only?
+ * \param name                 Text name of the extension.
+ * \param version_major        Major GLX version that requires this extension.
+ * \param version_minor        Minor GLX version that requires this extension.
+ * \param bit                  Bit number in the global table that is set if
+ *                             this extension is enabled.
+ * \param client_enabled_flag  Client-side support in libGL present?
+ * \param direct_enabled_flag  Direct-rendering support in DRI driver present?
+ * \param client_only_flag     Is this extension client-side only?
+ * \param direct_only_flag     Is this extension direct-rendering only?
  */
 static void
 add_extension( const char * name, GLuint version_major, GLuint version_minor,
@@ -312,39 +312,9 @@
 }
 
 
-
-
 /**
- * Add a new extension string to the set of possible strings.  This is
- * intended to be used by drivers to advertise support for unlisted,
- * proprietary extensions.
- * 
- * \param enabled      Is the extension enabled by default?
- * \param name         Name of the extension.
- * \param client_only  Is the extension client-side only?
+ * Make sure that global extension support tables are initialized.
  */
-void
-__glXAddExtension( GLboolean enabled, const char * name, 
-                  GLboolean client_only )
-{
-   if ( __glXGLXClientExtensions == NULL ) {
-      GLuint bit;
-
-      __glXExtensionsCtr();
-
-      bit = next_bit;
-      if ( next_bit < 255 ) {
-        next_bit++;
-      }
-
-      add_extension( name, 0, 0, bit, enabled, enabled,
-                    client_only, GL_TRUE );
-   }
-}
-
-
-
-
 static void
 __glXExtensionsCtr( void )
 {
@@ -370,26 +340,41 @@
                        default_glx_extensions[i].direct_support,
                        default_glx_extensions[i].client_only,
                        default_glx_extensions[i].direct_only );
-        if ( default_glx_extensions[i].bit >= next_bit ) {
-           next_bit = default_glx_extensions[i].bit + 1;
-        }
       }
    }
 }
 
 
+/**
+ * Make sure that per-screen direct-support table is initialized.
+ *
+ * \param psc  Pointer to GLX per-screen record.
+ */
+static void
+__glXExtensionsCtrScreen( __GLXscreenConfigs *psc )
+{
+    if (psc->ext_list_first_time) {
+       psc->ext_list_first_time = GL_FALSE;
+       (void) memcpy( psc->direct_support, direct_support, sizeof( direct_support ) );
+    }
+}
 
 
+/**
+ * Check if a certain extension is enabled on a given screen.
+ *
+ * \param psc  Pointer to GLX per-screen record.
+ * \param bit  Bit index in the direct-support table.
+ */
 GLboolean
-__glXExtensionBitIsEnabled( unsigned bit )
+__glXExtensionBitIsEnabled( __GLXscreenConfigs *psc, unsigned bit )
 {
    __glXExtensionsCtr();
-   return EXT_ENABLED( bit, direct_support );
+   __glXExtensionsCtrScreen( psc );
+   return EXT_ENABLED( bit, psc->direct_support );
 }
 
 
-
-
 /**
  * Convert a bit-field to a string of supported extensions.
  */
@@ -448,16 +433,19 @@
 /**
  * Get the list of application usable extensions.
  * 
- * \returns A pointer to the string.
+ * \param psc            Pointer to GLX per-screen record.
+ * \param server_string  Extension string describing server-side support.
+ * \returns              A pointer to the string of usable extensions.
  */
 char *
-__glXGetUsableExtensions( const char * server_string )
+__glXGetUsableExtensions( __GLXscreenConfigs *psc, const char * server_string )
 {
    unsigned char server_support[8];
    unsigned char usable[8];
    unsigned      i;
 
    __glXExtensionsCtr();
+   __glXExtensionsCtrScreen( psc );
    __glXProcessServerString( server_string, server_support );
 
    /* An extension is supported if the client-side (i.e., libGL) supports
@@ -467,8 +455,8 @@
     */
    for ( i = 0 ; i < 8 ; i++ ) {
       usable[i] = (client_support[i] & client_only[i])
-         | (client_support[i] & (direct_support[i] & server_support[i]))
-         | (client_support[i] & (direct_support[i] & direct_only[i]));
+         | (client_support[i] & psc->direct_support[i] & server_support[i])
+         | (client_support[i] & psc->direct_support[i] & direct_only[i]);
    }
 
    return __glXGetStringFromTable( usable );
Index: glx/glxextensions.h
===================================================================
RCS file: /cvsroot/dri/xc/xc/lib/GL/glx/glxextensions.h,v
retrieving revision 1.2
diff -u -r1.2 glxextensions.h
--- glx/glxextensions.h 30 Apr 2003 01:50:35 -0000      1.2
+++ glx/glxextensions.h 14 Aug 2003 16:32:43 -0000
@@ -69,15 +69,19 @@
    SUN_get_transparent_index_bit
 };
 
-extern GLboolean __glXExtensionBitIsEnabled( unsigned bit );
+extern GLboolean __glXExtensionBitIsEnabled( __GLXscreenConfigs *psc, unsigned bit );
 extern const char * __glXGetClientExtensions( void );
-extern char * __glXGetUsableExtensions( const char * server_string );
-extern void __glXAddExtension( GLboolean enabled, const char * name,
-    GLboolean client_side );
-extern void __glXEnableExtension( const char * name, GLboolean force_client );
-extern void __glXDisableExtension( const char * name );
+extern char * __glXGetUsableExtensions( __GLXscreenConfigs *psc, const char * 
server_string );
+extern void __glXScrEnableExtension( __GLXscreenConfigs *psc, const char * name );
+extern void __glXScrDisableExtension( __GLXscreenConfigs *psc, const char * name );
 
-typedef void (* PFNGLXADDEXTENSIONPROC) ( GLboolean enabled, const char * name );
+/* The void pointers here are because __GLXscreenConfigs is opaque for
+ * DRI drivers. */
+typedef void (* PFNGLXSCRENABLEEXTENSIONPROC) ( void *psc, const char * name );
+typedef void (* PFNGLXSCRDISABLEEXTENSIONPROC) ( void *psc, const char * name );
+
+/* Source-level backwards compatibility with old drivers. They won't
+ * find the respective functions, though. */
 typedef void (* PFNGLXENABLEEXTENSIONPROC) ( const char * name,
     GLboolean force_client );
 typedef void (* PFNGLXDISABLEEXTENSIONPROC) ( const char * name );

Reply via email to