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