瀏覽代碼

Remove _glapi_check_multithread from the interface exported by the loader to

the driver.  The loader now takes care of this for the driver.

Remove _glapi_DispatchTSD and give _glapi_Dispatch its semantic (i.e.,
having a NULL value means that the application is multithreaded and
_glapi_get_dispatch must be called).

Gut all of the dispatch override code.  This removes _glapi_RealDispatch,
_glapi_tls_RealDispatch, _glapi_begin_dispatch_override,
_glapi_end_dispatch_override, and _glapi_get_override_dispatch.

Remove _glapi_get_proc_address, _glapi_get_proc_name, _glapi_get_version,
and _glapi_check_table from the loader / driver interface.

Reviewed by: Brian Paul
tags/mesa_6_3_2
Ian Romanick 20 年之前
父節點
當前提交
967b006f51

+ 3
- 2
src/glx/x11/glxext.c 查看文件

@@ -1589,7 +1589,9 @@ 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) {
@@ -1609,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);


+ 1
- 1
src/mesa/glapi/gl_x86-64_asm.py 查看文件

@@ -245,7 +245,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
print '\tjmp\t*%r11'

print '#else'
print '\tmovq\t_glapi_DispatchTSD(%rip), %rax'
print '\tmovq\t_glapi_Dispatch(%rip), %rax'
print '\ttestq\t%rax, %rax'
print '\tje\t1f'
print '\tmovq\t%u(%%rax), %%r11' % (f.offset * 8)

+ 2
- 2
src/mesa/glapi/gl_x86_asm.py 查看文件

@@ -105,7 +105,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
print 'ALIGNTEXT16;\t\t\t\t\t\t\\'
print 'GLOBL_FN(GL_PREFIX(fn, fn_alt));\t\t\t\\'
print 'GL_PREFIX(fn, fn_alt):\t\t\t\t\t\\'
print '\tMOV_L(CONTENT(GLNAME(_glapi_DispatchTSD)), EAX) ;\t\\'
print '\tMOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) ;\t\\'
print '\tTEST_L(EAX, EAX) ;\t\t\t\t\\'
print '\tJE(1f) ;\t\t\t\t\t\\'
print '\tJMP(GL_OFFSET(off)) ;\t\t\t\t\\'
@@ -116,7 +116,7 @@ class PrintGenericStubs(gl_XML.gl_print_base):
print 'ALIGNTEXT16;\t\t\t\t\t\t\\'
print 'GLOBL_FN(GL_PREFIX(fn, fn_alt));\t\t\t\\'
print 'GL_PREFIX(fn, fn_alt):\t\t\t\t\t\\'
print '\tMOV_L(CONTENT(GLNAME(_glapi_DispatchTSD)), EAX) ;\t\\'
print '\tMOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) ;\t\\'
print '\tTEST_L(EAX, EAX) ;\t\t\t\t\\'
print '\tJE(1f) ;\t\t\t\t\t\\'
print '\tJMP(GL_OFFSET(off)) ;\t\t\t\t\\'

+ 57
- 262
src/mesa/glapi/glapi.c 查看文件

@@ -133,122 +133,65 @@ static GLint NoOpUnused(void)



/***** BEGIN THREAD-SAFE DISPATCH *****/

#if defined(THREADS)

/**
* \name Current dispatch and current context control variables
*
* Depending on whether or not multithreading is support, and the type of
* support available, several variables are used to store the current context
* pointer and the current dispatch table pointer. In the non-threaded case,
* the variables \c _glapi_Dispatch and \c _glapi_Context are used for this
* purpose.
*
* In the "normal" threaded case, the variables \c _glapi_Dispatch and
* \c _glapi_Context will be \c NULL if an application is detected as being
* multithreaded. Single-threaded applications will use \c _glapi_Dispatch
* and \c _glapi_Context just like the case without any threading support.
* When \c _glapi_Dispatch and \c _glapi_Context are \c NULL, the thread state
* data \c _gl_DispatchTSD and \c ContextTSD are used. Drivers and the
* static dispatch functions access these variables via \c _glapi_get_dispatch
* and \c _glapi_get_context.
*
* There is a race condition in setting \c _glapi_Dispatch to \c NULL. It is
* possible for the original thread to be setting it at the same instant a new
* thread, perhaps running on a different processor, is clearing it. Because
* of that, \c ThreadSafe, which can only ever be changed to \c GL_TRUE, is
* used to determine whether or not the application is multithreaded.
*
* In the TLS case, the variables \c _glapi_Dispatch and \c _glapi_Context are
* hardcoded to \c NULL. Instead the TLS variables \c _glapi_tls_Dispatch and
* \c _glapi_tls_Context are used. Having \c _glapi_Dispatch and
* \c _glapi_Context be hardcoded to \c NULL maintains binary compatability
* between TLS enabled loaders and non-TLS DRI drivers.
*/
/*@{*/
#if defined(GLX_USE_TLS)

__thread struct _glapi_table * _glapi_tls_Dispatch
__attribute__((tls_model("initial-exec")))
= (struct _glapi_table *) __glapi_noop_table;

static __thread struct _glapi_table * _glapi_tls_RealDispatch
PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch
__attribute__((tls_model("initial-exec")))
= (struct _glapi_table *) __glapi_noop_table;

__thread void * _glapi_tls_Context
PUBLIC __thread void * _glapi_tls_Context
__attribute__((tls_model("initial-exec")));

/**
* Legacy per-thread dispatch pointer. This is only needed to support
* non-TLS DRI drivers.
*/

_glthread_TSD _gl_DispatchTSD;
PUBLIC const struct _glapi_table *_glapi_Dispatch = NULL;
PUBLIC const void *_glapi_Context = NULL;

#else

/**
* \name Multi-threaded control support variables
*
* If thread-safety is supported, there are two potential mechanisms that can
* be used. The old-style mechanism would set \c _glapi_Dispatch to a special
* thread-safe dispatch table. These dispatch routines would call
* \c _glapi_get_dispatch to get the actual dispatch pointer. In this
* setup \c _glapi_Dispatch could never be \c NULL. This dual layered
* dispatch setup performed great for single-threaded apps, but didn't
* perform well for multithreaded apps.
*
* In the new mechansim, there are two variables. The first is
* \c _glapi_DispatchTSD. In the single-threaded case, this variable points
* to the dispatch table. In the multi-threaded case, this variable is
* \c NULL, and thread-specific variable \c _gl_DispatchTSD points to the
* actual dispatch table. \c _glapi_DispatchTSD is used to signal to the
* static dispatch functions to call \c _glapi_get_dispatch to get the real
* dispatch table.
*
* There is a race condition in setting \c _glapi_DispatchTSD to \c NULL.
* It is possible for the original thread to be setting it at the same instant
* a new thread, perhaps running on a different processor, is clearing it.
* Because of that, \c ThreadSafe, which can only ever be changed to
* \c GL_TRUE, is used to determine whether or not the application is
* multithreaded.
*/
/*@{*/
#if defined(THREADS)

static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
static _glthread_TSD RealDispatchTSD; /**< only when using override */
static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
/*@}*/

#endif /* defined(GLX_USE_TLS) */

#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
#define UNUSED_TABLE_NAME __unused_threadsafe_functions

#define TABLE_ENTRY(name) (_glapi_proc) gl##name

static GLint glUnused(void)
{
return 0;
}

#include "glapitemp.h"

#endif

/***** END THREAD-SAFE DISPATCH *****/


#if defined(GLX_USE_TLS)

/**
* \name Old dispatch pointers
*
* Very old DRI based drivers assume that \c _glapi_Dispatch will never be
* \c NULL. Becuase of that, special "thread-safe" dispatch functions are
* needed here. Slightly more recent drivers detect the multi-threaded case
* by \c _glapi_DispatchTSD being \c NULL.
*
* \deprecated
*
* \warning
* \c _glapi_RealDispatch does not exist in TLS builds. I don't think it was
* ever used outside libGL.so, so this should be safe.
*/
/*@{*/
PUBLIC const struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
PUBLIC const struct _glapi_table *_glapi_DispatchTSD = NULL;
PUBLIC const void *_glapi_Context = NULL;
/*@}*/
#endif /* defined(THREADS) */

#else

PUBLIC struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
#if defined( THREADS )
PUBLIC struct _glapi_table *_glapi_DispatchTSD = (struct _glapi_table *) __glapi_noop_table;
#endif
PUBLIC struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;

/* Used when thread safety disabled */
PUBLIC struct _glapi_table *_glapi_Dispatch =
(struct _glapi_table *) __glapi_noop_table;
PUBLIC void *_glapi_Context = NULL;

#endif /* defined(GLX_USE_TLS) */


static GLboolean DispatchOverride = GL_FALSE;

/*@}*/


/**
@@ -272,7 +215,7 @@ str_dup(const char *str)
* We should call this periodically from a function such as glXMakeCurrent
* in order to test if multiple threads are being used.
*/
PUBLIC void
void
_glapi_check_multithread(void)
{
#if defined(THREADS) && !defined(GLX_USE_TLS)
@@ -309,7 +252,6 @@ _glapi_set_context(void *context)
#if defined(GLX_USE_TLS)
_glapi_tls_Context = context;
#elif defined(THREADS)
(void) __unused_threadsafe_functions; /* silence a warning */
_glthread_SetTSD(&ContextTSD, context);
_glapi_Context = (ThreadSafe) ? NULL : context;
#else
@@ -367,40 +309,12 @@ _glapi_set_dispatch(struct _glapi_table *dispatch)
#endif

#if defined(GLX_USE_TLS)
if (DispatchOverride) {
_glapi_tls_RealDispatch = dispatch;
}
else {
_glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
_glapi_tls_Dispatch = dispatch;
}
_glapi_tls_Dispatch = dispatch;
#elif defined(THREADS)
if (DispatchOverride) {
_glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
if (ThreadSafe)
_glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
else
_glapi_RealDispatch = dispatch;
}
else {
/* normal operation */
_glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
if (ThreadSafe) {
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
_glapi_DispatchTSD = NULL;
}
else {
_glapi_Dispatch = dispatch;
_glapi_DispatchTSD = dispatch;
}
}
_glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
_glapi_Dispatch = (ThreadSafe) ? NULL : dispatch;
#else /*THREADS*/
if (DispatchOverride) {
_glapi_RealDispatch = dispatch;
}
else {
_glapi_Dispatch = dispatch;
}
_glapi_Dispatch = dispatch;
#endif /*THREADS*/
}

@@ -412,128 +326,20 @@ _glapi_set_dispatch(struct _glapi_table *dispatch)
PUBLIC struct _glapi_table *
_glapi_get_dispatch(void)
{
#if defined(GLX_USE_TLS)
struct _glapi_table * api = (DispatchOverride)
? _glapi_tls_RealDispatch : _glapi_tls_Dispatch;

assert( api != NULL );
return api;
#elif defined(THREADS)
if (ThreadSafe) {
if (DispatchOverride) {
return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
}
else {
return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
}
}
else {
if (DispatchOverride) {
assert(_glapi_RealDispatch);
return _glapi_RealDispatch;
}
else {
assert(_glapi_DispatchTSD);
return _glapi_DispatchTSD;
}
}
#else
return _glapi_Dispatch;
#endif
}


/*
* Notes on dispatch overrride:
*
* Dispatch override allows an external agent to hook into the GL dispatch
* mechanism before execution goes into the core rendering library. For
* example, a trace mechanism would insert itself as an overrider, print
* logging info for each GL function, then dispatch to the real GL function.
*
* libGLS (GL Stream library) is another agent that might use override.
*
* We don't allow more than one layer of overriding at this time.
* In the future we may allow nested/layered override. In that case
* _glapi_begin_dispatch_override() will return an override layer,
* _glapi_end_dispatch_override(layer) will remove an override layer
* and _glapi_get_override_dispatch(layer) will return the dispatch
* table for a given override layer. layer = 0 will be the "real"
* dispatch table.
*/

/*
* Return: dispatch override layer number.
*/
PUBLIC int
_glapi_begin_dispatch_override(struct _glapi_table *override)
{
struct _glapi_table *real = _glapi_get_dispatch();

assert(!DispatchOverride); /* can't nest at this time */
DispatchOverride = GL_TRUE;

_glapi_set_dispatch(real);
struct _glapi_table * api;

#if defined(GLX_USE_TLS)
_glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
_glapi_tls_Dispatch = override;
api = _glapi_tls_Dispatch;
#elif defined(THREADS)
_glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
if ( ThreadSafe ) {
_glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
_glapi_DispatchTSD = NULL;
}
else {
_glapi_Dispatch = override;
_glapi_DispatchTSD = override;
}
api = (ThreadSafe)
? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD)
: _glapi_Dispatch;
#else
_glapi_Dispatch = override;
api = _glapi_Dispatch;
#endif
return 1;
}


PUBLIC void
_glapi_end_dispatch_override(int layer)
{
struct _glapi_table *real = _glapi_get_dispatch();
(void) layer;
DispatchOverride = GL_FALSE;
_glapi_set_dispatch(real);
/* the rest of this isn't needed, just play it safe */
#if defined(GLX_USE_TLS)
_glapi_tls_RealDispatch = NULL;
#else
# if defined(THREADS)
_glthread_SetTSD(&RealDispatchTSD, NULL);
# endif
_glapi_RealDispatch = NULL;
#endif
}


PUBLIC struct _glapi_table *
_glapi_get_override_dispatch(int layer)
{
if (layer == 0) {
return _glapi_get_dispatch();
}
else {
if (DispatchOverride) {
#if defined(GLX_USE_TLS)
return (struct _glapi_table *) _glapi_tls_Dispatch;
#elif defined(THREADS)
return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
#else
return _glapi_Dispatch;
#endif
}
else {
return NULL;
}
}
assert( api != NULL );
return api;
}


@@ -1063,7 +869,7 @@ _glapi_get_proc_offset(const char *funcName)
* in the name of static functions, try generating a new API entrypoint on
* the fly with assembly language.
*/
PUBLIC _glapi_proc
_glapi_proc
_glapi_get_proc_address(const char *funcName)
{
struct _glapi_function * entry;
@@ -1101,7 +907,7 @@ _glapi_get_proc_address(const char *funcName)
* Return the name of the function at the given dispatch offset.
* This is only intended for debugging.
*/
PUBLIC const char *
const char *
_glapi_get_proc_name(GLuint offset)
{
GLuint i;
@@ -1136,22 +942,11 @@ _glapi_get_dispatch_table_size(void)



/**
* Get API dispatcher version string.
*/
PUBLIC const char *
_glapi_get_version(void)
{
return "20021001"; /* YYYYMMDD */
}



/**
* Make sure there are no NULL pointers in the given dispatch table.
* Intended for debugging purposes.
*/
PUBLIC void
void
_glapi_check_table(const struct _glapi_table *table)
{
#ifdef DEBUG

+ 0
- 4
src/mesa/glapi/glapi.h 查看文件

@@ -129,10 +129,6 @@ extern GLuint
_glapi_get_dispatch_table_size(void);


extern const char *
_glapi_get_version(void);


extern void
_glapi_check_table(const struct _glapi_table *table);


+ 2
- 17
src/mesa/glapi/glthread.h 查看文件

@@ -110,20 +110,6 @@ typedef pthread_mutex_t _glthread_Mutex;
#define _glthread_UNLOCK_MUTEX(name) \
(void) pthread_mutex_unlock(&(name))

/* This is temporarilly removed because driver binaries cannot count on
* the existance of _gl_DispatchTSD in libGL. It only exists in "new"
* libGL. We may be able to ressurect this optimization at some point
* for DRI driver or for software Mesa.
*/
#if 0
extern struct _glapi_table * _glapi_DispatchTSD;
extern _glthread_TSD _gl_DispatchTSD;

#define GET_DISPATCH() \
((__builtin_expect( _glapi_DispatchTSD != NULL, 1 )) \
? _glapi_DispatchTSD : (struct _glapi_table *) pthread_getspecific(_gl_DispatchTSD.key))
#endif

#endif /* PTHREADS */


@@ -316,10 +302,9 @@ extern __thread struct _glapi_table * _glapi_tls_Dispatch

#elif !defined(GL_CALL)
# if defined(THREADS)
extern struct _glapi_table * _glapi_DispatchTSD;
# define GET_DISPATCH() \
((__builtin_expect( _glapi_DispatchTSD != NULL, 1 )) \
? _glapi_DispatchTSD : _glapi_get_dispatch())
((__builtin_expect( _glapi_Dispatch != NULL, 1 )) \
? _glapi_Dispatch : _glapi_get_dispatch())
# else
# define GET_DISPATCH() _glapi_Dispatch
# endif /* defined(THREADS) */

+ 4
- 7
src/mesa/main/context.c 查看文件

@@ -645,13 +645,7 @@ one_time_init( GLcontext *ctx )
#endif
if (_mesa_getenv("MESA_DEBUG")) {
_glapi_noop_enable_warnings(GL_TRUE);
#ifndef GLX_DIRECT_RENDERING
/* libGL from before 2002/06/28 don't have this function. Someday,
* when newer libGL libs are common, remove the #ifdef test. This
* only serves to print warnings when calling undefined GL functions.
*/
_glapi_set_warning_func( (_glapi_warning_func) _mesa_warning );
#endif
}
else {
_glapi_noop_enable_warnings(GL_FALSE);
@@ -1538,10 +1532,13 @@ _mesa_make_current( GLcontext *newCtx, GLframebuffer *drawBuffer,
return;
}

#if !defined(IN_DRI_DRIVER)
/* We call this function periodically (just here for now) in
* order to detect when multithreading has begun.
* order to detect when multithreading has begun. In a DRI driver, this
* step is done by the driver loader (e.g., libGL).
*/
_glapi_check_multithread();
#endif /* !defined(IN_DRI_DRIVER) */

_glapi_set_context((void *) newCtx);
ASSERT(_mesa_get_current_context() == newCtx);

+ 816
- 816
src/mesa/x86-64/glapi_x86-64.S
文件差異過大導致無法顯示
查看文件


+ 2
- 2
src/mesa/x86/glapi_x86.S 查看文件

@@ -82,7 +82,7 @@ GL_PREFIX(fn, fn_alt): \
ALIGNTEXT16; \
GLOBL_FN(GL_PREFIX(fn, fn_alt)); \
GL_PREFIX(fn, fn_alt): \
MOV_L(CONTENT(GLNAME(_glapi_DispatchTSD)), EAX) ; \
MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) ; \
TEST_L(EAX, EAX) ; \
JE(1f) ; \
JMP(GL_OFFSET(off)) ; \
@@ -93,7 +93,7 @@ GL_PREFIX(fn, fn_alt): \
ALIGNTEXT16; \
GLOBL_FN(GL_PREFIX(fn, fn_alt)); \
GL_PREFIX(fn, fn_alt): \
MOV_L(CONTENT(GLNAME(_glapi_DispatchTSD)), EAX) ; \
MOV_L(CONTENT(GLNAME(_glapi_Dispatch)), EAX) ; \
TEST_L(EAX, EAX) ; \
JE(1f) ; \
JMP(GL_OFFSET(off)) ; \

Loading…
取消
儲存