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