* \author Kevin E. Martin <kevin@precisioninsight.com>
*/
-#include "packrender.h"
+#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"
#ifdef GLX_DIRECT_RENDERING
#include <inttypes.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
#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);
* Current context management and locking
*/
-#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+#if defined( USE_XTHREADS )
/* thread safe */
static GLboolean TSDinitialized = GL_FALSE;
/* 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 */
*/
int __glXCloseDisplay(Display *dpy, XExtCodes *codes);
-static GLboolean FillInVisuals( __GLXscreenConfigs * psc );
/************************************************************************/
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 */
}
priv->driDisplay.private = NULL;
#endif
-#ifdef GLX_DIRECT_RENDERING
- XFree(priv->driDisplay.createScreen);
-#endif
-
Xfree((char*) priv);
return 0;
}
}
-/**
- * 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,
}
+/**
+ * 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
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;
err_msg = "XF86DRIOpenConnection";
err_extra = NULL;
+ framebuffer.base = MAP_FAILED;
framebuffer.dev_priv = NULL;
if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
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,
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);
pSAREA,
fd,
api_ver,
+ & interface_methods,
& driver_modes );
filter_modes( & configs->configs,
fb_req->glxCode = X_GLXGetFBConfigs;
fb_req->screen = i;
break;
-
+
case 2:
GetReqExtra(GLXVendorPrivateWithReply,
sz_xGLXGetFBConfigsSGIXReq-sz_xGLXVendorPrivateWithReplyReq,vpreq);
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]) {
& 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
}
XEDataObject dataObj;
int major, minor;
-#if defined(GLX_DIRECT_RENDERING) && defined(XTHREADS)
+#if defined(USE_XTHREADS)
{
static int firstCall = 1;
if (firstCall) {
/* 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 =
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);
_XSend(dpy, (char *)ctx->buf, size);
UnlockDisplay(dpy);
SyncHandle();
+#endif
}
/* Reset pointer and return it */
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);
}
UnlockDisplay(dpy);
SyncHandle();
}
+#endif /* USE_XCB */
}
}
+#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 */
/*
** Make a particular context current.
** NOTE: this is in this file so that it can access dummyContext.
*/
-static Bool MakeContextCurrent(Display *dpy,
- GLXDrawable draw, GLXDrawable read,
- GLXContext gc)
+USED static Bool MakeContextCurrent(Display *dpy, GLXDrawable draw,
+ GLXDrawable read, GLXContext gc)
{
xGLXMakeCurrentReply reply;
GLXContext oldGC;
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;
}
}
} else {
#endif
- _glapi_check_multithread();
/* Send a glXMakeCurrent request to bind the new context. */
LockDisplay(dpy);
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
}
-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 );
}
-GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
+PUBLIC GLX_ALIAS(Bool, glXMakeCurrentReadSGI,
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
(dpy, d, r, ctx), MakeContextCurrent)
-GLX_ALIAS(Bool, glXMakeContextCurrent,
+PUBLIC GLX_ALIAS(Bool, glXMakeContextCurrent,
(Display *dpy, GLXDrawable d, GLXDrawable r, GLXContext ctx),
(dpy, d, r, ctx), MakeContextCurrent)