Fix Windows build problems.
[mesa.git] / src / glx / x11 / glxext.c
index c24e22ff4f81c52a4653d3d7095561dfa65ebbbe..eb6e870e9840a3a1b522b78585dc628d48dce0ef 100644 (file)
 
 #include "glxclient.h"
 #include <stdio.h>
-#include <Xext.h>
-#include <extutil.h>
+#include <X11/extensions/Xext.h>
+#include <X11/extensions/extutil.h>
 #include <assert.h>
 #include "indirect_init.h"
 #include "glapi.h"
-#ifdef XTHREADS
-#include "Xthreads.h"
-#endif
 #include "glxextensions.h"
 #include "glcontextmodes.h"
 #include "glheader.h"
 #include "dri_glx.h"
 #endif
 
+#ifdef USE_XCB
+#include <X11/xcl.h>
+#include <X11/XCB/xcb.h>
+#include <X11/XCB/glx.h>
+#endif
+
 #include <assert.h>
 
 #ifdef DEBUG
@@ -103,6 +106,10 @@ static int _mesa_sparc_needs_init = 1;
 #define INIT_MESA_SPARC
 #endif
 
+#ifdef GLX_DIRECT_RENDERING
+static __DRIscreen *__glXFindDRIScreen(__DRInativeDisplay *dpy, int scrn);
+#endif /* GLX_DIRECT_RENDERING */
+
 static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
     GLXDrawable read, GLXContext gc);
 
@@ -138,7 +145,7 @@ static __GLapi *IndirectAPI = NULL;
  * Current context management and locking
  */
 
-#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+#if defined( USE_XTHREADS )
 
 /* thread safe */
 static GLboolean TSDinitialized = GL_FALSE;
@@ -174,6 +181,77 @@ void __glXSetCurrentContext(__GLXcontext *c)
 /* Used by the __glXLock() and __glXUnlock() macros */
 xmutex_rec __glXmutex;
 
+#elif defined( PTHREADS )
+
+pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER;
+
+# if defined( GLX_USE_TLS )
+
+/**
+ * Per-thread GLX context pointer.
+ * 
+ * \c __glXSetCurrentContext is written is such a way that this pointer can
+ * \b never be \c NULL.  This is important!  Because of this
+ * \c __glXGetCurrentContext can be implemented as trivial macro.
+ */
+__thread void * __glX_tls_Context __attribute__((tls_model("initial-exec")))
+    = &dummyContext;
+
+void __glXSetCurrentContext( __GLXcontext * c )
+{
+    __glX_tls_Context = (c != NULL) ? c : &dummyContext;
+}
+
+# else
+
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+/**
+ * Per-thread data key.
+ * 
+ * Once \c init_thread_data has been called, the per-thread data key will
+ * take a value of \c NULL.  As each new thread is created the default
+ * value, in that thread, will be \c NULL.
+ */
+static pthread_key_t ContextTSD;
+
+/**
+ * Initialize the per-thread data key.
+ * 
+ * This function is called \b exactly once per-process (not per-thread!) to
+ * initialize the per-thread data key.  This is ideally done using the
+ * \c pthread_once mechanism.
+ */
+static void init_thread_data( void )
+{
+    if ( pthread_key_create( & ContextTSD, NULL ) != 0 ) {
+       perror( "pthread_key_create" );
+       exit( -1 );
+    }
+}
+
+void __glXSetCurrentContext( __GLXcontext * c )
+{
+    pthread_once( & once_control, init_thread_data );
+    pthread_setspecific( ContextTSD, c );
+}
+
+__GLXcontext * __glXGetCurrentContext( void )
+{
+    void * v;
+
+    pthread_once( & once_control, init_thread_data );
+
+    v = pthread_getspecific( ContextTSD );
+    return (v == NULL) ? & dummyContext : (__GLXcontext *) v;
+}
+
+# endif /* defined( GLX_USE_TLS ) */
+
+#elif defined( THREADS )
+
+#error Unknown threading method specified.
+
 #else
 
 /* not thread safe */
@@ -193,7 +271,6 @@ int __glXDebug = 0;
 */
 int __glXCloseDisplay(Display *dpy, XExtCodes *codes);
 
-static GLboolean FillInVisuals( __GLXscreenConfigs * psc );
 
 /************************************************************************/
 
@@ -273,12 +350,6 @@ static void FreeScreenConfigs(__GLXdisplayPrivate *priv)
            if(psc->effectiveGLXexts)
                Xfree(psc->effectiveGLXexts);
 
-           if ( psc->old_configs != NULL ) {
-               Xfree( psc->old_configs );
-               psc->old_configs = NULL;
-               psc->numOldConfigs = 0;
-           }
-
            psc->configs = NULL;        /* NOTE: just for paranoia */
        }
 
@@ -320,10 +391,6 @@ static int __glXFreeDisplayPrivate(XExtData *extension)
     priv->driDisplay.private = NULL;
 #endif
 
-#ifdef GLX_DIRECT_RENDERING
-    XFree(priv->driDisplay.createScreen);
-#endif
-
     Xfree((char*) priv);
     return 0;
 }
@@ -363,112 +430,6 @@ static Bool QueryVersion(Display *dpy, int opcode, int *major, int *minor)
 }
 
 
-/**
- * Determine if a \c __GLcontextModes structure has the right mojo to be
- * converted to a \c __GLXvisualConfig to be sent to an "old" style DRI
- * driver.
- */
-#define MODE_HAS_MOJO(m) \
-    ((m)->visualID != GLX_DONT_CARE) \
-       && ((m)->sampleBuffers == 0) \
-       && ((m)->samples == 0) \
-       && (((m)->drawableType & GLX_WINDOW_BIT) != 0) \
-       && (((m)->xRenderable == GL_TRUE) \
-           || ((m)->xRenderable == GLX_DONT_CARE))
-
-
-/**
- * Convert the FBConfigs associated with a screen into an array of
- * \c __GLXvisualConfig structures.  These structures are passed into DRI
- * drivers that use the "old" interface.  The old-style drivers had a fairly
- * strict set of visual types that could be supported.  FBConfigs that
- * cannot be supported are not converted.
- *
- * \param psc  Screen whose FBConfigs need to be swizzled.
- *
- * \returns 
- * If memory could be allocated and at least one FBConfig could be converted
- * to a \c __GLXvisualConfig structure, \c GL_TRUE is returned.  Otherwise,
- * \c GL_FALSE is returned.
- *
- * \todo
- * When the old DRI driver interface is no longer supported, this function
- * can be removed.
- */
-static GLboolean
-FillInVisuals( __GLXscreenConfigs * psc )
-{
-    __GLcontextModes *modes;
-    int glx_visual_count;
-
-
-    glx_visual_count = 0;
-    for ( modes = psc->configs ; modes != NULL ; modes = modes->next ) {
-       if ( MODE_HAS_MOJO( modes ) ) {
-           glx_visual_count++;
-       }
-    }
-
-    psc->old_configs = (__GLXvisualConfig *)
-       Xmalloc( sizeof( __GLXvisualConfig ) * glx_visual_count );
-    if ( psc->old_configs == NULL ) {
-       return GL_FALSE;
-    }
-
-    glx_visual_count = 0;
-    for ( modes = psc->configs ; modes != NULL ; modes = modes->next ) {
-       if ( MODE_HAS_MOJO( modes ) ) {
-
-#define COPY_VALUE(src_tag,dst_tag) \
-    psc->old_configs[glx_visual_count]. dst_tag = modes-> src_tag
-
-           COPY_VALUE( visualID,  vid );
-           COPY_VALUE( rgbMode,   rgba );
-           COPY_VALUE( stereoMode, stereo );
-           COPY_VALUE( doubleBufferMode, doubleBuffer );
-
-           psc->old_configs[glx_visual_count].class = 
-               _gl_convert_to_x_visual_type( modes->visualType );
-
-           COPY_VALUE( level, level );
-           COPY_VALUE( numAuxBuffers, auxBuffers );
-
-           COPY_VALUE( redBits,        redSize );
-           COPY_VALUE( greenBits,      greenSize );
-           COPY_VALUE( blueBits,       blueSize );
-           COPY_VALUE( alphaBits,      alphaSize );
-           COPY_VALUE( rgbBits,        bufferSize );
-           COPY_VALUE( accumRedBits,   accumRedSize );
-           COPY_VALUE( accumGreenBits, accumGreenSize );
-           COPY_VALUE( accumBlueBits,  accumBlueSize );
-           COPY_VALUE( accumAlphaBits, accumAlphaSize );
-           COPY_VALUE( depthBits,      depthSize );
-           COPY_VALUE( stencilBits,    stencilSize );
-
-           COPY_VALUE( visualRating, visualRating );
-           COPY_VALUE( transparentPixel, transparentPixel );
-           COPY_VALUE( transparentRed,   transparentRed );
-           COPY_VALUE( transparentGreen, transparentGreen );
-           COPY_VALUE( transparentBlue,  transparentBlue );
-           COPY_VALUE( transparentAlpha, transparentAlpha );
-           COPY_VALUE( transparentIndex, transparentIndex );
-
-#undef COPY_VALUE
-
-           glx_visual_count++;
-       }
-    }
-
-    psc->numOldConfigs = glx_visual_count;
-    if ( glx_visual_count == 0 ) {
-       Xfree( psc->old_configs );
-       psc->old_configs = NULL;
-    }
-
-    return (glx_visual_count != 0);
-}
-
-
 void 
 __glXInitializeVisualConfigFromTags( __GLcontextModes *config, int count, 
                                     const INT32 *bp, Bool tagged_only,
@@ -705,6 +666,42 @@ filter_modes( __GLcontextModes ** server_modes,
 }
 
 
+/**
+ * Implement \c __DRIinterfaceMethods::getProcAddress.
+ */
+static __DRIfuncPtr get_proc_address( const char * proc_name )
+{
+    if (strcmp( proc_name, "glxEnableExtension" ) == 0) {
+       return (__DRIfuncPtr) __glXScrEnableExtension;
+    }
+    
+    return NULL;
+}
+
+
+/**
+ * Table of functions exported by the loader to the driver.
+ */
+static const __DRIinterfaceMethods interface_methods = {
+    get_proc_address,
+
+    _gl_context_modes_create,
+    _gl_context_modes_destroy,
+      
+    __glXFindDRIScreen,
+    __glXWindowExists,
+      
+    XF86DRICreateContextWithConfig,
+    XF86DRIDestroyContext,
+
+    XF86DRICreateDrawable,
+    XF86DRIDestroyDrawable,
+    XF86DRIGetDrawableInfo,
+
+    __glXGetUST,
+    glXGetMscRateOML,
+};
+
 
 /**
  * Perform the required libGL-side initialization and call the client-side
@@ -726,12 +723,12 @@ filter_modes( __GLcontextModes ** server_modes,
 static void *
 CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
                    __DRIdisplay * driDpy,
-                   CreateNewScreenFunc createNewScreen)
+                   PFNCREATENEWSCREENFUNC createNewScreen)
 {
     __DRIscreenPrivate *psp = NULL;
 #ifndef GLX_USE_APPLEGL
     drm_handle_t hSAREA;
-    drmAddress pSAREA;
+    drmAddress pSAREA = MAP_FAILED;
     char *BusID;
     __DRIversion   ddx_version;
     __DRIversion   dri_version;
@@ -752,6 +749,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
     err_msg = "XF86DRIOpenConnection";
     err_extra = NULL;
 
+    framebuffer.base = MAP_FAILED;
     framebuffer.dev_priv = NULL;
 
     if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
@@ -786,9 +784,9 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
                    char *driverName;
 
                    /*
-                    * Get device name (like "tdfx") and the ddx version numbers.
-                    * We'll check the version in each DRI driver's "createScreen"
-                    * function.
+                    * Get device name (like "tdfx") and the ddx version
+                    * numbers.  We'll check the version in each DRI driver's
+                    * "createNewScreen" function.
                     */
                    err_msg = "XF86DRIGetClientDriverName";
                    if (XF86DRIGetClientDriverName(dpy, scrn,
@@ -831,8 +829,9 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
 
                            if ( status == 0 ) {
                                /*
-                                * Map the SAREA region.  Further mmap regions may be setup in
-                                * each DRI driver's "createScreen" function.
+                                * Map the SAREA region.  Further mmap regions
+                                * may be setup in each DRI driver's
+                                * "createNewScreen" function.
                                 */
                                status = drmMap(fd, hSAREA, SAREA_MAX, 
                                                &pSAREA);
@@ -856,6 +855,7 @@ CallCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
                                                             pSAREA,
                                                             fd,
                                                             api_ver,
+                                                            & interface_methods,
                                                             & driver_modes );
 
                                    filter_modes( & configs->configs,
@@ -974,7 +974,7 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
            fb_req->glxCode = X_GLXGetFBConfigs;
            fb_req->screen = i;
            break;
-           
+          
            case 2:
            GetReqExtra(GLXVendorPrivateWithReply,
                        sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
@@ -1077,6 +1077,9 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
        psc->ext_list_first_time = GL_TRUE;
        /* Initialize the direct rendering per screen data and functions */
        if (priv->driDisplay.private != NULL) {
+           /* FIXME: Should it be some sort of an error if createNewScreen[i]
+            * FIXME: is NULL?
+            */
            if (priv->driDisplay.createNewScreen &&
                priv->driDisplay.createNewScreen[i]) {
 
@@ -1086,21 +1089,6 @@ static Bool AllocAndFetchScreenConfigs(Display *dpy, __GLXdisplayPrivate *priv)
                                        & priv->driDisplay,
                                        priv->driDisplay.createNewScreen[i] );
            }
-           else if (priv->driDisplay.createScreen &&
-                    priv->driDisplay.createScreen[i]) {
-               /* 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,
-                                                         psc->old_configs);
-           }
        }
 #endif
     }
@@ -1119,7 +1107,7 @@ __GLXdisplayPrivate *__glXInitialize(Display* dpy)
     XEDataObject dataObj;
     int major, minor;
 
-#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+#if defined(USE_XTHREADS)
     {
         static int firstCall = 1;
         if (firstCall) {
@@ -1194,7 +1182,6 @@ __GLXdisplayPrivate *__glXInitialize(Display* dpy)
         /* Assinging zero here assures we'll never go direct */
         dpyPriv->driDisplay.private = 0;
         dpyPriv->driDisplay.destroyDisplay = 0;
-        dpyPriv->driDisplay.createScreen = 0;
     }
     else {
         dpyPriv->driDisplay.private =
@@ -1263,23 +1250,30 @@ CARD8 __glXSetupForCommand(Display *dpy)
     return priv->majorOpcode;
 }
 
-/*
-** Flush the drawing command transport buffer.
-*/
+/**
+ * Flush the drawing command transport buffer.
+ * 
+ * \param ctx  Context whose transport buffer is to be flushed.
+ * \param pc   Pointer to first unused buffer location.
+ * 
+ * \todo
+ * Modify this function to use \c ctx->pc instead of the explicit
+ * \c pc parameter.
+ */
 GLubyte *__glXFlushRenderBuffer(__GLXcontext *ctx, GLubyte *pc)
 {
-    Display *dpy;
+    Display * const dpy = ctx->currentDpy;
+#ifdef USE_XCB
+    XCBConnection *c = XCBConnectionOfDisplay(dpy);
+#else
     xGLXRenderReq *req;
-    GLint size;
+#endif /* USE_XCB */
+    const GLint size = pc - ctx->buf;
 
-    if (!(dpy = ctx->currentDpy)) {
-       /* Using the dummy context */
-       ctx->pc = ctx->buf;
-       return ctx->pc;
-    }
-
-    size = pc - ctx->buf;
-    if (size) {
+    if ( (dpy != NULL) && (size > 0) ) {
+#ifdef USE_XCB
+       XCBGlxRender(c, ctx->currentContextTag, size, (char *)ctx->buf);
+#else
        /* Send the entire buffer as an X request */
        LockDisplay(dpy);
        GetReq(GLXRender,req); 
@@ -1290,6 +1284,7 @@ GLubyte *__glXFlushRenderBuffer(__GLXcontext *ctx, GLubyte *pc)
        _XSend(dpy, (char *)ctx->buf, size);
        UnlockDisplay(dpy);
        SyncHandle();
+#endif
     }
 
     /* Reset pointer and return it */
@@ -1319,8 +1314,12 @@ void __glXSendLargeChunk(__GLXcontext *gc, GLint requestNumber,
                         const GLvoid * data, GLint dataLen)
 {
     Display *dpy = gc->currentDpy;
+#ifdef USE_XCB
+    XCBConnection *c = XCBConnectionOfDisplay(dpy);
+    XCBGlxRenderLarge(c, gc->currentContextTag, requestNumber, totalRequests, dataLen, data);
+#else
     xGLXRenderLargeReq *req;
-
+    
     if ( requestNumber == 1 ) {
        LockDisplay(dpy);
     }
@@ -1339,6 +1338,7 @@ void __glXSendLargeChunk(__GLXcontext *gc, GLint requestNumber,
        UnlockDisplay(dpy);
        SyncHandle();
     }
+#endif /* USE_XCB */
 }
 
 
@@ -1515,42 +1515,23 @@ static Bool SendMakeCurrentRequest( Display *dpy, CARD8 opcode,
 }
 
 
+#ifdef GLX_DIRECT_RENDERING
 static Bool BindContextWrapper( Display *dpy, GLXContext gc,
                                GLXDrawable draw, GLXDrawable read )
 {
-#ifdef GLX_DIRECT_RENDERING
-    if ( gc->driContext.bindContext3 != NULL ) {
-       return (*gc->driContext.bindContext3)(dpy, gc->screen, draw, read, 
-                                             & gc->driContext);
-    }
-    else {
-       return (*gc->driContext.bindContext2)(dpy, gc->screen, draw, read,
-                                             gc);
-    }
-#else
-    return GL_FALSE;
-#endif
+    return (*gc->driContext.bindContext)(dpy, gc->screen, draw, read,
+                                        & gc->driContext);
 }
 
 
-static Bool UnbindContextWrapper( Display *dpy, GLXContext gc )
+static Bool UnbindContextWrapper( GLXContext gc )
 {
-#ifdef GLX_DIRECT_RENDERING
-    if ( gc->driContext.unbindContext3 != NULL ) {
-       return (*gc->driContext.unbindContext3)(dpy, gc->screen, 
-                                               gc->currentDrawable,
-                                               gc->currentReadable,
-                                               & gc->driContext );
-    }
-    else {
-       return (*gc->driContext.unbindContext2)(dpy, gc->screen,
-                                               gc->currentDrawable,
-                                               gc->currentReadable, gc);
-    }
-#else
-    return GL_FALSE;
-#endif
+    return (*gc->driContext.unbindContext)(gc->currentDpy, gc->screen, 
+                                          gc->currentDrawable,
+                                          gc->currentReadable,
+                                          & gc->driContext );
 }
+#endif /* GLX_DIRECT_RENDERING */
 
 
 /*
@@ -1608,12 +1589,14 @@ USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
 
        oldGC->currentContextTag = 0;
     }
-    
+
+    _glapi_check_multithread();
+
 #ifdef GLX_DIRECT_RENDERING
     /* Unbind the old direct rendering context */
     if (oldGC->isDirect) {
        if (oldGC->driContext.private) {
-           if (! UnbindContextWrapper( oldGC->currentDpy, oldGC )) {
+           if (! UnbindContextWrapper( oldGC )) {
                /* The make current failed.  Just return GL_FALSE. */
                return GL_FALSE;
            }
@@ -1628,7 +1611,6 @@ USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
        }
     } else {
 #endif
-        _glapi_check_multithread();
        /* Send a glXMakeCurrent request to bind the new context. */
        LockDisplay(dpy);
 
@@ -1759,10 +1741,20 @@ USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
            gc->currentDpy = dpy;
            gc->currentDrawable = draw;
            gc->currentReadable = read;
-#ifdef GLX_DIRECT_RENDERING
-           if (gc->isDirect) reply.contextTag = -1;
-#endif
-           gc->currentContextTag = reply.contextTag;
+
+           if ( ! gc->isDirect ) {
+               __GLXattribute * state = (__GLXattribute *)(gc->client_state_private);
+
+               gc->currentContextTag = reply.contextTag;
+               if ( state->array_state == NULL ) {
+                   (void) glGetString( GL_EXTENSIONS );
+                   (void) glGetString( GL_VERSION );
+                   __glXInitVertexArrayState(gc);
+               }
+           }
+           else {
+               gc->currentContextTag = -1;
+           }
        } else {
            __glXSetCurrentContext(&dummyContext);
 #ifdef GLX_DIRECT_RENDERING
@@ -1775,8 +1767,7 @@ USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
 }
 
 
-PUBLIC Bool GLX_PREFIX(glXMakeCurrent)(Display *dpy, GLXDrawable draw,
-                                       GLXContext gc)
+PUBLIC Bool glXMakeCurrent(Display *dpy, GLXDrawable draw, GLXContext gc)
 {
     return MakeContextCurrent( dpy, draw, draw, gc );
 }