Bug #1588: abort if no palette format matches. (Egbert Eich, Stefan Dirsch)
[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_texcoord( GLuint count, GLfloat * f )
405 {
406 switch( count ) {
407 case 3:
408 GL_CALL(TexCoord3fv)( f );
409 break;
410 case 2:
411 GL_CALL(TexCoord2fv)( f );
412 break;
413 case 1:
414 GL_CALL(TexCoord1fv)( f );
415 break;
416 default:
417 assert( count == 0 );
418 break;
419 }
420 }
421
422 static void dispatch_multitexcoord( GLuint count, GLuint unit, GLfloat * f )
423 {
424 switch( count ) {
425 case 3:
426 GL_CALL(MultiTexCoord3fvARB)( GL_TEXTURE0+unit, f );
427 break;
428 case 2:
429 GL_CALL(MultiTexCoord2fvARB)( GL_TEXTURE0+unit, f );
430 break;
431 case 1:
432 GL_CALL(MultiTexCoord1fvARB)( GL_TEXTURE0+unit, f );
433 break;
434 default:
435 assert( count == 0 );
436 break;
437 }
438 }
439
440 static void VFMT_FALLBACK( const char *caller )
441 {
442 GET_CURRENT_CONTEXT(ctx);
443 r200ContextPtr rmesa = R200_CONTEXT(ctx);
444 GLfloat tmp[3][R200_MAX_VERTEX_SIZE];
445 GLuint i, prim;
446 GLuint ind0 = rmesa->vb.vtxfmt_0;
447 GLuint ind1 = rmesa->vb.vtxfmt_1;
448 GLuint nrverts;
449 GLfloat alpha = 1.0;
450 GLuint count;
451 GLuint unit;
452
453 if (R200_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT))
454 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
455
456 if (rmesa->vb.prim[0] == GL_POLYGON+1) {
457 VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
458 return;
459 }
460
461 /* Copy vertices out of dma:
462 */
463 nrverts = copy_dma_verts( rmesa, tmp );
464
465 /* Finish the prim at this point:
466 */
467 note_last_prim( rmesa, 0 );
468 flush_prims( rmesa );
469
470 /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl.
471 */
472 prim = rmesa->vb.prim[0];
473 ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
474 _tnl_wakeup_exec( ctx );
475 ctx->Driver.FlushVertices = r200FlushVertices;
476
477 assert(rmesa->dma.flush == 0);
478 rmesa->vb.fell_back = GL_TRUE;
479 rmesa->vb.installed = GL_FALSE;
480 GL_CALL(Begin)( prim );
481
482 if (rmesa->vb.installed_color_3f_sz == 4)
483 alpha = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
484
485 /* Replay saved vertices
486 */
487 for (i = 0 ; i < nrverts; i++) {
488 GLuint offset = 3;
489
490 if (ind0 & R200_VTX_N0) {
491 GL_CALL(Normal3fv)( &tmp[i][offset] );
492 offset += 3;
493 }
494
495 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
496 GL_CALL(Color4ubv)( (GLubyte *)&tmp[i][offset] );
497 offset++;
498 }
499 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
500 GL_CALL(Color4fv)( &tmp[i][offset] );
501 offset+=4;
502 }
503 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
504 GL_CALL(Color3fv)( &tmp[i][offset] );
505 offset+=3;
506 }
507
508 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
509 GL_CALL(SecondaryColor3ubvEXT)( (GLubyte *)&tmp[i][offset] );
510 offset++;
511 }
512
513 for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
514 count = VTX_TEXn_COUNT( ind1, unit );
515 dispatch_multitexcoord( count, unit, &tmp[i][offset] );
516 offset += count;
517 }
518
519 GL_CALL(Vertex3fv)( &tmp[i][0] );
520 }
521
522 /* Replay current vertex
523 */
524 if (ind0 & R200_VTX_N0)
525 GL_CALL(Normal3fv)( rmesa->vb.normalptr );
526
527 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
528 GL_CALL(Color4ub)( rmesa->vb.colorptr->red,
529 rmesa->vb.colorptr->green,
530 rmesa->vb.colorptr->blue,
531 rmesa->vb.colorptr->alpha );
532 }
533 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
534 GL_CALL(Color4fv)( rmesa->vb.floatcolorptr );
535 }
536 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
537 if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0) {
538 GL_CALL(Color4f)( rmesa->vb.floatcolorptr[0],
539 rmesa->vb.floatcolorptr[1],
540 rmesa->vb.floatcolorptr[2],
541 alpha );
542 }
543 else {
544 GL_CALL(Color3fv)( rmesa->vb.floatcolorptr );
545 }
546 }
547
548 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA)
549 GL_CALL(SecondaryColor3ubEXT)( rmesa->vb.specptr->red,
550 rmesa->vb.specptr->green,
551 rmesa->vb.specptr->blue );
552
553 for ( unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++ ) {
554 count = VTX_TEXn_COUNT( ind1, unit );
555 dispatch_multitexcoord( count, unit, rmesa->vb.texcoordptr[unit] );
556 }
557 }
558
559
560
561 static void wrap_buffer( void )
562 {
563 GET_CURRENT_CONTEXT(ctx);
564 r200ContextPtr rmesa = R200_CONTEXT(ctx);
565 GLfloat tmp[3][R200_MAX_VERTEX_SIZE];
566 GLuint i, nrverts;
567
568 if (R200_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
569 fprintf(stderr, "%s %d\n", __FUNCTION__,
570 rmesa->vb.initial_counter - rmesa->vb.counter);
571
572 /* Don't deal with parity.
573 */
574 if ((((rmesa->vb.initial_counter - rmesa->vb.counter) -
575 rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) {
576 rmesa->vb.counter++;
577 rmesa->vb.initial_counter++;
578 return;
579 }
580
581 /* Copy vertices out of dma:
582 */
583 if (rmesa->vb.prim[0] == GL_POLYGON+1)
584 nrverts = 0;
585 else {
586 nrverts = copy_dma_verts( rmesa, tmp );
587
588 if (R200_DEBUG & DEBUG_VFMT)
589 fprintf(stderr, "%d vertices to copy\n", nrverts);
590
591 /* Finish the prim at this point:
592 */
593 note_last_prim( rmesa, 0 );
594 }
595
596 /* Fire any buffered primitives
597 */
598 flush_prims( rmesa );
599
600 /* Get new buffer
601 */
602 r200RefillCurrentDmaRegion( rmesa );
603
604 /* Reset counter, dmaptr
605 */
606 rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address);
607 rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
608 (rmesa->vb.vertex_size * 4);
609 rmesa->vb.counter--;
610 rmesa->vb.initial_counter = rmesa->vb.counter;
611 rmesa->vb.notify = wrap_buffer;
612
613 rmesa->dma.flush = flush_prims;
614
615 /* Restart wrapped primitive:
616 */
617 if (rmesa->vb.prim[0] != GL_POLYGON+1)
618 start_prim( rmesa, rmesa->vb.prim[0] );
619
620
621 /* Reemit saved vertices
622 */
623 for (i = 0 ; i < nrverts; i++) {
624 if (R200_DEBUG & DEBUG_VERTS) {
625 int j;
626 fprintf(stderr, "re-emit vertex %d to %p\n", i,
627 (void *)rmesa->vb.dmaptr);
628 if (R200_DEBUG & DEBUG_VERBOSE)
629 for (j = 0 ; j < rmesa->vb.vertex_size; j++)
630 fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
631 }
632
633 memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 );
634 rmesa->vb.dmaptr += rmesa->vb.vertex_size;
635 rmesa->vb.counter--;
636 }
637 }
638
639
640 /**
641 * Determines the hardware vertex format based on the current state vector.
642 *
643 * \returns
644 * If the hardware TCL unit is capable of handling the current state vector,
645 * \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned.
646 *
647 * \todo
648 * Make this color format selection data driven. If we receive only ubytes,
649 * send color as ubytes. Also check if converting (with free checking for
650 * overflow) is cheaper than sending floats directly.
651 *
652 * \todo
653 * When intializing texture coordinates, it might be faster to just copy the
654 * entire \c VERT_ATTRIB_TEX0 vector into the vertex buffer. It may mean that
655 * some of the data (i.e., the last texture coordinate components) get copied
656 * over, but that still may be faster than the conditional branching. If
657 * nothing else, the code will be smaller and easier to follow.
658 */
659 static GLboolean check_vtx_fmt( GLcontext *ctx )
660 {
661 r200ContextPtr rmesa = R200_CONTEXT(ctx);
662 GLuint ind0 = R200_VTX_Z0;
663 GLuint ind1 = 0;
664 GLuint i;
665 GLuint count[R200_MAX_TEXTURE_UNITS];
666 GLuint re_cntl;
667
668
669 if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
670 return GL_FALSE;
671
672 if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
673 ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
674
675 /* Make all this event-driven:
676 */
677 if (ctx->Light.Enabled) {
678 ind0 |= R200_VTX_N0;
679
680 if (ctx->Light.ColorMaterialEnabled)
681 ind0 |= R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT;
682 else
683 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
684 }
685 else {
686 /* TODO: make this data driven?
687 */
688 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT;
689
690 if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
691 ind0 |= R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT;
692 }
693 }
694
695 re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D |
696 R200_VTX_STQ1_D3D |
697 R200_VTX_STQ2_D3D |
698 R200_VTX_STQ3_D3D |
699 R200_VTX_STQ4_D3D |
700 R200_VTX_STQ5_D3D );
701 for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
702 count[i] = 0;
703
704 if (ctx->Texture.Unit[i]._ReallyEnabled) {
705 if (ctx->Texture.Unit[i].TexGenEnabled) {
706 if (rmesa->TexGenNeedNormals[i]) {
707 ind0 |= R200_VTX_N0;
708 }
709 }
710 else {
711 switch( ctx->Texture.Unit[i]._ReallyEnabled ) {
712 case TEXTURE_CUBE_BIT:
713 re_cntl |= R200_VTX_STQ0_D3D << (2 * i);
714 /* FALLTHROUGH */
715 case TEXTURE_3D_BIT:
716 count[i] = 3;
717 break;
718 case TEXTURE_2D_BIT:
719 case TEXTURE_RECT_BIT:
720 count[i] = 2;
721 break;
722 case TEXTURE_1D_BIT:
723 count[i] = 1;
724 break;
725 }
726
727 ind1 |= count[i] << (3 * i);
728 }
729 }
730 }
731
732 if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
733 R200_STATECHANGE( rmesa, set );
734 rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
735 }
736
737 if (R200_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
738 fprintf(stderr, "%s: format: 0x%x, 0x%x\n", __FUNCTION__, ind0, ind1 );
739
740 R200_NEWPRIM(rmesa);
741 rmesa->vb.vtxfmt_0 = ind0;
742 rmesa->vb.vtxfmt_1 = ind1;
743 rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
744
745 rmesa->vb.vertex_size = 3;
746 rmesa->vb.normalptr = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
747 rmesa->vb.colorptr = NULL;
748 rmesa->vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
749 rmesa->vb.specptr = NULL;
750 rmesa->vb.floatspecptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
751 rmesa->vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
752 rmesa->vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1];
753 rmesa->vb.texcoordptr[2] = ctx->Current.Attrib[VERT_ATTRIB_TEX2];
754 rmesa->vb.texcoordptr[3] = ctx->Current.Attrib[VERT_ATTRIB_TEX3];
755 rmesa->vb.texcoordptr[4] = ctx->Current.Attrib[VERT_ATTRIB_TEX4];
756 rmesa->vb.texcoordptr[5] = ctx->Current.Attrib[VERT_ATTRIB_TEX5];
757 rmesa->vb.texcoordptr[6] = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* dummy */
758 rmesa->vb.texcoordptr[7] = ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* dummy */
759
760 /* Run through and initialize the vertex components in the order
761 * the hardware understands:
762 */
763 if (ind0 & R200_VTX_N0) {
764 rmesa->vb.normalptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
765 rmesa->vb.vertex_size += 3;
766 rmesa->vb.normalptr[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
767 rmesa->vb.normalptr[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
768 rmesa->vb.normalptr[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2];
769 }
770
771 if (VTX_COLOR(ind0, 0) == R200_VTX_PK_RGBA) {
772 rmesa->vb.colorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
773 rmesa->vb.vertex_size += 1;
774 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] );
775 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] );
776 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] );
777 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->alpha, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] );
778 }
779 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGBA) {
780 rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
781 rmesa->vb.vertex_size += 4;
782 rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
783 rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
784 rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
785 rmesa->vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
786 }
787 else if (VTX_COLOR(ind0, 0) == R200_VTX_FP_RGB) {
788 rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
789 rmesa->vb.vertex_size += 3;
790 rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
791 rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
792 rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
793 }
794
795 if (VTX_COLOR(ind0, 1) == R200_VTX_PK_RGBA) {
796 rmesa->vb.specptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
797 rmesa->vb.vertex_size += 1;
798 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
799 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
800 UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
801 }
802
803
804 for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
805 if ( count[i] != 0 ) {
806 float * const attr = ctx->Current.Attrib[VERT_ATTRIB_TEX0+i];
807 unsigned j;
808
809 rmesa->vb.texcoordptr[i] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
810
811 for ( j = 0 ; j < count[i] ; j++ ) {
812 rmesa->vb.texcoordptr[i][j] = attr[j];
813 }
814
815 rmesa->vb.vertex_size += count[i];
816 }
817 }
818
819 if (rmesa->vb.installed_vertex_format != rmesa->vb.vtxfmt_0) {
820 if (R200_DEBUG & DEBUG_VFMT)
821 fprintf(stderr, "reinstall on vertex_format change\n");
822 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
823 rmesa->vb.installed_vertex_format = rmesa->vb.vtxfmt_0;
824 }
825
826 if (R200_DEBUG & DEBUG_VFMT)
827 fprintf(stderr, "%s -- success\n", __FUNCTION__);
828
829 return GL_TRUE;
830 }
831
832
833 void r200VtxfmtInvalidate( GLcontext *ctx )
834 {
835 r200ContextPtr rmesa = R200_CONTEXT( ctx );
836
837 rmesa->vb.recheck = GL_TRUE;
838 rmesa->vb.fell_back = GL_FALSE;
839 }
840
841
842 static void r200VtxfmtValidate( GLcontext *ctx )
843 {
844 r200ContextPtr rmesa = R200_CONTEXT( ctx );
845
846 if (R200_DEBUG & DEBUG_VFMT)
847 fprintf(stderr, "%s\n", __FUNCTION__);
848
849 if (ctx->Driver.NeedFlush)
850 ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
851
852 rmesa->vb.recheck = GL_FALSE;
853
854 if (check_vtx_fmt( ctx )) {
855 if (!rmesa->vb.installed) {
856 if (R200_DEBUG & DEBUG_VFMT)
857 fprintf(stderr, "reinstall (new install)\n");
858
859 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
860 ctx->Driver.FlushVertices = r200VtxFmtFlushVertices;
861 rmesa->vb.installed = GL_TRUE;
862 }
863 else if (R200_DEBUG & DEBUG_VFMT)
864 fprintf(stderr, "%s: already installed", __FUNCTION__);
865 }
866 else {
867 if (R200_DEBUG & DEBUG_VFMT)
868 fprintf(stderr, "%s: failed\n", __FUNCTION__);
869
870 if (rmesa->vb.installed) {
871 if (rmesa->dma.flush)
872 rmesa->dma.flush( rmesa );
873 _tnl_wakeup_exec( ctx );
874 ctx->Driver.FlushVertices = r200FlushVertices;
875 rmesa->vb.installed = GL_FALSE;
876 }
877 }
878 }
879
880
881
882 /* Materials:
883 */
884 static void r200_Materialfv( GLenum face, GLenum pname,
885 const GLfloat *params )
886 {
887 GET_CURRENT_CONTEXT(ctx);
888 r200ContextPtr rmesa = R200_CONTEXT( ctx );
889
890 if (R200_DEBUG & DEBUG_VFMT)
891 fprintf(stderr, "%s\n", __FUNCTION__);
892
893 if (rmesa->vb.prim[0] != GL_POLYGON+1) {
894 VFMT_FALLBACK( __FUNCTION__ );
895 GL_CALL(Materialfv)( face, pname, params );
896 return;
897 }
898 _mesa_noop_Materialfv( face, pname, params );
899 r200UpdateMaterial( ctx );
900 }
901
902
903 /* Begin/End
904 */
905 static void r200_Begin( GLenum mode )
906 {
907 GET_CURRENT_CONTEXT(ctx);
908 r200ContextPtr rmesa = R200_CONTEXT(ctx);
909
910 if (R200_DEBUG & DEBUG_VFMT)
911 fprintf(stderr, "%s( %s )\n", __FUNCTION__,
912 _mesa_lookup_enum_by_nr( mode ));
913
914 if (mode > GL_POLYGON) {
915 _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
916 return;
917 }
918
919 if (rmesa->vb.prim[0] != GL_POLYGON+1) {
920 _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
921 return;
922 }
923
924 if (ctx->NewState)
925 _mesa_update_state( ctx );
926
927 if (rmesa->NewGLState)
928 r200ValidateState( ctx );
929
930 if (rmesa->vb.recheck)
931 r200VtxfmtValidate( ctx );
932
933 if (!rmesa->vb.installed) {
934 GL_CALL(Begin)( mode );
935 return;
936 }
937
938
939 if (rmesa->dma.flush && rmesa->vb.counter < 12) {
940 if (R200_DEBUG & DEBUG_VFMT)
941 fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
942 flush_prims( rmesa );
943 }
944
945 /* Need to arrange to save vertices here? Or always copy from dma (yuk)?
946 */
947 if (!rmesa->dma.flush) {
948 if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 >
949 rmesa->dma.current.end) {
950 R200_NEWPRIM( rmesa );
951 r200RefillCurrentDmaRegion( rmesa );
952 }
953
954 rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
955 rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) /
956 (rmesa->vb.vertex_size * 4);
957 rmesa->vb.counter--;
958 rmesa->vb.initial_counter = rmesa->vb.counter;
959 rmesa->vb.notify = wrap_buffer;
960 rmesa->dma.flush = flush_prims;
961 ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
962 }
963
964
965 rmesa->vb.prim[0] = mode;
966 start_prim( rmesa, mode | PRIM_BEGIN );
967 }
968
969
970
971 static void r200_End( void )
972 {
973 GET_CURRENT_CONTEXT(ctx);
974 r200ContextPtr rmesa = R200_CONTEXT(ctx);
975
976 if (R200_DEBUG & DEBUG_VFMT)
977 fprintf(stderr, "%s\n", __FUNCTION__);
978
979 if (rmesa->vb.prim[0] == GL_POLYGON+1) {
980 _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
981 return;
982 }
983
984 note_last_prim( rmesa, PRIM_END );
985 rmesa->vb.prim[0] = GL_POLYGON+1;
986 }
987
988
989 /* Fallback on difficult entrypoints:
990 */
991 #define PRE_LOOPBACK( FUNC ) \
992 do { \
993 if (R200_DEBUG & DEBUG_VFMT) \
994 fprintf(stderr, "%s\n", __FUNCTION__); \
995 VFMT_FALLBACK( __FUNCTION__ ); \
996 } while (0)
997 #define TAG(x) r200_fallback_##x
998 #include "vtxfmt_tmp.h"
999
1000
1001
1002 static GLboolean r200NotifyBegin( GLcontext *ctx, GLenum p )
1003 {
1004 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1005
1006 if (R200_DEBUG & DEBUG_VFMT)
1007 fprintf(stderr, "%s\n", __FUNCTION__);
1008
1009 assert(!rmesa->vb.installed);
1010
1011 if (ctx->NewState)
1012 _mesa_update_state( ctx );
1013
1014 if (rmesa->NewGLState)
1015 r200ValidateState( ctx );
1016
1017 if (ctx->Driver.NeedFlush)
1018 ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
1019
1020 if (rmesa->vb.recheck)
1021 r200VtxfmtValidate( ctx );
1022
1023 if (!rmesa->vb.installed) {
1024 if (R200_DEBUG & DEBUG_VFMT)
1025 fprintf(stderr, "%s -- failed\n", __FUNCTION__);
1026 return GL_FALSE;
1027 }
1028
1029 r200_Begin( p );
1030 return GL_TRUE;
1031 }
1032
1033 static void r200VtxFmtFlushVertices( GLcontext *ctx, GLuint flags )
1034 {
1035 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1036
1037 if (R200_DEBUG & DEBUG_VFMT)
1038 fprintf(stderr, "%s\n", __FUNCTION__);
1039
1040 assert(rmesa->vb.installed);
1041
1042 if (flags & FLUSH_UPDATE_CURRENT) {
1043 r200_copy_to_current( ctx );
1044 if (R200_DEBUG & DEBUG_VFMT)
1045 fprintf(stderr, "reinstall on update_current\n");
1046 _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
1047 ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
1048 }
1049
1050 if (flags & FLUSH_STORED_VERTICES) {
1051 assert (rmesa->dma.flush == 0 ||
1052 rmesa->dma.flush == flush_prims);
1053 if (rmesa->dma.flush == flush_prims)
1054 flush_prims( rmesa );
1055 ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
1056 }
1057 }
1058
1059
1060
1061 /* At this point, don't expect very many versions of each function to
1062 * be generated, so not concerned about freeing them?
1063 */
1064
1065
1066 void r200VtxfmtInit( GLcontext *ctx, GLboolean useCodegen )
1067 {
1068 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1069 GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
1070
1071 MEMSET( vfmt, 0, sizeof(GLvertexformat) );
1072
1073 /* Hook in chooser functions for codegen, etc:
1074 */
1075 r200VtxfmtInitChoosers( vfmt );
1076
1077 /* Handled fully in supported states, but no codegen:
1078 */
1079 vfmt->Materialfv = r200_Materialfv;
1080 vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
1081 vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
1082 vfmt->Begin = r200_Begin;
1083 vfmt->End = r200_End;
1084
1085 /* Fallback for performance reasons: (Fix with cva/elt path here and
1086 * dmatmp2.h style primitive-merging)
1087 *
1088 * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow
1089 * a driver-hook.
1090 */
1091 vfmt->DrawArrays = r200_fallback_DrawArrays;
1092 vfmt->DrawElements = r200_fallback_DrawElements;
1093 vfmt->DrawRangeElements = r200_fallback_DrawRangeElements;
1094
1095
1096 /* Not active in supported states; just keep ctx->Current uptodate:
1097 */
1098 vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
1099 vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
1100 vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
1101 vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
1102 vfmt->Indexf = _mesa_noop_Indexf;
1103 vfmt->Indexfv = _mesa_noop_Indexfv;
1104
1105
1106 /* Active but unsupported -- fallback if we receive these:
1107 */
1108 vfmt->CallList = r200_fallback_CallList;
1109 vfmt->CallLists = r200_fallback_CallLists;
1110 vfmt->EvalCoord1f = r200_fallback_EvalCoord1f;
1111 vfmt->EvalCoord1fv = r200_fallback_EvalCoord1fv;
1112 vfmt->EvalCoord2f = r200_fallback_EvalCoord2f;
1113 vfmt->EvalCoord2fv = r200_fallback_EvalCoord2fv;
1114 vfmt->EvalMesh1 = r200_fallback_EvalMesh1;
1115 vfmt->EvalMesh2 = r200_fallback_EvalMesh2;
1116 vfmt->EvalPoint1 = r200_fallback_EvalPoint1;
1117 vfmt->EvalPoint2 = r200_fallback_EvalPoint2;
1118 vfmt->TexCoord4f = r200_fallback_TexCoord4f;
1119 vfmt->TexCoord4fv = r200_fallback_TexCoord4fv;
1120 vfmt->MultiTexCoord4fARB = r200_fallback_MultiTexCoord4fARB;
1121 vfmt->MultiTexCoord4fvARB = r200_fallback_MultiTexCoord4fvARB;
1122 vfmt->Vertex4f = r200_fallback_Vertex4f;
1123 vfmt->Vertex4fv = r200_fallback_Vertex4fv;
1124 vfmt->VertexAttrib1fNV = r200_fallback_VertexAttrib1fNV;
1125 vfmt->VertexAttrib1fvNV = r200_fallback_VertexAttrib1fvNV;
1126 vfmt->VertexAttrib2fNV = r200_fallback_VertexAttrib2fNV;
1127 vfmt->VertexAttrib2fvNV = r200_fallback_VertexAttrib2fvNV;
1128 vfmt->VertexAttrib3fNV = r200_fallback_VertexAttrib3fNV;
1129 vfmt->VertexAttrib3fvNV = r200_fallback_VertexAttrib3fvNV;
1130 vfmt->VertexAttrib4fNV = r200_fallback_VertexAttrib4fNV;
1131 vfmt->VertexAttrib4fvNV = r200_fallback_VertexAttrib4fvNV;
1132
1133 (void)r200_fallback_vtxfmt;
1134
1135 TNL_CONTEXT(ctx)->Driver.NotifyBegin = r200NotifyBegin;
1136
1137 rmesa->vb.enabled = 1;
1138 rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
1139 rmesa->vb.primflags = 0;
1140
1141 make_empty_list( &rmesa->vb.dfn_cache.Vertex2f );
1142 make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv );
1143 make_empty_list( &rmesa->vb.dfn_cache.Vertex3f );
1144 make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv );
1145 make_empty_list( &rmesa->vb.dfn_cache.Color4ub );
1146 make_empty_list( &rmesa->vb.dfn_cache.Color4ubv );
1147 make_empty_list( &rmesa->vb.dfn_cache.Color3ub );
1148 make_empty_list( &rmesa->vb.dfn_cache.Color3ubv );
1149 make_empty_list( &rmesa->vb.dfn_cache.Color4f );
1150 make_empty_list( &rmesa->vb.dfn_cache.Color4fv );
1151 make_empty_list( &rmesa->vb.dfn_cache.Color3f );
1152 make_empty_list( &rmesa->vb.dfn_cache.Color3fv );
1153 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
1154 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
1155 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
1156 make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
1157 make_empty_list( &rmesa->vb.dfn_cache.Normal3f );
1158 make_empty_list( &rmesa->vb.dfn_cache.Normal3fv );
1159 make_empty_list( &rmesa->vb.dfn_cache.TexCoord3f );
1160 make_empty_list( &rmesa->vb.dfn_cache.TexCoord3fv );
1161 make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f );
1162 make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv );
1163 make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f );
1164 make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv );
1165 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord3fARB );
1166 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord3fvARB );
1167 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
1168 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
1169 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
1170 make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
1171
1172 r200InitCodegen( &rmesa->vb.codegen, useCodegen );
1173 }
1174
1175 static void free_funcs( struct dynfn *l )
1176 {
1177 struct dynfn *f, *tmp;
1178 foreach_s (f, tmp, l) {
1179 remove_from_list( f );
1180 ALIGN_FREE( f->code );
1181 FREE( f );
1182 }
1183 }
1184
1185 void r200VtxfmtUnbindContext( GLcontext *ctx )
1186 {
1187 }
1188
1189
1190 void r200VtxfmtMakeCurrent( GLcontext *ctx )
1191 {
1192 }
1193
1194
1195 void r200VtxfmtDestroy( GLcontext *ctx )
1196 {
1197 r200ContextPtr rmesa = R200_CONTEXT( ctx );
1198
1199 count_funcs( rmesa );
1200 free_funcs( &rmesa->vb.dfn_cache.Vertex2f );
1201 free_funcs( &rmesa->vb.dfn_cache.Vertex2fv );
1202 free_funcs( &rmesa->vb.dfn_cache.Vertex3f );
1203 free_funcs( &rmesa->vb.dfn_cache.Vertex3fv );
1204 free_funcs( &rmesa->vb.dfn_cache.Color4ub );
1205 free_funcs( &rmesa->vb.dfn_cache.Color4ubv );
1206 free_funcs( &rmesa->vb.dfn_cache.Color3ub );
1207 free_funcs( &rmesa->vb.dfn_cache.Color3ubv );
1208 free_funcs( &rmesa->vb.dfn_cache.Color4f );
1209 free_funcs( &rmesa->vb.dfn_cache.Color4fv );
1210 free_funcs( &rmesa->vb.dfn_cache.Color3f );
1211 free_funcs( &rmesa->vb.dfn_cache.Color3fv );
1212 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
1213 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
1214 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
1215 free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
1216 free_funcs( &rmesa->vb.dfn_cache.Normal3f );
1217 free_funcs( &rmesa->vb.dfn_cache.Normal3fv );
1218 free_funcs( &rmesa->vb.dfn_cache.TexCoord3f );
1219 free_funcs( &rmesa->vb.dfn_cache.TexCoord3fv );
1220 free_funcs( &rmesa->vb.dfn_cache.TexCoord2f );
1221 free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv );
1222 free_funcs( &rmesa->vb.dfn_cache.TexCoord1f );
1223 free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv );
1224 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord3fARB );
1225 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord3fvARB );
1226 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
1227 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
1228 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
1229 free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
1230 }
1231