Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenglapi.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 /* 00027 * This file manages the OpenGL API dispatch layer. 00028 * The dispatch table (struct _glapi_table) is basically just a list 00029 * of function pointers. 00030 * There are functions to set/get the current dispatch table for the 00031 * current thread and to manage registration/dispatch of dynamically 00032 * added extension functions. 00033 * 00034 * It's intended that this file and the other glapi*.[ch] files are 00035 * flexible enough to be reused in several places: XFree86, DRI- 00036 * based libGL.so, and perhaps the SGI SI. 00037 * 00038 * NOTE: There are no dependencies on Mesa in this code. 00039 * 00040 * Versions (API changes): 00041 * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0 00042 * 2001/01/16 - added dispatch override feature for Mesa 3.5 00043 * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1. 00044 * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints 00045 * itself (using offset ~0). _glapi_add_entrypoint() can be 00046 * called afterward and it'll fill in the correct dispatch 00047 * offset. This allows DRI libGL to avoid probing for DRI 00048 * drivers! No changes to the public glapi interface. 00049 */ 00050 00051 00052 00053 #ifdef HAVE_DIX_CONFIG_H 00054 00055 #include <dix-config.h> 00056 #define PUBLIC 00057 00058 #else 00059 00060 #include "main/glheader.h" 00061 00062 #endif 00063 00064 #include <stdlib.h> 00065 #include <string.h> 00066 #ifdef DEBUG 00067 #include <assert.h> 00068 #endif 00069 00070 #include "glapi.h" 00071 #include "glapioffsets.h" 00072 #include "glapitable.h" 00073 00074 00075 /***** BEGIN NO-OP DISPATCH *****/ 00076 00077 static GLboolean WarnFlag = GL_FALSE; 00078 static _glapi_warning_func warning_func; 00079 00080 /* 00081 * Enable/disable printing of warning messages. 00082 */ 00083 PUBLIC void 00084 _glapi_noop_enable_warnings(GLboolean enable) 00085 { 00086 WarnFlag = enable; 00087 } 00088 00089 /* 00090 * Register a callback function for reporting errors. 00091 */ 00092 PUBLIC void 00093 _glapi_set_warning_func( _glapi_warning_func func ) 00094 { 00095 warning_func = func; 00096 } 00097 00098 static GLboolean 00099 warn(void) 00100 { 00101 if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG")) 00102 && warning_func) { 00103 return GL_TRUE; 00104 } 00105 else { 00106 return GL_FALSE; 00107 } 00108 } 00109 00110 00111 #define KEYWORD1 static 00112 #define KEYWORD1_ALT static 00113 #define KEYWORD2 GLAPIENTRY 00114 #define NAME(func) NoOp##func 00115 00116 #define F NULL 00117 00118 #define DISPATCH(func, args, msg) \ 00119 if (warn()) { \ 00120 warning_func(NULL, "GL User Error: called without context: %s", #func); \ 00121 } 00122 00123 #define RETURN_DISPATCH(func, args, msg) \ 00124 if (warn()) { \ 00125 warning_func(NULL, "GL User Error: called without context: %s", #func); \ 00126 } \ 00127 return 0 00128 00129 #define DISPATCH_TABLE_NAME __glapi_noop_table 00130 #define UNUSED_TABLE_NAME __unused_noop_functions 00131 00132 #define TABLE_ENTRY(name) (_glapi_proc) NoOp##name 00133 00134 static GLint NoOpUnused(void) 00135 { 00136 if (warn()) { 00137 warning_func(NULL, "GL User Error: calling extension function without a current context\n"); 00138 } 00139 return 0; 00140 } 00141 00142 #include "glapitemp.h" 00143 00144 /***** END NO-OP DISPATCH *****/ 00145 00146 00147 00179 #if defined(GLX_USE_TLS) 00180 00181 PUBLIC __thread struct _glapi_table * _glapi_tls_Dispatch 00182 __attribute__((tls_model("initial-exec"))) 00183 = (struct _glapi_table *) __glapi_noop_table; 00184 00185 PUBLIC __thread void * _glapi_tls_Context 00186 __attribute__((tls_model("initial-exec"))); 00187 00188 PUBLIC const struct _glapi_table *_glapi_Dispatch = NULL; 00189 PUBLIC const void *_glapi_Context = NULL; 00190 00191 #else 00192 00193 #if defined(THREADS) 00194 00195 static GLboolean ThreadSafe = GL_FALSE; 00196 _glthread_TSD _gl_DispatchTSD; 00197 static _glthread_TSD ContextTSD; 00199 #if defined(WIN32_THREADS) 00200 void FreeTSD(_glthread_TSD *p); 00201 void FreeAllTSD(void) 00202 { 00203 FreeTSD(&_gl_DispatchTSD); 00204 FreeTSD(&ContextTSD); 00205 } 00206 #endif /* defined(WIN32_THREADS) */ 00207 00208 #endif /* defined(THREADS) */ 00209 00210 PUBLIC struct _glapi_table *_glapi_Dispatch = 00211 (struct _glapi_table *) __glapi_noop_table; 00212 PUBLIC void *_glapi_Context = NULL; 00213 00214 #endif /* defined(GLX_USE_TLS) */ 00215 00224 void 00225 _glapi_check_multithread(void) 00226 { 00227 #if defined(THREADS) && !defined(GLX_USE_TLS) 00228 if (!ThreadSafe) { 00229 static unsigned long knownID; 00230 static GLboolean firstCall = GL_TRUE; 00231 if (firstCall) { 00232 knownID = _glthread_GetID(); 00233 firstCall = GL_FALSE; 00234 } 00235 else if (knownID != _glthread_GetID()) { 00236 ThreadSafe = GL_TRUE; 00237 _glapi_set_dispatch(NULL); 00238 _glapi_set_context(NULL); 00239 } 00240 } 00241 else if (!_glapi_get_dispatch()) { 00242 /* make sure that this thread's dispatch pointer isn't null */ 00243 _glapi_set_dispatch(NULL); 00244 } 00245 #endif 00246 } 00247 00248 00249 00255 PUBLIC void 00256 _glapi_set_context(void *context) 00257 { 00258 (void) __unused_noop_functions; /* silence a warning */ 00259 #if defined(GLX_USE_TLS) 00260 _glapi_tls_Context = context; 00261 #elif defined(THREADS) 00262 _glthread_SetTSD(&ContextTSD, context); 00263 _glapi_Context = (ThreadSafe) ? NULL : context; 00264 #else 00265 _glapi_Context = context; 00266 #endif 00267 } 00268 00269 00270 00276 PUBLIC void * 00277 _glapi_get_context(void) 00278 { 00279 #if defined(GLX_USE_TLS) 00280 return _glapi_tls_Context; 00281 #elif defined(THREADS) 00282 if (ThreadSafe) { 00283 return _glthread_GetTSD(&ContextTSD); 00284 } 00285 else { 00286 return _glapi_Context; 00287 } 00288 #else 00289 return _glapi_Context; 00290 #endif 00291 } 00292 00293 #ifdef USE_X86_ASM 00294 00295 #if defined( GLX_USE_TLS ) 00296 extern GLubyte gl_dispatch_functions_start[]; 00297 extern GLubyte gl_dispatch_functions_end[]; 00298 #else 00299 extern const GLubyte gl_dispatch_functions_start[]; 00300 #endif 00301 00302 #endif /* USE_X86_ASM */ 00303 00304 00305 #if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS) 00306 # define DISPATCH_FUNCTION_SIZE 16 00307 #elif defined(USE_X86_ASM) 00308 # if defined(THREADS) && !defined(GLX_USE_TLS) 00309 # define DISPATCH_FUNCTION_SIZE 32 00310 # else 00311 # define DISPATCH_FUNCTION_SIZE 16 00312 # endif 00313 #endif 00314 00315 #if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer) 00316 # define NEED_FUNCTION_POINTER 00317 #endif 00318 00319 #if defined(PTHREADS) || defined(GLX_USE_TLS) 00320 00323 static void 00324 init_glapi_relocs( void ) 00325 { 00326 #if defined(USE_X86_ASM) && defined(GLX_USE_TLS) && !defined(GLX_X86_READONLY_TEXT) 00327 extern unsigned long _x86_get_dispatch(void); 00328 char run_time_patch[] = { 00329 0x65, 0xa1, 0, 0, 0, 0 /* movl %gs:0,%eax */ 00330 }; 00331 GLuint *offset = (GLuint *) &run_time_patch[2]; /* 32-bits for x86/32 */ 00332 const GLubyte * const get_disp = (const GLubyte *) run_time_patch; 00333 GLubyte * curr_func = (GLubyte *) gl_dispatch_functions_start; 00334 00335 *offset = _x86_get_dispatch(); 00336 while ( curr_func != (GLubyte *) gl_dispatch_functions_end ) { 00337 (void) memcpy( curr_func, get_disp, sizeof(run_time_patch)); 00338 curr_func += DISPATCH_FUNCTION_SIZE; 00339 } 00340 #endif 00341 } 00342 #endif /* defined(PTHREADS) || defined(GLX_USE_TLS) */ 00343 00344 00350 PUBLIC void 00351 _glapi_set_dispatch(struct _glapi_table *dispatch) 00352 { 00353 #if defined(PTHREADS) || defined(GLX_USE_TLS) 00354 static pthread_once_t once_control = PTHREAD_ONCE_INIT; 00355 pthread_once( & once_control, init_glapi_relocs ); 00356 #endif 00357 00358 if (!dispatch) { 00359 /* use the no-op functions */ 00360 dispatch = (struct _glapi_table *) __glapi_noop_table; 00361 } 00362 #ifdef DEBUG 00363 else { 00364 _glapi_check_table(dispatch); 00365 } 00366 #endif 00367 00368 #if defined(GLX_USE_TLS) 00369 _glapi_tls_Dispatch = dispatch; 00370 #elif defined(THREADS) 00371 _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch); 00372 _glapi_Dispatch = (ThreadSafe) ? NULL : dispatch; 00373 #else /*THREADS*/ 00374 _glapi_Dispatch = dispatch; 00375 #endif /*THREADS*/ 00376 } 00377 00378 00379 00383 PUBLIC struct _glapi_table * 00384 _glapi_get_dispatch(void) 00385 { 00386 struct _glapi_table * api; 00387 #if defined(GLX_USE_TLS) 00388 api = _glapi_tls_Dispatch; 00389 #elif defined(THREADS) 00390 api = (ThreadSafe) 00391 ? (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD) 00392 : _glapi_Dispatch; 00393 #else 00394 api = _glapi_Dispatch; 00395 #endif 00396 return api; 00397 } 00398 00399 00400 00401 00402 /* 00403 * The dispatch table size (number of entries) is the size of the 00404 * _glapi_table struct plus the number of dynamic entries we can add. 00405 * The extra slots can be filled in by DRI drivers that register new extension 00406 * functions. 00407 */ 00408 #define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS) 00409 00410 00415 PUBLIC GLuint 00416 _glapi_get_dispatch_table_size(void) 00417 { 00418 return DISPATCH_TABLE_SIZE; 00419 } 00420 00421 00426 void 00427 _glapi_check_table(const struct _glapi_table *table) 00428 { 00429 #ifdef EXTRA_DEBUG 00430 const GLuint entries = _glapi_get_dispatch_table_size(); 00431 const void **tab = (const void **) table; 00432 GLuint i; 00433 for (i = 1; i < entries; i++) { 00434 assert(tab[i]); 00435 } 00436 00437 /* Do some spot checks to be sure that the dispatch table 00438 * slots are assigned correctly. 00439 */ 00440 { 00441 GLuint BeginOffset = _glapi_get_proc_offset("glBegin"); 00442 char *BeginFunc = (char*) &table->Begin; 00443 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *); 00444 assert(BeginOffset == _gloffset_Begin); 00445 assert(BeginOffset == offset); 00446 } 00447 { 00448 GLuint viewportOffset = _glapi_get_proc_offset("glViewport"); 00449 char *viewportFunc = (char*) &table->Viewport; 00450 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *); 00451 assert(viewportOffset == _gloffset_Viewport); 00452 assert(viewportOffset == offset); 00453 } 00454 { 00455 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer"); 00456 char *VertexPointerFunc = (char*) &table->VertexPointer; 00457 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *); 00458 assert(VertexPointerOffset == _gloffset_VertexPointer); 00459 assert(VertexPointerOffset == offset); 00460 } 00461 { 00462 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax"); 00463 char *ResetMinMaxFunc = (char*) &table->ResetMinmax; 00464 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *); 00465 assert(ResetMinMaxOffset == _gloffset_ResetMinmax); 00466 assert(ResetMinMaxOffset == offset); 00467 } 00468 { 00469 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor"); 00470 char *blendColorFunc = (char*) &table->BlendColor; 00471 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *); 00472 assert(blendColorOffset == _gloffset_BlendColor); 00473 assert(blendColorOffset == offset); 00474 } 00475 { 00476 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT"); 00477 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT; 00478 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *); 00479 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT); 00480 assert(secondaryColor3fOffset == offset); 00481 } 00482 { 00483 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV"); 00484 char *pointParameterivFunc = (char*) &table->PointParameterivNV; 00485 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *); 00486 assert(pointParameterivOffset == _gloffset_PointParameterivNV); 00487 assert(pointParameterivOffset == offset); 00488 } 00489 { 00490 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV"); 00491 char *setFenceFunc = (char*) &table->SetFenceNV; 00492 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *); 00493 assert(setFenceOffset == _gloffset_SetFenceNV); 00494 assert(setFenceOffset == offset); 00495 } 00496 #else 00497 (void) table; 00498 #endif 00499 } Generated on Sat May 26 2012 04:18:45 for ReactOS by
1.7.6.1
|