f6d33dfa1a4c8055f63b2c5b618941deafda8d1a
[mesa.git] / src / mesa / tnl / t_imm_eval.c
1 /* $Id: t_imm_eval.c,v 1.13 2001/05/14 09:00:51 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * Authors:
27 * Keith Whitwell <keithw@valinux.com>
28 *
29 */
30
31
32 #include "glheader.h"
33 #include "colormac.h"
34 #include "context.h"
35 #include "macros.h"
36 #include "mem.h"
37 #include "mmath.h"
38 #include "mtypes.h"
39 #include "math/m_eval.h"
40
41 #include "t_context.h"
42 #include "t_imm_debug.h"
43 #include "t_imm_eval.h"
44 #include "t_imm_exec.h"
45 #include "t_imm_fixup.h"
46 #include "t_imm_alloc.h"
47
48
49 static void eval_points1( GLfloat outcoord[][4],
50 GLfloat coord[][4],
51 const GLuint *flags,
52 GLfloat du, GLfloat u1 )
53 {
54 GLuint i;
55 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
56 if (flags[i] & VERT_EVAL_ANY) {
57 outcoord[i][0] = coord[i][0];
58 outcoord[i][1] = coord[i][1];
59 if (flags[i] & VERT_EVAL_P1)
60 outcoord[i][0] = coord[i][0] * du + u1;
61 }
62 }
63
64 static void eval_points2( GLfloat outcoord[][4],
65 GLfloat coord[][4],
66 const GLuint *flags,
67 GLfloat du, GLfloat u1,
68 GLfloat dv, GLfloat v1 )
69 {
70 GLuint i;
71 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) {
72 if (flags[i] & VERT_EVAL_ANY) {
73 outcoord[i][0] = coord[i][0];
74 outcoord[i][1] = coord[i][1];
75 if (flags[i] & VERT_EVAL_P2) {
76 outcoord[i][0] = coord[i][0] * du + u1;
77 outcoord[i][1] = coord[i][1] * dv + v1;
78 }
79 }
80 }
81 }
82
83 static const GLubyte dirty_flags[5] = {
84 0, /* not possible */
85 VEC_DIRTY_0,
86 VEC_DIRTY_1,
87 VEC_DIRTY_2,
88 VEC_DIRTY_3
89 };
90
91
92 static void eval1_4f( GLvector4f *dest,
93 GLfloat coord[][4],
94 const GLuint *flags,
95 GLuint dimension,
96 struct gl_1d_map *map )
97 {
98 const GLfloat u1 = map->u1;
99 const GLfloat du = map->du;
100 GLfloat (*to)[4] = dest->data;
101 GLuint i;
102
103 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
104 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
105 GLfloat u = (coord[i][0] - u1) * du;
106 ASSIGN_4V(to[i], 0,0,0,1);
107 _math_horner_bezier_curve(map->Points, to[i], u,
108 dimension, map->Order);
109 }
110
111 dest->size = MAX2(dest->size, dimension);
112 dest->flags |= dirty_flags[dimension];
113 }
114
115 static void eval1_4f_ca( struct gl_client_array *dest,
116 GLfloat coord[][4],
117 const GLuint *flags,
118 GLuint dimension,
119 struct gl_1d_map *map )
120 {
121 const GLfloat u1 = map->u1;
122 const GLfloat du = map->du;
123 GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr;
124 GLuint i;
125
126 ASSERT(dest->Type == GL_FLOAT);
127 ASSERT(dest->StrideB == 4 * sizeof(GLfloat));
128
129 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
130 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
131 GLfloat u = (coord[i][0] - u1) * du;
132 ASSIGN_4V(to[i], 0,0,0,1);
133 _math_horner_bezier_curve(map->Points, to[i], u,
134 dimension, map->Order);
135 }
136
137 dest->Size = MAX2(dest->Size, (GLint) dimension);
138 }
139
140
141 static void eval1_1ui( GLvector1ui *dest,
142 GLfloat coord[][4],
143 const GLuint *flags,
144 struct gl_1d_map *map )
145 {
146 const GLfloat u1 = map->u1;
147 const GLfloat du = map->du;
148 GLuint *to = dest->data;
149 GLuint i;
150
151 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
152 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
153 GLfloat u = (coord[i][0] - u1) * du;
154 GLfloat tmp;
155 _math_horner_bezier_curve(map->Points, &tmp, u, 1, map->Order);
156 to[i] = (GLuint) (GLint) tmp;
157 }
158
159 }
160
161 static void eval1_norm( GLvector3f *dest,
162 GLfloat coord[][4],
163 const GLuint *flags,
164 struct gl_1d_map *map )
165 {
166 const GLfloat u1 = map->u1;
167 const GLfloat du = map->du;
168 GLfloat (*to)[3] = dest->data;
169 GLuint i;
170
171 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
172 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
173 GLfloat u = (coord[i][0] - u1) * du;
174 _math_horner_bezier_curve(map->Points, to[i], u, 3, map->Order);
175 }
176 }
177
178
179
180
181
182 static void eval2_obj_norm( GLvector4f *obj_ptr,
183 GLvector3f *norm_ptr,
184 GLfloat coord[][4],
185 GLuint *flags,
186 GLuint dimension,
187 struct gl_2d_map *map )
188 {
189 const GLfloat u1 = map->u1;
190 const GLfloat du = map->du;
191 const GLfloat v1 = map->v1;
192 const GLfloat dv = map->dv;
193 GLfloat (*obj)[4] = obj_ptr->data;
194 GLfloat (*normal)[3] = norm_ptr->data;
195 GLuint i;
196
197 /* fprintf(stderr, "%s\n", __FUNCTION__); */
198
199 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
200 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
201 GLfloat u = (coord[i][0] - u1) * du;
202 GLfloat v = (coord[i][1] - v1) * dv;
203 GLfloat du[4], dv[4];
204
205 ASSIGN_4V(obj[i], 0,0,0,1);
206 _math_de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension,
207 map->Uorder, map->Vorder);
208
209 CROSS3(normal[i], du, dv);
210 NORMALIZE_3FV(normal[i]);
211 }
212
213 obj_ptr->size = MAX2(obj_ptr->size, dimension);
214 obj_ptr->flags |= dirty_flags[dimension];
215 }
216
217
218 static void eval2_4f( GLvector4f *dest,
219 GLfloat coord[][4],
220 const GLuint *flags,
221 GLuint dimension,
222 struct gl_2d_map *map )
223 {
224 const GLfloat u1 = map->u1;
225 const GLfloat du = map->du;
226 const GLfloat v1 = map->v1;
227 const GLfloat dv = map->dv;
228 GLfloat (*to)[4] = dest->data;
229 GLuint i;
230
231 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
232 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
233 GLfloat u = (coord[i][0] - u1) * du;
234 GLfloat v = (coord[i][1] - v1) * dv;
235 /* fprintf(stderr, "coord %d: %f %f\n", i, coord[i][0], coord[i][1]); */
236
237 _math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
238 map->Uorder, map->Vorder);
239 }
240
241 dest->size = MAX2(dest->size, dimension);
242 dest->flags |= dirty_flags[dimension];
243 }
244
245 static void eval2_4f_ca( struct gl_client_array *dest,
246 GLfloat coord[][4],
247 const GLuint *flags,
248 GLuint dimension,
249 struct gl_2d_map *map )
250 {
251 const GLfloat u1 = map->u1;
252 const GLfloat du = map->du;
253 const GLfloat v1 = map->v1;
254 const GLfloat dv = map->dv;
255 GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr;
256 GLuint i;
257
258 ASSERT(dest->Type == GL_FLOAT);
259 ASSERT(dest->StrideB == 4 * sizeof(GLfloat));
260
261 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
262 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
263 GLfloat u = (coord[i][0] - u1) * du;
264 GLfloat v = (coord[i][1] - v1) * dv;
265 _math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
266 map->Uorder, map->Vorder);
267 }
268
269 dest->Size = MAX2(dest->Size, (GLint) dimension);
270 }
271
272
273 static void eval2_norm( GLvector3f *dest,
274 GLfloat coord[][4],
275 GLuint *flags,
276 struct gl_2d_map *map )
277 {
278 const GLfloat u1 = map->u1;
279 const GLfloat du = map->du;
280 const GLfloat v1 = map->v1;
281 const GLfloat dv = map->dv;
282 GLfloat (*to)[3] = dest->data;
283 GLuint i;
284
285 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
286 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
287 GLfloat u = (coord[i][0] - u1) * du;
288 GLfloat v = (coord[i][1] - v1) * dv;
289 _math_horner_bezier_surf(map->Points, to[i], u, v, 3,
290 map->Uorder, map->Vorder);
291 }
292
293 }
294
295
296 static void eval2_1ui( GLvector1ui *dest,
297 GLfloat coord[][4],
298 const GLuint *flags,
299 struct gl_2d_map *map )
300 {
301 const GLfloat u1 = map->u1;
302 const GLfloat du = map->du;
303 const GLfloat v1 = map->v1;
304 const GLfloat dv = map->dv;
305 GLuint *to = dest->data;
306 GLuint i;
307
308 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
309 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
310 GLfloat u = (coord[i][0] - u1) * du;
311 GLfloat v = (coord[i][1] - v1) * dv;
312 GLfloat tmp;
313 _math_horner_bezier_surf(map->Points, &tmp, u, v, 1,
314 map->Uorder, map->Vorder);
315
316 to[i] = (GLuint) (GLint) tmp;
317 }
318 }
319
320
321
322
323
324
325 static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count )
326 {
327 MEMCPY( to, from, count * sizeof(to[0]));
328 }
329
330 static void copy_4f_stride( GLfloat to[][4], GLfloat *from,
331 GLuint stride, GLuint count )
332 {
333 if (stride == 4 * sizeof(GLfloat))
334 MEMCPY( to, from, count * sizeof(to[0]));
335 else {
336 GLuint i;
337 /* fprintf(stderr, "%s stride %d count %d\n", __FUNCTION__, */
338 /* stride, count); */
339 for (i = 0 ; i < count ; i++, STRIDE_F(from, stride))
340 COPY_4FV( to[i], from );
341 }
342 }
343
344 static void copy_3f( GLfloat to[][3], GLfloat from[][3], GLuint count )
345 {
346 MEMCPY( to, from, (count) * sizeof(to[0]));
347 }
348
349
350 static void copy_1ui( GLuint to[], GLuint from[], GLuint count )
351 {
352 MEMCPY( to, from, (count) * sizeof(to[0]));
353 }
354
355
356
357 /* Translate eval enabled flags to VERT_* flags.
358 */
359 static void update_eval( GLcontext *ctx )
360 {
361 TNLcontext *tnl = TNL_CONTEXT(ctx);
362 GLuint eval1 = 0, eval2 = 0;
363
364 if (ctx->Eval.Map1Index)
365 eval1 |= VERT_INDEX;
366
367 if (ctx->Eval.Map2Index)
368 eval2 |= VERT_INDEX;
369
370 if (ctx->Eval.Map1Color4)
371 eval1 |= VERT_RGBA;
372
373 if (ctx->Eval.Map2Color4)
374 eval2 |= VERT_RGBA;
375
376 if (ctx->Eval.Map1Normal)
377 eval1 |= VERT_NORM;
378
379 if (ctx->Eval.Map2Normal)
380 eval2 |= VERT_NORM;
381
382 if (ctx->Eval.Map1TextureCoord4 ||
383 ctx->Eval.Map1TextureCoord3 ||
384 ctx->Eval.Map1TextureCoord2 ||
385 ctx->Eval.Map1TextureCoord1)
386 eval1 |= VERT_TEX0;
387
388 if (ctx->Eval.Map2TextureCoord4 ||
389 ctx->Eval.Map2TextureCoord3 ||
390 ctx->Eval.Map2TextureCoord2 ||
391 ctx->Eval.Map2TextureCoord1)
392 eval2 |= VERT_TEX0;
393
394 if (ctx->Eval.Map1Vertex4)
395 eval1 |= VERT_OBJ_234;
396
397 if (ctx->Eval.Map1Vertex3)
398 eval1 |= VERT_OBJ_23;
399
400 if (ctx->Eval.Map2Vertex4) {
401 if (ctx->Eval.AutoNormal)
402 eval2 |= VERT_OBJ_234 | VERT_NORM;
403 else
404 eval2 |= VERT_OBJ_234;
405 }
406 else if (ctx->Eval.Map2Vertex3) {
407 if (ctx->Eval.AutoNormal)
408 eval2 |= VERT_OBJ_23 | VERT_NORM;
409 else
410 eval2 |= VERT_OBJ_23;
411 }
412
413 tnl->eval.EvalMap1Flags = eval1;
414 tnl->eval.EvalMap2Flags = eval2;
415 tnl->eval.EvalNewState = 0;
416 }
417
418
419 /* This looks a lot like a pipeline stage, but for various reasons is
420 * better handled outside the pipeline, and considered the final stage
421 * of fixing up an immediate struct for execution.
422 *
423 * Really want to cache the results of this function in display lists,
424 * at least for EvalMesh commands.
425 */
426 void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM )
427 {
428 TNLcontext *tnl = TNL_CONTEXT(ctx);
429 struct vertex_arrays *tmp = &tnl->imm_inputs;
430 struct immediate *store = tnl->eval.im;
431 GLuint *flags = IM->Flag + IM->CopyStart;
432 GLuint copycount;
433 GLuint orflag = IM->OrFlag;
434 GLuint any_eval1 = orflag & (VERT_EVAL_C1|VERT_EVAL_P1);
435 GLuint any_eval2 = orflag & (VERT_EVAL_C2|VERT_EVAL_P2);
436 GLuint req = 0;
437 GLuint purge_flags = 0;
438 GLfloat (*coord)[4] = IM->Obj + IM->CopyStart;
439
440 if (IM->AndFlag & VERT_EVAL_ANY)
441 copycount = IM->Start - IM->CopyStart; /* just copy copied vertices */
442 else
443 copycount = IM->Count - IM->CopyStart; /* copy all vertices */
444
445 /* fprintf(stderr, "%s copystart %d start %d count %d copycount %d\n", */
446 /* __FUNCTION__, IM->CopyStart, IM->Start, IM->Count, copycount); */
447
448 if (!store)
449 store = tnl->eval.im = _tnl_alloc_immediate( ctx );
450
451 if (tnl->eval.EvalNewState & _NEW_EVAL)
452 update_eval( ctx );
453
454 if (any_eval1) {
455 req |= tnl->pipeline.inputs & tnl->eval.EvalMap1Flags;
456
457 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
458 purge_flags = (VERT_EVAL_P1|VERT_EVAL_C1);
459
460 if (orflag & VERT_EVAL_P1) {
461 eval_points1( store->Obj + IM->CopyStart,
462 coord, flags,
463 ctx->Eval.MapGrid1du,
464 ctx->Eval.MapGrid1u1);
465
466 coord = store->Obj + IM->CopyStart;
467 }
468 }
469
470 if (any_eval2) {
471 req |= tnl->pipeline.inputs & tnl->eval.EvalMap2Flags;
472
473 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
474 purge_flags |= (VERT_EVAL_P2|VERT_EVAL_C2);
475
476 if (orflag & VERT_EVAL_P2) {
477 eval_points2( store->Obj + IM->CopyStart,
478 coord, flags,
479 ctx->Eval.MapGrid2du,
480 ctx->Eval.MapGrid2u1,
481 ctx->Eval.MapGrid2dv,
482 ctx->Eval.MapGrid2v1 );
483
484 coord = store->Obj + IM->CopyStart;
485 }
486 }
487
488
489 /* _tnl_print_vert_flags(__FUNCTION__, req); */
490
491 /* Perform the evaluations on active data elements.
492 */
493 if (req & VERT_INDEX)
494 {
495 GLuint generated = 0;
496
497 if (copycount)
498 copy_1ui( store->Index + IM->CopyStart, tmp->Index.data, copycount );
499
500 tmp->Index.data = store->Index + IM->CopyStart;
501 tmp->Index.start = store->Index + IM->CopyStart;
502
503 if (ctx->Eval.Map1Index && any_eval1) {
504 eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index );
505 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
506 }
507
508 if (ctx->Eval.Map2Index && any_eval2) {
509 eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index );
510 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
511 }
512
513 /* Propogate values to generate correct vertices when vertex
514 * maps are disabled.
515 */
516 if (purge_flags & generated)
517 _tnl_fixup_1ui( tmp->Index.data, flags, 0,
518 VERT_INDEX|
519 VERT_OBJ|
520 generated|
521 (VERT_EVAL_ANY&~purge_flags) );
522 }
523
524 if (req & VERT_RGBA)
525 {
526 GLuint generated = 0;
527
528 if (copycount)
529 copy_4f_stride( store->Color + IM->CopyStart,
530 (GLfloat *)tmp->Color.Ptr,
531 tmp->Color.StrideB,
532 copycount );
533
534 tmp->Color.Ptr = store->Color + IM->CopyStart;
535 tmp->Color.StrideB = 4 * sizeof(GLfloat);
536 tmp->Color.Flags = 0;
537 tnl->vb.importable_data &= ~VERT_RGBA;
538
539 if (ctx->Eval.Map1Color4 && any_eval1) {
540 eval1_4f_ca( &tmp->Color, coord, flags, 4, &ctx->EvalMap.Map1Color4 );
541 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
542 }
543
544 if (ctx->Eval.Map2Color4 && any_eval2) {
545 eval2_4f_ca( &tmp->Color, coord, flags, 4, &ctx->EvalMap.Map2Color4 );
546 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
547 }
548
549 /* Propogate values to generate correct vertices when vertex
550 * maps are disabled.
551 */
552 if (purge_flags & generated)
553 _tnl_fixup_4f( store->Color + IM->CopyStart,
554 flags, 0,
555 VERT_RGBA|
556 VERT_OBJ|
557 generated|
558 (VERT_EVAL_ANY&~purge_flags) );
559 }
560
561
562 if (req & VERT_TEX(0))
563 {
564 GLuint generated = 0;
565
566 if (copycount)
567 copy_4f( store->TexCoord[0] + IM->CopyStart,
568 tmp->TexCoord[0].data, copycount );
569 else
570 tmp->TexCoord[0].size = 0;
571
572 tmp->TexCoord[0].data = store->TexCoord[0] + IM->CopyStart;
573 tmp->TexCoord[0].start = (GLfloat *)tmp->TexCoord[0].data;
574
575 if (any_eval1) {
576 if (ctx->Eval.Map1TextureCoord4) {
577 eval1_4f( &tmp->TexCoord[0], coord, flags, 4,
578 &ctx->EvalMap.Map1Texture4 );
579 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
580 }
581 else if (ctx->Eval.Map1TextureCoord3) {
582 eval1_4f( &tmp->TexCoord[0], coord, flags, 3,
583 &ctx->EvalMap.Map1Texture3 );
584 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
585 }
586 else if (ctx->Eval.Map1TextureCoord2) {
587 eval1_4f( &tmp->TexCoord[0], coord, flags, 2,
588 &ctx->EvalMap.Map1Texture2 );
589 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
590 }
591 else if (ctx->Eval.Map1TextureCoord1) {
592 eval1_4f( &tmp->TexCoord[0], coord, flags, 1,
593 &ctx->EvalMap.Map1Texture1 );
594 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
595 }
596 }
597
598 if (any_eval2) {
599 if (ctx->Eval.Map2TextureCoord4) {
600 eval2_4f( &tmp->TexCoord[0], coord, flags, 4,
601 &ctx->EvalMap.Map2Texture4 );
602 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
603 }
604 else if (ctx->Eval.Map2TextureCoord3) {
605 eval2_4f( &tmp->TexCoord[0], coord, flags, 3,
606 &ctx->EvalMap.Map2Texture3 );
607 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
608 }
609 else if (ctx->Eval.Map2TextureCoord2) {
610 eval2_4f( &tmp->TexCoord[0], coord, flags, 2,
611 &ctx->EvalMap.Map2Texture2 );
612 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
613 }
614 else if (ctx->Eval.Map2TextureCoord1) {
615 eval2_4f( &tmp->TexCoord[0], coord, flags, 1,
616 &ctx->EvalMap.Map2Texture1 );
617 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
618 }
619 }
620
621 /* Propogate values to generate correct vertices when vertex
622 * maps are disabled.
623 */
624 if (purge_flags & generated)
625 _tnl_fixup_4f( tmp->TexCoord[0].data, flags, 0,
626 VERT_TEX0|
627 VERT_OBJ|
628 generated|
629 (VERT_EVAL_ANY&~purge_flags) );
630 }
631
632
633 if (req & VERT_NORM)
634 {
635 GLuint generated = 0;
636
637 if (copycount) {
638 /* fprintf(stderr, "%s: Copy normals\n", __FUNCTION__); */
639 copy_3f( store->Normal + IM->CopyStart, tmp->Normal.data,
640 copycount );
641 }
642
643 tmp->Normal.data = store->Normal + IM->CopyStart;
644 tmp->Normal.start = (GLfloat *)tmp->Normal.data;
645
646 if (ctx->Eval.Map1Normal && any_eval1) {
647 eval1_norm( &tmp->Normal, coord, flags,
648 &ctx->EvalMap.Map1Normal );
649 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
650 }
651
652 if (ctx->Eval.Map2Normal && any_eval2) {
653 eval2_norm( &tmp->Normal, coord, flags,
654 &ctx->EvalMap.Map2Normal );
655 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
656 }
657
658 /* Propogate values to generate correct vertices when vertex
659 * maps are disabled.
660 */
661 if (purge_flags & generated)
662 _tnl_fixup_3f( tmp->Normal.data, flags, 0,
663 VERT_NORM|
664 VERT_OBJ|
665 generated|
666 (VERT_EVAL_ANY&~purge_flags) );
667 }
668
669
670
671 /* In the AutoNormal case, the copy and assignment of tmp->NormalPtr
672 * are done above.
673 */
674 if (req & VERT_OBJ)
675 {
676 if (copycount) {
677 /* This copy may already have occurred when eliminating
678 * glEvalPoint calls:
679 */
680 if (coord != store->Obj + IM->CopyStart)
681 copy_4f( store->Obj + IM->CopyStart, tmp->Obj.data, copycount );
682 } else
683 tmp->Obj.size = 0;
684
685 tmp->Obj.data = store->Obj + IM->CopyStart;
686 tmp->Obj.start = (GLfloat *)tmp->Obj.data;
687
688 /* Note: Normal data is already prepared above.
689 */
690
691 if (any_eval1) {
692 if (ctx->Eval.Map1Vertex4) {
693 eval1_4f( &tmp->Obj, coord, flags, 4,
694 &ctx->EvalMap.Map1Vertex4 );
695 }
696 else if (ctx->Eval.Map1Vertex3) {
697 eval1_4f( &tmp->Obj, coord, flags, 3,
698 &ctx->EvalMap.Map1Vertex3 );
699 }
700 }
701
702 if (any_eval2) {
703 if (ctx->Eval.Map2Vertex4)
704 {
705 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
706 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4,
707 &ctx->EvalMap.Map2Vertex4 );
708 else
709 eval2_4f( &tmp->Obj, coord, flags, 4,
710 &ctx->EvalMap.Map2Vertex4 );
711 }
712 else if (ctx->Eval.Map2Vertex3)
713 {
714 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
715 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3,
716 &ctx->EvalMap.Map2Vertex3 );
717 else
718 eval2_4f( &tmp->Obj, coord, flags, 3,
719 &ctx->EvalMap.Map2Vertex3 );
720 }
721 }
722 }
723
724
725 /* Calculate new IM->Elts, IM->Primitive, IM->PrimitiveLength for
726 * the case where vertex maps are not enabled for some received eval
727 * coordinates.
728 */
729 if (purge_flags) {
730 GLuint vertex = VERT_OBJ|(VERT_EVAL_ANY & ~purge_flags);
731 GLuint last_new_prim = 0;
732 GLuint new_prim_length = 0;
733 GLuint next_old_prim = 0;
734 struct vertex_buffer *VB = &tnl->vb;
735 GLuint i,j,count = VB->Count;
736
737 /* fprintf(stderr, "PURGING\n"); */
738
739 for (i = 0, j = 0 ; i < count ; i++) {
740 if (flags[i] & vertex) {
741 store->Elt[j++] = i;
742 new_prim_length++;
743 }
744 if (i == next_old_prim) {
745 next_old_prim += VB->PrimitiveLength[i];
746 VB->PrimitiveLength[last_new_prim] = new_prim_length;
747 VB->Primitive[j] = VB->Primitive[i];
748 last_new_prim = j;
749 }
750 }
751
752 VB->Elts = store->Elt;
753 _tnl_get_purged_copy_verts( ctx, store );
754 }
755
756 /* Produce new flags array:
757 */
758 {
759 GLuint i;
760 GLuint count = tnl->vb.Count + 1;
761
762 copy_1ui( store->Flag, flags, count );
763 tnl->vb.Flag = store->Flag;
764 for (i = 0 ; i < count ; i++)
765 store->Flag[i] |= req;
766 IM->CopyOrFlag |= req; /* hack for copying. */
767 }
768 }