1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2009 Chia-I Wu <olv@0xlab.org>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 
26 /**
27  * \file remap.c
28  * Remap table management.
29  *
30  * Entries in the dispatch table are either static or dynamic.  The
31  * dispatch table is shared by mesa core and glapi.  When they are
32  * built separately, it is possible that a static entry in mesa core
33  * is dynamic, or assigned a different static offset, in glapi.  The
34  * remap table is in charge of mapping a static entry in mesa core to
35  * a dynamic entry, or the corresponding static entry, in glapi.
36  */
37 
38 #include <stdbool.h>
39 #include <string.h>
40 #include "remap.h"
41 
42 #include "glapi/glapi.h"
43 
44 #define MAX_ENTRY_POINTS 16
45 
46 #define need_MESA_remap_table
47 #include "main/remap_helper.h"
48 #include "errors.h"
49 
50 
51 /* this is global for quick access */
52 int driDispatchRemapTable[driDispatchRemapTable_size];
53 
54 
55 /**
56  * Map a function by its spec.  The function will be added to glapi,
57  * and the dispatch offset will be returned.
58  *
59  * \param spec a '\0'-separated string array specifying a function.
60  *        It begins with the parameter signature of the function,
61  *        followed by the names of the entry points.  An empty entry
62  *        point name terminates the array.
63  *
64  * \return the offset of the (re-)mapped function in the dispatch
65  *         table, or -1.
66  */
67 static int
map_function_spec(const char * spec)68 map_function_spec(const char *spec)
69 {
70    const char *signature;
71    const char *names[MAX_ENTRY_POINTS + 1];
72    int num_names = 0;
73 
74    if (!spec)
75       return -1;
76 
77    signature = spec;
78    spec += strlen(spec) + 1;
79 
80    /* spec is terminated by an empty string */
81    while (*spec) {
82       names[num_names] = spec;
83       num_names++;
84       if (num_names >= MAX_ENTRY_POINTS)
85          break;
86       spec += strlen(spec) + 1;
87    }
88    if (!num_names)
89       return -1;
90 
91    names[num_names] = NULL;
92 
93    /* add the entry points to the dispatch table */
94    return _glapi_add_dispatch(names, signature);
95 }
96 
97 
98 /**
99  * Initialize the remap table.  This is called in one_time_init().
100  * The remap table needs to be initialized before calling the
101  * CALL/GET/SET macros defined in main/dispatch.h.
102  */
103 void
_mesa_init_remap_table(void)104 _mesa_init_remap_table(void)
105 {
106    static bool initialized = false;
107    GLint i;
108 
109    if (initialized)
110       return;
111    initialized = true;
112 
113    /* initialize the MESA_remap_table_functions table */
114    for (i = 0; i < driDispatchRemapTable_size; i++) {
115       int offset;
116       const char *spec;
117 
118       /* sanity check */
119       assert(i == MESA_remap_table_functions[i].remap_index);
120       spec = _mesa_function_pool + MESA_remap_table_functions[i].pool_index;
121 
122       offset = map_function_spec(spec);
123       /* store the dispatch offset in the MESA_remap_table_functions table */
124       driDispatchRemapTable[i] = offset;
125       if (offset < 0) {
126          const char *name = spec + strlen(spec) + 1;
127          _mesa_warning(NULL, "failed to remap %s", name);
128       }
129    }
130 }
131