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