Follow suggestion by Aapo Tahkola to fix giant memory leak from forgetting to free...
[mesa.git] / src / mesa / tnl / t_vtx_generic.c
1 /**************************************************************************
2
3 Copyright 2004 Tungsten Graphics Inc., Cedar Park, Texas.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keith@tungstengraphics.com>
31 */
32
33 #include "glheader.h"
34 #include "context.h"
35 #include "macros.h"
36 #include "vtxfmt.h"
37 #include "dlist.h"
38 #include "state.h"
39 #include "light.h"
40 #include "api_arrayelt.h"
41 #include "api_noop.h"
42 #include "t_vtx_api.h"
43
44
45 /* Versions of all the entrypoints for situations where codegen isn't
46 * available.
47 *
48 * Note: Only one size for each attribute may be active at once.
49 * Eg. if Color3f is installed/active, then Color4f may not be, even
50 * if the vertex actually contains 4 color coordinates. This is
51 * because the 3f version won't otherwise set color[3] to 1.0 -- this
52 * is the job of the chooser function when switching between Color4f
53 * and Color3f.
54 */
55 #define ATTRFV( ATTR, N ) \
56 static void attrib_##ATTR##_##N( const GLfloat *v ) \
57 { \
58 GET_CURRENT_CONTEXT( ctx ); \
59 TNLcontext *tnl = TNL_CONTEXT(ctx); \
60 \
61 if ((ATTR) == 0) { \
62 GLuint i; \
63 \
64 if (N>0) tnl->vtx.vbptr[0] = v[0]; \
65 if (N>1) tnl->vtx.vbptr[1] = v[1]; \
66 if (N>2) tnl->vtx.vbptr[2] = v[2]; \
67 if (N>3) tnl->vtx.vbptr[3] = v[3]; \
68 \
69 for (i = N; i < tnl->vtx.vertex_size; i++) \
70 tnl->vtx.vbptr[i] = tnl->vtx.vertex[i]; \
71 \
72 tnl->vtx.vbptr += tnl->vtx.vertex_size; \
73 \
74 if (--tnl->vtx.counter == 0) \
75 _tnl_wrap_filled_vertex( ctx ); \
76 } \
77 else { \
78 GLfloat *dest = tnl->vtx.attrptr[ATTR]; \
79 if (N>0) dest[0] = v[0]; \
80 if (N>1) dest[1] = v[1]; \
81 if (N>2) dest[2] = v[2]; \
82 if (N>3) dest[3] = v[3]; \
83 } \
84 }
85
86 #define INIT(TAB, ATTR) \
87 TAB[ATTR][0] = attrib_##ATTR##_1; \
88 TAB[ATTR][1] = attrib_##ATTR##_2; \
89 TAB[ATTR][2] = attrib_##ATTR##_3; \
90 TAB[ATTR][3] = attrib_##ATTR##_4;
91
92
93 #define ATTRS( ATTRIB ) \
94 ATTRFV( ATTRIB, 1 ) \
95 ATTRFV( ATTRIB, 2 ) \
96 ATTRFV( ATTRIB, 3 ) \
97 ATTRFV( ATTRIB, 4 )
98
99 ATTRS( 0 )
100 ATTRS( 1 )
101 ATTRS( 2 )
102 ATTRS( 3 )
103 ATTRS( 4 )
104 ATTRS( 5 )
105 ATTRS( 6 )
106 ATTRS( 7 )
107 ATTRS( 8 )
108 ATTRS( 9 )
109 ATTRS( 10 )
110 ATTRS( 11 )
111 ATTRS( 12 )
112 ATTRS( 13 )
113 ATTRS( 14 )
114 ATTRS( 15 )
115
116 void _tnl_generic_attr_table_init( tnl_attrfv_func (*tab)[4] )
117 {
118 INIT( tab, 0 );
119 INIT( tab, 1 );
120 INIT( tab, 2 );
121 INIT( tab, 3 );
122 INIT( tab, 4 );
123 INIT( tab, 5 );
124 INIT( tab, 6 );
125 INIT( tab, 7 );
126 INIT( tab, 8 );
127 INIT( tab, 9 );
128 INIT( tab, 10 );
129 INIT( tab, 11 );
130 INIT( tab, 12 );
131 INIT( tab, 13 );
132 INIT( tab, 14 );
133 INIT( tab, 15 );
134 }
135
136 /* These can be made efficient with codegen. Further, by adding more
137 * logic to do_choose(), the double-dispatch for legacy entrypoints
138 * like glVertex3f() can be removed.
139 */
140 #define DISPATCH_ATTRFV( ATTR, COUNT, P ) \
141 do { \
142 GET_CURRENT_CONTEXT( ctx ); \
143 TNLcontext *tnl = TNL_CONTEXT(ctx); \
144 tnl->vtx.tabfv[ATTR][COUNT-1]( P ); \
145 } while (0)
146
147 #define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V )
148 #define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V )
149 #define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V )
150 #define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V )
151
152 #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) )
153
154 #if defined(USE_X86_ASM) && 0 /* will break register calling convention */
155 /* Naughty cheat:
156 */
157 #define DISPATCH_ATTR2F( ATTR, S,T ) DISPATCH_ATTRFV( ATTR, 2, &(S) )
158 #define DISPATCH_ATTR3F( ATTR, S,T,R ) DISPATCH_ATTRFV( ATTR, 3, &(S) )
159 #define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) DISPATCH_ATTRFV( ATTR, 4, &(S) )
160 #else
161 /* Safe:
162 */
163 #define DISPATCH_ATTR2F( ATTR, S,T ) \
164 do { \
165 GLfloat v[2]; \
166 v[0] = S; v[1] = T; \
167 DISPATCH_ATTR2FV( ATTR, v ); \
168 } while (0)
169 #define DISPATCH_ATTR3F( ATTR, S,T,R ) \
170 do { \
171 GLfloat v[3]; \
172 v[0] = S; v[1] = T; v[2] = R; \
173 DISPATCH_ATTR3FV( ATTR, v ); \
174 } while (0)
175 #define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \
176 do { \
177 GLfloat v[4]; \
178 v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \
179 DISPATCH_ATTR4FV( ATTR, v ); \
180 } while (0)
181 #endif
182
183
184 static void GLAPIENTRY _tnl_Vertex2f( GLfloat x, GLfloat y )
185 {
186 DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y );
187 }
188
189 static void GLAPIENTRY _tnl_Vertex2fv( const GLfloat *v )
190 {
191 DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v );
192 }
193
194 static void GLAPIENTRY _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
195 {
196 DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z );
197 }
198
199 static void GLAPIENTRY _tnl_Vertex3fv( const GLfloat *v )
200 {
201 DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v );
202 }
203
204 static void GLAPIENTRY _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z,
205 GLfloat w )
206 {
207 DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w );
208 }
209
210 static void GLAPIENTRY _tnl_Vertex4fv( const GLfloat *v )
211 {
212 DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v );
213 }
214
215 static void GLAPIENTRY _tnl_TexCoord1f( GLfloat x )
216 {
217 DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x );
218 }
219
220 static void GLAPIENTRY _tnl_TexCoord1fv( const GLfloat *v )
221 {
222 DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v );
223 }
224
225 static void GLAPIENTRY _tnl_TexCoord2f( GLfloat x, GLfloat y )
226 {
227 DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y );
228 }
229
230 static void GLAPIENTRY _tnl_TexCoord2fv( const GLfloat *v )
231 {
232 DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v );
233 }
234
235 static void GLAPIENTRY _tnl_TexCoord3f( GLfloat x, GLfloat y, GLfloat z )
236 {
237 DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z );
238 }
239
240 static void GLAPIENTRY _tnl_TexCoord3fv( const GLfloat *v )
241 {
242 DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v );
243 }
244
245 static void GLAPIENTRY _tnl_TexCoord4f( GLfloat x, GLfloat y, GLfloat z,
246 GLfloat w )
247 {
248 DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w );
249 }
250
251 static void GLAPIENTRY _tnl_TexCoord4fv( const GLfloat *v )
252 {
253 DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v );
254 }
255
256 static void GLAPIENTRY _tnl_Normal3f( GLfloat x, GLfloat y, GLfloat z )
257 {
258 DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z );
259 }
260
261 static void GLAPIENTRY _tnl_Normal3fv( const GLfloat *v )
262 {
263 DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v );
264 }
265
266 static void GLAPIENTRY _tnl_FogCoordfEXT( GLfloat x )
267 {
268 DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x );
269 }
270
271 static void GLAPIENTRY _tnl_FogCoordfvEXT( const GLfloat *v )
272 {
273 DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v );
274 }
275
276 static void GLAPIENTRY _tnl_Color3f( GLfloat x, GLfloat y, GLfloat z )
277 {
278 DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z );
279 }
280
281 static void GLAPIENTRY _tnl_Color3fv( const GLfloat *v )
282 {
283 DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v );
284 }
285
286 static void GLAPIENTRY _tnl_Color4f( GLfloat x, GLfloat y, GLfloat z,
287 GLfloat w )
288 {
289 DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w );
290 }
291
292 static void GLAPIENTRY _tnl_Color4fv( const GLfloat *v )
293 {
294 DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v );
295 }
296
297 static void GLAPIENTRY _tnl_SecondaryColor3fEXT( GLfloat x, GLfloat y,
298 GLfloat z )
299 {
300 DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z );
301 }
302
303 static void GLAPIENTRY _tnl_SecondaryColor3fvEXT( const GLfloat *v )
304 {
305 DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v );
306 }
307
308 static void GLAPIENTRY _tnl_MultiTexCoord1f( GLenum target, GLfloat x )
309 {
310 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
311 DISPATCH_ATTR1F( attr, x );
312 }
313
314 static void GLAPIENTRY _tnl_MultiTexCoord1fv( GLenum target,
315 const GLfloat *v )
316 {
317 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
318 DISPATCH_ATTR1FV( attr, v );
319 }
320
321 static void GLAPIENTRY _tnl_MultiTexCoord2f( GLenum target, GLfloat x,
322 GLfloat y )
323 {
324 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
325 DISPATCH_ATTR2F( attr, x, y );
326 }
327
328 static void GLAPIENTRY _tnl_MultiTexCoord2fv( GLenum target,
329 const GLfloat *v )
330 {
331 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
332 DISPATCH_ATTR2FV( attr, v );
333 }
334
335 static void GLAPIENTRY _tnl_MultiTexCoord3f( GLenum target, GLfloat x,
336 GLfloat y, GLfloat z)
337 {
338 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
339 DISPATCH_ATTR3F( attr, x, y, z );
340 }
341
342 static void GLAPIENTRY _tnl_MultiTexCoord3fv( GLenum target,
343 const GLfloat *v )
344 {
345 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
346 DISPATCH_ATTR3FV( attr, v );
347 }
348
349 static void GLAPIENTRY _tnl_MultiTexCoord4f( GLenum target, GLfloat x,
350 GLfloat y, GLfloat z,
351 GLfloat w )
352 {
353 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
354 DISPATCH_ATTR4F( attr, x, y, z, w );
355 }
356
357 static void GLAPIENTRY _tnl_MultiTexCoord4fv( GLenum target,
358 const GLfloat *v )
359 {
360 GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0;
361 DISPATCH_ATTR4FV( attr, v );
362 }
363
364
365 static void GLAPIENTRY _tnl_VertexAttrib1fNV( GLuint index, GLfloat x )
366 {
367 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
368 DISPATCH_ATTR1F( index, x );
369 }
370
371 static void GLAPIENTRY _tnl_VertexAttrib1fvNV( GLuint index,
372 const GLfloat *v )
373 {
374 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
375 DISPATCH_ATTR1FV( index, v );
376 }
377
378 static void GLAPIENTRY _tnl_VertexAttrib2fNV( GLuint index, GLfloat x,
379 GLfloat y )
380 {
381 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
382 DISPATCH_ATTR2F( index, x, y );
383 }
384
385 static void GLAPIENTRY _tnl_VertexAttrib2fvNV( GLuint index,
386 const GLfloat *v )
387 {
388 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
389 DISPATCH_ATTR2FV( index, v );
390 }
391
392 static void GLAPIENTRY _tnl_VertexAttrib3fNV( GLuint index, GLfloat x,
393 GLfloat y, GLfloat z )
394 {
395 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
396 DISPATCH_ATTR3F( index, x, y, z );
397 }
398
399 static void GLAPIENTRY _tnl_VertexAttrib3fvNV( GLuint index,
400 const GLfloat *v )
401 {
402 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
403 DISPATCH_ATTR3FV( index, v );
404 }
405
406 static void GLAPIENTRY _tnl_VertexAttrib4fNV( GLuint index, GLfloat x,
407 GLfloat y, GLfloat z,
408 GLfloat w )
409 {
410 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
411 DISPATCH_ATTR4F( index, x, y, z, w );
412 }
413
414 static void GLAPIENTRY _tnl_VertexAttrib4fvNV( GLuint index,
415 const GLfloat *v )
416 {
417 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
418 DISPATCH_ATTR4FV( index, v );
419 }
420
421
422 /*
423 * XXX adjust index
424 */
425
426 static void GLAPIENTRY _tnl_VertexAttrib1fARB( GLuint index, GLfloat x )
427 {
428 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
429 DISPATCH_ATTR1F( index, x );
430 }
431
432 static void GLAPIENTRY _tnl_VertexAttrib1fvARB( GLuint index,
433 const GLfloat *v )
434 {
435 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
436 DISPATCH_ATTR1FV( index, v );
437 }
438
439 static void GLAPIENTRY _tnl_VertexAttrib2fARB( GLuint index, GLfloat x,
440 GLfloat y )
441 {
442 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
443 DISPATCH_ATTR2F( index, x, y );
444 }
445
446 static void GLAPIENTRY _tnl_VertexAttrib2fvARB( GLuint index,
447 const GLfloat *v )
448 {
449 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
450 DISPATCH_ATTR2FV( index, v );
451 }
452
453 static void GLAPIENTRY _tnl_VertexAttrib3fARB( GLuint index, GLfloat x,
454 GLfloat y, GLfloat z )
455 {
456 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
457 DISPATCH_ATTR3F( index, x, y, z );
458 }
459
460 static void GLAPIENTRY _tnl_VertexAttrib3fvARB( GLuint index,
461 const GLfloat *v )
462 {
463 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
464 DISPATCH_ATTR3FV( index, v );
465 }
466
467 static void GLAPIENTRY _tnl_VertexAttrib4fARB( GLuint index, GLfloat x,
468 GLfloat y, GLfloat z,
469 GLfloat w )
470 {
471 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
472 DISPATCH_ATTR4F( index, x, y, z, w );
473 }
474
475 static void GLAPIENTRY _tnl_VertexAttrib4fvARB( GLuint index,
476 const GLfloat *v )
477 {
478 if (index >= VERT_ATTRIB_MAX) index = ERROR_ATTRIB;
479 DISPATCH_ATTR4FV( index, v );
480 }
481
482
483 /* Install the generic versions of the 2nd level dispatch
484 * functions. Some of these have a codegen alternative.
485 */
486 void _tnl_generic_exec_vtxfmt_init( GLcontext *ctx )
487 {
488 GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt);
489
490 vfmt->Color3f = _tnl_Color3f;
491 vfmt->Color3fv = _tnl_Color3fv;
492 vfmt->Color4f = _tnl_Color4f;
493 vfmt->Color4fv = _tnl_Color4fv;
494 vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
495 vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
496 vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1f;
497 vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv;
498 vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2f;
499 vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv;
500 vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3f;
501 vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv;
502 vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4f;
503 vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv;
504 vfmt->Normal3f = _tnl_Normal3f;
505 vfmt->Normal3fv = _tnl_Normal3fv;
506 vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
507 vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
508 vfmt->TexCoord1f = _tnl_TexCoord1f;
509 vfmt->TexCoord1fv = _tnl_TexCoord1fv;
510 vfmt->TexCoord2f = _tnl_TexCoord2f;
511 vfmt->TexCoord2fv = _tnl_TexCoord2fv;
512 vfmt->TexCoord3f = _tnl_TexCoord3f;
513 vfmt->TexCoord3fv = _tnl_TexCoord3fv;
514 vfmt->TexCoord4f = _tnl_TexCoord4f;
515 vfmt->TexCoord4fv = _tnl_TexCoord4fv;
516 vfmt->Vertex2f = _tnl_Vertex2f;
517 vfmt->Vertex2fv = _tnl_Vertex2fv;
518 vfmt->Vertex3f = _tnl_Vertex3f;
519 vfmt->Vertex3fv = _tnl_Vertex3fv;
520 vfmt->Vertex4f = _tnl_Vertex4f;
521 vfmt->Vertex4fv = _tnl_Vertex4fv;
522 vfmt->VertexAttrib1fNV = _tnl_VertexAttrib1fNV;
523 vfmt->VertexAttrib1fvNV = _tnl_VertexAttrib1fvNV;
524 vfmt->VertexAttrib2fNV = _tnl_VertexAttrib2fNV;
525 vfmt->VertexAttrib2fvNV = _tnl_VertexAttrib2fvNV;
526 vfmt->VertexAttrib3fNV = _tnl_VertexAttrib3fNV;
527 vfmt->VertexAttrib3fvNV = _tnl_VertexAttrib3fvNV;
528 vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
529 vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
530 vfmt->VertexAttrib1fARB = _tnl_VertexAttrib1fARB;
531 vfmt->VertexAttrib1fvARB = _tnl_VertexAttrib1fvARB;
532 vfmt->VertexAttrib2fARB = _tnl_VertexAttrib2fARB;
533 vfmt->VertexAttrib2fvARB = _tnl_VertexAttrib2fvARB;
534 vfmt->VertexAttrib3fARB = _tnl_VertexAttrib3fARB;
535 vfmt->VertexAttrib3fvARB = _tnl_VertexAttrib3fvARB;
536 vfmt->VertexAttrib4fARB = _tnl_VertexAttrib4fARB;
537 vfmt->VertexAttrib4fvARB = _tnl_VertexAttrib4fvARB;
538 }