blob: 0f0add891554296cfbd8558b2b7dc887e6a35651 [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
Ian Romanick10b3bf62004-07-05 22:42:14 +0000162 * \c GL_TRUE, is used to determine whether or not the application is
Ian Romanickd14d1032004-07-02 00:01:09 +0000163 * 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 Romanick6c5402b2004-07-05 22:40:54 +0000297 if (!dispatch) {
298 /* use the no-op functions */
299 dispatch = (struct _glapi_table *) __glapi_noop_table;
300 }
Brian Paul7fb54ae1999-11-19 22:33:50 +0000301#ifdef DEBUG
Ian Romanick6c5402b2004-07-05 22:40:54 +0000302 else {
Brian Paul7fb54ae1999-11-19 22:33:50 +0000303 _glapi_check_table(dispatch);
304 }
305#endif
306
307#if defined(THREADS)
Brian Paulab0c8862001-01-23 23:35:47 +0000308 if (DispatchOverride) {
Ian Romanick6c5402b2004-07-05 22:40:54 +0000309 _glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000310 if (ThreadSafe)
Brian Paul3c257e12001-03-28 17:19:58 +0000311 _glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
Brian Paul3a71d052000-09-05 20:17:37 +0000312 else
Brian Paulab0c8862001-01-23 23:35:47 +0000313 _glapi_RealDispatch = dispatch;
Brian Paul3b18a362000-09-26 15:27:20 +0000314 }
315 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000316 /* normal operation */
Ian Romanick6c5402b2004-07-05 22:40:54 +0000317 _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000318 if (ThreadSafe) {
319 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
320 _glapi_DispatchTSD = NULL;
321 }
322 else {
Ian Romanick6c5402b2004-07-05 22:40:54 +0000323 _glapi_Dispatch = dispatch;
Ian Romanickd14d1032004-07-02 00:01:09 +0000324 _glapi_DispatchTSD = dispatch;
325 }
Brian Paul3a71d052000-09-05 20:17:37 +0000326 }
Brian Paul3a71d052000-09-05 20:17:37 +0000327#else /*THREADS*/
Brian Paulab0c8862001-01-23 23:35:47 +0000328 if (DispatchOverride) {
329 _glapi_RealDispatch = dispatch;
330 }
331 else {
332 _glapi_Dispatch = dispatch;
333 }
Brian Paul3a71d052000-09-05 20:17:37 +0000334#endif /*THREADS*/
Brian Paul7fb54ae1999-11-19 22:33:50 +0000335}
336
337
Brian Paulbb72d321999-12-16 17:31:59 +0000338
Brian Paul7fb54ae1999-11-19 22:33:50 +0000339/*
Brian Paulbb72d321999-12-16 17:31:59 +0000340 * Return pointer to current dispatch table for calling thread.
Brian Paul7fb54ae1999-11-19 22:33:50 +0000341 */
342struct _glapi_table *
343_glapi_get_dispatch(void)
344{
345#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000346 if (ThreadSafe) {
Brian Paulab0c8862001-01-23 23:35:47 +0000347 if (DispatchOverride) {
348 return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
349 }
350 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000351 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paulab0c8862001-01-23 23:35:47 +0000352 }
Brian Paulbb72d321999-12-16 17:31:59 +0000353 }
Brian Paul590d3471999-12-17 12:20:23 +0000354 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000355 if (DispatchOverride) {
356 assert(_glapi_RealDispatch);
357 return _glapi_RealDispatch;
358 }
359 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000360 assert(_glapi_DispatchTSD);
361 return _glapi_DispatchTSD;
Brian Paulab0c8862001-01-23 23:35:47 +0000362 }
Brian Paul590d3471999-12-17 12:20:23 +0000363 }
Brian Paul7fb54ae1999-11-19 22:33:50 +0000364#else
Brian Paulc2319b42000-01-17 19:28:31 +0000365 return _glapi_Dispatch;
Brian Paul7fb54ae1999-11-19 22:33:50 +0000366#endif
367}
368
369
Brian Paulab0c8862001-01-23 23:35:47 +0000370/*
371 * Notes on dispatch overrride:
372 *
373 * Dispatch override allows an external agent to hook into the GL dispatch
374 * mechanism before execution goes into the core rendering library. For
375 * example, a trace mechanism would insert itself as an overrider, print
376 * logging info for each GL function, then dispatch to the real GL function.
377 *
378 * libGLS (GL Stream library) is another agent that might use override.
379 *
380 * We don't allow more than one layer of overriding at this time.
381 * In the future we may allow nested/layered override. In that case
382 * _glapi_begin_dispatch_override() will return an override layer,
383 * _glapi_end_dispatch_override(layer) will remove an override layer
384 * and _glapi_get_override_dispatch(layer) will return the dispatch
385 * table for a given override layer. layer = 0 will be the "real"
386 * dispatch table.
387 */
388
389/*
390 * Return: dispatch override layer number.
391 */
392int
393_glapi_begin_dispatch_override(struct _glapi_table *override)
Brian Paul3a71d052000-09-05 20:17:37 +0000394{
Brian Paulab0c8862001-01-23 23:35:47 +0000395 struct _glapi_table *real = _glapi_get_dispatch();
396
397 assert(!DispatchOverride); /* can't nest at this time */
398 DispatchOverride = GL_TRUE;
399
400 _glapi_set_dispatch(real);
Brian Paul3a71d052000-09-05 20:17:37 +0000401
402#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000403 _glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
Ian Romanickd14d1032004-07-02 00:01:09 +0000404 if ( ThreadSafe ) {
Brian Paul3c257e12001-03-28 17:19:58 +0000405 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000406 _glapi_DispatchTSD = NULL;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000407 }
408 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000409 _glapi_Dispatch = override;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000410 _glapi_DispatchTSD = override;
411 }
Brian Paulab0c8862001-01-23 23:35:47 +0000412#else
413 _glapi_Dispatch = override;
414#endif
415 return 1;
416}
417
418
419void
420_glapi_end_dispatch_override(int layer)
421{
422 struct _glapi_table *real = _glapi_get_dispatch();
423 (void) layer;
424 DispatchOverride = GL_FALSE;
425 _glapi_set_dispatch(real);
426 /* the rest of this isn't needed, just play it safe */
427#if defined(THREADS)
428 _glthread_SetTSD(&RealDispatchTSD, NULL);
429#endif
430 _glapi_RealDispatch = NULL;
431}
432
433
434struct _glapi_table *
435_glapi_get_override_dispatch(int layer)
436{
437 if (layer == 0) {
438 return _glapi_get_dispatch();
Brian Paul3a71d052000-09-05 20:17:37 +0000439 }
440 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000441 if (DispatchOverride) {
442#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000443 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paul3a71d052000-09-05 20:17:37 +0000444#else
Brian Paulab0c8862001-01-23 23:35:47 +0000445 return _glapi_Dispatch;
Brian Paul3a71d052000-09-05 20:17:37 +0000446#endif
Brian Paulab0c8862001-01-23 23:35:47 +0000447 }
448 else {
449 return NULL;
450 }
451 }
Brian Paul3a71d052000-09-05 20:17:37 +0000452}
Brian Paulab0c8862001-01-23 23:35:47 +0000453
Brian Paul3a71d052000-09-05 20:17:37 +0000454
Brian Paul959f8022000-03-19 01:10:11 +0000455struct name_address_offset {
456 const char *Name;
457 GLvoid *Address;
458 GLuint Offset;
459};
460
Brian Paul0c239fc1999-12-16 12:38:11 +0000461
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000462#if !defined( USE_X86_ASM )
Ian Romanick78677992004-05-27 00:05:13 +0000463#define NEED_FUNCTION_POINTER
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000464#endif
Ian Romanick78677992004-05-27 00:05:13 +0000465
Brian Paul54f3aab2002-10-02 01:51:44 +0000466/* The code in this file is auto-generated with Python */
Brian Paulb5fd8862001-11-18 22:48:11 +0000467#include "glprocs.h"
Brian Paul7fb54ae1999-11-19 22:33:50 +0000468
Brian Paul959f8022000-03-19 01:10:11 +0000469
Ian Romanick78677992004-05-27 00:05:13 +0000470static const glprocs_table_t *
471find_entry( const char * n )
472{
473 unsigned i;
474
475 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
476 const char * test_name;
477
478 test_name = gl_string_table + static_functions[i].Name_offset;
479 if (strcmp(test_name, n) == 0) {
480 return & static_functions[i];
481 }
482 }
483 return NULL;
484}
485
Brian Paul959f8022000-03-19 01:10:11 +0000486/*
487 * Return dispatch table offset of the named static (built-in) function.
488 * Return -1 if function not found.
489 */
490static GLint
491get_static_proc_offset(const char *funcName)
492{
Ian Romanick78677992004-05-27 00:05:13 +0000493 const glprocs_table_t * const f = find_entry( funcName );
494
495 if ( f != NULL ) {
496 return f->Offset;
Brian Paul959f8022000-03-19 01:10:11 +0000497 }
498 return -1;
499}
500
501
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000502#ifdef USE_X86_ASM
503extern const GLubyte gl_dispatch_functions_start[];
504
Roland Scheideggerd2dbb252004-07-06 00:32:03 +0000505# if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000506# define X86_DISPATCH_FUNCTION_SIZE 32
507# else
508# define X86_DISPATCH_FUNCTION_SIZE 16
509# endif
510
511
512/*
513 * Return dispatch function address the named static (built-in) function.
514 * Return NULL if function not found.
515 */
516static const GLvoid *
517get_static_proc_address(const char *funcName)
518{
519 const glprocs_table_t * const f = find_entry( funcName );
520
521 if ( f != NULL ) {
522 return gl_dispatch_functions_start
523 + (X86_DISPATCH_FUNCTION_SIZE * f->Offset);
524 }
525 else {
526 return NULL;
527 }
528}
529
530#else
531
532
Brian Paul959f8022000-03-19 01:10:11 +0000533/*
534 * Return dispatch function address the named static (built-in) function.
535 * Return NULL if function not found.
536 */
Ian Romanick78677992004-05-27 00:05:13 +0000537static const GLvoid *
Brian Paul959f8022000-03-19 01:10:11 +0000538get_static_proc_address(const char *funcName)
539{
Ian Romanick78677992004-05-27 00:05:13 +0000540 const glprocs_table_t * const f = find_entry( funcName );
541 return ( f != NULL ) ? f->Address : NULL;
542}
543
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000544#endif /* USE_X86_ASM */
545
Ian Romanick78677992004-05-27 00:05:13 +0000546
547static const char *
548get_static_proc_name( GLuint offset )
549{
550 unsigned i;
551
552 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
553 if (static_functions[i].Offset == offset) {
554 return gl_string_table + static_functions[i].Name_offset;
Brian Paul9c7ca852000-10-19 20:13:12 +0000555 }
556 }
557 return NULL;
Brian Paul959f8022000-03-19 01:10:11 +0000558}
559
560
561
562/**********************************************************************
563 * Extension function management.
564 */
565
Brian Paul54f3aab2002-10-02 01:51:44 +0000566/*
567 * Number of extension functions which we can dynamically add at runtime.
568 */
569#define MAX_EXTENSION_FUNCS 300
Brian Paul959f8022000-03-19 01:10:11 +0000570
Brian Paul54f3aab2002-10-02 01:51:44 +0000571
572/*
573 * The disptach table size (number of entries) is the sizeof the
574 * _glapi_table struct plus the number of dynamic entries we can add.
575 * The extra slots can be filled in by DRI drivers that register new extension
576 * functions.
577 */
578#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
579
Brian Paul959f8022000-03-19 01:10:11 +0000580
581static struct name_address_offset ExtEntryTable[MAX_EXTENSION_FUNCS];
582static GLuint NumExtEntryPoints = 0;
583
davem694a497e62001-06-06 22:55:28 +0000584#ifdef USE_SPARC_ASM
585extern void __glapi_sparc_icache_flush(unsigned int *);
586#endif
Brian Paul959f8022000-03-19 01:10:11 +0000587
588/*
589 * Generate a dispatch function (entrypoint) which jumps through
590 * the given slot number (offset) in the current dispatch table.
591 * We need assembly language in order to accomplish this.
592 */
593static void *
594generate_entrypoint(GLuint functionOffset)
595{
596#if defined(USE_X86_ASM)
597 /*
598 * This x86 code contributed by Josh Vanderhoof.
599 *
600 * 0: a1 10 32 54 76 movl __glapi_Dispatch,%eax
601 * 00 01 02 03 04
602 * 5: 85 c0 testl %eax,%eax
603 * 05 06
604 * 7: 74 06 je f <entrypoint+0xf>
605 * 07 08
606 * 9: ff a0 10 32 54 76 jmp *0x76543210(%eax)
607 * 09 0a 0b 0c 0d 0e
608 * f: e8 fc ff ff ff call __glapi_get_dispatch
609 * 0f 10 11 12 13
610 * 14: ff a0 10 32 54 76 jmp *0x76543210(%eax)
611 * 14 15 16 17 18 19
612 */
Brian Paul54f3aab2002-10-02 01:51:44 +0000613 static const unsigned char insn_template[] = {
Brian Paul959f8022000-03-19 01:10:11 +0000614 0xa1, 0x00, 0x00, 0x00, 0x00,
615 0x85, 0xc0,
616 0x74, 0x06,
617 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
618 0xe8, 0x00, 0x00, 0x00, 0x00,
619 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
620 };
Brian Pauldec2a4d2002-10-29 15:03:14 +0000621 unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000622 unsigned int next_insn;
623 if (code) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000624 memcpy(code, insn_template, sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000625
Daniel Borcafd003822004-07-05 06:15:37 +0000626#if defined( THREADS )
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000627 *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_DispatchTSD;
Daniel Borcafd003822004-07-05 06:15:37 +0000628#else
629 *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_Dispatch;
630#endif
Brian Paul959f8022000-03-19 01:10:11 +0000631 *(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
632 next_insn = (unsigned int)(code + 0x14);
633 *(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
634 *(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
635 }
636 return code;
davem69775355a2001-06-05 23:54:00 +0000637#elif defined(USE_SPARC_ASM)
638
Brian Paul9a90cd42003-12-01 22:40:26 +0000639#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000640 static const unsigned int insn_template[] = {
641 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
642 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
643 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
644 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
645 0x8528b020, /* sllx %g2, 32, %g2 */
646 0xc2584002, /* ldx [%g1 + %g2], %g1 */
647 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
648 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
649 0xc6584002, /* ldx [%g1 + %g2], %g3 */
650 0x81c0c000, /* jmpl %g3, %g0 */
651 0x01000000 /* nop */
652 };
653#else
654 static const unsigned int insn_template[] = {
655 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
656 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
657 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
658 0x81c0c000, /* jmpl %g3, %g0 */
659 0x01000000 /* nop */
660 };
661#endif
Brian Pauldec2a4d2002-10-29 15:03:14 +0000662 unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
davem69775355a2001-06-05 23:54:00 +0000663 unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
664 if (code) {
665 memcpy(code, insn_template, sizeof(insn_template));
666
Brian Paul9a90cd42003-12-01 22:40:26 +0000667#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000668 code[0] |= (glapi_addr >> (32 + 10));
669 code[1] |= ((glapi_addr & 0xffffffff) >> 10);
davem694a497e62001-06-06 22:55:28 +0000670 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000671 code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
672 code[3] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000673 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000674 code[6] |= ((functionOffset * 8) >> 10);
675 code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000676 __glapi_sparc_icache_flush(&code[6]);
davem69775355a2001-06-05 23:54:00 +0000677#else
678 code[0] |= (glapi_addr >> 10);
679 code[1] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000680 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000681 code[2] |= (functionOffset * 4);
davem694a497e62001-06-06 22:55:28 +0000682 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000683#endif
684 }
685 return code;
Brian Paul959f8022000-03-19 01:10:11 +0000686#else
Brian Paula6c423d2004-08-25 15:59:48 +0000687 (void) functionOffset;
Brian Paul959f8022000-03-19 01:10:11 +0000688 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
Brian Paula6c423d2004-08-25 15:59:48 +0000722#else
723
724 /* an unimplemented architecture */
725 (void) entrypoint;
726 (void) offset;
727
Brian Paul54f3aab2002-10-02 01:51:44 +0000728#endif /* USE_*_ASM */
729}
730
Brian Paul959f8022000-03-19 01:10:11 +0000731
732/*
733 * Add a new extension function entrypoint.
734 * Return: GL_TRUE = success or GL_FALSE = failure
735 */
736GLboolean
737_glapi_add_entrypoint(const char *funcName, GLuint offset)
738{
Brian Paul8ad10762002-10-11 17:41:03 +0000739 /* trivial rejection test */
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000740#ifdef MANGLE
741 if (!funcName || funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
Brian Paula6c423d2004-08-25 15:59:48 +0000742 return GL_FALSE;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000743#else
Brian Paul8ad10762002-10-11 17:41:03 +0000744 if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
745 return GL_FALSE;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000746#endif
Brian Paul8ad10762002-10-11 17:41:03 +0000747
Brian Paul959f8022000-03-19 01:10:11 +0000748 /* first check if the named function is already statically present */
749 {
750 GLint index = get_static_proc_offset(funcName);
751 if (index >= 0) {
Brian Paulb51b0a82001-03-07 05:06:11 +0000752 return (GLboolean) ((GLuint) index == offset); /* bad offset! */
Brian Paul959f8022000-03-19 01:10:11 +0000753 }
754 }
755
Brian Paul54f3aab2002-10-02 01:51:44 +0000756 /* See if this function has already been dynamically added */
Brian Paul959f8022000-03-19 01:10:11 +0000757 {
Brian Paul959f8022000-03-19 01:10:11 +0000758 GLuint i;
759 for (i = 0; i < NumExtEntryPoints; i++) {
760 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000761 /* function already registered */
Brian Paul959f8022000-03-19 01:10:11 +0000762 if (ExtEntryTable[i].Offset == offset) {
763 return GL_TRUE; /* offsets match */
764 }
Brian Paule4fcea22003-09-19 15:38:15 +0000765 else if (ExtEntryTable[i].Offset == (GLuint) ~0
Brian Paul54f3aab2002-10-02 01:51:44 +0000766 && offset < DISPATCH_TABLE_SIZE) {
767 /* need to patch-up the dispatch code */
Brian Paule4fcea22003-09-19 15:38:15 +0000768 if (offset != (GLuint) ~0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000769 fill_in_entrypoint_offset(ExtEntryTable[i].Address, offset);
770 ExtEntryTable[i].Offset = offset;
771 }
772 return GL_TRUE;
773 }
Brian Paul959f8022000-03-19 01:10:11 +0000774 else {
775 return GL_FALSE; /* bad offset! */
776 }
777 }
778 }
Brian Paul959f8022000-03-19 01:10:11 +0000779 }
780
Brian Paul8ad10762002-10-11 17:41:03 +0000781 /* This is a new function, try to add it. */
782 if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS ||
783 offset >= DISPATCH_TABLE_SIZE) {
784 /* No space left */
785 return GL_FALSE;
786 }
787 else {
788 void *entrypoint = generate_entrypoint(offset);
789 if (!entrypoint)
790 return GL_FALSE; /* couldn't generate assembly */
791
792 /* OK! */
793 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
794 ExtEntryTable[NumExtEntryPoints].Offset = offset;
795 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
796 NumExtEntryPoints++;
797
798 return GL_TRUE; /* success */
799 }
800
801 /* should never get here, silence compiler warnings */
Brian Paul959f8022000-03-19 01:10:11 +0000802 return GL_FALSE;
803}
804
805
Brian Paul959f8022000-03-19 01:10:11 +0000806/*
807 * Return offset of entrypoint for named function within dispatch table.
808 */
809GLint
810_glapi_get_proc_offset(const char *funcName)
811{
812 /* search extension functions first */
Brian Paulb51b0a82001-03-07 05:06:11 +0000813 GLuint i;
Brian Paul959f8022000-03-19 01:10:11 +0000814 for (i = 0; i < NumExtEntryPoints; i++) {
815 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
816 return ExtEntryTable[i].Offset;
817 }
818 }
819
820 /* search static functions */
821 return get_static_proc_offset(funcName);
822}
823
824
825
826/*
827 * Return entrypoint for named function.
828 */
829const GLvoid *
830_glapi_get_proc_address(const char *funcName)
831{
Brian Paulb51b0a82001-03-07 05:06:11 +0000832 GLuint i;
Brian Paula6ed6f42003-08-27 14:48:16 +0000833
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000834#ifdef MANGLE
835 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
836 return NULL;
837#else
Brian Paula6ed6f42003-08-27 14:48:16 +0000838 if (funcName[0] != 'g' || funcName[1] != 'l')
839 return NULL;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000840#endif
Brian Paula6ed6f42003-08-27 14:48:16 +0000841
842 /* search extension functions first */
Brian Paul959f8022000-03-19 01:10:11 +0000843 for (i = 0; i < NumExtEntryPoints; i++) {
844 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
845 return ExtEntryTable[i].Address;
846 }
847 }
848
849 /* search static functions */
Brian Paul54f3aab2002-10-02 01:51:44 +0000850 {
851 const GLvoid *func = get_static_proc_address(funcName);
852 if (func)
853 return func;
854 }
Brian Paul959f8022000-03-19 01:10:11 +0000855
Brian Paul54f3aab2002-10-02 01:51:44 +0000856 /* generate new entrypoint - use a temporary dispatch offset of
857 * ~0 (i.e. -1). Later, when the driver calls _glapi_add_entrypoint()
858 * we'll put in the proper offset. If that never happens, and the
859 * user calls this function, he'll segfault. That's what you get
860 * when you try calling a GL function that doesn't really exist.
861 */
862 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
863 GLvoid *entrypoint = generate_entrypoint(~0);
864 if (!entrypoint)
865 return GL_FALSE;
866
867 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
868 ExtEntryTable[NumExtEntryPoints].Offset = ~0;
869 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
870 NumExtEntryPoints++;
871
872 return entrypoint;
873 }
874 else {
875 /* no space for new functions! */
876 return NULL;
877 }
878}
Brian Paul959f8022000-03-19 01:10:11 +0000879
880
881
882/*
883 * Return the name of the function at the given dispatch offset.
884 * This is only intended for debugging.
885 */
886const char *
887_glapi_get_proc_name(GLuint offset)
888{
Brian Paul959f8022000-03-19 01:10:11 +0000889 GLuint i;
Ian Romanick78677992004-05-27 00:05:13 +0000890 const char * n;
Brian Paul54f3aab2002-10-02 01:51:44 +0000891
892 /* search built-in functions */
Ian Romanick78677992004-05-27 00:05:13 +0000893 n = get_static_proc_name(offset);
894 if ( n != NULL ) {
895 return n;
Brian Paul959f8022000-03-19 01:10:11 +0000896 }
897
898 /* search added extension functions */
899 for (i = 0; i < NumExtEntryPoints; i++) {
900 if (ExtEntryTable[i].Offset == offset) {
901 return ExtEntryTable[i].Name;
902 }
903 }
904 return NULL;
905}
906
907
908
909/*
Brian Paul54f3aab2002-10-02 01:51:44 +0000910 * Return size of dispatch table struct as number of functions (or
911 * slots).
912 */
913GLuint
914_glapi_get_dispatch_table_size(void)
915{
916 return DISPATCH_TABLE_SIZE;
917}
918
919
920
921/*
922 * Get API dispatcher version string.
923 */
924const char *
925_glapi_get_version(void)
926{
927 return "20021001"; /* YYYYMMDD */
928}
929
930
931
932/*
Brian Paul959f8022000-03-19 01:10:11 +0000933 * Make sure there are no NULL pointers in the given dispatch table.
Brian Paul5104b4d2002-03-07 21:50:41 +0000934 * Intended for debugging purposes.
Brian Paul959f8022000-03-19 01:10:11 +0000935 */
936void
937_glapi_check_table(const struct _glapi_table *table)
938{
Brian Paul5104b4d2002-03-07 21:50:41 +0000939#ifdef DEBUG
Brian Paul959f8022000-03-19 01:10:11 +0000940 const GLuint entries = _glapi_get_dispatch_table_size();
941 const void **tab = (const void **) table;
942 GLuint i;
943 for (i = 1; i < entries; i++) {
944 assert(tab[i]);
945 }
946
Brian Paul959f8022000-03-19 01:10:11 +0000947 /* Do some spot checks to be sure that the dispatch table
948 * slots are assigned correctly.
949 */
950 {
951 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
952 char *BeginFunc = (char*) &table->Begin;
953 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
954 assert(BeginOffset == _gloffset_Begin);
955 assert(BeginOffset == offset);
956 }
957 {
958 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
959 char *viewportFunc = (char*) &table->Viewport;
960 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
961 assert(viewportOffset == _gloffset_Viewport);
962 assert(viewportOffset == offset);
963 }
964 {
965 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
966 char *VertexPointerFunc = (char*) &table->VertexPointer;
967 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
968 assert(VertexPointerOffset == _gloffset_VertexPointer);
969 assert(VertexPointerOffset == offset);
970 }
971 {
972 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
973 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
974 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
975 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
976 assert(ResetMinMaxOffset == offset);
977 }
978 {
979 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
980 char *blendColorFunc = (char*) &table->BlendColor;
981 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
982 assert(blendColorOffset == _gloffset_BlendColor);
983 assert(blendColorOffset == offset);
984 }
985 {
986 GLuint istextureOffset = _glapi_get_proc_offset("glIsTextureEXT");
987 char *istextureFunc = (char*) &table->IsTextureEXT;
988 GLuint offset = (istextureFunc - (char *) table) / sizeof(void *);
989 assert(istextureOffset == _gloffset_IsTextureEXT);
990 assert(istextureOffset == offset);
991 }
Brian Paula14cbff2000-10-27 18:31:21 +0000992 {
993 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
994 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
995 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
996 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
997 assert(secondaryColor3fOffset == offset);
998 assert(_glapi_get_proc_address("glSecondaryColor3fEXT") == (void *) &glSecondaryColor3fEXT);
999 }
Brian Paul91d6f122002-05-29 15:23:16 +00001000 {
1001 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
1002 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
1003 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
1004 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
1005 assert(pointParameterivOffset == offset);
1006 assert(_glapi_get_proc_address("glPointParameterivNV") == (void *) &glPointParameterivNV);
1007 }
Brian Paul54f3aab2002-10-02 01:51:44 +00001008 {
1009 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
1010 char *setFenceFunc = (char*) &table->SetFenceNV;
1011 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
1012 assert(setFenceOffset == _gloffset_SetFenceNV);
1013 assert(setFenceOffset == offset);
1014 assert(_glapi_get_proc_address("glSetFenceNV") == (void *) &glSetFenceNV);
1015 }
Brian Paula6c423d2004-08-25 15:59:48 +00001016#else
1017 (void) table;
Brian Paul959f8022000-03-19 01:10:11 +00001018#endif
1019}