home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / glapi.cpp < prev    next >
C/C++ Source or Header  |  2002-10-29  |  27KB  |  921 lines

  1. /* $Id: glapi.c,v 1.67 2002/10/29 15:03:14 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27.  
  28. /*
  29.  * This file manages the OpenGL API dispatch layer.
  30.  * The dispatch table (struct _glapi_table) is basically just a list
  31.  * of function pointers.
  32.  * There are functions to set/get the current dispatch table for the
  33.  * current thread and to manage registration/dispatch of dynamically
  34.  * added extension functions.
  35.  *
  36.  * It's intended that this file and the other glapi*.[ch] files are
  37.  * flexible enough to be reused in several places:  XFree86, DRI-
  38.  * based libGL.so, and perhaps the SGI SI.
  39.  *
  40.  * NOTE: There are no dependencies on Mesa in this code.
  41.  *
  42.  * Versions (API changes):
  43.  *   2000/02/23  - original version for Mesa 3.3 and XFree86 4.0
  44.  *   2001/01/16  - added dispatch override feature for Mesa 3.5
  45.  *   2002/06/28  - added _glapi_set_warning_func(), Mesa 4.1.
  46.  *   2002/10/01  - _glapi_get_proc_address() will now generate new entrypoints
  47.  *                 itself (using offset ~0).  _glapi_add_entrypoint() can be
  48.  *                 called afterward and it'll fill in the correct dispatch
  49.  *                 offset.  This allows DRI libGL to avoid probing for DRI
  50.  *                 drivers!  No changes to the public glapi interface.
  51.  */
  52.  
  53.  
  54.  
  55. #include "glheader.h"
  56. #include "glapi.h"
  57. #include "glapioffsets.h"
  58. #include "glapitable.h"
  59. #include "glthread.h"
  60.  
  61. /***** BEGIN NO-OP DISPATCH *****/
  62.  
  63. static GLboolean WarnFlag = GL_FALSE;
  64. static _glapi_warning_func warning_func;
  65.  
  66.  
  67. /*
  68.  * Enable/disable printing of warning messages.
  69.  */
  70. void
  71. _glapi_noop_enable_warnings(GLboolean enable)
  72. {
  73.    WarnFlag = enable;
  74. }
  75.  
  76. /*
  77.  * Register a callback function for reporting errors.
  78.  */
  79. void
  80. _glapi_set_warning_func( _glapi_warning_func func )
  81. {
  82.    warning_func = func;
  83. }
  84.  
  85. static GLboolean
  86. warn(void)
  87. {
  88.    if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
  89.        && warning_func) {
  90.       return GL_TRUE;
  91.    }
  92.    else {
  93.       return GL_FALSE;
  94.    }
  95. }
  96.  
  97.  
  98. #define KEYWORD1 static
  99. #define KEYWORD2
  100. #define NAME(func)  NoOp##func
  101.  
  102. #define F NULL
  103.  
  104. #define DISPATCH(func, args, msg)                    \
  105.    if (warn()) {                            \
  106.       warning_func(NULL, "GL User Error: called without context:");    \
  107.       warning_func msg;                            \
  108.    }
  109.  
  110. #define RETURN_DISPATCH(func, args, msg)                \
  111.    if (warn()) {                            \
  112.       warning_func(NULL, "GL User Error: called without context:");    \
  113.       warning_func msg;                            \
  114.    }                                    \
  115.    return 0
  116.  
  117. #define DISPATCH_TABLE_NAME __glapi_noop_table
  118. #define UNUSED_TABLE_NAME __usused_noop_functions
  119.  
  120. #define TABLE_ENTRY(name) (void *) NoOp##name
  121.  
  122. static int NoOpUnused(void)
  123. {
  124.    if (warn()) {
  125.       warning_func(NULL, "GL User Error: calling extension function without a current context\n");
  126.    }
  127.    return 0;
  128. }
  129.  
  130. #include "glapitemp.h"
  131.  
  132. /***** END NO-OP DISPATCH *****/
  133.  
  134.  
  135.  
  136. /***** BEGIN THREAD-SAFE DISPATCH *****/
  137. /* if we support thread-safety, build a special dispatch table for use
  138.  * in thread-safety mode (ThreadSafe == GL_TRUE).  Each entry in the
  139.  * dispatch table will call _glthread_GetTSD() to get the actual dispatch
  140.  * table bound to the current thread, then jump through that table.
  141.  */
  142.  
  143. #if defined(THREADS)
  144.  
  145. static GLboolean ThreadSafe = GL_FALSE;  /* In thread-safe mode? */
  146. static _glthread_TSD DispatchTSD;        /* Per-thread dispatch pointer */
  147. static _glthread_TSD RealDispatchTSD;    /* only when using override */
  148. static _glthread_TSD ContextTSD;         /* Per-thread context pointer */
  149.  
  150.  
  151. #define KEYWORD1 static
  152. #define KEYWORD2 GLAPIENTRY
  153. #define NAME(func)  _ts_##func
  154.  
  155. #define DISPATCH(FUNC, ARGS, MESSAGE)                    \
  156.    struct _glapi_table *dispatch;                    \
  157.    dispatch = (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);    \
  158.    if (!dispatch)                            \
  159.       dispatch = (struct _glapi_table *) __glapi_noop_table;        \
  160.    (dispatch->FUNC) ARGS
  161.  
  162. #define RETURN_DISPATCH(FUNC, ARGS, MESSAGE)                 \
  163.    struct _glapi_table *dispatch;                    \
  164.    dispatch = (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);    \
  165.    if (!dispatch)                            \
  166.       dispatch = (struct _glapi_table *) __glapi_noop_table;        \
  167.    return (dispatch->FUNC) ARGS
  168.  
  169. #define DISPATCH_TABLE_NAME __glapi_threadsafe_table
  170. #define UNUSED_TABLE_NAME __usused_threadsafe_functions
  171.  
  172. #define TABLE_ENTRY(name) (void *) _ts_##name
  173.  
  174. static int _ts_Unused(void)
  175. {
  176.    return 0;
  177. }
  178.  
  179. #include "glapitemp.h"
  180.  
  181. #endif
  182.  
  183. /***** END THREAD-SAFE DISPATCH *****/
  184.  
  185.  
  186.  
  187. struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
  188. struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
  189.  
  190. /* Used when thread safety disabled */
  191. void *_glapi_Context = NULL;
  192.  
  193.  
  194. static GLboolean DispatchOverride = GL_FALSE;
  195.  
  196.  
  197.  
  198. /* strdup() is actually not a standard ANSI C or POSIX routine.
  199.  * Irix will not define it if ANSI mode is in effect.
  200.  */
  201. static char *
  202. str_dup(const char *str)
  203. {
  204.    char *copy;
  205.    copy = (char*) malloc(strlen(str) + 1);
  206.    if (!copy)
  207.       return NULL;
  208.    strcpy(copy, str);
  209.    return copy;
  210. }
  211.  
  212.  
  213.  
  214. /*
  215.  * We should call this periodically from a function such as glXMakeCurrent
  216.  * in order to test if multiple threads are being used.
  217.  */
  218. void
  219. _glapi_check_multithread(void)
  220. {
  221. #if defined(THREADS)
  222.    if (!ThreadSafe) {
  223.       static unsigned long knownID;
  224.       static GLboolean firstCall = GL_TRUE;
  225.       if (firstCall) {
  226.          knownID = _glthread_GetID();
  227.          firstCall = GL_FALSE;
  228.       }
  229.       else if (knownID != _glthread_GetID()) {
  230.          ThreadSafe = GL_TRUE;
  231.       }
  232.    }
  233.    if (ThreadSafe) {
  234.       /* make sure that this thread's dispatch pointer isn't null */
  235.       if (!_glapi_get_dispatch()) {
  236.          _glapi_set_dispatch(NULL);
  237.       }
  238.    }
  239. #endif
  240. }
  241.  
  242.  
  243.  
  244. /*
  245.  * Set the current context pointer for this thread.
  246.  * The context pointer is an opaque type which should be cast to
  247.  * void from the real context pointer type.
  248.  */
  249. void
  250. _glapi_set_context(void *context)
  251. {
  252. #if defined(THREADS)
  253.    _glthread_SetTSD(&ContextTSD, context);
  254.    if (ThreadSafe)
  255.       _glapi_Context = NULL;
  256.    else
  257.       _glapi_Context = context;
  258. #else
  259.    _glapi_Context = context;
  260. #endif
  261. }
  262.  
  263.  
  264.  
  265. /*
  266.  * Get the current context pointer for this thread.
  267.  * The context pointer is an opaque type which should be cast from
  268.  * void to the real context pointer type.
  269.  */
  270. void *
  271. _glapi_get_context(void)
  272. {
  273. #if defined(THREADS)
  274.    if (ThreadSafe) {
  275.       return _glthread_GetTSD(&ContextTSD);
  276.    }
  277.    else {
  278.       return _glapi_Context;
  279.    }
  280. #else
  281.    return _glapi_Context;
  282. #endif
  283. }
  284.  
  285.  
  286.  
  287. /*
  288.  * Set the global or per-thread dispatch table pointer.
  289.  */
  290. void
  291. _glapi_set_dispatch(struct _glapi_table *dispatch)
  292. {
  293.    if (!dispatch) {
  294.       /* use the no-op functions */
  295.       dispatch = (struct _glapi_table *) __glapi_noop_table;
  296.    }
  297. #ifdef DEBUG
  298.    else {
  299.       _glapi_check_table(dispatch);
  300.    }
  301. #endif
  302.  
  303. #if defined(THREADS)
  304.    if (DispatchOverride) {
  305.       _glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
  306.       if (ThreadSafe)
  307.          _glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
  308.       else
  309.          _glapi_RealDispatch = dispatch;
  310.    }
  311.    else {
  312.       /* normal operation */
  313.       _glthread_SetTSD(&DispatchTSD, (void *) dispatch);
  314.       if (ThreadSafe)
  315.          _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
  316.       else
  317.          _glapi_Dispatch = dispatch;
  318.    }
  319. #else /*THREADS*/
  320.    if (DispatchOverride) {
  321.       _glapi_RealDispatch = dispatch;
  322.    }
  323.    else {
  324.       _glapi_Dispatch = dispatch;
  325.    }
  326. #endif /*THREADS*/
  327. }
  328.  
  329.  
  330.  
  331. /*
  332.  * Return pointer to current dispatch table for calling thread.
  333.  */
  334. struct _glapi_table *
  335. _glapi_get_dispatch(void)
  336. {
  337. #if defined(THREADS)
  338.    if (ThreadSafe) {
  339.       if (DispatchOverride) {
  340.          return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
  341.       }
  342.       else {
  343.          return (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);
  344.       }
  345.    }
  346.    else {
  347.       if (DispatchOverride) {
  348.          assert(_glapi_RealDispatch);
  349.          return _glapi_RealDispatch;
  350.       }
  351.       else {
  352.          assert(_glapi_Dispatch);
  353.          return _glapi_Dispatch;
  354.       }
  355.    }
  356. #else
  357.    return _glapi_Dispatch;
  358. #endif
  359. }
  360.  
  361.  
  362. /*
  363.  * Notes on dispatch overrride:
  364.  *
  365.  * Dispatch override allows an external agent to hook into the GL dispatch
  366.  * mechanism before execution goes into the core rendering library.  For
  367.  * example, a trace mechanism would insert itself as an overrider, print
  368.  * logging info for each GL function, then dispatch to the real GL function.
  369.  *
  370.  * libGLS (GL Stream library) is another agent that might use override.
  371.  *
  372.  * We don't allow more than one layer of overriding at this time.
  373.  * In the future we may allow nested/layered override.  In that case
  374.  * _glapi_begin_dispatch_override() will return an override layer,
  375.  * _glapi_end_dispatch_override(layer) will remove an override layer
  376.  * and _glapi_get_override_dispatch(layer) will return the dispatch
  377.  * table for a given override layer.  layer = 0 will be the "real"
  378.  * dispatch table.
  379.  */
  380.  
  381. /*
  382.  * Return: dispatch override layer number.
  383.  */
  384. int
  385. _glapi_begin_dispatch_override(struct _glapi_table *override)
  386. {
  387.    struct _glapi_table *real = _glapi_get_dispatch();
  388.  
  389.    assert(!DispatchOverride);  /* can't nest at this time */
  390.    DispatchOverride = GL_TRUE;
  391.  
  392.    _glapi_set_dispatch(real);
  393.  
  394. #if defined(THREADS)
  395.    _glthread_SetTSD(&DispatchTSD, (void *) override);
  396.    if (ThreadSafe)
  397.       _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
  398.    else
  399.       _glapi_Dispatch = override;
  400. #else
  401.    _glapi_Dispatch = override;
  402. #endif
  403.    return 1;
  404. }
  405.  
  406.  
  407. void
  408. _glapi_end_dispatch_override(int layer)
  409. {
  410.    struct _glapi_table *real = _glapi_get_dispatch();
  411.    (void) layer;
  412.    DispatchOverride = GL_FALSE;
  413.    _glapi_set_dispatch(real);
  414.    /* the rest of this isn't needed, just play it safe */
  415. #if defined(THREADS)
  416.    _glthread_SetTSD(&RealDispatchTSD, NULL);
  417. #endif
  418.    _glapi_RealDispatch = NULL;
  419. }
  420.  
  421.  
  422. struct _glapi_table *
  423. _glapi_get_override_dispatch(int layer)
  424. {
  425.    if (layer == 0) {
  426.       return _glapi_get_dispatch();
  427.    }
  428.    else {
  429.       if (DispatchOverride) {
  430. #if defined(THREADS)
  431.          return (struct _glapi_table *) _glthread_GetTSD(&DispatchTSD);
  432. #else
  433.          return _glapi_Dispatch;
  434. #endif
  435.       }
  436.       else {
  437.          return NULL;
  438.       }
  439.    }
  440. }
  441.  
  442.  
  443. struct name_address_offset {
  444.    const char *Name;
  445.    GLvoid *Address;
  446.    GLuint Offset;
  447. };
  448.  
  449.  
  450. /* The code in this file is auto-generated with Python */
  451. #include "glprocs.h"
  452.  
  453.  
  454.  
  455. /*
  456.  * Return dispatch table offset of the named static (built-in) function.
  457.  * Return -1 if function not found.
  458.  */
  459. static GLint
  460. get_static_proc_offset(const char *funcName)
  461. {
  462.    GLuint i;
  463.    for (i = 0; static_functions[i].Name; i++) {
  464.       if (strcmp(static_functions[i].Name, funcName) == 0) {
  465.      return static_functions[i].Offset;
  466.       }
  467.    }
  468.    return -1;
  469. }
  470.  
  471.  
  472. /*
  473.  * Return dispatch function address the named static (built-in) function.
  474.  * Return NULL if function not found.
  475.  */
  476. static GLvoid *
  477. get_static_proc_address(const char *funcName)
  478. {
  479.    GLint i;
  480.    for (i = 0; static_functions[i].Name; i++) {
  481.       if (strcmp(static_functions[i].Name, funcName) == 0) {
  482.          return static_functions[i].Address;
  483.       }
  484.    }
  485.    return NULL;
  486. }
  487.  
  488.  
  489.  
  490. /**********************************************************************
  491.  * Extension function management.
  492.  */
  493.  
  494. /*
  495.  * Number of extension functions which we can dynamically add at runtime.
  496.  */
  497. #define MAX_EXTENSION_FUNCS 300
  498.  
  499.  
  500. /*
  501.  * The disptach table size (number of entries) is the sizeof the
  502.  * _glapi_table struct plus the number of dynamic entries we can add.
  503.  * The extra slots can be filled in by DRI drivers that register new extension
  504.  * functions.
  505.  */
  506. #define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
  507.  
  508.  
  509. static struct name_address_offset ExtEntryTable[MAX_EXTENSION_FUNCS];
  510. static GLuint NumExtEntryPoints = 0;
  511.  
  512. #ifdef USE_SPARC_ASM
  513. extern void __glapi_sparc_icache_flush(unsigned int *);
  514. #endif
  515.  
  516. /*
  517.  * Generate a dispatch function (entrypoint) which jumps through
  518.  * the given slot number (offset) in the current dispatch table.
  519.  * We need assembly language in order to accomplish this.
  520.  */
  521. static void *
  522. generate_entrypoint(GLuint functionOffset)
  523. {
  524. #if defined(USE_X86_ASM)
  525.    /*
  526.     * This x86 code contributed by Josh Vanderhoof.
  527.     *
  528.     *  0:   a1 10 32 54 76          movl   __glapi_Dispatch,%eax
  529.     *       00 01 02 03 04
  530.     *  5:   85 c0                   testl  %eax,%eax
  531.     *       05 06
  532.     *  7:   74 06                   je     f <entrypoint+0xf>
  533.     *       07 08
  534.     *  9:   ff a0 10 32 54 76       jmp    *0x76543210(%eax)
  535.     *       09 0a 0b 0c 0d 0e
  536.     *  f:   e8 fc ff ff ff          call   __glapi_get_dispatch
  537.     *       0f 10 11 12 13
  538.     * 14:   ff a0 10 32 54 76       jmp    *0x76543210(%eax)
  539.     *       14 15 16 17 18 19
  540.     */
  541.    static const unsigned char insn_template[] = {
  542.       0xa1, 0x00, 0x00, 0x00, 0x00,
  543.       0x85, 0xc0,
  544.       0x74, 0x06,
  545.       0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
  546.       0xe8, 0x00, 0x00, 0x00, 0x00,
  547.       0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
  548.    };
  549.    unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
  550.    unsigned int next_insn;
  551.    if (code) {
  552.       memcpy(code, insn_template, sizeof(insn_template));
  553.  
  554.       *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_Dispatch;
  555.       *(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
  556.       next_insn = (unsigned int)(code + 0x14);
  557.       *(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
  558.       *(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
  559.    }
  560.    return code;
  561. #elif defined(USE_SPARC_ASM)
  562.  
  563. #ifdef __sparc_v9__
  564.    static const unsigned int insn_template[] = {
  565.        0x05000000,    /* sethi    %uhi(_glapi_Dispatch), %g2    */
  566.        0x03000000,    /* sethi    %hi(_glapi_Dispatch), %g1    */
  567.        0x8410a000,    /* or        %g2, %ulo(_glapi_Dispatch), %g2    */
  568.        0x82106000,    /* or        %g1, %lo(_glapi_Dispatch), %g1    */
  569.        0x8528b020,    /* sllx        %g2, 32, %g2            */
  570.        0xc2584002,    /* ldx        [%g1 + %g2], %g1        */
  571.        0x05000000,    /* sethi    %hi(8 * glapioffset), %g2    */
  572.        0x8410a000,    /* or        %g2, %lo(8 * glapioffset), %g2    */
  573.        0xc6584002,    /* ldx        [%g1 + %g2], %g3        */
  574.        0x81c0c000,    /* jmpl        %g3, %g0            */
  575.        0x01000000    /*  nop                        */
  576.    };
  577. #else
  578.    static const unsigned int insn_template[] = {
  579.        0x03000000,    /* sethi    %hi(_glapi_Dispatch), %g1      */
  580.        0xc2006000,    /* ld        [%g1 + %lo(_glapi_Dispatch)], %g1 */
  581.        0xc6006000,    /* ld        [%g1 + %lo(4*glapioffset)], %g3      */
  582.        0x81c0c000,    /* jmpl        %g3, %g0              */
  583.        0x01000000    /*  nop                          */
  584.    };
  585. #endif
  586.    unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
  587.    unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
  588.    if (code) {
  589.       memcpy(code, insn_template, sizeof(insn_template));
  590.  
  591. #ifdef __sparc_v9__
  592.       code[0] |= (glapi_addr >> (32 + 10));
  593.       code[1] |= ((glapi_addr & 0xffffffff) >> 10);
  594.       __glapi_sparc_icache_flush(&code[0]);
  595.       code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
  596.       code[3] |= (glapi_addr & ((1 << 10) - 1));
  597.       __glapi_sparc_icache_flush(&code[2]);
  598.       code[6] |= ((functionOffset * 8) >> 10);
  599.       code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
  600.       __glapi_sparc_icache_flush(&code[6]);
  601. #else
  602.       code[0] |= (glapi_addr >> 10);
  603.       code[1] |= (glapi_addr & ((1 << 10) - 1));
  604.       __glapi_sparc_icache_flush(&code[0]);
  605.       code[2] |= (functionOffset * 4);
  606.       __glapi_sparc_icache_flush(&code[2]);
  607. #endif
  608.    }
  609.    return code;
  610. #else
  611.    return NULL;
  612. #endif /* USE_*_ASM */
  613. }
  614.  
  615.  
  616. /*
  617.  * This function inserts a new dispatch offset into the assembly language
  618.  * stub that was generated with the preceeding function.
  619.  */
  620. static void
  621. fill_in_entrypoint_offset(void *entrypoint, GLuint offset)
  622. {
  623. #if defined(USE_X86_ASM)
  624.  
  625.    unsigned char *code = (unsigned char *) entrypoint;
  626.    *(unsigned int *)(code + 0x0b) = offset * 4;
  627.    *(unsigned int *)(code + 0x16) = offset * 4;
  628.  
  629. #elif defined(USE_SPARC_ASM)
  630.  
  631.    /* XXX this hasn't been tested! */
  632.    unsigned int *code = (unsigned int *) entrypoint;
  633. #ifdef __sparc_v9__
  634.    code[6] = 0x05000000;  /* sethi    %hi(8 * glapioffset), %g2    */
  635.    code[7] = 0x8410a000;  /* or        %g2, %lo(8 * glapioffset), %g2    */
  636.    code[6] |= ((offset * 8) >> 10);
  637.    code[7] |= ((offset * 8) & ((1 << 10) - 1));
  638.    __glapi_sparc_icache_flush(&code[6]);
  639. #else /* __sparc_v9__ */
  640.    code[2] = 0xc6006000;  /* ld        [%g1 + %lo(4*glapioffset)], %g3      */
  641.    code[2] |= (offset * 4);
  642.    __glapi_sparc_icache_flush(&code[2]);
  643. #endif /* __sparc_v9__ */
  644.  
  645. #endif /* USE_*_ASM */
  646. }
  647.  
  648.  
  649. /*
  650.  * Add a new extension function entrypoint.
  651.  * Return: GL_TRUE = success or GL_FALSE = failure
  652.  */
  653. GLboolean
  654. _glapi_add_entrypoint(const char *funcName, GLuint offset)
  655. {
  656.    /* trivial rejection test */
  657.    if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
  658.       return GL_FALSE;
  659.  
  660.    /* first check if the named function is already statically present */
  661.    {
  662.       GLint index = get_static_proc_offset(funcName);
  663.       if (index >= 0) {
  664.          return (GLboolean) ((GLuint) index == offset);  /* bad offset! */
  665.       }
  666.    }
  667.  
  668.    /* See if this function has already been dynamically added */
  669.    {
  670.       GLuint i;
  671.       for (i = 0; i < NumExtEntryPoints; i++) {
  672.          if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
  673.             /* function already registered */
  674.             if (ExtEntryTable[i].Offset == offset) {
  675.                return GL_TRUE;  /* offsets match */
  676.             }
  677.             else if (ExtEntryTable[i].Offset == ~0
  678.                      && offset < DISPATCH_TABLE_SIZE) {
  679.                /* need to patch-up the dispatch code */
  680.                if (offset != ~0) {
  681.                   fill_in_entrypoint_offset(ExtEntryTable[i].Address, offset);
  682.                   ExtEntryTable[i].Offset = offset;
  683.                }
  684.                return GL_TRUE;
  685.             }
  686.             else {
  687.                return GL_FALSE;  /* bad offset! */
  688.             }
  689.          }
  690.       }
  691.    }
  692.  
  693.    /* This is a new function, try to add it.  */
  694.    if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS ||
  695.        offset >= DISPATCH_TABLE_SIZE) {
  696.       /* No space left */
  697.       return GL_FALSE;
  698.    }
  699.    else {
  700.       void *entrypoint = generate_entrypoint(offset);
  701.       if (!entrypoint)
  702.          return GL_FALSE; /* couldn't generate assembly */
  703.  
  704.       /* OK! */
  705.       ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
  706.       ExtEntryTable[NumExtEntryPoints].Offset = offset;
  707.       ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
  708.       NumExtEntryPoints++;
  709.  
  710.       return GL_TRUE;  /* success */
  711.    }
  712.  
  713.    /* should never get here, silence compiler warnings */
  714.    return GL_FALSE;
  715. }
  716.  
  717.  
  718. /*
  719.  * Return offset of entrypoint for named function within dispatch table.
  720.  */
  721. GLint
  722. _glapi_get_proc_offset(const char *funcName)
  723. {
  724.    /* search extension functions first */
  725.    GLuint i;
  726.    for (i = 0; i < NumExtEntryPoints; i++) {
  727.       if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
  728.          return ExtEntryTable[i].Offset;
  729.       }
  730.    }
  731.  
  732.    /* search static functions */
  733.    return get_static_proc_offset(funcName);
  734. }
  735.  
  736.  
  737.  
  738. /*
  739.  * Return entrypoint for named function.
  740.  */
  741. const GLvoid *
  742. _glapi_get_proc_address(const char *funcName)
  743. {
  744.    /* search extension functions first */
  745.    GLuint i;
  746.    for (i = 0; i < NumExtEntryPoints; i++) {
  747.       if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
  748.          return ExtEntryTable[i].Address;
  749.       }
  750.    }
  751.  
  752.    /* search static functions */
  753.    {
  754.       const GLvoid *func = get_static_proc_address(funcName);
  755.       if (func)
  756.          return func;
  757.    }
  758.  
  759.    /* generate new entrypoint - use a temporary dispatch offset of
  760.     * ~0 (i.e. -1).  Later, when the driver calls _glapi_add_entrypoint()
  761.     * we'll put in the proper offset.  If that never happens, and the
  762.     * user calls this function, he'll segfault.  That's what you get
  763.     * when you try calling a GL function that doesn't really exist.
  764.     */
  765.    if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
  766.       GLvoid *entrypoint = generate_entrypoint(~0);
  767.       if (!entrypoint)
  768.          return GL_FALSE;
  769.  
  770.       ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
  771.       ExtEntryTable[NumExtEntryPoints].Offset = ~0;
  772.       ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
  773.       NumExtEntryPoints++;
  774.  
  775.       return entrypoint;
  776.    }
  777.    else {
  778.       /* no space for new functions! */
  779.       return NULL;
  780.    }
  781. }
  782.  
  783.  
  784.  
  785. /*
  786.  * Return the name of the function at the given dispatch offset.
  787.  * This is only intended for debugging.
  788.  */
  789. const char *
  790. _glapi_get_proc_name(GLuint offset)
  791. {
  792.    const GLuint n = sizeof(static_functions) / sizeof(struct name_address_offset);
  793.    GLuint i;
  794.  
  795.    /* search built-in functions */
  796.    for (i = 0; i < n; i++) {
  797.       if (static_functions[i].Offset == offset)
  798.          return static_functions[i].Name;
  799.    }
  800.  
  801.    /* search added extension functions */
  802.    for (i = 0; i < NumExtEntryPoints; i++) {
  803.       if (ExtEntryTable[i].Offset == offset) {
  804.          return ExtEntryTable[i].Name;
  805.       }
  806.    }
  807.    return NULL;
  808. }
  809.  
  810.  
  811.  
  812. /*
  813.  * Return size of dispatch table struct as number of functions (or
  814.  * slots).
  815.  */
  816. GLuint
  817. _glapi_get_dispatch_table_size(void)
  818. {
  819.    return DISPATCH_TABLE_SIZE;
  820. }
  821.  
  822.  
  823.  
  824. /*
  825.  * Get API dispatcher version string.
  826.  */
  827. const char *
  828. _glapi_get_version(void)
  829. {
  830.    return "20021001";  /* YYYYMMDD */
  831. }
  832.  
  833.  
  834.  
  835. /*
  836.  * Make sure there are no NULL pointers in the given dispatch table.
  837.  * Intended for debugging purposes.
  838.  */
  839. void
  840. _glapi_check_table(const struct _glapi_table *table)
  841. {
  842. #ifdef DEBUG
  843.    const GLuint entries = _glapi_get_dispatch_table_size();
  844.    const void **tab = (const void **) table;
  845.    GLuint i;
  846.    for (i = 1; i < entries; i++) {
  847.       assert(tab[i]);
  848.    }
  849.  
  850.    /* Do some spot checks to be sure that the dispatch table
  851.     * slots are assigned correctly.
  852.     */
  853.    {
  854.       GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
  855.       char *BeginFunc = (char*) &table->Begin;
  856.       GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
  857.       assert(BeginOffset == _gloffset_Begin);
  858.       assert(BeginOffset == offset);
  859.    }
  860.    {
  861.       GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
  862.       char *viewportFunc = (char*) &table->Viewport;
  863.       GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
  864.       assert(viewportOffset == _gloffset_Viewport);
  865.       assert(viewportOffset == offset);
  866.    }
  867.    {
  868.       GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
  869.       char *VertexPointerFunc = (char*) &table->VertexPointer;
  870.       GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
  871.       assert(VertexPointerOffset == _gloffset_VertexPointer);
  872.       assert(VertexPointerOffset == offset);
  873.    }
  874.    {
  875.       GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
  876.       char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
  877.       GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
  878.       assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
  879.       assert(ResetMinMaxOffset == offset);
  880.    }
  881.    {
  882.       GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
  883.       char *blendColorFunc = (char*) &table->BlendColor;
  884.       GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
  885.       assert(blendColorOffset == _gloffset_BlendColor);
  886.       assert(blendColorOffset == offset);
  887.    }
  888.    {
  889.       GLuint istextureOffset = _glapi_get_proc_offset("glIsTextureEXT");
  890.       char *istextureFunc = (char*) &table->IsTextureEXT;
  891.       GLuint offset = (istextureFunc - (char *) table) / sizeof(void *);
  892.       assert(istextureOffset == _gloffset_IsTextureEXT);
  893.       assert(istextureOffset == offset);
  894.    }
  895.    {
  896.       GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
  897.       char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
  898.       GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
  899.       assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
  900.       assert(secondaryColor3fOffset == offset);
  901.       assert(_glapi_get_proc_address("glSecondaryColor3fEXT") == (void *) &glSecondaryColor3fEXT);
  902.    }
  903.    {
  904.       GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
  905.       char *pointParameterivFunc = (char*) &table->PointParameterivNV;
  906.       GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
  907.       assert(pointParameterivOffset == _gloffset_PointParameterivNV);
  908.       assert(pointParameterivOffset == offset);
  909.       assert(_glapi_get_proc_address("glPointParameterivNV") == (void *) &glPointParameterivNV);
  910.    }
  911.    {
  912.       GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
  913.       char *setFenceFunc = (char*) &table->SetFenceNV;
  914.       GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
  915.       assert(setFenceOffset == _gloffset_SetFenceNV);
  916.       assert(setFenceOffset == offset);
  917.       assert(_glapi_get_proc_address("glSetFenceNV") == (void *) &glSetFenceNV);
  918.    }
  919. #endif
  920. }
  921.