Major rework of tnl module
[mesa.git] / src / mesa / tnl / t_imm_eval.c
1 /* $Id: t_imm_eval.c,v 1.1 2000/12/26 05:09:32 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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_eval.h"
39 #include "t_imm_exec.h"
40 #include "t_imm_fixup.h"
41
42
43 static void eval_points1( GLfloat outcoord[][4],
44 GLfloat coord[][4],
45 const GLuint *flags,
46 GLfloat du, GLfloat u1 )
47 {
48 GLuint i;
49 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
50 if (flags[i] & VERT_EVAL_ANY) {
51 outcoord[i][0] = coord[i][0];
52 outcoord[i][1] = coord[i][1];
53 if (flags[i] & VERT_EVAL_P1)
54 outcoord[i][0] = coord[i][0] * du + u1;
55 }
56 }
57
58 static void eval_points2( GLfloat outcoord[][4],
59 GLfloat coord[][4],
60 const GLuint *flags,
61 GLfloat du, GLfloat u1,
62 GLfloat dv, GLfloat v1 )
63 {
64 GLuint i;
65 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) {
66 if (flags[i] & VERT_EVAL_ANY) {
67 outcoord[i][0] = coord[i][0];
68 outcoord[i][1] = coord[i][1];
69 if (flags[i] & VERT_EVAL_P2) {
70 outcoord[i][0] = coord[i][0] * du + u1;
71 outcoord[i][1] = coord[i][1] * dv + v1;
72 }
73 }
74 }
75 }
76
77 static const GLubyte dirty_flags[5] = {
78 0, /* not possible */
79 VEC_DIRTY_0,
80 VEC_DIRTY_1,
81 VEC_DIRTY_2,
82 VEC_DIRTY_3
83 };
84
85
86 static void eval1_4f( GLvector4f *dest,
87 GLfloat coord[][4],
88 const GLuint *flags,
89 GLuint dimension,
90 struct gl_1d_map *map )
91 {
92 const GLfloat u1 = map->u1;
93 const GLfloat du = map->du;
94 GLfloat (*to)[4] = dest->data;
95 GLuint i;
96
97 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
98 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
99 GLfloat u = (coord[i][0] - u1) * du;
100 ASSIGN_4V(to[i], 0,0,0,1);
101 _math_horner_bezier_curve(map->Points, to[i], u,
102 dimension, map->Order);
103 }
104
105 dest->size = MAX2(dest->size, dimension);
106 dest->flags |= dirty_flags[dimension];
107 }
108
109
110 static void eval1_1ui( GLvector1ui *dest,
111 GLfloat coord[][4],
112 const GLuint *flags,
113 struct gl_1d_map *map )
114 {
115 const GLfloat u1 = map->u1;
116 const GLfloat du = map->du;
117 GLuint *to = dest->data;
118 GLuint i;
119
120 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
121 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
122 GLfloat u = (coord[i][0] - u1) * du;
123 GLfloat tmp;
124 _math_horner_bezier_curve(map->Points, &tmp, u, 1, map->Order);
125 to[i] = (GLuint) (GLint) tmp;
126 }
127
128 }
129
130 static void eval1_norm( GLvector3f *dest,
131 GLfloat coord[][4],
132 const GLuint *flags,
133 struct gl_1d_map *map )
134 {
135 const GLfloat u1 = map->u1;
136 const GLfloat du = map->du;
137 GLfloat (*to)[3] = dest->data;
138 GLuint i;
139
140 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
141 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
142 GLfloat u = (coord[i][0] - u1) * du;
143 _math_horner_bezier_curve(map->Points, to[i], u, 3, map->Order);
144 }
145 }
146
147 static void eval1_color( GLvector4ub *dest,
148 GLfloat coord[][4],
149 const GLuint *flags,
150 struct gl_1d_map *map )
151 {
152 const GLfloat u1 = map->u1;
153 const GLfloat du = map->du;
154 GLubyte (*to)[4] = dest->data;
155 GLuint i;
156
157 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
158 if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
159 GLfloat u = (coord[i][0] - u1) * du;
160 GLfloat fcolor[4];
161 _math_horner_bezier_curve(map->Points, fcolor, u, 4, map->Order);
162 FLOAT_RGBA_TO_CHAN_RGBA(to[i], fcolor);
163 }
164 }
165
166
167
168
169 static void eval2_obj_norm( GLvector4f *obj_ptr,
170 GLvector3f *norm_ptr,
171 GLfloat coord[][4],
172 GLuint *flags,
173 GLuint dimension,
174 struct gl_2d_map *map )
175 {
176 const GLfloat u1 = map->u1;
177 const GLfloat du = map->du;
178 const GLfloat v1 = map->v1;
179 const GLfloat dv = map->dv;
180 GLfloat (*obj)[4] = obj_ptr->data;
181 GLfloat (*normal)[3] = norm_ptr->data;
182 GLuint i;
183
184 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
185 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
186 GLfloat u = (coord[i][0] - u1) * du;
187 GLfloat v = (coord[i][1] - v1) * dv;
188 GLfloat du[4], dv[4];
189
190 ASSIGN_4V(obj[i], 0,0,0,1);
191 _math_de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension,
192 map->Uorder, map->Vorder);
193
194 CROSS3(normal[i], du, dv);
195 NORMALIZE_3FV(normal[i]);
196 }
197
198 obj_ptr->size = MAX2(obj_ptr->size, dimension);
199 obj_ptr->flags |= dirty_flags[dimension];
200 }
201
202
203 static void eval2_4f( GLvector4f *dest,
204 GLfloat coord[][4],
205 const GLuint *flags,
206 GLuint dimension,
207 struct gl_2d_map *map )
208 {
209 const GLfloat u1 = map->u1;
210 const GLfloat du = map->du;
211 const GLfloat v1 = map->v1;
212 const GLfloat dv = map->dv;
213 GLfloat (*to)[4] = dest->data;
214 GLuint i;
215
216 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
217 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
218 GLfloat u = (coord[i][0] - u1) * du;
219 GLfloat v = (coord[i][1] - v1) * dv;
220 _math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
221 map->Uorder, map->Vorder);
222 }
223
224 dest->size = MAX2(dest->size, dimension);
225 dest->flags |= dirty_flags[dimension];
226 }
227
228
229 static void eval2_norm( GLvector3f *dest,
230 GLfloat coord[][4],
231 GLuint *flags,
232 struct gl_2d_map *map )
233 {
234 const GLfloat u1 = map->u1;
235 const GLfloat du = map->du;
236 const GLfloat v1 = map->v1;
237 const GLfloat dv = map->dv;
238 GLfloat (*to)[3] = dest->data;
239 GLuint i;
240
241 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
242 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
243 GLfloat u = (coord[i][0] - u1) * du;
244 GLfloat v = (coord[i][1] - v1) * dv;
245 _math_horner_bezier_surf(map->Points, to[i], u, v, 3,
246 map->Uorder, map->Vorder);
247 }
248
249 }
250
251
252 static void eval2_1ui( GLvector1ui *dest,
253 GLfloat coord[][4],
254 const GLuint *flags,
255 struct gl_2d_map *map )
256 {
257 const GLfloat u1 = map->u1;
258 const GLfloat du = map->du;
259 const GLfloat v1 = map->v1;
260 const GLfloat dv = map->dv;
261 GLuint *to = dest->data;
262 GLuint i;
263
264 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
265 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
266 GLfloat u = (coord[i][0] - u1) * du;
267 GLfloat v = (coord[i][1] - v1) * dv;
268 GLfloat tmp;
269 _math_horner_bezier_surf(map->Points, &tmp, u, v, 1,
270 map->Uorder, map->Vorder);
271
272 to[i] = (GLuint) (GLint) tmp;
273 }
274 }
275
276
277
278 static void eval2_color( GLvector4ub *dest,
279 GLfloat coord[][4],
280 GLuint *flags,
281 struct gl_2d_map *map )
282 {
283 const GLfloat u1 = map->u1;
284 const GLfloat du = map->du;
285 const GLfloat v1 = map->v1;
286 const GLfloat dv = map->dv;
287 GLubyte (*to)[4] = dest->data;
288 GLuint i;
289
290 for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++)
291 if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
292 GLfloat u = (coord[i][0] - u1) * du;
293 GLfloat v = (coord[i][1] - v1) * dv;
294 GLfloat fcolor[4];
295 _math_horner_bezier_surf(map->Points, fcolor, u, v, 4,
296 map->Uorder, map->Vorder);
297 FLOAT_RGBA_TO_CHAN_RGBA(to[i], fcolor);
298 }
299
300 }
301
302
303
304 static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count )
305 {
306 MEMCPY( to, from, count * sizeof(to[0]));
307 }
308
309 static void copy_3f( GLfloat to[][3], GLfloat from[][3], GLuint count )
310 {
311 MEMCPY( to, from, (count) * sizeof(to[0]));
312 }
313
314 static void copy_4ub( GLubyte to[][4], GLubyte from[][4], GLuint count )
315 {
316 MEMCPY( to, from, (count) * sizeof(to[0]));
317 }
318
319 static void copy_1ui( GLuint to[], GLuint from[], GLuint count )
320 {
321 MEMCPY( to, from, (count) * sizeof(to[0]));
322 }
323
324
325
326 /* Translate eval enabled flags to VERT_* flags.
327 */
328 static void update_eval( GLcontext *ctx )
329 {
330 TNLcontext *tnl = TNL_CONTEXT(ctx);
331 GLuint eval1 = 0, eval2 = 0;
332
333 if (ctx->Eval.Map1Index)
334 eval1 |= VERT_INDEX;
335
336 if (ctx->Eval.Map2Index)
337 eval2 |= VERT_INDEX;
338
339 if (ctx->Eval.Map1Color4)
340 eval1 |= VERT_RGBA;
341
342 if (ctx->Eval.Map2Color4)
343 eval2 |= VERT_RGBA;
344
345 if (ctx->Eval.Map1Normal)
346 eval1 |= VERT_NORM;
347
348 if (ctx->Eval.Map2Normal)
349 eval2 |= VERT_NORM;
350
351 if (ctx->Eval.Map1TextureCoord4 ||
352 ctx->Eval.Map1TextureCoord3 ||
353 ctx->Eval.Map1TextureCoord2 ||
354 ctx->Eval.Map1TextureCoord1)
355 eval1 |= VERT_TEX0;
356
357 if (ctx->Eval.Map2TextureCoord4 ||
358 ctx->Eval.Map2TextureCoord3 ||
359 ctx->Eval.Map2TextureCoord2 ||
360 ctx->Eval.Map2TextureCoord1)
361 eval2 |= VERT_TEX0;
362
363 if (ctx->Eval.Map1Vertex4)
364 eval1 |= VERT_OBJ_234;
365
366 if (ctx->Eval.Map1Vertex3)
367 eval1 |= VERT_OBJ_23;
368
369 if (ctx->Eval.Map2Vertex4) {
370 if (ctx->Eval.AutoNormal)
371 eval2 |= VERT_OBJ_234 | VERT_NORM;
372 else
373 eval2 |= VERT_OBJ_234;
374 }
375 else if (ctx->Eval.Map2Vertex3) {
376 if (ctx->Eval.AutoNormal)
377 eval2 |= VERT_OBJ_23 | VERT_NORM;
378 else
379 eval2 |= VERT_OBJ_23;
380 }
381
382 tnl->eval.EvalMap1Flags = eval1;
383 tnl->eval.EvalMap2Flags = eval2;
384 tnl->eval.EvalNewState = 0;
385 }
386
387
388 /* This looks a lot like a pipeline stage, but for various reasons is
389 * better handled outside the pipeline, and considered the final stage
390 * of fixing up an immediate struct for execution.
391 *
392 * Really want to cache the results of this function in display lists,
393 * at least for EvalMesh commands.
394 */
395 void _tnl_eval_vb( GLcontext *ctx,
396 GLfloat (*coord)[4],
397 GLuint orflag,
398 GLuint andflag )
399 {
400 TNLcontext *tnl = TNL_CONTEXT(ctx);
401 struct vertex_arrays *tmp = &tnl->imm_inputs;
402 struct tnl_eval_store *store = &tnl->eval;
403 GLuint *flags = tnl->vb.Flag;
404 GLuint count = tnl->vb.Count;
405 GLuint any_eval1 = orflag & (VERT_EVAL_C1|VERT_EVAL_P1);
406 GLuint any_eval2 = orflag & (VERT_EVAL_C2|VERT_EVAL_P2);
407 GLuint all_eval = andflag & VERT_EVAL_ANY; /* may have false negatives */
408 GLuint req = 0;
409 GLuint purge_flags = 0;
410
411 if (tnl->eval.EvalNewState & _NEW_EVAL)
412 update_eval( ctx );
413
414 /* Handle the degenerate cases.
415 */
416 if (any_eval1 && !ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
417 purge_flags = (VERT_EVAL_P1|VERT_EVAL_C1);
418
419 if (any_eval2 && !ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
420 purge_flags |= (VERT_EVAL_P1|VERT_EVAL_C1);
421
422 if (any_eval1)
423 req |= tnl->pipeline.inputs & tnl->eval.EvalMap1Flags;
424
425 if (any_eval2)
426 req |= tnl->pipeline.inputs & tnl->eval.EvalMap2Flags;
427
428
429 /* Translate points into coords. Use store->Obj to hold the
430 * new data.
431 */
432 if (any_eval1 && (orflag & VERT_EVAL_P1))
433 {
434 eval_points1( store->Obj, coord, flags,
435 ctx->Eval.MapGrid1du,
436 ctx->Eval.MapGrid1u1);
437
438 coord = store->Obj;
439 }
440
441 if (any_eval2 && (orflag & VERT_EVAL_P2))
442 {
443 eval_points2( store->Obj, coord, flags,
444 ctx->Eval.MapGrid2du,
445 ctx->Eval.MapGrid2u1,
446 ctx->Eval.MapGrid2dv,
447 ctx->Eval.MapGrid2v1 );
448
449 coord = store->Obj;
450 }
451
452
453 /* Perform the evaluations on active data elements.
454 */
455 if (req & VERT_INDEX)
456 {
457 if (!all_eval)
458 copy_1ui( store->Index, tmp->Index.data, count );
459
460 tmp->Index.data = store->Index;
461 tmp->Index.start = store->Index;
462
463 if (ctx->Eval.Map1Index && any_eval1)
464 eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index );
465
466 if (ctx->Eval.Map2Index && any_eval2)
467 eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index );
468
469 }
470
471 if (req & VERT_RGBA)
472 {
473 if (!all_eval)
474 copy_4ub( store->Color, tmp->Color.data, count );
475
476 tmp->Color.data = store->Color;
477 tmp->Color.start = (GLubyte *)store->Color;
478
479 if (ctx->Eval.Map1Color4 && any_eval1)
480 eval1_color( &tmp->Color, coord, flags, &ctx->EvalMap.Map1Color4 );
481
482 if (ctx->Eval.Map2Color4 && any_eval2)
483 eval2_color( &tmp->Color, coord, flags, &ctx->EvalMap.Map2Color4 );
484 }
485
486
487 if (req & VERT_TEX(0))
488 {
489 if (!all_eval)
490 copy_4f( store->TexCoord, tmp->TexCoord[0].data, count );
491 else
492 tmp->TexCoord[0].size = 0;
493
494 tmp->TexCoord[0].data = store->TexCoord;
495 tmp->TexCoord[0].start = (GLfloat *)store->TexCoord;
496
497 if (any_eval1) {
498 if (ctx->Eval.Map1TextureCoord4) {
499 eval1_4f( &tmp->TexCoord[0], coord, flags, 4,
500 &ctx->EvalMap.Map1Texture4 );
501 }
502 else if (ctx->Eval.Map1TextureCoord3) {
503 eval1_4f( &tmp->TexCoord[0], coord, flags, 3,
504 &ctx->EvalMap.Map1Texture3 );
505 }
506 else if (ctx->Eval.Map1TextureCoord2) {
507 eval1_4f( &tmp->TexCoord[0], coord, flags, 2,
508 &ctx->EvalMap.Map1Texture2 );
509 }
510 else if (ctx->Eval.Map1TextureCoord1) {
511 eval1_4f( &tmp->TexCoord[0], coord, flags, 1,
512 &ctx->EvalMap.Map1Texture1 );
513 }
514 }
515
516 if (any_eval2) {
517 if (ctx->Eval.Map2TextureCoord4) {
518 eval2_4f( &tmp->TexCoord[0], coord, flags, 4,
519 &ctx->EvalMap.Map2Texture4 );
520 }
521 else if (ctx->Eval.Map2TextureCoord3) {
522 eval2_4f( &tmp->TexCoord[0], coord, flags, 3,
523 &ctx->EvalMap.Map2Texture3 );
524 }
525 else if (ctx->Eval.Map2TextureCoord2) {
526 eval2_4f( &tmp->TexCoord[0], coord, flags, 2,
527 &ctx->EvalMap.Map2Texture2 );
528 }
529 else if (ctx->Eval.Map2TextureCoord1) {
530 eval2_4f( &tmp->TexCoord[0], coord, flags, 1,
531 &ctx->EvalMap.Map2Texture1 );
532 }
533 }
534 }
535
536
537 if (req & VERT_NORM)
538 {
539 if (!all_eval)
540 copy_3f( store->Normal, tmp->Normal.data, count );
541
542 tmp->Normal.data = store->Normal;
543 tmp->Normal.start = (GLfloat *)store->Normal;
544
545 if (ctx->Eval.Map1Normal && any_eval1)
546 eval1_norm( &tmp->Normal, coord, flags,
547 &ctx->EvalMap.Map1Normal );
548
549 if (ctx->Eval.Map2Normal && any_eval2)
550 eval2_norm( &tmp->Normal, coord, flags,
551 &ctx->EvalMap.Map2Normal );
552 }
553
554
555
556 /* In the AutoNormal case, the copy and assignment of tmp->NormalPtr
557 * are done above.
558 */
559 if (req & VERT_OBJ)
560 {
561 if (!all_eval) {
562 copy_4f( store->Obj, tmp->Obj.data, count );
563 } else
564 tmp->Obj.size = 0;
565
566 tmp->Obj.data = store->Obj;
567 tmp->Obj.start = (GLfloat *)store->Obj;
568
569 if (any_eval1) {
570 if (ctx->Eval.Map1Vertex4) {
571 eval1_4f( &tmp->Obj, coord, flags, 4,
572 &ctx->EvalMap.Map1Vertex4 );
573 }
574 else if (ctx->Eval.Map1Vertex3) {
575 eval1_4f( &tmp->Obj, coord, flags, 3,
576 &ctx->EvalMap.Map1Vertex3 );
577 }
578 }
579
580 if (any_eval2) {
581 if (ctx->Eval.Map2Vertex4)
582 {
583 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
584 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4,
585 &ctx->EvalMap.Map2Vertex4 );
586 else
587 eval2_4f( &tmp->Obj, coord, flags, 4,
588 &ctx->EvalMap.Map2Vertex4 );
589 }
590 else if (ctx->Eval.Map2Vertex3)
591 {
592 if (ctx->Eval.AutoNormal && (req & VERT_NORM))
593 eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3,
594 &ctx->EvalMap.Map2Vertex3 );
595 else
596 eval2_4f( &tmp->Obj, coord, flags, 3,
597 &ctx->EvalMap.Map2Vertex3 );
598 }
599 }
600 }
601
602
603 {
604 GLuint i;
605 copy_1ui( store->Flag, flags, count );
606 tnl->vb.Flag = store->Flag;
607
608 /* This is overkill, but correct as fixup will have copied the
609 * values to all vertices in the VB - we may be falsely stating
610 * that some repeated values are new, but doing so is fairly
611 * harmless.
612 */
613 for (i = 0 ; i < count ; i++)
614 store->Flag[i] |= req;
615 }
616 }
617
618
619
620
621
622
623