blob: 9c488169591f154317d7a534058dabba1e54eee7 [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 Paul5849e3d2004-11-05 18:32:02 +0000103#define DISPATCH(func, args, msg) \
104 if (warn()) { \
105 warning_func(NULL, "GL User Error: called without context: %s", #func); \
Brian Paul3c257e12001-03-28 17:19:58 +0000106 }
107
Brian Paul5849e3d2004-11-05 18:32:02 +0000108#define RETURN_DISPATCH(func, args, msg) \
109 if (warn()) { \
110 warning_func(NULL, "GL User Error: called without context: %s", #func); \
111 } \
Brian Paul3c257e12001-03-28 17:19:58 +0000112 return 0
113
114#define DISPATCH_TABLE_NAME __glapi_noop_table
115#define UNUSED_TABLE_NAME __usused_noop_functions
116
117#define TABLE_ENTRY(name) (void *) NoOp##name
118
119static int NoOpUnused(void)
120{
121 if (warn()) {
Brian Paul4e9676f2002-06-29 19:48:15 +0000122 warning_func(NULL, "GL User Error: calling extension function without a current context\n");
Brian Paul3c257e12001-03-28 17:19:58 +0000123 }
124 return 0;
125}
126
127#include "glapitemp.h"
128
129/***** END NO-OP DISPATCH *****/
130
131
132
133/***** BEGIN THREAD-SAFE DISPATCH *****/
Brian Paul3c257e12001-03-28 17:19:58 +0000134
135#if defined(THREADS)
136
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000137/**
138 * \name Multi-threaded control support variables
139 *
140 * If thread-safety is supported, there are two potential mechanisms that can
141 * be used. The old-style mechanism would set \c _glapi_Dispatch to a special
142 * thread-safe dispatch table. These dispatch routines would call
143 * \c _glapi_get_dispatch to get the actual dispatch pointer. In this
144 * setup \c _glapi_Dispatch could never be \c NULL. This dual layered
145 * dispatch setup performed great for single-threaded apps, but didn't
146 * perform well for multithreaded apps.
147 *
148 * In the new mechansim, there are two variables. The first is
149 * \c _glapi_DispatchTSD. In the single-threaded case, this variable points
150 * to the dispatch table. In the multi-threaded case, this variable is
151 * \c NULL, and thread-specific variable \c _gl_DispatchTSD points to the
152 * actual dispatch table. \c _glapi_DispatchTSD is used to signal to the
153 * static dispatch functions to call \c _glapi_get_dispatch to get the real
154 * dispatch table.
155 *
Ian Romanickd14d1032004-07-02 00:01:09 +0000156 * There is a race condition in setting \c _glapi_DispatchTSD to \c NULL.
157 * It is possible for the original thread to be setting it at the same instant
158 * a new thread, perhaps running on a different processor, is clearing it.
159 * Because of that, \c ThreadSafe, which can only ever be changed to
Ian Romanick10b3bf62004-07-05 22:42:14 +0000160 * \c GL_TRUE, is used to determine whether or not the application is
Ian Romanickd14d1032004-07-02 00:01:09 +0000161 * multithreaded.
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000162 */
163/*@{*/
Ian Romanickd14d1032004-07-02 00:01:09 +0000164static GLboolean ThreadSafe = GL_FALSE; /**< In thread-safe mode? */
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000165_glthread_TSD _gl_DispatchTSD; /**< Per-thread dispatch pointer */
166static _glthread_TSD RealDispatchTSD; /**< only when using override */
167static _glthread_TSD ContextTSD; /**< Per-thread context pointer */
168/*@}*/
Brian Paul3c257e12001-03-28 17:19:58 +0000169
170
Brian Paul3c257e12001-03-28 17:19:58 +0000171#define DISPATCH_TABLE_NAME __glapi_threadsafe_table
172#define UNUSED_TABLE_NAME __usused_threadsafe_functions
173
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000174#define TABLE_ENTRY(name) (void *) gl##name
Brian Paul3c257e12001-03-28 17:19:58 +0000175
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000176static int glUnused(void)
Brian Paul3c257e12001-03-28 17:19:58 +0000177{
178 return 0;
179}
180
181#include "glapitemp.h"
182
183#endif
184
185/***** END THREAD-SAFE DISPATCH *****/
186
187
188
Brian Paul8ceb5c32000-02-24 22:14:04 +0000189struct _glapi_table *_glapi_Dispatch = (struct _glapi_table *) __glapi_noop_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000190#if defined( THREADS )
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000191struct _glapi_table *_glapi_DispatchTSD = (struct _glapi_table *) __glapi_noop_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000192#endif
Brian Paulab0c8862001-01-23 23:35:47 +0000193struct _glapi_table *_glapi_RealDispatch = (struct _glapi_table *) __glapi_noop_table;
Brian Paul0f710251999-12-15 15:02:30 +0000194
Ian Romanickd14d1032004-07-02 00:01:09 +0000195
Brian Paul8f91fb61999-12-17 14:51:28 +0000196/* Used when thread safety disabled */
Brian Paulf9b97d92000-01-28 20:17:42 +0000197void *_glapi_Context = NULL;
Brian Paul8f91fb61999-12-17 14:51:28 +0000198
Brian Paul0f710251999-12-15 15:02:30 +0000199
Brian Paulab0c8862001-01-23 23:35:47 +0000200static GLboolean DispatchOverride = GL_FALSE;
201
202
Brian Paul54f3aab2002-10-02 01:51:44 +0000203
Brian Paul3c257e12001-03-28 17:19:58 +0000204/* strdup() is actually not a standard ANSI C or POSIX routine.
205 * Irix will not define it if ANSI mode is in effect.
206 */
207static char *
208str_dup(const char *str)
Randy Frankd7361e12000-03-27 21:13:58 +0000209{
Brian Paulfffb8092000-03-29 18:46:11 +0000210 char *copy;
211 copy = (char*) malloc(strlen(str) + 1);
212 if (!copy)
213 return NULL;
214 strcpy(copy, str);
215 return copy;
Randy Frankd7361e12000-03-27 21:13:58 +0000216}
217
Brian Paul7fb54ae1999-11-19 22:33:50 +0000218
Brian Paulbb72d321999-12-16 17:31:59 +0000219
220/*
221 * We should call this periodically from a function such as glXMakeCurrent
Brian Paul5104b4d2002-03-07 21:50:41 +0000222 * in order to test if multiple threads are being used.
Brian Paulbb72d321999-12-16 17:31:59 +0000223 */
224void
225_glapi_check_multithread(void)
226{
227#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000228 if (!ThreadSafe) {
Brian Paulbb72d321999-12-16 17:31:59 +0000229 static unsigned long knownID;
230 static GLboolean firstCall = GL_TRUE;
231 if (firstCall) {
232 knownID = _glthread_GetID();
233 firstCall = GL_FALSE;
234 }
235 else if (knownID != _glthread_GetID()) {
Ian Romanickd14d1032004-07-02 00:01:09 +0000236 ThreadSafe = GL_TRUE;
Brian Paulbb72d321999-12-16 17:31:59 +0000237 _glapi_set_dispatch(NULL);
238 }
239 }
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000240 else if (!_glapi_get_dispatch()) {
241 /* make sure that this thread's dispatch pointer isn't null */
242 _glapi_set_dispatch(NULL);
243 }
Brian Paulbb72d321999-12-16 17:31:59 +0000244#endif
245}
246
247
248
249/*
Brian Paul8f91fb61999-12-17 14:51:28 +0000250 * Set the current context pointer for this thread.
251 * The context pointer is an opaque type which should be cast to
252 * void from the real context pointer type.
253 */
254void
Brian Paulf9b97d92000-01-28 20:17:42 +0000255_glapi_set_context(void *context)
Brian Paul8f91fb61999-12-17 14:51:28 +0000256{
257#if defined(THREADS)
Brian Paul3c27be32000-02-10 21:27:48 +0000258 _glthread_SetTSD(&ContextTSD, context);
Ian Romanickd14d1032004-07-02 00:01:09 +0000259 _glapi_Context = (ThreadSafe) ? NULL : context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000260#else
Brian Paulf9b97d92000-01-28 20:17:42 +0000261 _glapi_Context = context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000262#endif
263}
264
265
266
267/*
268 * Get the current context pointer for this thread.
269 * The context pointer is an opaque type which should be cast from
270 * void to the real context pointer type.
271 */
272void *
Brian Paulf9b97d92000-01-28 20:17:42 +0000273_glapi_get_context(void)
Brian Paul8f91fb61999-12-17 14:51:28 +0000274{
275#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000276 if (ThreadSafe) {
Brian Paul8f91fb61999-12-17 14:51:28 +0000277 return _glthread_GetTSD(&ContextTSD);
278 }
279 else {
Brian Paulf9b97d92000-01-28 20:17:42 +0000280 return _glapi_Context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000281 }
282#else
Brian Paulf9b97d92000-01-28 20:17:42 +0000283 return _glapi_Context;
Brian Paul8f91fb61999-12-17 14:51:28 +0000284#endif
285}
286
287
288
289/*
Brian Paul7fb54ae1999-11-19 22:33:50 +0000290 * Set the global or per-thread dispatch table pointer.
291 */
292void
293_glapi_set_dispatch(struct _glapi_table *dispatch)
294{
Ian Romanick6c5402b2004-07-05 22:40:54 +0000295 if (!dispatch) {
296 /* use the no-op functions */
297 dispatch = (struct _glapi_table *) __glapi_noop_table;
298 }
Brian Paul7fb54ae1999-11-19 22:33:50 +0000299#ifdef DEBUG
Ian Romanick6c5402b2004-07-05 22:40:54 +0000300 else {
Brian Paul7fb54ae1999-11-19 22:33:50 +0000301 _glapi_check_table(dispatch);
302 }
303#endif
304
305#if defined(THREADS)
Brian Paulab0c8862001-01-23 23:35:47 +0000306 if (DispatchOverride) {
Ian Romanick6c5402b2004-07-05 22:40:54 +0000307 _glthread_SetTSD(&RealDispatchTSD, (void *) dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000308 if (ThreadSafe)
Brian Paul3c257e12001-03-28 17:19:58 +0000309 _glapi_RealDispatch = (struct _glapi_table*) __glapi_threadsafe_table;
Brian Paul3a71d052000-09-05 20:17:37 +0000310 else
Brian Paulab0c8862001-01-23 23:35:47 +0000311 _glapi_RealDispatch = dispatch;
Brian Paul3b18a362000-09-26 15:27:20 +0000312 }
313 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000314 /* normal operation */
Ian Romanick6c5402b2004-07-05 22:40:54 +0000315 _glthread_SetTSD(&_gl_DispatchTSD, (void *) dispatch);
Ian Romanickd14d1032004-07-02 00:01:09 +0000316 if (ThreadSafe) {
317 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
318 _glapi_DispatchTSD = NULL;
319 }
320 else {
Ian Romanick6c5402b2004-07-05 22:40:54 +0000321 _glapi_Dispatch = dispatch;
Ian Romanickd14d1032004-07-02 00:01:09 +0000322 _glapi_DispatchTSD = dispatch;
323 }
Brian Paul3a71d052000-09-05 20:17:37 +0000324 }
Brian Paul3a71d052000-09-05 20:17:37 +0000325#else /*THREADS*/
Brian Paulab0c8862001-01-23 23:35:47 +0000326 if (DispatchOverride) {
327 _glapi_RealDispatch = dispatch;
328 }
329 else {
330 _glapi_Dispatch = dispatch;
331 }
Brian Paul3a71d052000-09-05 20:17:37 +0000332#endif /*THREADS*/
Brian Paul7fb54ae1999-11-19 22:33:50 +0000333}
334
335
Brian Paulbb72d321999-12-16 17:31:59 +0000336
Brian Paul7fb54ae1999-11-19 22:33:50 +0000337/*
Brian Paulbb72d321999-12-16 17:31:59 +0000338 * Return pointer to current dispatch table for calling thread.
Brian Paul7fb54ae1999-11-19 22:33:50 +0000339 */
340struct _glapi_table *
341_glapi_get_dispatch(void)
342{
343#if defined(THREADS)
Ian Romanickd14d1032004-07-02 00:01:09 +0000344 if (ThreadSafe) {
Brian Paulab0c8862001-01-23 23:35:47 +0000345 if (DispatchOverride) {
346 return (struct _glapi_table *) _glthread_GetTSD(&RealDispatchTSD);
347 }
348 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000349 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paulab0c8862001-01-23 23:35:47 +0000350 }
Brian Paulbb72d321999-12-16 17:31:59 +0000351 }
Brian Paul590d3471999-12-17 12:20:23 +0000352 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000353 if (DispatchOverride) {
354 assert(_glapi_RealDispatch);
355 return _glapi_RealDispatch;
356 }
357 else {
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000358 assert(_glapi_DispatchTSD);
359 return _glapi_DispatchTSD;
Brian Paulab0c8862001-01-23 23:35:47 +0000360 }
Brian Paul590d3471999-12-17 12:20:23 +0000361 }
Brian Paul7fb54ae1999-11-19 22:33:50 +0000362#else
Brian Paulc2319b42000-01-17 19:28:31 +0000363 return _glapi_Dispatch;
Brian Paul7fb54ae1999-11-19 22:33:50 +0000364#endif
365}
366
367
Brian Paulab0c8862001-01-23 23:35:47 +0000368/*
369 * Notes on dispatch overrride:
370 *
371 * Dispatch override allows an external agent to hook into the GL dispatch
372 * mechanism before execution goes into the core rendering library. For
373 * example, a trace mechanism would insert itself as an overrider, print
374 * logging info for each GL function, then dispatch to the real GL function.
375 *
376 * libGLS (GL Stream library) is another agent that might use override.
377 *
378 * We don't allow more than one layer of overriding at this time.
379 * In the future we may allow nested/layered override. In that case
380 * _glapi_begin_dispatch_override() will return an override layer,
381 * _glapi_end_dispatch_override(layer) will remove an override layer
382 * and _glapi_get_override_dispatch(layer) will return the dispatch
383 * table for a given override layer. layer = 0 will be the "real"
384 * dispatch table.
385 */
386
387/*
388 * Return: dispatch override layer number.
389 */
390int
391_glapi_begin_dispatch_override(struct _glapi_table *override)
Brian Paul3a71d052000-09-05 20:17:37 +0000392{
Brian Paulab0c8862001-01-23 23:35:47 +0000393 struct _glapi_table *real = _glapi_get_dispatch();
394
395 assert(!DispatchOverride); /* can't nest at this time */
396 DispatchOverride = GL_TRUE;
397
398 _glapi_set_dispatch(real);
Brian Paul3a71d052000-09-05 20:17:37 +0000399
400#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000401 _glthread_SetTSD(&_gl_DispatchTSD, (void *) override);
Ian Romanickd14d1032004-07-02 00:01:09 +0000402 if ( ThreadSafe ) {
Brian Paul3c257e12001-03-28 17:19:58 +0000403 _glapi_Dispatch = (struct _glapi_table *) __glapi_threadsafe_table;
Ian Romanickd14d1032004-07-02 00:01:09 +0000404 _glapi_DispatchTSD = NULL;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000405 }
406 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000407 _glapi_Dispatch = override;
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000408 _glapi_DispatchTSD = override;
409 }
Brian Paulab0c8862001-01-23 23:35:47 +0000410#else
411 _glapi_Dispatch = override;
412#endif
413 return 1;
414}
415
416
417void
418_glapi_end_dispatch_override(int layer)
419{
420 struct _glapi_table *real = _glapi_get_dispatch();
421 (void) layer;
422 DispatchOverride = GL_FALSE;
423 _glapi_set_dispatch(real);
424 /* the rest of this isn't needed, just play it safe */
425#if defined(THREADS)
426 _glthread_SetTSD(&RealDispatchTSD, NULL);
427#endif
428 _glapi_RealDispatch = NULL;
429}
430
431
432struct _glapi_table *
433_glapi_get_override_dispatch(int layer)
434{
435 if (layer == 0) {
436 return _glapi_get_dispatch();
Brian Paul3a71d052000-09-05 20:17:37 +0000437 }
438 else {
Brian Paulab0c8862001-01-23 23:35:47 +0000439 if (DispatchOverride) {
440#if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000441 return (struct _glapi_table *) _glthread_GetTSD(&_gl_DispatchTSD);
Brian Paul3a71d052000-09-05 20:17:37 +0000442#else
Brian Paulab0c8862001-01-23 23:35:47 +0000443 return _glapi_Dispatch;
Brian Paul3a71d052000-09-05 20:17:37 +0000444#endif
Brian Paulab0c8862001-01-23 23:35:47 +0000445 }
446 else {
447 return NULL;
448 }
449 }
Brian Paul3a71d052000-09-05 20:17:37 +0000450}
Brian Paulab0c8862001-01-23 23:35:47 +0000451
Brian Paul3a71d052000-09-05 20:17:37 +0000452
Brian Paul959f8022000-03-19 01:10:11 +0000453struct name_address_offset {
454 const char *Name;
455 GLvoid *Address;
456 GLuint Offset;
457};
458
Brian Paul0c239fc1999-12-16 12:38:11 +0000459
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000460#if !defined( USE_X86_ASM )
Ian Romanick78677992004-05-27 00:05:13 +0000461#define NEED_FUNCTION_POINTER
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000462#endif
Ian Romanick78677992004-05-27 00:05:13 +0000463
Brian Paul54f3aab2002-10-02 01:51:44 +0000464/* The code in this file is auto-generated with Python */
Brian Paulb5fd8862001-11-18 22:48:11 +0000465#include "glprocs.h"
Brian Paul7fb54ae1999-11-19 22:33:50 +0000466
Brian Paul959f8022000-03-19 01:10:11 +0000467
Ian Romanick78677992004-05-27 00:05:13 +0000468static const glprocs_table_t *
469find_entry( const char * n )
470{
471 unsigned i;
472
473 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
474 const char * test_name;
475
476 test_name = gl_string_table + static_functions[i].Name_offset;
477 if (strcmp(test_name, n) == 0) {
478 return & static_functions[i];
479 }
480 }
481 return NULL;
482}
483
Brian Paul959f8022000-03-19 01:10:11 +0000484/*
485 * Return dispatch table offset of the named static (built-in) function.
486 * Return -1 if function not found.
487 */
488static GLint
489get_static_proc_offset(const char *funcName)
490{
Ian Romanick78677992004-05-27 00:05:13 +0000491 const glprocs_table_t * const f = find_entry( funcName );
492
493 if ( f != NULL ) {
494 return f->Offset;
Brian Paul959f8022000-03-19 01:10:11 +0000495 }
496 return -1;
497}
498
499
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000500#ifdef USE_X86_ASM
501extern const GLubyte gl_dispatch_functions_start[];
502
Roland Scheideggerd2dbb252004-07-06 00:32:03 +0000503# if defined(THREADS)
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000504# define X86_DISPATCH_FUNCTION_SIZE 32
505# else
506# define X86_DISPATCH_FUNCTION_SIZE 16
507# endif
508
509
510/*
511 * Return dispatch function address the named static (built-in) function.
512 * Return NULL if function not found.
513 */
514static const GLvoid *
515get_static_proc_address(const char *funcName)
516{
517 const glprocs_table_t * const f = find_entry( funcName );
518
519 if ( f != NULL ) {
520 return gl_dispatch_functions_start
521 + (X86_DISPATCH_FUNCTION_SIZE * f->Offset);
522 }
523 else {
524 return NULL;
525 }
526}
527
528#else
529
530
Brian Paul959f8022000-03-19 01:10:11 +0000531/*
532 * Return dispatch function address the named static (built-in) function.
533 * Return NULL if function not found.
534 */
Ian Romanick78677992004-05-27 00:05:13 +0000535static const GLvoid *
Brian Paul959f8022000-03-19 01:10:11 +0000536get_static_proc_address(const char *funcName)
537{
Ian Romanick78677992004-05-27 00:05:13 +0000538 const glprocs_table_t * const f = find_entry( funcName );
539 return ( f != NULL ) ? f->Address : NULL;
540}
541
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000542#endif /* USE_X86_ASM */
543
Ian Romanick78677992004-05-27 00:05:13 +0000544
545static const char *
546get_static_proc_name( GLuint offset )
547{
548 unsigned i;
549
550 for ( i = 0 ; static_functions[i].Name_offset >= 0 ; i++ ) {
551 if (static_functions[i].Offset == offset) {
552 return gl_string_table + static_functions[i].Name_offset;
Brian Paul9c7ca852000-10-19 20:13:12 +0000553 }
554 }
555 return NULL;
Brian Paul959f8022000-03-19 01:10:11 +0000556}
557
558
559
560/**********************************************************************
561 * Extension function management.
562 */
563
Brian Paul54f3aab2002-10-02 01:51:44 +0000564/*
565 * Number of extension functions which we can dynamically add at runtime.
566 */
567#define MAX_EXTENSION_FUNCS 300
Brian Paul959f8022000-03-19 01:10:11 +0000568
Brian Paul54f3aab2002-10-02 01:51:44 +0000569
570/*
571 * The disptach table size (number of entries) is the sizeof the
572 * _glapi_table struct plus the number of dynamic entries we can add.
573 * The extra slots can be filled in by DRI drivers that register new extension
574 * functions.
575 */
576#define DISPATCH_TABLE_SIZE (sizeof(struct _glapi_table) / sizeof(void *) + MAX_EXTENSION_FUNCS)
577
Brian Paul959f8022000-03-19 01:10:11 +0000578
579static struct name_address_offset ExtEntryTable[MAX_EXTENSION_FUNCS];
580static GLuint NumExtEntryPoints = 0;
581
davem694a497e62001-06-06 22:55:28 +0000582#ifdef USE_SPARC_ASM
583extern void __glapi_sparc_icache_flush(unsigned int *);
584#endif
Brian Paul959f8022000-03-19 01:10:11 +0000585
586/*
587 * Generate a dispatch function (entrypoint) which jumps through
588 * the given slot number (offset) in the current dispatch table.
589 * We need assembly language in order to accomplish this.
590 */
591static void *
592generate_entrypoint(GLuint functionOffset)
593{
594#if defined(USE_X86_ASM)
595 /*
596 * This x86 code contributed by Josh Vanderhoof.
597 *
598 * 0: a1 10 32 54 76 movl __glapi_Dispatch,%eax
599 * 00 01 02 03 04
600 * 5: 85 c0 testl %eax,%eax
601 * 05 06
602 * 7: 74 06 je f <entrypoint+0xf>
603 * 07 08
604 * 9: ff a0 10 32 54 76 jmp *0x76543210(%eax)
605 * 09 0a 0b 0c 0d 0e
606 * f: e8 fc ff ff ff call __glapi_get_dispatch
607 * 0f 10 11 12 13
608 * 14: ff a0 10 32 54 76 jmp *0x76543210(%eax)
609 * 14 15 16 17 18 19
610 */
Brian Paul54f3aab2002-10-02 01:51:44 +0000611 static const unsigned char insn_template[] = {
Brian Paul959f8022000-03-19 01:10:11 +0000612 0xa1, 0x00, 0x00, 0x00, 0x00,
613 0x85, 0xc0,
614 0x74, 0x06,
615 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00,
616 0xe8, 0x00, 0x00, 0x00, 0x00,
617 0xff, 0xa0, 0x00, 0x00, 0x00, 0x00
618 };
Brian Pauldec2a4d2002-10-29 15:03:14 +0000619 unsigned char *code = (unsigned char *) malloc(sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000620 unsigned int next_insn;
621 if (code) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000622 memcpy(code, insn_template, sizeof(insn_template));
Brian Paul959f8022000-03-19 01:10:11 +0000623
Daniel Borcafd003822004-07-05 06:15:37 +0000624#if defined( THREADS )
Ian Romanick8e77da1c2004-06-29 19:08:20 +0000625 *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_DispatchTSD;
Daniel Borcafd003822004-07-05 06:15:37 +0000626#else
627 *(unsigned int *)(code + 0x01) = (unsigned int)&_glapi_Dispatch;
628#endif
Brian Paul959f8022000-03-19 01:10:11 +0000629 *(unsigned int *)(code + 0x0b) = (unsigned int)functionOffset * 4;
630 next_insn = (unsigned int)(code + 0x14);
631 *(unsigned int *)(code + 0x10) = (unsigned int)_glapi_get_dispatch - next_insn;
632 *(unsigned int *)(code + 0x16) = (unsigned int)functionOffset * 4;
633 }
634 return code;
davem69775355a2001-06-05 23:54:00 +0000635#elif defined(USE_SPARC_ASM)
636
Brian Paul9a90cd42003-12-01 22:40:26 +0000637#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000638 static const unsigned int insn_template[] = {
639 0x05000000, /* sethi %uhi(_glapi_Dispatch), %g2 */
640 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
641 0x8410a000, /* or %g2, %ulo(_glapi_Dispatch), %g2 */
642 0x82106000, /* or %g1, %lo(_glapi_Dispatch), %g1 */
643 0x8528b020, /* sllx %g2, 32, %g2 */
644 0xc2584002, /* ldx [%g1 + %g2], %g1 */
645 0x05000000, /* sethi %hi(8 * glapioffset), %g2 */
646 0x8410a000, /* or %g2, %lo(8 * glapioffset), %g2 */
647 0xc6584002, /* ldx [%g1 + %g2], %g3 */
648 0x81c0c000, /* jmpl %g3, %g0 */
649 0x01000000 /* nop */
650 };
651#else
652 static const unsigned int insn_template[] = {
653 0x03000000, /* sethi %hi(_glapi_Dispatch), %g1 */
654 0xc2006000, /* ld [%g1 + %lo(_glapi_Dispatch)], %g1 */
655 0xc6006000, /* ld [%g1 + %lo(4*glapioffset)], %g3 */
656 0x81c0c000, /* jmpl %g3, %g0 */
657 0x01000000 /* nop */
658 };
659#endif
Brian Pauldec2a4d2002-10-29 15:03:14 +0000660 unsigned int *code = (unsigned int *) malloc(sizeof(insn_template));
davem69775355a2001-06-05 23:54:00 +0000661 unsigned long glapi_addr = (unsigned long) &_glapi_Dispatch;
662 if (code) {
663 memcpy(code, insn_template, sizeof(insn_template));
664
Brian Paul9a90cd42003-12-01 22:40:26 +0000665#if defined(__sparc_v9__) && !defined(__linux__)
davem69775355a2001-06-05 23:54:00 +0000666 code[0] |= (glapi_addr >> (32 + 10));
667 code[1] |= ((glapi_addr & 0xffffffff) >> 10);
davem694a497e62001-06-06 22:55:28 +0000668 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000669 code[2] |= ((glapi_addr >> 32) & ((1 << 10) - 1));
670 code[3] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000671 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000672 code[6] |= ((functionOffset * 8) >> 10);
673 code[7] |= ((functionOffset * 8) & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000674 __glapi_sparc_icache_flush(&code[6]);
davem69775355a2001-06-05 23:54:00 +0000675#else
676 code[0] |= (glapi_addr >> 10);
677 code[1] |= (glapi_addr & ((1 << 10) - 1));
davem694a497e62001-06-06 22:55:28 +0000678 __glapi_sparc_icache_flush(&code[0]);
davem69775355a2001-06-05 23:54:00 +0000679 code[2] |= (functionOffset * 4);
davem694a497e62001-06-06 22:55:28 +0000680 __glapi_sparc_icache_flush(&code[2]);
davem69775355a2001-06-05 23:54:00 +0000681#endif
682 }
683 return code;
Brian Paul959f8022000-03-19 01:10:11 +0000684#else
Brian Paula6c423d2004-08-25 15:59:48 +0000685 (void) functionOffset;
Brian Paul959f8022000-03-19 01:10:11 +0000686 return NULL;
Brian Paul54f3aab2002-10-02 01:51:44 +0000687#endif /* USE_*_ASM */
Brian Paul959f8022000-03-19 01:10:11 +0000688}
689
690
Brian Paul54f3aab2002-10-02 01:51:44 +0000691/*
692 * This function inserts a new dispatch offset into the assembly language
693 * stub that was generated with the preceeding function.
694 */
695static void
696fill_in_entrypoint_offset(void *entrypoint, GLuint offset)
697{
698#if defined(USE_X86_ASM)
699
700 unsigned char *code = (unsigned char *) entrypoint;
701 *(unsigned int *)(code + 0x0b) = offset * 4;
702 *(unsigned int *)(code + 0x16) = offset * 4;
703
704#elif defined(USE_SPARC_ASM)
705
706 /* XXX this hasn't been tested! */
707 unsigned int *code = (unsigned int *) entrypoint;
Brian Paul9a90cd42003-12-01 22:40:26 +0000708#if defined(__sparc_v9__) && !defined(__linux__)
Brian Paul54f3aab2002-10-02 01:51:44 +0000709 code[6] = 0x05000000; /* sethi %hi(8 * glapioffset), %g2 */
710 code[7] = 0x8410a000; /* or %g2, %lo(8 * glapioffset), %g2 */
711 code[6] |= ((offset * 8) >> 10);
712 code[7] |= ((offset * 8) & ((1 << 10) - 1));
713 __glapi_sparc_icache_flush(&code[6]);
Brian Paul9a90cd42003-12-01 22:40:26 +0000714#else /* __sparc_v9__ && !linux */
Brian Paul54f3aab2002-10-02 01:51:44 +0000715 code[2] = 0xc6006000; /* ld [%g1 + %lo(4*glapioffset)], %g3 */
Brian Paul944ea202002-10-17 16:29:17 +0000716 code[2] |= (offset * 4);
Brian Paul54f3aab2002-10-02 01:51:44 +0000717 __glapi_sparc_icache_flush(&code[2]);
Brian Paul9a90cd42003-12-01 22:40:26 +0000718#endif /* __sparc_v9__ && !linux */
Brian Paul54f3aab2002-10-02 01:51:44 +0000719
Brian Paula6c423d2004-08-25 15:59:48 +0000720#else
721
722 /* an unimplemented architecture */
723 (void) entrypoint;
724 (void) offset;
725
Brian Paul54f3aab2002-10-02 01:51:44 +0000726#endif /* USE_*_ASM */
727}
728
Brian Paul959f8022000-03-19 01:10:11 +0000729
730/*
731 * Add a new extension function entrypoint.
732 * Return: GL_TRUE = success or GL_FALSE = failure
733 */
734GLboolean
735_glapi_add_entrypoint(const char *funcName, GLuint offset)
736{
Brian Paul8ad10762002-10-11 17:41:03 +0000737 /* trivial rejection test */
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000738#ifdef MANGLE
739 if (!funcName || funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
Brian Paula6c423d2004-08-25 15:59:48 +0000740 return GL_FALSE;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000741#else
Brian Paul8ad10762002-10-11 17:41:03 +0000742 if (!funcName || funcName[0] != 'g' || funcName[1] != 'l')
743 return GL_FALSE;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000744#endif
Brian Paul8ad10762002-10-11 17:41:03 +0000745
Brian Paul959f8022000-03-19 01:10:11 +0000746 /* first check if the named function is already statically present */
747 {
748 GLint index = get_static_proc_offset(funcName);
749 if (index >= 0) {
Brian Paulb51b0a82001-03-07 05:06:11 +0000750 return (GLboolean) ((GLuint) index == offset); /* bad offset! */
Brian Paul959f8022000-03-19 01:10:11 +0000751 }
752 }
753
Brian Paul54f3aab2002-10-02 01:51:44 +0000754 /* See if this function has already been dynamically added */
Brian Paul959f8022000-03-19 01:10:11 +0000755 {
Brian Paul959f8022000-03-19 01:10:11 +0000756 GLuint i;
757 for (i = 0; i < NumExtEntryPoints; i++) {
758 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000759 /* function already registered */
Brian Paul959f8022000-03-19 01:10:11 +0000760 if (ExtEntryTable[i].Offset == offset) {
761 return GL_TRUE; /* offsets match */
762 }
Brian Paule4fcea22003-09-19 15:38:15 +0000763 else if (ExtEntryTable[i].Offset == (GLuint) ~0
Brian Paul54f3aab2002-10-02 01:51:44 +0000764 && offset < DISPATCH_TABLE_SIZE) {
765 /* need to patch-up the dispatch code */
Brian Paule4fcea22003-09-19 15:38:15 +0000766 if (offset != (GLuint) ~0) {
Brian Paul54f3aab2002-10-02 01:51:44 +0000767 fill_in_entrypoint_offset(ExtEntryTable[i].Address, offset);
768 ExtEntryTable[i].Offset = offset;
769 }
770 return GL_TRUE;
771 }
Brian Paul959f8022000-03-19 01:10:11 +0000772 else {
773 return GL_FALSE; /* bad offset! */
774 }
775 }
776 }
Brian Paul959f8022000-03-19 01:10:11 +0000777 }
778
Brian Paul8ad10762002-10-11 17:41:03 +0000779 /* This is a new function, try to add it. */
780 if (NumExtEntryPoints >= MAX_EXTENSION_FUNCS ||
781 offset >= DISPATCH_TABLE_SIZE) {
782 /* No space left */
783 return GL_FALSE;
784 }
785 else {
786 void *entrypoint = generate_entrypoint(offset);
787 if (!entrypoint)
788 return GL_FALSE; /* couldn't generate assembly */
789
790 /* OK! */
791 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
792 ExtEntryTable[NumExtEntryPoints].Offset = offset;
793 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
794 NumExtEntryPoints++;
795
796 return GL_TRUE; /* success */
797 }
798
799 /* should never get here, silence compiler warnings */
Brian Paul959f8022000-03-19 01:10:11 +0000800 return GL_FALSE;
801}
802
803
Brian Paul959f8022000-03-19 01:10:11 +0000804/*
805 * Return offset of entrypoint for named function within dispatch table.
806 */
807GLint
808_glapi_get_proc_offset(const char *funcName)
809{
810 /* search extension functions first */
Brian Paulb51b0a82001-03-07 05:06:11 +0000811 GLuint i;
Brian Paul959f8022000-03-19 01:10:11 +0000812 for (i = 0; i < NumExtEntryPoints; i++) {
813 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
814 return ExtEntryTable[i].Offset;
815 }
816 }
817
818 /* search static functions */
819 return get_static_proc_offset(funcName);
820}
821
822
823
824/*
825 * Return entrypoint for named function.
826 */
827const GLvoid *
828_glapi_get_proc_address(const char *funcName)
829{
Brian Paulb51b0a82001-03-07 05:06:11 +0000830 GLuint i;
Brian Paula6ed6f42003-08-27 14:48:16 +0000831
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000832#ifdef MANGLE
833 if (funcName[0] != 'm' || funcName[1] != 'g' || funcName[2] != 'l')
834 return NULL;
835#else
Brian Paula6ed6f42003-08-27 14:48:16 +0000836 if (funcName[0] != 'g' || funcName[1] != 'l')
837 return NULL;
Brian Paulf7b4e0d2004-04-23 20:33:07 +0000838#endif
Brian Paula6ed6f42003-08-27 14:48:16 +0000839
840 /* search extension functions first */
Brian Paul959f8022000-03-19 01:10:11 +0000841 for (i = 0; i < NumExtEntryPoints; i++) {
842 if (strcmp(ExtEntryTable[i].Name, funcName) == 0) {
843 return ExtEntryTable[i].Address;
844 }
845 }
846
847 /* search static functions */
Brian Paul54f3aab2002-10-02 01:51:44 +0000848 {
849 const GLvoid *func = get_static_proc_address(funcName);
850 if (func)
851 return func;
852 }
Brian Paul959f8022000-03-19 01:10:11 +0000853
Brian Paul54f3aab2002-10-02 01:51:44 +0000854 /* generate new entrypoint - use a temporary dispatch offset of
855 * ~0 (i.e. -1). Later, when the driver calls _glapi_add_entrypoint()
856 * we'll put in the proper offset. If that never happens, and the
857 * user calls this function, he'll segfault. That's what you get
858 * when you try calling a GL function that doesn't really exist.
859 */
860 if (NumExtEntryPoints < MAX_EXTENSION_FUNCS) {
861 GLvoid *entrypoint = generate_entrypoint(~0);
862 if (!entrypoint)
863 return GL_FALSE;
864
865 ExtEntryTable[NumExtEntryPoints].Name = str_dup(funcName);
866 ExtEntryTable[NumExtEntryPoints].Offset = ~0;
867 ExtEntryTable[NumExtEntryPoints].Address = entrypoint;
868 NumExtEntryPoints++;
869
870 return entrypoint;
871 }
872 else {
873 /* no space for new functions! */
874 return NULL;
875 }
876}
Brian Paul959f8022000-03-19 01:10:11 +0000877
878
879
880/*
881 * Return the name of the function at the given dispatch offset.
882 * This is only intended for debugging.
883 */
884const char *
885_glapi_get_proc_name(GLuint offset)
886{
Brian Paul959f8022000-03-19 01:10:11 +0000887 GLuint i;
Ian Romanick78677992004-05-27 00:05:13 +0000888 const char * n;
Brian Paul54f3aab2002-10-02 01:51:44 +0000889
890 /* search built-in functions */
Ian Romanick78677992004-05-27 00:05:13 +0000891 n = get_static_proc_name(offset);
892 if ( n != NULL ) {
893 return n;
Brian Paul959f8022000-03-19 01:10:11 +0000894 }
895
896 /* search added extension functions */
897 for (i = 0; i < NumExtEntryPoints; i++) {
898 if (ExtEntryTable[i].Offset == offset) {
899 return ExtEntryTable[i].Name;
900 }
901 }
902 return NULL;
903}
904
905
906
907/*
Brian Paul54f3aab2002-10-02 01:51:44 +0000908 * Return size of dispatch table struct as number of functions (or
909 * slots).
910 */
911GLuint
912_glapi_get_dispatch_table_size(void)
913{
914 return DISPATCH_TABLE_SIZE;
915}
916
917
918
919/*
920 * Get API dispatcher version string.
921 */
922const char *
923_glapi_get_version(void)
924{
925 return "20021001"; /* YYYYMMDD */
926}
927
928
929
930/*
Brian Paul959f8022000-03-19 01:10:11 +0000931 * Make sure there are no NULL pointers in the given dispatch table.
Brian Paul5104b4d2002-03-07 21:50:41 +0000932 * Intended for debugging purposes.
Brian Paul959f8022000-03-19 01:10:11 +0000933 */
934void
935_glapi_check_table(const struct _glapi_table *table)
936{
Brian Paul5104b4d2002-03-07 21:50:41 +0000937#ifdef DEBUG
Brian Paul959f8022000-03-19 01:10:11 +0000938 const GLuint entries = _glapi_get_dispatch_table_size();
939 const void **tab = (const void **) table;
940 GLuint i;
941 for (i = 1; i < entries; i++) {
942 assert(tab[i]);
943 }
944
Brian Paul959f8022000-03-19 01:10:11 +0000945 /* Do some spot checks to be sure that the dispatch table
946 * slots are assigned correctly.
947 */
948 {
949 GLuint BeginOffset = _glapi_get_proc_offset("glBegin");
950 char *BeginFunc = (char*) &table->Begin;
951 GLuint offset = (BeginFunc - (char *) table) / sizeof(void *);
952 assert(BeginOffset == _gloffset_Begin);
953 assert(BeginOffset == offset);
954 }
955 {
956 GLuint viewportOffset = _glapi_get_proc_offset("glViewport");
957 char *viewportFunc = (char*) &table->Viewport;
958 GLuint offset = (viewportFunc - (char *) table) / sizeof(void *);
959 assert(viewportOffset == _gloffset_Viewport);
960 assert(viewportOffset == offset);
961 }
962 {
963 GLuint VertexPointerOffset = _glapi_get_proc_offset("glVertexPointer");
964 char *VertexPointerFunc = (char*) &table->VertexPointer;
965 GLuint offset = (VertexPointerFunc - (char *) table) / sizeof(void *);
966 assert(VertexPointerOffset == _gloffset_VertexPointer);
967 assert(VertexPointerOffset == offset);
968 }
969 {
970 GLuint ResetMinMaxOffset = _glapi_get_proc_offset("glResetMinmax");
971 char *ResetMinMaxFunc = (char*) &table->ResetMinmax;
972 GLuint offset = (ResetMinMaxFunc - (char *) table) / sizeof(void *);
973 assert(ResetMinMaxOffset == _gloffset_ResetMinmax);
974 assert(ResetMinMaxOffset == offset);
975 }
976 {
977 GLuint blendColorOffset = _glapi_get_proc_offset("glBlendColor");
978 char *blendColorFunc = (char*) &table->BlendColor;
979 GLuint offset = (blendColorFunc - (char *) table) / sizeof(void *);
980 assert(blendColorOffset == _gloffset_BlendColor);
981 assert(blendColorOffset == offset);
982 }
983 {
984 GLuint istextureOffset = _glapi_get_proc_offset("glIsTextureEXT");
985 char *istextureFunc = (char*) &table->IsTextureEXT;
986 GLuint offset = (istextureFunc - (char *) table) / sizeof(void *);
987 assert(istextureOffset == _gloffset_IsTextureEXT);
988 assert(istextureOffset == offset);
989 }
Brian Paula14cbff2000-10-27 18:31:21 +0000990 {
991 GLuint secondaryColor3fOffset = _glapi_get_proc_offset("glSecondaryColor3fEXT");
992 char *secondaryColor3fFunc = (char*) &table->SecondaryColor3fEXT;
993 GLuint offset = (secondaryColor3fFunc - (char *) table) / sizeof(void *);
994 assert(secondaryColor3fOffset == _gloffset_SecondaryColor3fEXT);
995 assert(secondaryColor3fOffset == offset);
996 assert(_glapi_get_proc_address("glSecondaryColor3fEXT") == (void *) &glSecondaryColor3fEXT);
997 }
Brian Paul91d6f122002-05-29 15:23:16 +0000998 {
999 GLuint pointParameterivOffset = _glapi_get_proc_offset("glPointParameterivNV");
1000 char *pointParameterivFunc = (char*) &table->PointParameterivNV;
1001 GLuint offset = (pointParameterivFunc - (char *) table) / sizeof(void *);
1002 assert(pointParameterivOffset == _gloffset_PointParameterivNV);
1003 assert(pointParameterivOffset == offset);
1004 assert(_glapi_get_proc_address("glPointParameterivNV") == (void *) &glPointParameterivNV);
1005 }
Brian Paul54f3aab2002-10-02 01:51:44 +00001006 {
1007 GLuint setFenceOffset = _glapi_get_proc_offset("glSetFenceNV");
1008 char *setFenceFunc = (char*) &table->SetFenceNV;
1009 GLuint offset = (setFenceFunc - (char *) table) / sizeof(void *);
1010 assert(setFenceOffset == _gloffset_SetFenceNV);
1011 assert(setFenceOffset == offset);
1012 assert(_glapi_get_proc_address("glSetFenceNV") == (void *) &glSetFenceNV);
1013 }
Brian Paula6c423d2004-08-25 15:59:48 +00001014#else
1015 (void) table;
Brian Paul959f8022000-03-19 01:10:11 +00001016#endif
1017}