Fixed off by one errors in clipping.
[mesa.git] / src / mesa / drivers / dri / r200 / r200_vtxfmt.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_vtxfmt.c,v 1.4 2003/05/06 23:52:08 daenzer Exp $ */
2 /*
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 /*
32 * Authors:
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "glheader.h"
37 #include "imports.h"
38 #include "r200_context.h"
39 #include "r200_state.h"
40 #include "r200_ioctl.h"
41 #include "r200_tex.h"
42 #include "r200_tcl.h"
43 #include "r200_swtcl.h"
44 #include "r200_vtxfmt.h"
45
46 #include "api_noop.h"
47 #include "api_arrayelt.h"
48 #include "context.h"
49 #include "mtypes.h"
50 #include "enums.h"
51 #include "glapi.h"
52 #include "colormac.h"
53 #include "light.h"
54 #include "state.h"
55 #include "vtxfmt.h"
56
57 #include "tnl/tnl.h"
58 #include "tnl/t_context.h"
59 #include "tnl/t_array_api.h"
60
61 static void r200VtxFmtFlushVertices( GLcontext *, GLuint );
62
63 static void count_func( const char *name, struct dynfn *l )
64 {
65 int i = 0;
66 struct dynfn *f;
67 foreach (f, l) i++;
68 if (i) fprintf(stderr, "%s: %d\n", name, i );
69 }
70
71 static void count_funcs( r200ContextPtr rmesa )
72 {
73 count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f );
74 count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv );
75 count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f );
76 count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv );
77 count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub );
78 count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv );
79 count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub );
80 count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv );
81 count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f );
82 count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv );
83 count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f );
84 count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv );
85 count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
86 count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
87 count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
88 count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
89 count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f );
90 count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv );
91 count_func( "TexCoord3f", &rmesa->vb.dfn_cache.TexCoord3f );
92 count_func( "TexCoord3fv", &rmesa->vb.dfn_cache.TexCoord3fv );
93 count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f );
94 count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv );
95 count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f );
96 count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv );
97 count_func( "MultiTexCoord3fARB", &rmesa->vb.dfn_cache.MultiTexCoord3fARB );
98 count_func( "MultiTexCoord3fvARB", &rmesa->vb.dfn_cache.MultiTexCoord3fvARB );
99 count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
100 count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
101 count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
102 count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
103 }
104
105
106 void r200_copy_to_current( GLcontext *ctx )
107 {
108 r200ContextPtr rmesa = R200_CONTEXT(ctx);
109 unsigned i;
110
111 if (R200_DEBUG & DEBUG_VFMT)
112 fprintf(stderr, "%s\n", __FUNCTION__);
113
114 assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
115
116 if (rmesa->vb.vtxfmt_0 & R200_VTX_N0) {
117 ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0] = rmesa->vb.normalptr[0];
118 ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1] = rmesa->vb.normalptr[1];
119 ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2] = rmesa->vb.normalptr[2];
120 }
121
122 switch( VTX_COLOR(rmesa->vb.vtxfmt_0, 0) ) {
123 case R200_VTX_PK_RGBA:
124 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->red );
125 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->green );
126 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->blue );
127 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->alpha );
128 break;
129
130 case R200_VTX_FP_RGB:
131 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
132 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
133 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
134 break;
135
136 case R200_VTX_FP_RGBA:
137 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
138 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
139 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
140 ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = rmesa->vb.floatcolorptr[3];
141 break;
142
143 default:
144 break;
145 }
146
147 if (VTX_COLOR(rmesa->vb.vtxfmt_0, 1) == R200_VTX_PK_RGBA) {
148 ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] = UBYTE_TO_FLOAT( rmesa->vb.specptr->red );
149 ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] = UBYTE_TO_FLOAT( rmesa->vb.specptr->green );
150 ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] = UBYTE_TO_FLOAT( rmesa->vb.specptr->blue );
151 }
152
153 for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
154 const unsigned count = VTX_TEXn_COUNT( rmesa->vb.vtxfmt_1, i );
155 GLfloat * const src = rmesa->vb.texcoordptr[i];
156
157 if ( count != 0 ) {
158 switch( count ) {
159 case 3:
160 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = src[1];
161 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = src[2];
162 break;
163 case 2:
164 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = src[1];
165 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = 0.0F;
166 break;
167 case 1:
168 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][1] = 0.0F;
169 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][2] = 0.0F;
170 break;
171 }
172
173 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][0] = src[0];
174 ctx->Current.Attrib[VERT_ATTRIB_TEX0+i][3] = 1.0F;
175 }
176 }
177
178 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
179 }
180
181 static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
182 1, /* 0 points */
183 1, /* 1 lines */
184 0, /* 2 line_strip */
185 0, /* 3 line_loop */
186 1, /* 4 tris */
187 0, /* 5 tri_fan */
188 0, /* 6 tri_strip */
189 1, /* 7 quads */
190 0, /* 8 quadstrip */
191 0, /* 9 poly */
192 };
193
194 static void flush_prims( r200ContextPtr rmesa )
195 {
196 int i,j;
197 struct r200_dma_region tmp = rmesa->dma.current;
198
199 tmp.buf->refcount++;
200 tmp.aos_size = rmesa->vb.vertex_size;
201 tmp.aos_stride = rmesa->vb.vertex_size;
202 tmp.aos_start = GET_START(&tmp);
203
204 rmesa->dma.current.ptr = rmesa->dma.current.start +=
205 (rmesa->vb.initial_counter - rmesa->vb.counter) *
206 rmesa->vb.vertex_size * 4;
207
208 rmesa->tcl.vertex_format = rmesa->vb.vtxfmt_0;
209 rmesa->tcl.aos_components[0] = &tmp;
210 rmesa->tcl.nr_aos_components = 1;
211 rmesa->dma.flush = 0;
212
213 /* Optimize the primitive list:
214 */
215 if (rmesa->vb.nrprims > 1) {
216 for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) {
217 int pj = rmesa->vb.primlist[j].prim & 0xf;
218 int pi = rmesa->vb.primlist[i].prim & 0xf;
219
220 if (pj == pi && discreet_gl_prim[pj] &&
221 rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) {
222 rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end;
223 }
224 else {
225 j++;
226 if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i];
227 }
228 }
229 rmesa->vb.nrprims = j+1;
230 }
231
232 if (rmesa->vb.vtxfmt_0 != rmesa->hw.vtx.cmd[VTX_VTXFMT_0] ||
233 rmesa->vb.vtxfmt_1 != rmesa->hw.vtx.cmd[VTX_VTXFMT_1]) {
234 R200_STATECHANGE( rmesa, vtx );
235 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = rmesa->vb.vtxfmt_0;
236 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = rmesa->vb.vtxfmt_1;
237 }
238
239
240 for (i = 0 ; i < rmesa->vb.nrprims; i++) {
241 if (R200_DEBUG & DEBUG_PRIMS)
242 fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i,
243 _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim &
244 PRIM_MODE_MASK ),
245 rmesa->vb.primlist[i].start,
246 rmesa->vb.primlist[i].end);
247
248 if (rmesa->vb.primlist[i].start < rmesa->vb.primlist[i].end)
249 r200EmitPrimitive( rmesa->glCtx,
250 rmesa->vb.primlist[i].start,
251 rmesa->vb.primlist[i].end,
252 rmesa->vb.primlist[i].prim );
253 }
254
255 rmesa->vb.nrprims = 0;
256 r200ReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ );
257 }
258
259
260 static void start_prim( r200ContextPtr rmesa, GLuint mode )
261 {
262 if (R200_DEBUG & DEBUG_VFMT)
263 fprintf(stderr, "%s %d\n", __FUNCTION__,
264 rmesa->vb.initial_counter - rmesa->vb.counter);
265
266 rmesa->vb.primlist[rmesa->vb.nrprims].start =
267 rmesa->vb.initial_counter - rmesa->vb.counter;
268 rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode;
269 }
270
271 static void note_last_prim( r200ContextPtr rmesa, GLuint flags )
272 {
273 if (R200_DEBUG & DEBUG_VFMT)
274 fprintf(stderr, "%s %d\n", __FUNCTION__,
275 rmesa->vb.initial_counter - rmesa->vb.counter);
276
277 if (rmesa->vb.prim[0] != GL_POLYGON+1) {
278 rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags;
279 rmesa->vb.primlist[rmesa->vb.nrprims].end =
280 rmesa->vb.initial_counter - rmesa->vb.counter;
281
282 if (++(rmesa->vb.nrprims) == R200_MAX_PRIMS)
283 flush_prims( rmesa );
284 }
285 }
286
287
288 static void copy_vertex( r200ContextPtr rmesa, GLuint n, GLfloat *dst )
289 {
290 GLuint i;
291 GLfloat *src = (GLfloat *)(rmesa->dma.current.address +
292 rmesa->dma.current.ptr +
293 (rmesa->vb.primlist[rmesa->vb.nrprims].start + n) *
294 rmesa->vb.vertex_size * 4);
295
296 if (R200_DEBUG & DEBUG_VFMT)
297 fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n);
298
299 for (i = 0 ; i < rmesa->vb.vertex_size; i++) {
300 dst[i] = src[i];
301 }
302 }
303
304 /* NOTE: This actually reads the copied vertices back from uncached
305 * memory. Could also use the counter/notify mechanism to populate
306 * tmp on the fly as vertices are generated.
307 */
308 static GLuint copy_dma_verts( r200ContextPtr rmesa, GLfloat (*tmp)[R200_MAX_VERTEX_SIZE] )
309 {
310 GLuint ovf, i;
311 GLuint nr = (rmesa->vb.initial_counter - rmesa->vb.counter) -
312 rmesa->vb.primlist[rmesa->vb.nrprims].start;
313
314 if (R200_DEBUG & DEBUG_VFMT)
315 fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr);
316
317 switch( rmesa->vb.prim[0] )
318 {
319 case GL_POINTS:
320 return 0;
321 case GL_LINES:
322 ovf = nr&1;
323 for (i = 0 ; i < ovf ; i++)
324 copy_vertex( rmesa, nr-ovf+i, tmp[i] );
325 return i;
326 case GL_TRIANGLES:
327 ovf = nr%3;
328 for (i = 0 ; i < ovf ; i++)
329 copy_vertex( rmesa, nr-ovf+i, tmp[i] );
330 return i;
331 case GL_QUADS:
332 ovf = nr&3;
333 for (i = 0 ; i < ovf ; i++)
334 copy_vertex( rmesa, nr-ovf+i, tmp[i] );
335 return i;
336 case GL_LINE_STRIP:
337 if (nr == 0)
338 return 0;
339 copy_vertex( rmesa, nr-1, tmp[0] );
340 return 1;
341 case GL_LINE_LOOP:
342 case GL_TRIANGLE_FAN:
343 case GL_POLYGON:
344 if (nr == 0)
345 return 0;
346 else if (nr == 1) {
347 copy_vertex( rmesa, 0, tmp[0] );
348 return 1;
349 } else {
350 copy_vertex( rmesa, 0, tmp[0] );
351 copy_vertex( rmesa, nr-1, tmp[1] );
352 return 2;
353 }
354 case GL_TRIANGLE_STRIP:
355 ovf = MIN2( nr, 2 );
356 for (i = 0 ; i < ovf ; i++)
357 copy_vertex( rmesa, nr-ovf+i, tmp[i] );
358 return i;
359 case GL_QUAD_STRIP:
360 switch (nr) {
361 case 0: ovf = 0; break;
362 case 1: ovf = 1; break;
363 default: ovf = 2 + (nr&1); break;
364 }
365 for (i = 0 ; i < ovf ; i++)
366 copy_vertex( rmesa, nr-ovf+i, tmp[i] );
367 return i;
368 default:
369 assert(0);
370 return 0;
371 }
372 }
373
374 static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller )
375 {
376 GET_CURRENT_CONTEXT(ctx);
377 r200ContextPtr rmesa = R200_CONTEXT(ctx);
378
379 if (R200_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
380 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
381
382 if (ctx->Driver.NeedFlush)
383 r200VtxFmtFlushVertices( ctx, ctx->Driver.NeedFlush );
384
385 if (ctx->NewState)
386 _mesa_update_state( ctx ); /* clear state so fell_back sticks */
387
388 _tnl_wakeup_exec( ctx );
389 ctx->Driver.FlushVertices = r200FlushVertices;
390
391 assert( rmesa->dma.flush == 0 );
392 rmesa->vb.fell_back = GL_TRUE;
393 rmesa->vb.installed = GL_FALSE;
394 }
395
396
397 /**
398 * \todo
399 * An interesting optimization of this function would be to have 3 element
400 * table with the dispatch offsets of the TexCoord?fv functions, use count
401 * to look-up the table, and a specialized version of GL_CALL that used the
402 * offset number instead of the name.
403 */
404 static void dispatch_multitexcoord( GLuint count, GLuint unit, GLfloat * f )
405 {
406 switch( count ) {
407 case 3:
408 GL_CALL(MultiTexCoord3fvARB)( GL_TEXTURE0+unit, f );
409 break;
410 case 2:
411 GL_CALL(MultiTexCoord2fvARB)( GL_TEXTURE0+unit, f );
412 break;
413 case 1:
414 GL_CALL(MultiTexCoord1fvARB)( GL_TEXTURE0+unit, f );
415 break;
416 default:
417 assert( count == 0 );
418 break;
419 }
420 }
421
422 void VFMT_FALLBACK( const char *caller )
423 {
424 GET_CURRENT_CONTEXT(ctx);
425 r200ContextPtr rmesa = R200_CONTEXT(ctx);
426 GLfloat tmp[3][R200_MAX_VERTEX_SIZE];
427 GLuint i, prim;
428 GLuint ind0 = rmesa->vb.vtxfmt_0;
429 GLuint ind1 = rmesa->vb.vtxfmt_1;
430 GLuint nrverts;
431 GLfloat alpha = 1.0;
432 GLuint count;
433 GLuint unit;
434
435 if (R200_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT))
436 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
437
438 if (rmesa->vb.prim[0] == GL_POLYGON+1) {
439 VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
440 return;
441 }
442
443 /* Copy vertices out of dma:
444 */
445 nrverts = copy_dma_verts( rmesa, tmp );
446
447 /* Finish the prim at this point:
448 */
449 note_last_prim( rmesa, 0 );
450 flush_prims( rmesa );
451
452 /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl.
453 */
454 prim = rmesa->vb.prim[0];
455 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
456 _tnl_wakeup_exec( ctx );
457 ctx->Driver.FlushVertices = r200FlushVertices;
458
459 assert(rmesa->dma.flush == 0);
460 rmesa->vb.fell_back = GL_TRUE;
461 rmesa->vb.installed = GL_FALSE;
462 GL_CALL(Begin)( prim );
463
464 if (rmesa->vb.installed_color_3f_sz == 4)
465 alpha = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
466
467 /* Replay saved vertices
468 */
469 for (i = 0 ; i < nrverts; i++) {
470 GLuint offset = 3;
471
472 if (ind0 & R200_VTX_N0) {
473 GL_CALL(Normal3fv)( &tmp[i][offset] );
474 offset += 3;
475 }
476
477 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
478 GL_CALL(Color4ubv)( (GLubyte *)&tmp[i][offset] );
479 offset++;
480 }
481 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
482 GL_CALL(Color4fv)( &tmp[i][offset] );
483 offset+=4;
484 }
485 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
486 GL_CALL(Color3fv)( &tmp[i][offset] );
487 offset+=3;
488 }
489
490 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
491 GL_CALL(SecondaryColor3ubvEXT)( (GLubyte *)&tmp[i][offset] );
492 offset++;
493 }
494
495 for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
496 count = VTX_TEXn_COUNT( ind1, unit );
497 dispatch_multitexcoord( count, unit, &tmp[i][offset] );
498 offset += count;
499 }
500
501 GL_CALL(Vertex3fv)( &tmp[i][0] );
502 }
503
504 /* Replay current vertex
505 */
506 if (ind0 & R200_VTX_N0)
507 GL_CALL(Normal3fv)( rmesa->vb.normalptr );
508
509 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
510 GL_CALL(Color4ub)( rmesa->vb.colorptr->red,
511 rmesa->vb.colorptr->green,
512 rmesa->vb.colorptr->blue,
513 rmesa->vb.colorptr->alpha );
514 }
515 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
516 GL_CALL(Color4fv)( rmesa->vb.floatcolorptr );
517 }
518 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
519 if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0) {
520 GL_CALL(Color4f)( rmesa->vb.floatcolorptr[0],
521 rmesa->vb.floatcolorptr[1],
522 rmesa->vb.floatcolorptr[2],
523 alpha );
524 }
525 else {
526 GL_CALL(Color3fv)( rmesa->vb.floatcolorptr );
527 }
528 }
529
530 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA)
531 GL_CALL(SecondaryColor3ubEXT)( rmesa->vb.specptr->red,
532 rmesa->vb.specptr->green,
533 rmesa->vb.specptr->blue );
534
535 for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
536 count = VTX_TEXn_COUNT( ind1, unit );
537 dispatch_multitexcoord( count, unit, rmesa->vb.texcoordptr[unit] );
538 }
539 }
540
541
542
543 static void wrap_buffer( void )
544 {
545 GET_CURRENT_CONTEXT(ctx);
546 r200ContextPtr rmesa = R200_CONTEXT(ctx);
547 GLfloat tmp[3][R200_MAX_VERTEX_SIZE];
548 GLuint i, nrverts;
549
550 if (R200_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
551 fprintf(stderr, "%s %d\n", __FUNCTION__,
552 rmesa->vb.initial_counter - rmesa->vb.counter);
553
554 /* Don't deal with parity.
555 */
556 if ((((rmesa->vb.initial_counter - rmesa->vb.counter) -
557 rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) {
558 rmesa->vb.counter++;
559 rmesa->vb.initial_counter++;
560 return;
561 }
562
563 /* Copy vertices out of dma:
564 */
565 if (rmesa->vb.prim[0] == GL_POLYGON+1)
566 nrverts = 0;
567 else {
568 nrverts = copy_dma_verts( rmesa, tmp );
569
570 if (R200_DEBUG & DEBUG_VFMT)
571 fprintf(stderr, "%d vertices to copy\n", nrverts);
572
573 /* Finish the prim at this point:
574 */
575 note_last_prim( rmesa, 0 );
576 }
577
578 /* Fire any buffered primitives
579 */
580 flush_prims( rmesa );
581
582 /* Get new buffer
583 */
584 r200RefillCurrentDmaRegion( rmesa );
585
586 /* Reset counter, dmaptr
587 */
588 rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address);
589 rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
590 (rmesa->vb.vertex_size * 4);
591 rmesa->vb.counter--;
592 rmesa->vb.initial_counter = rmesa->vb.counter;
593 rmesa->vb.notify = wrap_buffer;
594
595 rmesa->dma.flush = flush_prims;
596
597 /* Restart wrapped primitive:
598 */
599 if (rmesa->vb.prim[0] != GL_POLYGON+1)
600 start_prim( rmesa, rmesa->vb.prim[0] );
601
602
603 /* Reemit saved vertices
604 */
605 for (i = 0 ; i < nrverts; i++) {
606 if (R200_DEBUG & DEBUG_VERTS) {
607 int j;
608 fprintf(stderr, "re-emit vertex %d to %p\n", i,
609 (void *)rmesa->vb.dmaptr);
610 if (R200_DEBUG & DEBUG_VERBOSE)
611 for (j = 0 ; j < rmesa->vb.vertex_size; j++)
612 fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
613 }
614
615 memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 );
616 rmesa->vb.dmaptr += rmesa->vb.vertex_size;
617 rmesa->vb.counter--;
618 }
619 }
620
621
622 /**
623 * Determines the hardware vertex format based on the current state vector.
624 *
625 * \returns
626 * If the hardware TCL unit is capable of handling the current state vector,
627 * \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
628 *
629 * \todo
630 * Make this color format selection data driven. If we receive only ubytes,
631 * send color as ubytes. Also check if converting (with free checking for
632 * overflow) is cheaper than sending floats directly.
633 *
634 * \todo
635 * When intializing texture coordinates, it might be faster to just copy the
636 * entire \c VERT_ATTRIB_TEX0 vector into the vertex buffer. It may mean that
637 * some of the data (i.e., the last texture coordinate components) get copied
638 * over, but that still may be faster than the conditional branching. If
639 * nothing else, the code will be smaller and easier to follow.
640 */
641 static GLboolean check_vtx_fmt( GLcontext *ctx )
642 {
643 r200ContextPtr rmesa = R200_CONTEXT(ctx);
644 GLuint ind0 = R200_VTX_Z0;
645 GLuint ind1 = 0;
646 GLuint i;
647 GLuint count[R200_MAX_TEXTURE_UNITS];
648
649 if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
650 return GL_FALSE;
651
652 if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
653 ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
654
655 /* Make all this event-driven:
656 */
657 if (ctx->Light.Enabled) {
658 ind0 |= R200_VTX_N0;
659
660 if (ctx->Light.ColorMaterialEnabled)
661 ind0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
662 else
663 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
664 }
665 else {
666 /* TODO: make this data driven?
667 */
668 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
669
670 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
671 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT;
672 }
673 }
674
675 for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
676 count[i] = 0;
677
678 if (ctx->Texture.Unit[i]._ReallyEnabled) {
679 if (rmesa->TexGenNeedNormals[i]) {
680 ind0 |= R200_VTX_N0;
681 }
682 else {
683 switch( ctx->Texture.Unit[i]._ReallyEnabled ) {
684 case TEXTURE_CUBE_BIT:
685 case TEXTURE_3D_BIT:
686 count[i] = 3;
687 break;
688 case TEXTURE_2D_BIT:
689 case TEXTURE_RECT_BIT:
690 count[i] = 2;
691 break;
692 case TEXTURE_1D_BIT:
693 count[i] = 1;
694 break;
695 }
696
697 ind1 |= count[i] << (3 * i);
698 }
699 }
700 }
701
702 if (R200_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
703 fprintf(stderr, "%s: format: 0x%x, 0x%x\n", __FUNCTION__, ind0, ind1 );
704
705 R200_NEWPRIM(rmesa);
706 rmesa->vb.vtxfmt_0 = ind0;
707 rmesa->vb.vtxfmt_1 = ind1;
708 rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
709
710 rmesa->vb.vertex_size = 3;
711 rmesa->vb.normalptr = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
712 rmesa->vb.colorptr = NULL;
713 rmesa->vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
714 rmesa->vb.specptr = NULL;
715 rmesa->vb.floatspecptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
716 rmesa->vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
717 rmesa->vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1];
718 rmesa->vb.texcoordptr[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX2];
719 rmesa->vb.texcoordptr[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX3];
720 rmesa->vb.texcoordptr[4] = ctx->Current.Attrib[VERT_ATTRIB_TEX4];
721 rmesa->vb.texcoordptr[5] = ctx->Current.Attrib[VERT_ATTRIB_TEX5];
722 rmesa->vb.texcoordptr[6] = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* dummy */
723 rmesa->vb.texcoordptr[7] = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* dummy */
724
725 /* Run through and initialize the vertex components in the order
726 * the hardware understands:
727 */
728 if (ind0 & R200_VTX_N0) {
729 rmesa->vb.normalptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
730 rmesa->vb.vertex_size += 3;
731 rmesa->vb.normalptr[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
732 rmesa->vb.normalptr[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
733 rmesa->vb.normalptr[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2];
734 }
735
736 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
737 rmesa->vb.colorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
738 rmesa->vb.vertex_size += 1;
739 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] );
740 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] );
741 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] );
742 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->alpha, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] );
743 }
744 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
745 rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
746 rmesa->vb.vertex_size += 4;
747 rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
748 rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
749 rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
750 rmesa->vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
751 }
752 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
753 rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
754 rmesa->vb.vertex_size += 3;
755 rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
756 rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
757 rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
758 }
759
760 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
761 rmesa->vb.specptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
762 rmesa->vb.vertex_size += 1;
763 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
764 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
765 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
766 }
767
768
769 for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
770 if ( count[i] != 0 ) {
771 float * const attr = ctx->Current.Attrib[VERT_ATTRIB_TEX0+i];
772 unsigned j;
773
774 rmesa->vb.texcoordptr[i] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
775
776 for ( j = 0 ; j < count[i] ; j++ ) {
777 rmesa->vb.texcoordptr[i][j] = attr[j];
778 }
779
780 rmesa->vb.vertex_size += count[i];
781 }
782 }
783
784 if (rmesa->vb.installed_vertex_format != rmesa->vb.vtxfmt_0) {
785 if (R200_DEBUG & DEBUG_VFMT)
786 fprintf(stderr, "reinstall on vertex_format change\n");
787 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
788 rmesa->vb.installed_vertex_format = rmesa->vb.vtxfmt_0;
789 }
790
791 if (R200_DEBUG & DEBUG_VFMT)
792 fprintf(stderr, "%s -- success\n", __FUNCTION__);
793
794 return GL_TRUE;
795 }
796
797
798 void r200VtxfmtInvalidate( GLcontext *ctx )
799 {
800 r200ContextPtr rmesa = R200_CONTEXT( ctx );
801
802 rmesa->vb.recheck = GL_TRUE;
803 rmesa->vb.fell_back = GL_FALSE;
804 }
805
806
807 static void r200VtxfmtValidate( GLcontext *ctx )
808 {
809 r200ContextPtr rmesa = R200_CONTEXT( ctx );
810
811 if (R200_DEBUG & DEBUG_VFMT)
812 fprintf(stderr, "%s\n", __FUNCTION__);
813
814 if (ctx->Driver.NeedFlush)
815 ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
816
817 rmesa->vb.recheck = GL_FALSE;
818
819 if (check_vtx_fmt( ctx )) {
820 if (!rmesa->vb.installed) {
821 if (R200_DEBUG & DEBUG_VFMT)
822 fprintf(stderr, "reinstall (new install)\n");
823
824 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
825 ctx->Driver.FlushVertices = r200VtxFmtFlushVertices;
826 rmesa->vb.installed = GL_TRUE;
827 }
828 else if (R200_DEBUG & DEBUG_VFMT)
829 fprintf(stderr, "%s: already installed", __FUNCTION__);
830 }
831 else {
832 if (R200_DEBUG & DEBUG_VFMT)
833 fprintf(stderr, "%s: failed\n", __FUNCTION__);
834
835 if (rmesa->vb.installed) {
836 if (rmesa->dma.flush)
837 rmesa->dma.flush( rmesa );
838 _tnl_wakeup_exec( ctx );
839 ctx->Driver.FlushVertices = r200FlushVertices;
840 rmesa->vb.installed = GL_FALSE;
841 }
842 }
843 }
844
845
846
847 /* Materials:
848 */
849 static void r200_Materialfv( GLenum face, GLenum pname,
850 const GLfloat *params )
851 {
852 GET_CURRENT_CONTEXT(ctx);
853 r200ContextPtr rmesa = R200_CONTEXT( ctx );
854
855 if (R200_DEBUG & DEBUG_VFMT)
856 fprintf(stderr, "%s\n", __FUNCTION__);
857
858 if (rmesa->vb.prim[0] != GL_POLYGON+1) {
859 VFMT_FALLBACK( __FUNCTION__ );
860 GL_CALL(Materialfv)( face, pname, params );
861 return;
862 }
863 _mesa_noop_Materialfv( face, pname, params );
864 r200UpdateMaterial( ctx );
865 }
866
867
868 /* Begin/End
869 */
870 static void r200_Begin( GLenum mode )
871 {
872 GET_CURRENT_CONTEXT(ctx);
873 r200ContextPtr rmesa = R200_CONTEXT(ctx);
874
875 if (R200_DEBUG & DEBUG_VFMT)
876 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
877 _mesa_lookup_enum_by_nr( mode ));
878
879 if (mode > GL_POLYGON) {
880 _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
881 return;
882 }
883
884 if (rmesa->vb.prim[0] != GL_POLYGON+1) {
885 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
886 return;
887 }
888
889 if (ctx->NewState)
890 _mesa_update_state( ctx );
891
892 if (rmesa->NewGLState)
893 r200ValidateState( ctx );
894
895 if (rmesa->vb.recheck)
896 r200VtxfmtValidate( ctx );
897
898 if (!rmesa->vb.installed) {
899 GL_CALL(Begin)( mode );
900 return;
901 }
902
903
904 if (rmesa->dma.flush && rmesa->vb.counter < 12) {
905 if (R200_DEBUG & DEBUG_VFMT)
906 fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
907 flush_prims( rmesa );
908 }
909
910 /* Need to arrange to save vertices here? Or always copy from dma (yuk)?
911 */
912 if (!rmesa->dma.flush) {
913 if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 >
914 rmesa->dma.current.end) {
915 R200_NEWPRIM( rmesa );
916 r200RefillCurrentDmaRegion( rmesa );
917 }
918
919 rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
920 rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
921 (rmesa->vb.vertex_size * 4);
922 rmesa->vb.counter--;
923 rmesa->vb.initial_counter = rmesa->vb.counter;
924 rmesa->vb.notify = wrap_buffer;
925 rmesa->dma.flush = flush_prims;
926 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
927 }
928
929
930 rmesa->vb.prim[0] = mode;
931 start_prim( rmesa, mode | PRIM_BEGIN );
932 }
933
934
935
936 static void r200_End( void )
937 {
938 GET_CURRENT_CONTEXT(ctx);
939 r200ContextPtr rmesa = R200_CONTEXT(ctx);
940
941 if (R200_DEBUG & DEBUG_VFMT)
942 fprintf(stderr, "%s\n", __FUNCTION__);
943
944 if (rmesa->vb.prim[0] == GL_POLYGON+1) {
945 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
946 return;
947 }
948
949 note_last_prim( rmesa, PRIM_END );
950 rmesa->vb.prim[0] = GL_POLYGON+1;
951 }
952
953
954 /* Fallback on difficult entrypoints:
955 */
956 #define PRE_LOOPBACK( FUNC ) \
957 do { \
958 if (R200_DEBUG & DEBUG_VFMT) \
959 fprintf(stderr, "%s\n", __FUNCTION__); \
960 VFMT_FALLBACK( __FUNCTION__ ); \
961 } while (0)
962 #define TAG(x) r200_fallback_##x
963 #include "vtxfmt_tmp.h"
964
965
966
967 static GLboolean r200NotifyBegin( GLcontext *ctx, GLenum p )
968 {
969 r200ContextPtr rmesa = R200_CONTEXT( ctx );
970
971 if (R200_DEBUG & DEBUG_VFMT)
972 fprintf(stderr, "%s\n", __FUNCTION__);
973
974 assert(!rmesa->vb.installed);
975
976 if (ctx->NewState)
977 _mesa_update_state( ctx );
978
979 if (rmesa->NewGLState)
980 r200ValidateState( ctx );
981
982 if (ctx->Driver.NeedFlush)
983 ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
984
985 if (rmesa->vb.recheck)
986 r200VtxfmtValidate( ctx );
987
988 if (!rmesa->vb.installed) {
989 if (R200_DEBUG & DEBUG_VFMT)
990 fprintf(stderr, "%s -- failed\n", __FUNCTION__);
991 return GL_FALSE;
992 }
993
994 r200_Begin( p );
995 return GL_TRUE;
996 }
997
998 static void r200VtxFmtFlushVertices( GLcontext *ctx, GLuint flags )
999 {
1000 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1001
1002 if (R200_DEBUG & DEBUG_VFMT)
1003 fprintf(stderr, "%s\n", __FUNCTION__);
1004
1005 assert(rmesa->vb.installed);
1006
1007 if (flags & FLUSH_UPDATE_CURRENT) {
1008 r200_copy_to_current( ctx );
1009 if (R200_DEBUG & DEBUG_VFMT)
1010 fprintf(stderr, "reinstall on update_current\n");
1011 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
1012 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
1013 }
1014
1015 if (flags & FLUSH_STORED_VERTICES) {
1016 assert (rmesa->dma.flush == 0 ||
1017 rmesa->dma.flush == flush_prims);
1018 if (rmesa->dma.flush == flush_prims)
1019 flush_prims( rmesa );
1020 ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
1021 }
1022 }
1023
1024
1025
1026 /* At this point, don't expect very many versions of each function to
1027 * be generated, so not concerned about freeing them?
1028 */
1029
1030
1031 void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
1032 {
1033 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1034 GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
1035
1036 MEMSET( vfmt, 0, sizeof(GLvertexformat) );
1037
1038 /* Hook in chooser functions for codegen, etc:
1039 */
1040 r200VtxfmtInitChoosers( vfmt );
1041
1042 /* Handled fully in supported states, but no codegen:
1043 */
1044 vfmt->Materialfv = r200_Materialfv;
1045 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
1046 vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
1047 vfmt->Begin = r200_Begin;
1048 vfmt->End = r200_End;
1049
1050 /* Fallback for performance reasons: (Fix with cva/elt path here and
1051 * dmatmp2.h style primitive-merging)
1052 *
1053 * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow
1054 * a driver-hook.
1055 */
1056 vfmt->DrawArrays = r200_fallback_DrawArrays;
1057 vfmt->DrawElements = r200_fallback_DrawElements;
1058 vfmt->DrawRangeElements = r200_fallback_DrawRangeElements;
1059
1060
1061 /* Not active in supported states; just keep ctx->Current uptodate:
1062 */
1063 vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
1064 vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
1065 vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
1066 vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
1067 vfmt->Indexf = _mesa_noop_Indexf;
1068 vfmt->Indexfv = _mesa_noop_Indexfv;
1069
1070
1071 /* Active but unsupported -- fallback if we receive these:
1072 */
1073 vfmt->CallList = r200_fallback_CallList;
1074 vfmt->CallLists = r200_fallback_CallLists;
1075 vfmt->EvalCoord1f = r200_fallback_EvalCoord1f;
1076 vfmt->EvalCoord1fv = r200_fallback_EvalCoord1fv;
1077 vfmt->EvalCoord2f = r200_fallback_EvalCoord2f;
1078 vfmt->EvalCoord2fv = r200_fallback_EvalCoord2fv;
1079 vfmt->EvalMesh1 = r200_fallback_EvalMesh1;
1080 vfmt->EvalMesh2 = r200_fallback_EvalMesh2;
1081 vfmt->EvalPoint1 = r200_fallback_EvalPoint1;
1082 vfmt->EvalPoint2 = r200_fallback_EvalPoint2;
1083 vfmt->TexCoord4f = r200_fallback_TexCoord4f;
1084 vfmt->TexCoord4fv = r200_fallback_TexCoord4fv;
1085 vfmt->MultiTexCoord4fARB = r200_fallback_MultiTexCoord4fARB;
1086 vfmt->MultiTexCoord4fvARB = r200_fallback_MultiTexCoord4fvARB;
1087 vfmt->Vertex4f = r200_fallback_Vertex4f;
1088 vfmt->Vertex4fv = r200_fallback_Vertex4fv;
1089 vfmt->VertexAttrib1fNV = r200_fallback_VertexAttrib1fNV;
1090 vfmt->VertexAttrib1fvNV = r200_fallback_VertexAttrib1fvNV;
1091 vfmt->VertexAttrib2fNV = r200_fallback_VertexAttrib2fNV;
1092 vfmt->VertexAttrib2fvNV = r200_fallback_VertexAttrib2fvNV;
1093 vfmt->VertexAttrib3fNV = r200_fallback_VertexAttrib3fNV;
1094 vfmt->VertexAttrib3fvNV = r200_fallback_VertexAttrib3fvNV;
1095 vfmt->VertexAttrib4fNV = r200_fallback_VertexAttrib4fNV;
1096 vfmt->VertexAttrib4fvNV = r200_fallback_VertexAttrib4fvNV;
1097
1098 (void)r200_fallback_vtxfmt;
1099
1100 TNL_CONTEXT(ctx)->Driver.NotifyBegin = r200NotifyBegin;
1101
1102 rmesa->vb.enabled = 1;
1103 rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
1104 rmesa->vb.primflags = 0;
1105
1106 make_empty_list( &rmesa->vb.dfn_cache.Vertex2f );
1107 make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv );
1108 make_empty_list( &rmesa->vb.dfn_cache.Vertex3f );
1109 make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv );
1110 make_empty_list( &rmesa->vb.dfn_cache.Color4ub );
1111 make_empty_list( &rmesa->vb.dfn_cache.Color4ubv );
1112 make_empty_list( &rmesa->vb.dfn_cache.Color3ub );
1113 make_empty_list( &rmesa->vb.dfn_cache.Color3ubv );
1114 make_empty_list( &rmesa->vb.dfn_cache.Color4f );
1115 make_empty_list( &rmesa->vb.dfn_cache.Color4fv );
1116 make_empty_list( &rmesa->vb.dfn_cache.Color3f );
1117 make_empty_list( &rmesa->vb.dfn_cache.Color3fv );
1118 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
1119 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
1120 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
1121 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
1122 make_empty_list( &rmesa->vb.dfn_cache.Normal3f );
1123 make_empty_list( &rmesa->vb.dfn_cache.Normal3fv );
1124 make_empty_list( &rmesa->vb.dfn_cache.TexCoord3f );
1125 make_empty_list( &rmesa->vb.dfn_cache.TexCoord3fv );
1126 make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f );
1127 make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv );
1128 make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f );
1129 make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv );
1130 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord3fARB );
1131 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord3fvARB );
1132 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
1133 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
1134 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
1135 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
1136
1137 r200InitCodegen( &rmesa->vb.codegen, useCodegen );
1138 }
1139
1140 static void free_funcs( struct dynfn *l )
1141 {
1142 struct dynfn *f, *tmp;
1143 foreach_s (f, tmp, l) {
1144 remove_from_list( f );
1145 ALIGN_FREE( f->code );
1146 FREE( f );
1147 }
1148 }
1149
1150 void r200VtxfmtUnbindContext( GLcontext *ctx )
1151 {
1152 }
1153
1154
1155 void r200VtxfmtMakeCurrent( GLcontext *ctx )
1156 {
1157 }
1158
1159
1160 void r200VtxfmtDestroy( GLcontext *ctx )
1161 {
1162 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1163
1164 count_funcs( rmesa );
1165 free_funcs( &rmesa->vb.dfn_cache.Vertex2f );
1166 free_funcs( &rmesa->vb.dfn_cache.Vertex2fv );
1167 free_funcs( &rmesa->vb.dfn_cache.Vertex3f );
1168 free_funcs( &rmesa->vb.dfn_cache.Vertex3fv );
1169 free_funcs( &rmesa->vb.dfn_cache.Color4ub );
1170 free_funcs( &rmesa->vb.dfn_cache.Color4ubv );
1171 free_funcs( &rmesa->vb.dfn_cache.Color3ub );
1172 free_funcs( &rmesa->vb.dfn_cache.Color3ubv );
1173 free_funcs( &rmesa->vb.dfn_cache.Color4f );
1174 free_funcs( &rmesa->vb.dfn_cache.Color4fv );
1175 free_funcs( &rmesa->vb.dfn_cache.Color3f );
1176 free_funcs( &rmesa->vb.dfn_cache.Color3fv );
1177 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
1178 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
1179 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
1180 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
1181 free_funcs( &rmesa->vb.dfn_cache.Normal3f );
1182 free_funcs( &rmesa->vb.dfn_cache.Normal3fv );
1183 free_funcs( &rmesa->vb.dfn_cache.TexCoord3f );
1184 free_funcs( &rmesa->vb.dfn_cache.TexCoord3fv );
1185 free_funcs( &rmesa->vb.dfn_cache.TexCoord2f );
1186 free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv );
1187 free_funcs( &rmesa->vb.dfn_cache.TexCoord1f );
1188 free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv );
1189 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord3fARB );
1190 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord3fvARB );
1191 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
1192 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
1193 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
1194 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
1195 }
1196