Undo last change - breaks other stuff.
[mesa.git] / src / mesa / tnl / t_imm_eval.c
1 /* $Id: t_imm_eval.c,v 1.16 2001/08/14 00:52:47 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 /* du[0] = du[0]*obj[i][3] - du[3]*obj[i][0]; */
210 /* du[1] = du[1]*obj[i][3] - du[3]*obj[i][1]; */
211 /* du[2] = du[2]*obj[i][3] - du[3]*obj[i][2]; */
212
213 /* dv[0] = dv[0]*obj[i][3] - dv[3]*obj[i][0]; */
214 /* dv[1] = dv[1]*obj[i][3] - dv[3]*obj[i][1]; */
215 /* dv[2] = dv[2]*obj[i][3] - dv[3]*obj[i][2]; */
216
217 CROSS3(normal[i], du, dv);
218 NORMALIZE_3FV(normal[i]);
219 }
220
221 obj_ptr->size = MAX2(obj_ptr->size, dimension);
222 obj_ptr->flags |= dirty_flags[dimension];
223 }
224
225
226 static void eval2_4f( GLvector4f *dest,
227 GLfloat coord[][4],
228 const GLuint *flags,
229 GLuint dimension,
230 struct gl_2d_map *map )
231 {
232 const GLfloat u1 = map->u1;
233 const GLfloat du = map->du;
234 const GLfloat v1 = map->v1;
235 const GLfloat dv = map->dv;
236 GLfloat (*to)[4] = dest->data;
237 GLuint i;
238
239 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
240 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
241 GLfloat u = (coord[i][0] - u1) * du;
242 GLfloat v = (coord[i][1] - v1) * dv;
243 /* fprintf(stderr, "coord %d: %f %f\n", i, coord[i][0], coord[i][1]); */
244
245 _math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
246 map->Uorder, map->Vorder);
247 }
248
249 dest->size = MAX2(dest->size, dimension);
250 dest->flags |= dirty_flags[dimension];
251 }
252
253 static void eval2_4f_ca( struct gl_client_array *dest,
254 GLfloat coord[][4],
255 const GLuint *flags,
256 GLuint dimension,
257 struct gl_2d_map *map )
258 {
259 const GLfloat u1 = map->u1;
260 const GLfloat du = map->du;
261 const GLfloat v1 = map->v1;
262 const GLfloat dv = map->dv;
263 GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr;
264 GLuint i;
265
266 ASSERT(dest->Type == GL_FLOAT);
267 ASSERT(dest->StrideB == 4 * sizeof(GLfloat));
268
269 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
270 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
271 GLfloat u = (coord[i][0] - u1) * du;
272 GLfloat v = (coord[i][1] - v1) * dv;
273 _math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
274 map->Uorder, map->Vorder);
275 }
276
277 dest->Size = MAX2(dest->Size, (GLint) dimension);
278 }
279
280
281 static void eval2_norm( GLvector3f *dest,
282 GLfloat coord[][4],
283 GLuint *flags,
284 struct gl_2d_map *map )
285 {
286 const GLfloat u1 = map->u1;
287 const GLfloat du = map->du;
288 const GLfloat v1 = map->v1;
289 const GLfloat dv = map->dv;
290 GLfloat (*to)[3] = dest->data;
291 GLuint i;
292
293 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
294 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
295 GLfloat u = (coord[i][0] - u1) * du;
296 GLfloat v = (coord[i][1] - v1) * dv;
297 _math_horner_bezier_surf(map->Points, to[i], u, v, 3,
298 map->Uorder, map->Vorder);
299 }
300
301 }
302
303
304 static void eval2_1ui( GLvector1ui *dest,
305 GLfloat coord[][4],
306 const GLuint *flags,
307 struct gl_2d_map *map )
308 {
309 const GLfloat u1 = map->u1;
310 const GLfloat du = map->du;
311 const GLfloat v1 = map->v1;
312 const GLfloat dv = map->dv;
313 GLuint *to = dest->data;
314 GLuint i;
315
316 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
317 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
318 GLfloat u = (coord[i][0] - u1) * du;
319 GLfloat v = (coord[i][1] - v1) * dv;
320 GLfloat tmp;
321 _math_horner_bezier_surf(map->Points, &tmp, u, v, 1,
322 map->Uorder, map->Vorder);
323
324 to[i] = (GLuint) (GLint) tmp;
325 }
326 }
327
328
329
330
331
332
333 static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count )
334 {
335 MEMCPY( to, from, count * sizeof(to[0]));
336 }
337
338 static void copy_4f_stride( GLfloat to[][4], GLfloat *from,
339 GLuint stride, GLuint count )
340 {
341 if (stride == 4 * sizeof(GLfloat))
342 MEMCPY( to, from, count * sizeof(to[0]));
343 else {
344 GLuint i;
345 /* fprintf(stderr, "%s stride %d count %d\n", __FUNCTION__, */
346 /* stride, count); */
347 for (i = 0 ; i < count ; i++, STRIDE_F(from, stride))
348 COPY_4FV( to[i], from );
349 }
350 }
351
352 static void copy_3f( GLfloat to[][3], GLfloat from[][3], GLuint count )
353 {
354 int i;
355 /* MEMCPY( to, from, (count) * sizeof(to[0])); */
356 for (i = 0 ; i < count ; i++) {
357 /* fprintf(stderr, "copy norm %d from %p: %f %f %f\n", i, */
358 /* from[i], */
359 /* from[i][0], from[i][1], from[i][2]); */
360 COPY_3FV(to[i], from[i]);
361 }
362 }
363
364
365 static void copy_1ui( GLuint to[], GLuint from[], GLuint count )
366 {
367 MEMCPY( to, from, (count) * sizeof(to[0]));
368 }
369
370
371
372 /* Translate eval enabled flags to VERT_* flags.
373 */
374 static void update_eval( GLcontext *ctx )
375 {
376 TNLcontext *tnl = TNL_CONTEXT(ctx);
377 GLuint eval1 = 0, eval2 = 0;
378
379 if (ctx->Eval.Map1Index)
380 eval1 |= VERT_INDEX;
381
382 if (ctx->Eval.Map2Index)
383 eval2 |= VERT_INDEX;
384
385 if (ctx->Eval.Map1Color4)
386 eval1 |= VERT_RGBA;
387
388 if (ctx->Eval.Map2Color4)
389 eval2 |= VERT_RGBA;
390
391 if (ctx->Eval.Map1Normal)
392 eval1 |= VERT_NORM;
393
394 if (ctx->Eval.Map2Normal)
395 eval2 |= VERT_NORM;
396
397 if (ctx->Eval.Map1TextureCoord4 ||
398 ctx->Eval.Map1TextureCoord3 ||
399 ctx->Eval.Map1TextureCoord2 ||
400 ctx->Eval.Map1TextureCoord1)
401 eval1 |= VERT_TEX0;
402
403 if (ctx->Eval.Map2TextureCoord4 ||
404 ctx->Eval.Map2TextureCoord3 ||
405 ctx->Eval.Map2TextureCoord2 ||
406 ctx->Eval.Map2TextureCoord1)
407 eval2 |= VERT_TEX0;
408
409 if (ctx->Eval.Map1Vertex4)
410 eval1 |= VERT_OBJ_234;
411
412 if (ctx->Eval.Map1Vertex3)
413 eval1 |= VERT_OBJ_23;
414
415 if (ctx->Eval.Map2Vertex4) {
416 if (ctx->Eval.AutoNormal)
417 eval2 |= VERT_OBJ_234 | VERT_NORM;
418 else
419 eval2 |= VERT_OBJ_234;
420 }
421 else if (ctx->Eval.Map2Vertex3) {
422 if (ctx->Eval.AutoNormal)
423 eval2 |= VERT_OBJ_23 | VERT_NORM;
424 else
425 eval2 |= VERT_OBJ_23;
426 }
427
428 tnl->eval.EvalMap1Flags = eval1;
429 tnl->eval.EvalMap2Flags = eval2;
430 tnl->eval.EvalNewState = 0;
431 }
432
433
434 /* This looks a lot like a pipeline stage, but for various reasons is
435 * better handled outside the pipeline, and considered the final stage
436 * of fixing up an immediate struct for execution.
437 *
438 * Really want to cache the results of this function in display lists,
439 * at least for EvalMesh commands.
440 */
441 void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM )
442 {
443 TNLcontext *tnl = TNL_CONTEXT(ctx);
444 struct vertex_arrays *tmp = &tnl->imm_inputs;
445 struct immediate *store = tnl->eval.im;
446 GLuint *flags = IM->Flag + IM->CopyStart;
447 GLuint copycount;
448 GLuint orflag = IM->OrFlag;
449 GLuint any_eval1 = orflag & (VERT_EVAL_C1|VERT_EVAL_P1);
450 GLuint any_eval2 = orflag & (VERT_EVAL_C2|VERT_EVAL_P2);
451 GLuint req = 0;
452 GLuint purge_flags = 0;
453 GLfloat (*coord)[4] = IM->Obj + IM->CopyStart;
454
455 if (IM->AndFlag & VERT_EVAL_ANY)
456 copycount = IM->Start - IM->CopyStart; /* just copy copied vertices */
457 else
458 copycount = IM->Count - IM->CopyStart; /* copy all vertices */
459
460 /* fprintf(stderr, "%s copystart %d start %d count %d copycount %d\n", */
461 /* __FUNCTION__, IM->CopyStart, IM->Start, IM->Count, copycount); */
462
463 if (!store)
464 store = tnl->eval.im = _tnl_alloc_immediate( ctx );
465
466 if (tnl->eval.EvalNewState & _NEW_EVAL)
467 update_eval( ctx );
468
469 if (any_eval1) {
470 req |= tnl->pipeline.inputs & tnl->eval.EvalMap1Flags;
471
472 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
473 purge_flags = (VERT_EVAL_P1|VERT_EVAL_C1);
474
475 if (orflag & VERT_EVAL_P1) {
476 eval_points1( store->Obj + IM->CopyStart,
477 coord, flags,
478 ctx->Eval.MapGrid1du,
479 ctx->Eval.MapGrid1u1);
480
481 coord = store->Obj + IM->CopyStart;
482 }
483 }
484
485 if (any_eval2) {
486 req |= tnl->pipeline.inputs & tnl->eval.EvalMap2Flags;
487
488 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
489 purge_flags |= (VERT_EVAL_P2|VERT_EVAL_C2);
490
491 if (orflag & VERT_EVAL_P2) {
492 eval_points2( store->Obj + IM->CopyStart,
493 coord, flags,
494 ctx->Eval.MapGrid2du,
495 ctx->Eval.MapGrid2u1,
496 ctx->Eval.MapGrid2dv,
497 ctx->Eval.MapGrid2v1 );
498
499 coord = store->Obj + IM->CopyStart;
500 }
501 }
502
503
504 /* _tnl_print_vert_flags(__FUNCTION__, req); */
505
506 /* Perform the evaluations on active data elements.
507 */
508 if (req & VERT_INDEX)
509 {
510 GLuint generated = 0;
511
512 if (copycount)
513 copy_1ui( store->Index + IM->CopyStart, tmp->Index.data, copycount );
514
515 tmp->Index.data = store->Index + IM->CopyStart;
516 tmp->Index.start = store->Index + IM->CopyStart;
517
518 if (ctx->Eval.Map1Index && any_eval1) {
519 eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index );
520 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
521 }
522
523 if (ctx->Eval.Map2Index && any_eval2) {
524 eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index );
525 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
526 }
527 }
528
529 if (req & VERT_RGBA)
530 {
531 GLuint generated = 0;
532
533 if (copycount)
534 copy_4f_stride( store->Color + IM->CopyStart,
535 (GLfloat *)tmp->Color.Ptr,
536 tmp->Color.StrideB,
537 copycount );
538
539 tmp->Color.Ptr = store->Color + IM->CopyStart;
540 tmp->Color.StrideB = 4 * sizeof(GLfloat);
541 tmp->Color.Flags = 0;
542 tnl->vb.importable_data &= ~VERT_RGBA;
543
544 if (ctx->Eval.Map1Color4 && any_eval1) {
545 eval1_4f_ca( &tmp->Color, coord, flags, 4, &ctx->EvalMap.Map1Color4 );
546 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
547 }
548
549 if (ctx->Eval.Map2Color4 && any_eval2) {
550 eval2_4f_ca( &tmp->Color, coord, flags, 4, &ctx->EvalMap.Map2Color4 );
551 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
552 }
553 }
554
555
556 if (req & VERT_TEX(0))
557 {
558 GLuint generated = 0;
559
560 if (copycount)
561 copy_4f( store->TexCoord[0] + IM->CopyStart,
562 tmp->TexCoord[0].data, copycount );
563 else
564 tmp->TexCoord[0].size = 0;
565
566 tmp->TexCoord[0].data = store->TexCoord[0] + IM->CopyStart;
567 tmp->TexCoord[0].start = (GLfloat *)tmp->TexCoord[0].data;
568
569 if (any_eval1) {
570 if (ctx->Eval.Map1TextureCoord4) {
571 eval1_4f( &tmp->TexCoord[0], coord, flags, 4,
572 &ctx->EvalMap.Map1Texture4 );
573 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
574 }
575 else if (ctx->Eval.Map1TextureCoord3) {
576 eval1_4f( &tmp->TexCoord[0], coord, flags, 3,
577 &ctx->EvalMap.Map1Texture3 );
578 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
579 }
580 else if (ctx->Eval.Map1TextureCoord2) {
581 eval1_4f( &tmp->TexCoord[0], coord, flags, 2,
582 &ctx->EvalMap.Map1Texture2 );
583 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
584 }
585 else if (ctx->Eval.Map1TextureCoord1) {
586 eval1_4f( &tmp->TexCoord[0], coord, flags, 1,
587 &ctx->EvalMap.Map1Texture1 );
588 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
589 }
590 }
591
592 if (any_eval2) {
593 if (ctx->Eval.Map2TextureCoord4) {
594 eval2_4f( &tmp->TexCoord[0], coord, flags, 4,
595 &ctx->EvalMap.Map2Texture4 );
596 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
597 }
598 else if (ctx->Eval.Map2TextureCoord3) {
599 eval2_4f( &tmp->TexCoord[0], coord, flags, 3,
600 &ctx->EvalMap.Map2Texture3 );
601 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
602 }
603 else if (ctx->Eval.Map2TextureCoord2) {
604 eval2_4f( &tmp->TexCoord[0], coord, flags, 2,
605 &ctx->EvalMap.Map2Texture2 );
606 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
607 }
608 else if (ctx->Eval.Map2TextureCoord1) {
609 eval2_4f( &tmp->TexCoord[0], coord, flags, 1,
610 &ctx->EvalMap.Map2Texture1 );
611 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
612 }
613 }
614 }
615
616
617 if (req & VERT_NORM)
618 {
619 GLuint generated = 0;
620
621 if (copycount) {
622 /* fprintf(stderr, "%s: Copy normals\n", __FUNCTION__); */
623 copy_3f( store->Normal + IM->CopyStart, tmp->Normal.data,
624 copycount );
625 }
626
627 tmp->Normal.data = store->Normal + IM->CopyStart;
628 tmp->Normal.start = (GLfloat *)tmp->Normal.data;
629
630 if (ctx->Eval.Map1Normal && any_eval1) {
631 eval1_norm( &tmp->Normal, coord, flags,
632 &ctx->EvalMap.Map1Normal );
633 generated |= VERT_EVAL_C1|VERT_EVAL_P1;
634 }
635
636 if (ctx->Eval.Map2Normal && any_eval2) {
637 eval2_norm( &tmp->Normal, coord, flags,
638 &ctx->EvalMap.Map2Normal );
639 generated |= VERT_EVAL_C2|VERT_EVAL_P2;
640 }
641 }
642
643
644
645 /* In the AutoNormal case, the copy and assignment of tmp->NormalPtr
646 * are done above.
647 */
648 if (req & VERT_OBJ)
649 {
650 if (copycount) {
651 /* This copy may already have occurred when eliminating
652 * glEvalPoint calls:
653 */
654 if (coord != store->Obj + IM->CopyStart)
655 copy_4f( store->Obj + IM->CopyStart, tmp->Obj.data, copycount );
656 } else
657 tmp->Obj.size = 0;
658
659 tmp->Obj.data = store->Obj + IM->CopyStart;
660 tmp->Obj.start = (GLfloat *)tmp->Obj.data;
661
662 /* Note: Normal data is already prepared above.
663 */
664
665 if (any_eval1) {
666 if (ctx->Eval.Map1Vertex4) {
667 eval1_4f( &tmp->Obj, coord, flags, 4,
668 &ctx->EvalMap.Map1Vertex4 );
669 }
670 else if (ctx->Eval.Map1Vertex3) {
671 eval1_4f( &tmp->Obj, coord, flags, 3,
672 &ctx->EvalMap.Map1Vertex3 );
673 }
674 }
675
676 if (any_eval2) {
677 if (ctx->Eval.Map2Vertex4)
678 {
679 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
680 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4,
681 &ctx->EvalMap.Map2Vertex4 );
682 else
683 eval2_4f( &tmp->Obj, coord, flags, 4,
684 &ctx->EvalMap.Map2Vertex4 );
685 }
686 else if (ctx->Eval.Map2Vertex3)
687 {
688 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
689 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3,
690 &ctx->EvalMap.Map2Vertex3 );
691 else
692 eval2_4f( &tmp->Obj, coord, flags, 3,
693 &ctx->EvalMap.Map2Vertex3 );
694 }
695 }
696 }
697
698
699 /* Calculate new IM->Elts, IM->Primitive, IM->PrimitiveLength for
700 * the case where vertex maps are not enabled for some received
701 * eval coordinates. In this case those slots in the immediate
702 * must be ignored.
703 */
704 if (purge_flags) {
705 GLuint vertex = VERT_OBJ|(VERT_EVAL_ANY & ~purge_flags);
706 GLuint last_new_prim = 0;
707 GLuint new_prim_length = 0;
708 GLuint next_old_prim = 0;
709 struct vertex_buffer *VB = &tnl->vb;
710 GLuint i,j,count = VB->Count;
711
712 /* fprintf(stderr, "PURGING\n"); */
713
714 for (i = 0, j = 0 ; i < count ; i++) {
715 if (flags[i] & vertex) {
716 store->Elt[j++] = i;
717 new_prim_length++;
718 }
719 if (i == next_old_prim) {
720 next_old_prim += VB->PrimitiveLength[i];
721 VB->PrimitiveLength[last_new_prim] = new_prim_length;
722 VB->Primitive[j] = VB->Primitive[i];
723 last_new_prim = j;
724 }
725 }
726
727 VB->Elts = store->Elt;
728 _tnl_get_purged_copy_verts( ctx, store );
729 }
730
731 /* Produce new flags array:
732 */
733 {
734 GLuint i;
735 GLuint count = tnl->vb.Count + 1;
736
737 copy_1ui( store->Flag, flags, count );
738 tnl->vb.Flag = store->Flag;
739 for (i = 0 ; i < count ; i++)
740 store->Flag[i] |= req;
741 IM->Evaluated = req; /* hack for copying. */
742 }
743 }