blob: 1f640e3e10e05b66cf72dc32389167a98a48951f [file] [log] [blame]
Brian Paulfbd8f211999-11-11 01:22:25 +00001
2/*
3 * Mesa 3-D graphics library
Brian Paul5104b4d2002-03-07 21:50:41 +00004 * Version: 4.1
Brian Paulfbd8f211999-11-11 01:22:25 +00005 *
Brian Paul5104b4d2002-03-07 21:50:41 +00006 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
Brian Paulfbd8f211999-11-11 01:22:25 +00007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
Brian Paul7e1161b1999-11-25 18:17:04 +000027/*
28 * This file manages the OpenGL API dispatch layer.
29 * The dispatch table (struct _glapi_table) is basically just a list
30 * of function pointers.
31 * There are functions to set/get the current dispatch table for the
32 * current thread and to manage registration/dispatch of dynamically
33 * added extension functions.
Brian Paul9f943992000-01-28 19:03:33 +000034 *
35 * It's intended that this file and the other glapi*.[ch] files are
36 * flexible enough to be reused in several places: XFree86, DRI-
37 * based libGL.so, and perhaps the SGI SI.
38 *
Brian Paul4e9676f2002-06-29 19:48:15 +000039 * NOTE: There are no dependencies on Mesa in this code.
Brian Paulab0c8862001-01-23 23:35:47 +000040 *
41 * Versions (API changes):
42 * 2000/02/23 - original version for Mesa 3.3 and XFree86 4.0
43 * 2001/01/16 - added dispatch override feature for Mesa 3.5
Brian Paul4e9676f2002-06-29 19:48:15 +000044 * 2002/06/28 - added _glapi_set_warning_func(), Mesa 4.1.
Brian Paul54f3aab2002-10-02 01:51:44 +000045 * 2002/10/01 - _glapi_get_proc_address() will now generate new entrypoints
46 * itself (using offset ~0). _glapi_add_entrypoint() can be
47 * called afterward and it'll fill in the correct dispatch
48 * offset. This allows DRI libGL to avoid probing for DRI
49 * drivers! No changes to the public glapi interface.
Brian Paul7e1161b1999-11-25 18:17:04 +000050 */
51
52
53
Brian Paul3c27be32000-02-10 21:27:48 +000054#include "glheader.h"
Brian Paulfbd8f211999-11-11 01:22:25 +000055#include "glapi.h"
Brian Paul0c239fc1999-12-16 12:38:11 +000056#include "glapioffsets.h"
57#include "glapitable.h"
Brian Paul9f943992000-01-28 19:03:33 +000058#include "glthread.h"
Brian Paulbb72d321999-12-16 17:31:59 +000059
Brian Paul3c257e12001-03-28 17:19:58 +000060/***** BEGIN NO-OP DISPATCH *****/
61
62static GLboolean WarnFlag = GL_FALSE;
Brian Paul4e9676f2002-06-29 19:48:15 +000063static _glapi_warning_func warning_func;
Brian Paul3c257e12001-03-28 17:19:58 +000064
Brian Paul4e9676f2002-06-29 19:48:15 +000065
66/*
67 * Enable/disable printing of warning messages.
68 */
Brian Paul3c257e12001-03-28 17:19:58 +000069void
70_glapi_noop_enable_warnings(GLboolean enable)
71{
72 WarnFlag = enable;
73}
74
Brian Paul4e9676f2002-06-29 19:48:15 +000075/*
76 * Register a callback function for reporting errors.
77 */
78void
79_glapi_set_warning_func( _glapi_warning_func func )
80{
81 warning_func = func;
82}
83
Brian Paul3c257e12001-03-28 17:19:58 +000084static GLboolean
85warn(void)
86{
Brian Paul4e9676f2002-06-29 19:48:15 +000087 if ((WarnFlag || getenv("MESA_DEBUG") || getenv("LIBGL_DEBUG"))
88 && warning_func) {
Brian Paul3c257e12001-03-28 17:19:58 +000089 return GL_TRUE;
Brian Paul4e9676f2002-06-29 19:48:15 +000090 }
91 else {
Brian Paul3c257e12001-03-28 17:19:58 +000092 return GL_FALSE;
Brian Paul4e9676f2002-06-29 19:48:15 +000093 }
Brian Paul3c257e12001-03-28 17:19:58 +000094}
95
96
97#define KEYWORD1 static
Daniel Borca722cb892004-01-07 12:37:09 +000098#define KEYWORD2 GLAPIENTRY
Brian Paul3c257e12001-03-28 17:19:58 +000099#define NAME(func) NoOp##func
100
Brian Paul4e9676f2002-06-29 19:48:15 +0000101#define F NULL
Brian Paul3c257e12001-03-28 17:19:58 +0000102
Brian Paul4e9676f2002-06-29 19:48:15 +0000103#define DISPATCH(func, args, msg) \
104 if (warn()) { \
105 warning_func(NULL, "GL User Error: called without context:"); \
106 warning_func msg; \
Brian Paul3c257e12001-03-28 17:19:58 +0000107 }
108
Brian Paul4e9676f2002-06-29 19:48:15 +0000109#define RETURN_DISPATCH(func, args, msg) \
110 if (warn()) { \
111 warning_func(NULL, "GL User Error: called without context:"); \
112 warning_func msg; \
113 } \
Brian Paul3c257e12001-03-28 17:19:58 +0000114 return 0
115
116#define DISPATCH_TABLE_NAME __glapi_noop_table
117#define UNUSED_TABLE_NAME __usused_noop_functions
118
119#define TABLE_ENTRY(name) (void *) NoOp##name
120
121static int NoOpUnused(void)
122{
123 if (warn()) {
Brian Paul4e9676f2002-06-29 19:48:15 +0000124 warning_func(NULL, "GL User Error: calling extension function without a current context\n");
Brian Paul3c257e12001-03-28 17:19:58 +0000125 }
126 return 0;
127}
128
129#include "glapitemp.h"
130
131/***** END NO-OP DISPATCH *****/
132
133
134
135/***** BEGIN THREAD-SAFE DISPATCH *****/
Brian Paul3c257e12001-03-28 17:19:58 +0000136
137#if defined(THREADS)
138
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000139/**
140 * \name Multi-threaded control support variables
141 *
142 * If thread-safety is supported, there are two potential mechanisms that can
143 * be used. The old-style mechanism would set \c _glapi_Dispatch to a special
144 * thread-safe dispatch table. These dispatch routines would call
145 * \c _glapi_get_dispatch to get the actual dispatch pointer. In this
146 * setup \c _glapi_Dispatch could never be \c NULL. This dual layered
147 * dispatch setup performed great for single-threaded apps, but didn't
148 * perform well for multithreaded apps.
149 *
150 * In the new mechansim, there are two variables. The first is
151 * \c _glapi_DispatchTSD. In the single-threaded case, this variable points
152 * to the dispatch table. In the multi-threaded case, this variable is
153 * \c NULL, and thread-specific variable \c _gl_DispatchTSD points to the
154 * actual dispatch table. \c _glapi_DispatchTSD is used to signal to the
155 * static dispatch functions to call \c _glapi_get_dispatch to get the real
156 * dispatch table.
157 *
Ian Romanickd14d1032004-07-02 00:01:09 +0000158 * There is a race condition in setting \c _glapi_DispatchTSD to \c NULL.
159 * It is possible for the original thread to be setting it at the same instant
160 * a new thread, perhaps running on a different processor, is clearing it.
161 * Because of that, \c ThreadSafe, which can only ever be changed to
162 * \c GL_FALSE, is used to determin whether or not the application is
163 * multithreaded.
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000164 */
165/*@{*/
Ian Romanickd14d1032004-07-02 00:01:09 +0000166static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000167_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
168static _glthread_TSD RealDispatchTSD; /**< only when using override */
169static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
170/*@}*/
Brian Paul3c257e12001-03-28 17:19:58 +0000171
172
Brian Paul3c257e12001-03-28 17:19:58 +0000173#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
174#define UNUSED_TABLE_NAME __usused_threadsafe_functions
175
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000176#define TABLE_ENTRY(name) (void *) gl##name
Brian Paul3c257e12001-03-28 17:19:58 +0000177
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000178static int glUnused(void)
Brian Paul3c257e12001-03-28 17:19:58 +0000179{
180 return 0;
181}
182
183#include "glapitemp.h"
184
185#endif
186
187/***** END THREAD-SAFE DISPATCH *****/
188
189
190
Brian Paul8ceb5c32000-02-24 22:14:04 +0000191struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000192#if defined( THREADS )
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000193struct _glapi_table *_glapi_DispatchTSD = (struct _glapi_table *) __glapi_noop_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000194#endif
Brian Paulab0c8862001-01-23 23:35:47 +0000195struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
Brian Paul0f710251999-12-15 15:02:30 +0000196
Ian Romanickd14d1032004-07-02 00:01:09 +0000197
Brian Paul8f91fb61999-12-17 14:51:28 +0000198/* Used when thread safety disabled */
Brian Paulf9b97d92000-01-28 20:17:42 +0000199void *_glapi_Context = NULL;
Brian Paul8f91fb61999-12-17 14:51:28 +0000200
Brian Paul0f710251999-12-15 15:02:30 +0000201
Brian Paulab0c8862001-01-23 23:35:47 +0000202static GLboolean DispatchOverride = GL_FALSE;
203
204
Brian Paul54f3aab2002-10-02 01:51:44 +0000205
Brian Paul3c257e12001-03-28 17:19:58 +0000206/* strdup() is actually not a standard ANSI C or POSIX routine.
207 * Irix will not define it if ANSI mode is in effect.
208 */
209static char *
210str_dup(const char *str)
Randy Frankd7361e12000-03-27 21:13:58 +0000211{
Brian Paulfffb8092000-03-29 18:46:11 +0000212 char *copy;
213 copy = (char*) malloc(strlen(str) + 1);
214 if (!copy)
215 return NULL;
216 strcpy(copy, str);
217 return copy;
Randy Frankd7361e12000-03-27 21:13:58 +0000218}
219
Brian Paul7fb54ae1999-11-19 22:33:50 +0000220
Brian Paulbb72d321999-12-16 17:31:59 +0000221
222/*
223 * We should call this periodically from a function such as glXMakeCurrent
Brian Paul5104b4d2002-03-07 21:50:41 +0000224 * in order to test if multiple threads are being used.
Brian Paulbb72d321999-12-16 17:31:59 +0000225 */
226void
227_glapi_check_multithread(void)
228{
229#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000230 if (!ThreadSafe) {
Brian Paulbb72d321999-12-16 17:31:59 +0000231 static unsigned long knownID;
232 static GLboolean firstCall = GL_TRUE;
233 if (firstCall) {
234 knownID = _glthread_GetID();
235 firstCall = GL_FALSE;
236 }
237 else if (knownID != _glthread_GetID()) {
Ian Romanickd14d1032004-07-02 00:01:09 +0000238 ThreadSafe = GL_TRUE;
Brian Paulbb72d321999-12-16 17:31:59 +0000239 _glapi_set_dispatch(NULL);
240 }
241 }
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000242 else if (!_glapi_get_dispatch()) {
243 /* make sure that this thread's dispatch pointer isn't null */
244 _glapi_set_dispatch(NULL);
245 }
Brian Paulbb72d321999-12-16 17:31:59 +0000246#endif
247}
248
249
250
251/*
Brian Paul8f91fb61999-12-17 14:51:28 +0000252 * Set the current context pointer for this thread.
253 * The context pointer is an opaque type which should be cast to
254 * void from the real context pointer type.
255 */
256void
Brian Paulf9b97d92000-01-28 20:17:42 +0000257_glapi_set_context(void *context)
Brian Paul8f91fb61999-12-17 14:51:28 +0000258{
259#if defined(THREADS)
Brian Paul3c27be32000-02-10 21:27:48 +0000260 _glthread_SetTSD(&ContextTSD, context);
Ian Romanickd14d1032004-07-02 00:01:09 +0000261 _glapi_Context = (ThreadSafe) ? NULL : context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000262#else
Brian Paulf9b97d92000-01-28 20:17:42 +0000263 _glapi_Context = context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000264#endif
265}
266
267
268
269/*
270 * Get the current context pointer for this thread.
271 * The context pointer is an opaque type which should be cast from
272 * void to the real context pointer type.
273 */
274void *
Brian Paulf9b97d92000-01-28 20:17:42 +0000275_glapi_get_context(void)
Brian Paul8f91fb61999-12-17 14:51:28 +0000276{
277#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000278 if (ThreadSafe) {
Brian Paul8f91fb61999-12-17 14:51:28 +0000279 return _glthread_GetTSD(&ContextTSD);
280 }
281 else {
Brian Paulf9b97d92000-01-28 20:17:42 +0000282 return _glapi_Context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000283 }
284#else
Brian Paulf9b97d92000-01-28 20:17:42 +0000285 return _glapi_Context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000286#endif
287}
288
289
290
291/*
Brian Paul7fb54ae1999-11-19 22:33:50 +0000292 * Set the global or per-thread dispatch table pointer.
293 */
294void
295_glapi_set_dispatch(struct _glapi_table *dispatch)
296{
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000297 struct _glapi_table * old_style_dispatch;
298
299
300 /* Use the no-op functions if a NULL dispatch table was requested.
301 */
302
Keith Whitwell009aa3e2004-06-30 11:48:21 +0000303 old_style_dispatch = (dispatch == NULL)
304 ? (struct _glapi_table *) __glapi_noop_table : dispatch;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000305
Brian Paul7fb54ae1999-11-19 22:33:50 +0000306#ifdef DEBUG
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000307 if (dispatch != NULL) {
Brian Paul7fb54ae1999-11-19 22:33:50 +0000308 _glapi_check_table(dispatch);
309 }
310#endif
311
312#if defined(THREADS)
Brian Paulab0c8862001-01-23 23:35:47 +0000313 if (DispatchOverride) {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000314 _glthread_SetTSD(&RealDispatchTSD, (void *) old_style_dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000315 if (ThreadSafe)
Brian Paul3c257e12001-03-28 17:19:58 +0000316 _glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
Brian Paul3a71d052000-09-05 20:17:37 +0000317 else
Brian Paulab0c8862001-01-23 23:35:47 +0000318 _glapi_RealDispatch = dispatch;
Brian Paul3b18a362000-09-26 15:27:20 +0000319 }
320 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000321 /* normal operation */
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000322 _glthread_SetTSD(&_gl_DispatchTSD, (void *) old_style_dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000323 if (ThreadSafe) {
324 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
325 _glapi_DispatchTSD = NULL;
326 }
327 else {
328 _glapi_Dispatch = old_style_dispatch;
329 _glapi_DispatchTSD = dispatch;
330 }
Brian Paul3a71d052000-09-05 20:17:37 +0000331 }
Brian Paul3a71d052000-09-05 20:17:37 +0000332#else /*THREADS*/
Brian Paulab0c8862001-01-23 23:35:47 +0000333 if (DispatchOverride) {
334 _glapi_RealDispatch = dispatch;
335 }
336 else {
337 _glapi_Dispatch = dispatch;
338 }
Brian Paul3a71d052000-09-05 20:17:37 +0000339#endif /*THREADS*/
Brian Paul7fb54ae1999-11-19 22:33:50 +0000340}
341
342
Brian Paulbb72d321999-12-16 17:31:59 +0000343
Brian Paul7fb54ae1999-11-19 22:33:50 +0000344/*
Brian Paulbb72d321999-12-16 17:31:59 +0000345 * Return pointer to current dispatch table for calling thread.
Brian Paul7fb54ae1999-11-19 22:33:50 +0000346 */
347struct _glapi_table *
348_glapi_get_dispatch(void)
349{
350#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000351 if (ThreadSafe) {
Brian Paulab0c8862001-01-23 23:35:47 +0000352 if (DispatchOverride) {
353 return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
354 }
355 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000356 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paulab0c8862001-01-23 23:35:47 +0000357 }
Brian Paulbb72d321999-12-16 17:31:59 +0000358 }
Brian Paul590d3471999-12-17 12:20:23 +0000359 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000360 if (DispatchOverride) {
361 assert(_glapi_RealDispatch);
362 return _glapi_RealDispatch;
363 }
364 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000365 assert(_glapi_DispatchTSD);
366 return _glapi_DispatchTSD;
Brian Paulab0c8862001-01-23 23:35:47 +0000367 }
Brian Paul590d3471999-12-17 12:20:23 +0000368 }
Brian Paul7fb54ae1999-11-19 22:33:50 +0000369#else
Brian Paulc2319b42000-01-17 19:28:31 +0000370 return _glapi_Dispatch;
Brian Paul7fb54ae1999-11-19 22:33:50 +0000371#endif
372}
373
374
Brian Paulab0c8862001-01-23 23:35:47 +0000375/*
376 * Notes on dispatch overrride:
377 *
378 * Dispatch override allows an external agent to hook into the GL dispatch
379 * mechanism before execution goes into the core rendering library. For
380 * example, a trace mechanism would insert itself as an overrider, print
381 * logging info for each GL function, then dispatch to the real GL function.
382 *
383 * libGLS (GL Stream library) is another agent that might use override.
384 *
385 * We don't allow more than one layer of overriding at this time.
386 * In the future we may allow nested/layered override. In that case
387 * _glapi_begin_dispatch_override() will return an override layer,
388 * _glapi_end_dispatch_override(layer) will remove an override layer
389 * and _glapi_get_override_dispatch(layer) will return the dispatch
390 * table for a given override layer. layer = 0 will be the "real"
391 * dispatch table.
392 */
393
394/*
395 * Return: dispatch override layer number.
396 */
397int
398_glapi_begin_dispatch_override(struct _glapi_table *override)
Brian Paul3a71d052000-09-05 20:17:37 +0000399{
Brian Paulab0c8862001-01-23 23:35:47 +0000400 struct _glapi_table *real = _glapi_get_dispatch();
401
402 assert(!DispatchOverride); /* can't nest at this time */
403 DispatchOverride = GL_TRUE;
404
405 _glapi_set_dispatch(real);
Brian Paul3a71d052000-09-05 20:17:37 +0000406
407#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000408 _glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
Ian Romanickd14d1032004-07-02 00:01:09 +0000409 if ( ThreadSafe ) {
Brian Paul3c257e12001-03-28 17:19:58 +0000410 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000411 _glapi_DispatchTSD = NULL;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000412 }
413 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000414 _glapi_Dispatch = override;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000415 _glapi_DispatchTSD = override;
416 }
Brian Paulab0c8862001-01-23 23:35:47 +0000417#else
418 _glapi_Dispatch = override;
419#endif
420 return 1;
421}
422
423
424void
425_glapi_end_dispatch_override(int layer)
426{
427 struct _glapi_table *real = _glapi_get_dispatch();
428 (void) layer;
429 DispatchOverride = GL_FALSE;
430 _glapi_set_dispatch(real);
431 /* the rest of this isn't needed, just play it safe */
432#if defined(THREADS)
433 _glthread_SetTSD(&RealDispatchTSD, NULL);
434#endif
435 _glapi_RealDispatch = NULL;
436}
437
438
439struct _glapi_table *
440_glapi_get_override_dispatch(int layer)
441{
442 if (layer == 0) {
443 return _glapi_get_dispatch();
Brian Paul3a71d052000-09-05 20:17:37 +0000444 }
445 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000446 if (DispatchOverride) {
447#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000448 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paul3a71d052000-09-05 20:17:37 +0000449#else
Brian Paulab0c8862001-01-23 23:35:47 +0000450 return _glapi_Dispatch;
Brian Paul3a71d052000-09-05 20:17:37 +0000451#endif
Brian Paulab0c8862001-01-23 23:35:47 +0000452 }
453 else {
454 return NULL;
455 }
456 }
Brian Paul3a71d052000-09-05 20:17:37 +0000457}
Brian Paulab0c8862001-01-23 23:35:47 +0000458
Brian Paul3a71d052000-09-05 20:17:37 +0000459
Brian Paul959f8022000-03-19 01:10:11 +0000460struct name_address_offset {
461 const char *Name;
462 GLvoid *Address;
463 GLuint Offset;
464};
465
Brian Paul0c239fc1999-12-16 12:38:11 +0000466
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000467#if !defined( USE_X86_ASM )
Ian Romanick78677992004-05-27 00:05:13 +0000468#define NEED_FUNCTION_POINTER
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000469#endif
Ian Romanick78677992004-05-27 00:05:13 +0000470
Brian Paul54f3aab2002-10-02 01:51:44 +0000471/* The code in this file is auto-generated with Python */
Brian Paulb5fd8862001-11-18 22:48:11 +0000472#include "glprocs.h"
Brian Paul7fb54ae1999-11-19 22:33:50 +0000473
Brian Paul959f8022000-03-19 01:10:11 +0000474
Ian Romanick78677992004-05-27 00:05:13 +0000475static const glprocs_table_t *
476find_entry( const char * n )
477{
478 unsigned i;
479
480 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
481 const char * test_name;
482
483 test_name = gl_string_table + static_functions[i].Name_offset;
484 if (strcmp(test_name, n) == 0) {
485 return & static_functions[i];
486 }
487 }
488 return NULL;
489}
490
Brian Paul959f8022000-03-19 01:10:11 +0000491/*
492 * Return dispatch table offset of the named static (built-in) function.
493 * Return -1 if function not found.
494 */
495static GLint
496get_static_proc_offset(const char *funcName)
497{
Ian Romanick78677992004-05-27 00:05:13 +0000498 const glprocs_table_t * const f = find_entry( funcName );
499
500 if ( f != NULL ) {
501 return f->Offset;
Brian Paul959f8022000-03-19 01:10:11 +0000502 }
503 return -1;
504}
505
506
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000507#ifdef USE_X86_ASM
508extern const GLubyte gl_dispatch_functions_start[];
509
510# if defined(PTHREADS)
511# define X86_DISPATCH_FUNCTION_SIZE 32
512# else
513# define X86_DISPATCH_FUNCTION_SIZE 16
514# endif
515
516
517/*
518 * Return dispatch function address the named static (built-in) function.
519 * Return NULL if function not found.
520 */
521static const GLvoid *
522get_static_proc_address(const char *funcName)
523{
524 const glprocs_table_t * const f = find_entry( funcName );
525
526 if ( f != NULL ) {
527 return gl_dispatch_functions_start
528 + (X86_DISPATCH_FUNCTION_SIZE * f->Offset);
529 }
530 else {
531 return NULL;
532 }
533}
534
535#else
536
537
Brian Paul959f8022000-03-19 01:10:11 +0000538/*
539 * Return dispatch function address the named static (built-in) function.
540 * Return NULL if function not found.
541 */
Ian Romanick78677992004-05-27 00:05:13 +0000542static const GLvoid *
Brian Paul959f8022000-03-19 01:10:11 +0000543get_static_proc_address(const char *funcName)
544{
Ian Romanick78677992004-05-27 00:05:13 +0000545 const glprocs_table_t * const f = find_entry( funcName );
546 return ( f != NULL ) ? f->Address : NULL;
547}
548
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000549#endif /* USE_X86_ASM */
550
Ian Romanick78677992004-05-27 00:05:13 +0000551
552static const char *
553get_static_proc_name( GLuint offset )
554{
555 unsigned i;
556
557 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
558 if (static_functions[i].Offset == offset) {
559 return gl_string_table + static_functions[i].Name_offset;
Brian Paul9c7ca852000-10-19 20:13:12 +0000560 }
561 }
562 return NULL;
Brian Paul959f8022000-03-19 01:10:11 +0000563}
564
565
566
567/**********************************************************************
568 * Extension function management.
569 */
570
Brian Paul54f3aab2002-10-02 01:51:44 +0000571/*
572 * Number of extension functions which we can dynamically add at runtime.
573 */
574#define MAX_EXTENSION_FUNCS 300
Brian Paul959f8022000-03-19 01:10:11 +0000575
Brian Paul54f3aab2002-10-02 01:51:44 +0000576
577/*
578 * The disptach table size (number of entries) is the sizeof the
579 * _glapi_table struct plus the number of dynamic entries we can add.
580 * The extra slots can be filled in by DRI drivers that register new extension
581 * functions.
582 */
583#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
584
Brian Paul959f8022000-03-19 01:10:11 +0000585
586static struct name_address_offset ExtEntryTable[MAX_EXTENSION_FUNCS];
587static GLuint NumExtEntryPoints = 0;
588
davem694a497e62001-06-06 22:55:28 +0000589#ifdef USE_SPARC_ASM
590extern void __glapi_sparc_icache_flush(unsigned int *);
591#endif
Brian Paul959f8022000-03-19 01:10:11 +0000592
593/*
594 * Generate a dispatch function (entrypoint) which jumps through
595 * the given slot number (offset) in the current dispatch table.
596 * We need assembly language in order to accomplish this.
597 */
598static void *
599generate_entrypoint(GLuint functionOffset)
600{
601#if defined(USE_X86_ASM)
602 /*
603 * This x86 code contributed by Josh Vanderhoof.
604 *
605 * 0: a1 10 32 54 76 movl __glapi_Dispatch,%eax
606 * 00 01 02 03 04
607 * 5: 85 c0 testl %eax,%eax
608 * 05 06
609 * 7: 74 06 je f <entrypoint+0xf>
610 * 07 08
611 * 9: ff a0 10 32 54 76 jmp *0x76543210(%eax)
612 * 09 0a 0b 0c 0d 0e
613 * f: e8 fc ff ff ff call __glapi_get_dispatch
614 * 0f 10 11 12 13
615 * 14: ff a0 10 32 54 76 jmp *0x76543210(%eax)
616 * 14 15 16 17 18 19
617 */
Brian Paul54f3aab2002-10-02 01:51:44 +0000618 static const unsigned char insn_template[] = {
Brian Paul959f8022000-03-19 01:10:11 +0000619 0xa1, 0x00, 0x00, 0x00, 0x00,
620 0x85, 0xc0,
621 0x74, 0x06,
622 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
623 0xe8, 0x00, 0x00, 0x00, 0x00,
624 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
625 };
Brian Pauldec2a4d2002-10-29 15:03:14 +0000626 unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000627 unsigned int next_insn;
628 if (code) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000629 memcpy(code, insn_template, sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000630
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000631 *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_DispatchTSD;
Brian Paul959f8022000-03-19 01:10:11 +0000632 *(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
633 next_insn = (unsigned int)(code + 0x14);
634 *(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
635 *(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
636 }
637 return code;
davem69775355a2001-06-05 23:54:00 +0000638#elif defined(USE_SPARC_ASM)
639
Brian Paul9a90cd42003-12-01 22:40:26 +0000640#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000641 static const unsigned int insn_template[] = {
642 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
643 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
644 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
645 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
646 0x8528b020, /* sllx %g2, 32, %g2 */
647 0xc2584002, /* ldx [%g1 + %g2], %g1 */
648 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
649 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
650 0xc6584002, /* ldx [%g1 + %g2], %g3 */
651 0x81c0c000, /* jmpl %g3, %g0 */
652 0x01000000 /* nop */
653 };
654#else
655 static const unsigned int insn_template[] = {
656 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
657 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
658 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
659 0x81c0c000, /* jmpl %g3, %g0 */
660 0x01000000 /* nop */
661 };
662#endif
Brian Pauldec2a4d2002-10-29 15:03:14 +0000663 unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
davem69775355a2001-06-05 23:54:00 +0000664 unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
665 if (code) {
666 memcpy(code, insn_template, sizeof(insn_template));
667
Brian Paul9a90cd42003-12-01 22:40:26 +0000668#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000669 code[0] |= (glapi_addr >> (32 + 10));
670 code[1] |= ((glapi_addr & 0xffffffff) >> 10);
davem694a497e62001-06-06 22:55:28 +0000671 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000672 code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
673 code[3] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000674 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000675 code[6] |= ((functionOffset * 8) >> 10);
676 code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000677 __glapi_sparc_icache_flush(&code[6]);
davem69775355a2001-06-05 23:54:00 +0000678#else
679 code[0] |= (glapi_addr >> 10);
680 code[1] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000681 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000682 code[2] |= (functionOffset * 4);
davem694a497e62001-06-06 22:55:28 +0000683 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000684#endif
685 }
686 return code;
Brian Paul959f8022000-03-19 01:10:11 +0000687#else
688 return NULL;
Brian Paul54f3aab2002-10-02 01:51:44 +0000689#endif /* USE_*_ASM */
Brian Paul959f8022000-03-19 01:10:11 +0000690}
691
692
Brian Paul54f3aab2002-10-02 01:51:44 +0000693/*
694 * This function inserts a new dispatch offset into the assembly language
695 * stub that was generated with the preceeding function.
696 */
697static void
698fill_in_entrypoint_offset(void *entrypoint, GLuint offset)
699{
700#if defined(USE_X86_ASM)
701
702 unsigned char *code = (unsigned char *) entrypoint;
703 *(unsigned int *)(code + 0x0b) = offset * 4;
704 *(unsigned int *)(code + 0x16) = offset * 4;
705
706#elif defined(USE_SPARC_ASM)
707
708 /* XXX this hasn't been tested! */
709 unsigned int *code = (unsigned int *) entrypoint;
Brian Paul9a90cd42003-12-01 22:40:26 +0000710#if defined(__sparc_v9__) && !defined(__linux__)
Brian Paul54f3aab2002-10-02 01:51:44 +0000711 code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
712 code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
713 code[6] |= ((offset * 8) >> 10);
714 code[7] |= ((offset * 8) & ((1 << 10) - 1));
715 __glapi_sparc_icache_flush(&code[6]);
Brian Paul9a90cd42003-12-01 22:40:26 +0000716#else /* __sparc_v9__ && !linux */
Brian Paul54f3aab2002-10-02 01:51:44 +0000717 code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
Brian Paul944ea202002-10-17 16:29:17 +0000718 code[2] |= (offset * 4);
Brian Paul54f3aab2002-10-02 01:51:44 +0000719 __glapi_sparc_icache_flush(&code[2]);
Brian Paul9a90cd42003-12-01 22:40:26 +0000720#endif /* __sparc_v9__ && !linux */
Brian Paul54f3aab2002-10-02 01:51:44 +0000721
722#endif /* USE_*_ASM */
723}
724
Brian Paul959f8022000-03-19 01:10:11 +0000725
726/*
727 * Add a new extension function entrypoint.
728 * Return: GL_TRUE = success or GL_FALSE = failure
729 */
730GLboolean
731_glapi_add_entrypoint(const char *funcName, GLuint offset)
732{
Brian Paul8ad10762002-10-11 17:41:03 +0000733 /* trivial rejection test */
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000734#ifdef MANGLE
735 if (!funcName || funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
736 return NULL;
737#else
Brian Paul8ad10762002-10-11 17:41:03 +0000738 if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
739 return GL_FALSE;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000740#endif
Brian Paul8ad10762002-10-11 17:41:03 +0000741
Brian Paul959f8022000-03-19 01:10:11 +0000742 /* first check if the named function is already statically present */
743 {
744 GLint index = get_static_proc_offset(funcName);
745 if (index >= 0) {
Brian Paulb51b0a82001-03-07 05:06:11 +0000746 return (GLboolean) ((GLuint) index == offset); /* bad offset! */
Brian Paul959f8022000-03-19 01:10:11 +0000747 }
748 }
749
Brian Paul54f3aab2002-10-02 01:51:44 +0000750 /* See if this function has already been dynamically added */
Brian Paul959f8022000-03-19 01:10:11 +0000751 {
Brian Paul959f8022000-03-19 01:10:11 +0000752 GLuint i;
753 for (i = 0; i < NumExtEntryPoints; i++) {
754 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000755 /* function already registered */
Brian Paul959f8022000-03-19 01:10:11 +0000756 if (ExtEntryTable[i].Offset == offset) {
757 return GL_TRUE; /* offsets match */
758 }
Brian Paule4fcea22003-09-19 15:38:15 +0000759 else if (ExtEntryTable[i].Offset == (GLuint) ~0
Brian Paul54f3aab2002-10-02 01:51:44 +0000760 && offset < DISPATCH_TABLE_SIZE) {
761 /* need to patch-up the dispatch code */
Brian Paule4fcea22003-09-19 15:38:15 +0000762 if (offset != (GLuint) ~0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000763 fill_in_entrypoint_offset(ExtEntryTable[i].Address, offset);
764 ExtEntryTable[i].Offset = offset;
765 }
766 return GL_TRUE;
767 }
Brian Paul959f8022000-03-19 01:10:11 +0000768 else {
769 return GL_FALSE; /* bad offset! */
770 }
771 }
772 }
Brian Paul959f8022000-03-19 01:10:11 +0000773 }
774
Brian Paul8ad10762002-10-11 17:41:03 +0000775 /* This is a new function, try to add it. */
776 if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS ||
777 offset >= DISPATCH_TABLE_SIZE) {
778 /* No space left */
779 return GL_FALSE;
780 }
781 else {
782 void *entrypoint = generate_entrypoint(offset);
783 if (!entrypoint)
784 return GL_FALSE; /* couldn't generate assembly */
785
786 /* OK! */
787 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
788 ExtEntryTable[NumExtEntryPoints].Offset = offset;
789 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
790 NumExtEntryPoints++;
791
792 return GL_TRUE; /* success */
793 }
794
795 /* should never get here, silence compiler warnings */
Brian Paul959f8022000-03-19 01:10:11 +0000796 return GL_FALSE;
797}
798
799
Brian Paul959f8022000-03-19 01:10:11 +0000800/*
801 * Return offset of entrypoint for named function within dispatch table.
802 */
803GLint
804_glapi_get_proc_offset(const char *funcName)
805{
806 /* search extension functions first */
Brian Paulb51b0a82001-03-07 05:06:11 +0000807 GLuint i;
Brian Paul959f8022000-03-19 01:10:11 +0000808 for (i = 0; i < NumExtEntryPoints; i++) {
809 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
810 return ExtEntryTable[i].Offset;
811 }
812 }
813
814 /* search static functions */
815 return get_static_proc_offset(funcName);
816}
817
818
819
820/*
821 * Return entrypoint for named function.
822 */
823const GLvoid *
824_glapi_get_proc_address(const char *funcName)
825{
Brian Paulb51b0a82001-03-07 05:06:11 +0000826 GLuint i;
Brian Paula6ed6f42003-08-27 14:48:16 +0000827
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000828#ifdef MANGLE
829 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
830 return NULL;
831#else
Brian Paula6ed6f42003-08-27 14:48:16 +0000832 if (funcName[0] != 'g' || funcName[1] != 'l')
833 return NULL;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000834#endif
Brian Paula6ed6f42003-08-27 14:48:16 +0000835
836 /* search extension functions first */
Brian Paul959f8022000-03-19 01:10:11 +0000837 for (i = 0; i < NumExtEntryPoints; i++) {
838 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
839 return ExtEntryTable[i].Address;
840 }
841 }
842
843 /* search static functions */
Brian Paul54f3aab2002-10-02 01:51:44 +0000844 {
845 const GLvoid *func = get_static_proc_address(funcName);
846 if (func)
847 return func;
848 }
Brian Paul959f8022000-03-19 01:10:11 +0000849
Brian Paul54f3aab2002-10-02 01:51:44 +0000850 /* generate new entrypoint - use a temporary dispatch offset of
851 * ~0 (i.e. -1). Later, when the driver calls _glapi_add_entrypoint()
852 * we'll put in the proper offset. If that never happens, and the
853 * user calls this function, he'll segfault. That's what you get
854 * when you try calling a GL function that doesn't really exist.
855 */
856 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
857 GLvoid *entrypoint = generate_entrypoint(~0);
858 if (!entrypoint)
859 return GL_FALSE;
860
861 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
862 ExtEntryTable[NumExtEntryPoints].Offset = ~0;
863 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
864 NumExtEntryPoints++;
865
866 return entrypoint;
867 }
868 else {
869 /* no space for new functions! */
870 return NULL;
871 }
872}
Brian Paul959f8022000-03-19 01:10:11 +0000873
874
875
876/*
877 * Return the name of the function at the given dispatch offset.
878 * This is only intended for debugging.
879 */
880const char *
881_glapi_get_proc_name(GLuint offset)
882{
Brian Paul959f8022000-03-19 01:10:11 +0000883 GLuint i;
Ian Romanick78677992004-05-27 00:05:13 +0000884 const char * n;
Brian Paul54f3aab2002-10-02 01:51:44 +0000885
886 /* search built-in functions */
Ian Romanick78677992004-05-27 00:05:13 +0000887 n = get_static_proc_name(offset);
888 if ( n != NULL ) {
889 return n;
Brian Paul959f8022000-03-19 01:10:11 +0000890 }
891
892 /* search added extension functions */
893 for (i = 0; i < NumExtEntryPoints; i++) {
894 if (ExtEntryTable[i].Offset == offset) {
895 return ExtEntryTable[i].Name;
896 }
897 }
898 return NULL;
899}
900
901
902
903/*
Brian Paul54f3aab2002-10-02 01:51:44 +0000904 * Return size of dispatch table struct as number of functions (or
905 * slots).
906 */
907GLuint
908_glapi_get_dispatch_table_size(void)
909{
910 return DISPATCH_TABLE_SIZE;
911}
912
913
914
915/*
916 * Get API dispatcher version string.
917 */
918const char *
919_glapi_get_version(void)
920{
921 return "20021001"; /* YYYYMMDD */
922}
923
924
925
926/*
Brian Paul959f8022000-03-19 01:10:11 +0000927 * Make sure there are no NULL pointers in the given dispatch table.
Brian Paul5104b4d2002-03-07 21:50:41 +0000928 * Intended for debugging purposes.
Brian Paul959f8022000-03-19 01:10:11 +0000929 */
930void
931_glapi_check_table(const struct _glapi_table *table)
932{
Brian Paul5104b4d2002-03-07 21:50:41 +0000933#ifdef DEBUG
Brian Paul959f8022000-03-19 01:10:11 +0000934 const GLuint entries = _glapi_get_dispatch_table_size();
935 const void **tab = (const void **) table;
936 GLuint i;
937 for (i = 1; i < entries; i++) {
938 assert(tab[i]);
939 }
940
Brian Paul959f8022000-03-19 01:10:11 +0000941 /* Do some spot checks to be sure that the dispatch table
942 * slots are assigned correctly.
943 */
944 {
945 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
946 char *BeginFunc = (char*) &table->Begin;
947 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
948 assert(BeginOffset == _gloffset_Begin);
949 assert(BeginOffset == offset);
950 }
951 {
952 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
953 char *viewportFunc = (char*) &table->Viewport;
954 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
955 assert(viewportOffset == _gloffset_Viewport);
956 assert(viewportOffset == offset);
957 }
958 {
959 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
960 char *VertexPointerFunc = (char*) &table->VertexPointer;
961 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
962 assert(VertexPointerOffset == _gloffset_VertexPointer);
963 assert(VertexPointerOffset == offset);
964 }
965 {
966 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
967 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
968 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
969 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
970 assert(ResetMinMaxOffset == offset);
971 }
972 {
973 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
974 char *blendColorFunc = (char*) &table->BlendColor;
975 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
976 assert(blendColorOffset == _gloffset_BlendColor);
977 assert(blendColorOffset == offset);
978 }
979 {
980 GLuint istextureOffset = _glapi_get_proc_offset("glIsTextureEXT");
981 char *istextureFunc = (char*) &table->IsTextureEXT;
982 GLuint offset = (istextureFunc - (char *) table) / sizeof(void *);
983 assert(istextureOffset == _gloffset_IsTextureEXT);
984 assert(istextureOffset == offset);
985 }
Brian Paula14cbff2000-10-27 18:31:21 +0000986 {
987 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
988 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
989 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
990 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
991 assert(secondaryColor3fOffset == offset);
992 assert(_glapi_get_proc_address("glSecondaryColor3fEXT") == (void *) &glSecondaryColor3fEXT);
993 }
Brian Paul91d6f122002-05-29 15:23:16 +0000994 {
995 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
996 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
997 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
998 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
999 assert(pointParameterivOffset == offset);
1000 assert(_glapi_get_proc_address("glPointParameterivNV") == (void *) &glPointParameterivNV);
1001 }
Brian Paul54f3aab2002-10-02 01:51:44 +00001002 {
1003 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
1004 char *setFenceFunc = (char*) &table->SetFenceNV;
1005 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
1006 assert(setFenceOffset == _gloffset_SetFenceNV);
1007 assert(setFenceOffset == offset);
1008 assert(_glapi_get_proc_address("glSetFenceNV") == (void *) &glSetFenceNV);
1009 }
Brian Paul959f8022000-03-19 01:10:11 +00001010#endif
1011}