Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenglapi_getproc.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 00033 #include <stdlib.h> 00034 #include <string.h> 00035 #include "main/glheader.h" 00036 #include "glapi.h" 00037 #include "glapioffsets.h" 00038 #include "glapitable.h" 00039 00040 00041 static void 00042 fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset); 00043 00044 00049 static char * 00050 str_dup(const char *str) 00051 { 00052 char *copy; 00053 copy = (char*) malloc(strlen(str) + 1); 00054 if (!copy) 00055 return NULL; 00056 strcpy(copy, str); 00057 return copy; 00058 } 00059 00060 00061 00062 #if defined(USE_X64_64_ASM) && defined(GLX_USE_TLS) 00063 # define DISPATCH_FUNCTION_SIZE 16 00064 #elif defined(USE_X86_ASM) 00065 # if defined(THREADS) && !defined(GLX_USE_TLS) 00066 # define DISPATCH_FUNCTION_SIZE 32 00067 # else 00068 # define DISPATCH_FUNCTION_SIZE 16 00069 # endif 00070 #endif 00071 00072 #if !defined(DISPATCH_FUNCTION_SIZE) && !defined(XFree86Server) && !defined(XGLServer) 00073 # define NEED_FUNCTION_POINTER 00074 #endif 00075 00076 /* The code in this file is auto-generated with Python */ 00077 #include "glprocs.h" 00078 00079 00084 static const glprocs_table_t * 00085 find_entry( const char * n ) 00086 { 00087 GLuint i; 00088 for (i = 0; static_functions[i].Name_offset >= 0; i++) { 00089 const char *testName = gl_string_table + static_functions[i].Name_offset; 00090 #ifdef MANGLE 00091 /* skip the "m" prefix on the name */ 00092 if (strcmp(testName, n + 1) == 0) 00093 #else 00094 if (strcmp(testName, n) == 0) 00095 #endif 00096 { 00097 return &static_functions[i]; 00098 } 00099 } 00100 return NULL; 00101 } 00102 00103 00108 static GLint 00109 get_static_proc_offset(const char *funcName) 00110 { 00111 const glprocs_table_t * const f = find_entry( funcName ); 00112 if (f) { 00113 return f->Offset; 00114 } 00115 return -1; 00116 } 00117 00118 00119 #if !defined(XFree86Server) && !defined(XGLServer) 00120 #ifdef USE_X86_ASM 00121 00122 #if defined( GLX_USE_TLS ) 00123 extern GLubyte gl_dispatch_functions_start[]; 00124 extern GLubyte gl_dispatch_functions_end[]; 00125 #else 00126 extern const GLubyte gl_dispatch_functions_start[]; 00127 #endif 00128 00129 #endif /* USE_X86_ASM */ 00130 00131 00136 static _glapi_proc 00137 get_static_proc_address(const char *funcName) 00138 { 00139 const glprocs_table_t * const f = find_entry( funcName ); 00140 if (f) { 00141 #if defined(DISPATCH_FUNCTION_SIZE) && defined(GLX_INDIRECT_RENDERING) 00142 return (f->Address == NULL) 00143 ? (_glapi_proc) (gl_dispatch_functions_start 00144 + (DISPATCH_FUNCTION_SIZE * f->Offset)) 00145 : f->Address; 00146 #elif defined(DISPATCH_FUNCTION_SIZE) 00147 return (_glapi_proc) (gl_dispatch_functions_start 00148 + (DISPATCH_FUNCTION_SIZE * f->Offset)); 00149 #else 00150 return f->Address; 00151 #endif 00152 } 00153 else { 00154 return NULL; 00155 } 00156 } 00157 00158 #endif /* !defined(XFree86Server) && !defined(XGLServer) */ 00159 00160 00161 00166 static const char * 00167 get_static_proc_name( GLuint offset ) 00168 { 00169 GLuint i; 00170 for (i = 0; static_functions[i].Name_offset >= 0; i++) { 00171 if (static_functions[i].Offset == offset) { 00172 return gl_string_table + static_functions[i].Name_offset; 00173 } 00174 } 00175 return NULL; 00176 } 00177 00178 00179 00180 /********************************************************************** 00181 * Extension function management. 00182 */ 00183 00184 00188 struct _glapi_function { 00192 const char * name; 00193 00194 00204 const char * parameter_signature; 00205 00206 00212 unsigned dispatch_offset; 00213 00214 00226 _glapi_proc dispatch_stub; 00227 }; 00228 00229 00230 static struct _glapi_function ExtEntryTable[MAX_EXTENSION_FUNCS]; 00231 static GLuint NumExtEntryPoints = 0; 00232 00233 #ifdef USE_SPARC_ASM 00234 extern void __glapi_sparc_icache_flush(unsigned int *); 00235 #endif 00236 00242 static _glapi_proc 00243 generate_entrypoint(GLuint functionOffset) 00244 { 00245 #if defined(USE_X86_ASM) 00246 /* 32 is chosen as something of a magic offset. For x86, the dispatch 00247 * at offset 32 is the first one where the offset in the 00248 * "jmp OFFSET*4(%eax)" can't be encoded in a single byte. 00249 */ 00250 const GLubyte * const template_func = gl_dispatch_functions_start 00251 + (DISPATCH_FUNCTION_SIZE * 32); 00252 GLubyte * const code = (GLubyte *) malloc(DISPATCH_FUNCTION_SIZE); 00253 00254 00255 if ( code != NULL ) { 00256 (void) memcpy(code, template_func, DISPATCH_FUNCTION_SIZE); 00257 fill_in_entrypoint_offset( (_glapi_proc) code, functionOffset ); 00258 } 00259 00260 return (_glapi_proc) code; 00261 #elif defined(USE_SPARC_ASM) 00262 00263 #ifdef __arch64__ 00264 static const unsigned int insn_template[] = { 00265 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */ 00266 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */ 00267 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */ 00268 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */ 00269 0x8528b020, /* sllx %g2, 32, %g2 */ 00270 0xc2584002, /* ldx [%g1 + %g2], %g1 */ 00271 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */ 00272 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */ 00273 0xc6584002, /* ldx [%g1 + %g2], %g3 */ 00274 0x81c0c000, /* jmpl %g3, %g0 */ 00275 0x01000000 /* nop */ 00276 }; 00277 #else 00278 static const unsigned int insn_template[] = { 00279 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */ 00280 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */ 00281 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */ 00282 0x81c0c000, /* jmpl %g3, %g0 */ 00283 0x01000000 /* nop */ 00284 }; 00285 #endif /* __arch64__ */ 00286 unsigned int *code = (unsigned int *) malloc(sizeof(insn_template)); 00287 unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch; 00288 if (code) { 00289 memcpy(code, insn_template, sizeof(insn_template)); 00290 00291 #ifdef __arch64__ 00292 code[0] |= (glapi_addr >> (32 + 10)); 00293 code[1] |= ((glapi_addr & 0xffffffff) >> 10); 00294 __glapi_sparc_icache_flush(&code[0]); 00295 code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1)); 00296 code[3] |= (glapi_addr & ((1 << 10) - 1)); 00297 __glapi_sparc_icache_flush(&code[2]); 00298 code[6] |= ((functionOffset * 8) >> 10); 00299 code[7] |= ((functionOffset * 8) & ((1 << 10) - 1)); 00300 __glapi_sparc_icache_flush(&code[6]); 00301 #else 00302 code[0] |= (glapi_addr >> 10); 00303 code[1] |= (glapi_addr & ((1 << 10) - 1)); 00304 __glapi_sparc_icache_flush(&code[0]); 00305 code[2] |= (functionOffset * 4); 00306 __glapi_sparc_icache_flush(&code[2]); 00307 #endif /* __arch64__ */ 00308 } 00309 return (_glapi_proc) code; 00310 #else 00311 (void) functionOffset; 00312 return NULL; 00313 #endif /* USE_*_ASM */ 00314 } 00315 00316 00321 static void 00322 fill_in_entrypoint_offset(_glapi_proc entrypoint, GLuint offset) 00323 { 00324 #if defined(USE_X86_ASM) 00325 GLubyte * const code = (GLubyte *) entrypoint; 00326 00327 #if DISPATCH_FUNCTION_SIZE == 32 00328 *((unsigned int *)(code + 11)) = 4 * offset; 00329 *((unsigned int *)(code + 22)) = 4 * offset; 00330 #elif DISPATCH_FUNCTION_SIZE == 16 && defined( GLX_USE_TLS ) 00331 *((unsigned int *)(code + 8)) = 4 * offset; 00332 #elif DISPATCH_FUNCTION_SIZE == 16 00333 *((unsigned int *)(code + 7)) = 4 * offset; 00334 #else 00335 # error Invalid DISPATCH_FUNCTION_SIZE! 00336 #endif 00337 00338 #elif defined(USE_SPARC_ASM) 00339 00340 /* XXX this hasn't been tested! */ 00341 unsigned int *code = (unsigned int *) entrypoint; 00342 #ifdef __arch64__ 00343 code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */ 00344 code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */ 00345 code[6] |= ((offset * 8) >> 10); 00346 code[7] |= ((offset * 8) & ((1 << 10) - 1)); 00347 __glapi_sparc_icache_flush(&code[6]); 00348 #else /* __arch64__ */ 00349 code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */ 00350 code[2] |= (offset * 4); 00351 __glapi_sparc_icache_flush(&code[2]); 00352 #endif /* __arch64__ */ 00353 00354 #else 00355 00356 /* an unimplemented architecture */ 00357 (void) entrypoint; 00358 (void) offset; 00359 00360 #endif /* USE_*_ASM */ 00361 } 00362 00363 00377 static struct _glapi_function * 00378 add_function_name( const char * funcName ) 00379 { 00380 struct _glapi_function * entry = NULL; 00381 00382 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) { 00383 _glapi_proc entrypoint = generate_entrypoint(~0); 00384 if (entrypoint != NULL) { 00385 entry = & ExtEntryTable[NumExtEntryPoints]; 00386 00387 ExtEntryTable[NumExtEntryPoints].name = str_dup(funcName); 00388 ExtEntryTable[NumExtEntryPoints].parameter_signature = NULL; 00389 ExtEntryTable[NumExtEntryPoints].dispatch_offset = ~0; 00390 ExtEntryTable[NumExtEntryPoints].dispatch_stub = entrypoint; 00391 NumExtEntryPoints++; 00392 } 00393 } 00394 00395 return entry; 00396 } 00397 00398 00446 PUBLIC int 00447 _glapi_add_dispatch( const char * const * function_names, 00448 const char * parameter_signature ) 00449 { 00450 static int next_dynamic_offset = _gloffset_FIRST_DYNAMIC; 00451 const char * const real_sig = (parameter_signature != NULL) 00452 ? parameter_signature : ""; 00453 struct _glapi_function * entry[8]; 00454 GLboolean is_static[8]; 00455 unsigned i; 00456 unsigned j; 00457 int offset = ~0; 00458 int new_offset; 00459 00460 00461 (void) memset( is_static, 0, sizeof( is_static ) ); 00462 (void) memset( entry, 0, sizeof( entry ) ); 00463 00464 for ( i = 0 ; function_names[i] != NULL ; i++ ) { 00465 /* Do some trivial validation on the name of the function. 00466 */ 00467 00468 if (!function_names[i] || function_names[i][0] != 'g' || function_names[i][1] != 'l') 00469 return -1; 00470 00471 /* Determine if the named function already exists. If the function does 00472 * exist, it must have the same parameter signature as the function 00473 * being added. 00474 */ 00475 00476 new_offset = get_static_proc_offset(function_names[i]); 00477 if (new_offset >= 0) { 00478 /* FIXME: Make sure the parameter signatures match! How do we get 00479 * FIXME: the parameter signature for static functions? 00480 */ 00481 00482 if ( (offset != ~0) && (new_offset != offset) ) { 00483 return -1; 00484 } 00485 00486 is_static[i] = GL_TRUE; 00487 offset = new_offset; 00488 } 00489 00490 00491 for ( j = 0 ; j < NumExtEntryPoints ; j++ ) { 00492 if (strcmp(ExtEntryTable[j].name, function_names[i]) == 0) { 00493 /* The offset may be ~0 if the function name was added by 00494 * glXGetProcAddress but never filled in by the driver. 00495 */ 00496 00497 if (ExtEntryTable[j].dispatch_offset != ~0) { 00498 if (strcmp(real_sig, ExtEntryTable[j].parameter_signature) 00499 != 0) { 00500 return -1; 00501 } 00502 00503 if ( (offset != ~0) && (ExtEntryTable[j].dispatch_offset != offset) ) { 00504 return -1; 00505 } 00506 00507 offset = ExtEntryTable[j].dispatch_offset; 00508 } 00509 00510 entry[i] = & ExtEntryTable[j]; 00511 break; 00512 } 00513 } 00514 } 00515 00516 if (offset == ~0) { 00517 offset = next_dynamic_offset; 00518 next_dynamic_offset++; 00519 } 00520 00521 for ( i = 0 ; function_names[i] != NULL ; i++ ) { 00522 if (! is_static[i] ) { 00523 if (entry[i] == NULL) { 00524 entry[i] = add_function_name( function_names[i] ); 00525 if (entry[i] == NULL) { 00526 /* FIXME: Possible memory leak here. 00527 */ 00528 return -1; 00529 } 00530 } 00531 00532 entry[i]->parameter_signature = str_dup(real_sig); 00533 fill_in_entrypoint_offset(entry[i]->dispatch_stub, offset); 00534 entry[i]->dispatch_offset = offset; 00535 } 00536 } 00537 00538 return offset; 00539 } 00540 00541 00545 PUBLIC GLint 00546 _glapi_get_proc_offset(const char *funcName) 00547 { 00548 /* search extension functions first */ 00549 GLuint i; 00550 for (i = 0; i < NumExtEntryPoints; i++) { 00551 if (strcmp(ExtEntryTable[i].name, funcName) == 0) { 00552 return ExtEntryTable[i].dispatch_offset; 00553 } 00554 } 00555 /* search static functions */ 00556 return get_static_proc_offset(funcName); 00557 } 00558 00559 00560 00566 _glapi_proc 00567 _glapi_get_proc_address(const char *funcName) 00568 { 00569 struct _glapi_function * entry; 00570 GLuint i; 00571 00572 #ifdef MANGLE 00573 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l') 00574 return NULL; 00575 #else 00576 if (funcName[0] != 'g' || funcName[1] != 'l') 00577 return NULL; 00578 #endif 00579 00580 /* search extension functions first */ 00581 for (i = 0; i < NumExtEntryPoints; i++) { 00582 if (strcmp(ExtEntryTable[i].name, funcName) == 0) { 00583 return ExtEntryTable[i].dispatch_stub; 00584 } 00585 } 00586 00587 #if !defined( XFree86Server ) && !defined( XGLServer ) 00588 /* search static functions */ 00589 { 00590 const _glapi_proc func = get_static_proc_address(funcName); 00591 if (func) 00592 return func; 00593 } 00594 #endif /* !defined( XFree86Server ) */ 00595 00596 entry = add_function_name(funcName); 00597 return (entry == NULL) ? NULL : entry->dispatch_stub; 00598 } 00599 00600 00601 00606 const char * 00607 _glapi_get_proc_name(GLuint offset) 00608 { 00609 GLuint i; 00610 const char * n; 00611 00612 /* search built-in functions */ 00613 n = get_static_proc_name(offset); 00614 if ( n != NULL ) { 00615 return n; 00616 } 00617 00618 /* search added extension functions */ 00619 for (i = 0; i < NumExtEntryPoints; i++) { 00620 if (ExtEntryTable[i].dispatch_offset == offset) { 00621 return ExtEntryTable[i].name; 00622 } 00623 } 00624 return NULL; 00625 } Generated on Sat May 26 2012 04:18:45 for ReactOS by
1.7.6.1
|