a7c5b7db039d1ef56cf34f86c5fefb1710e7aff6
1 /* $Id: t_imm_eval.c,v 1.4 2001/01/24 00:04:59 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
35 #include "math/m_eval.h"
37 #include "t_context.h"
38 #include "t_imm_eval.h"
39 #include "t_imm_exec.h"
40 #include "t_imm_fixup.h"
43 static void eval_points1( GLfloat outcoord
[][4],
46 GLfloat du
, GLfloat u1
)
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
;
58 static void eval_points2( GLfloat outcoord
[][4],
61 GLfloat du
, GLfloat u1
,
62 GLfloat dv
, GLfloat v1
)
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
;
77 static const GLubyte dirty_flags
[5] = {
86 static void eval1_4f( GLvector4f
*dest
,
90 struct gl_1d_map
*map
)
92 const GLfloat u1
= map
->u1
;
93 const GLfloat du
= map
->du
;
94 GLfloat (*to
)[4] = dest
->data
;
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
);
105 dest
->size
= MAX2(dest
->size
, dimension
);
106 dest
->flags
|= dirty_flags
[dimension
];
110 static void eval1_1ui( GLvector1ui
*dest
,
113 struct gl_1d_map
*map
)
115 const GLfloat u1
= map
->u1
;
116 const GLfloat du
= map
->du
;
117 GLuint
*to
= dest
->data
;
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
;
124 _math_horner_bezier_curve(map
->Points
, &tmp
, u
, 1, map
->Order
);
125 to
[i
] = (GLuint
) (GLint
) tmp
;
130 static void eval1_norm( GLvector3f
*dest
,
133 struct gl_1d_map
*map
)
135 const GLfloat u1
= map
->u1
;
136 const GLfloat du
= map
->du
;
137 GLfloat (*to
)[3] = dest
->data
;
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
);
147 static void eval1_color(
148 #if CHAN_TYPE == GL_UNSIGNED_BYTE
150 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
152 #elif CHAN_TYPE == GL_FLOAT
157 struct gl_1d_map
*map
)
159 const GLfloat u1
= map
->u1
;
160 const GLfloat du
= map
->du
;
161 GLchan (*to
)[4] = dest
->data
;
164 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++) {
165 if (flags
[i
] & (VERT_EVAL_C1
|VERT_EVAL_P1
)) {
166 GLfloat u
= (coord
[i
][0] - u1
) * du
;
168 _math_horner_bezier_curve(map
->Points
, fcolor
, u
, 4, map
->Order
);
169 UNCLAMPED_FLOAT_TO_RGBA_CHAN(to
[i
], fcolor
);
177 static void eval2_obj_norm( GLvector4f
*obj_ptr
,
178 GLvector3f
*norm_ptr
,
182 struct gl_2d_map
*map
)
184 const GLfloat u1
= map
->u1
;
185 const GLfloat du
= map
->du
;
186 const GLfloat v1
= map
->v1
;
187 const GLfloat dv
= map
->dv
;
188 GLfloat (*obj
)[4] = obj_ptr
->data
;
189 GLfloat (*normal
)[3] = norm_ptr
->data
;
192 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++)
193 if (flags
[i
] & (VERT_EVAL_C2
|VERT_EVAL_P2
)) {
194 GLfloat u
= (coord
[i
][0] - u1
) * du
;
195 GLfloat v
= (coord
[i
][1] - v1
) * dv
;
196 GLfloat du
[4], dv
[4];
198 ASSIGN_4V(obj
[i
], 0,0,0,1);
199 _math_de_casteljau_surf(map
->Points
, obj
[i
], du
, dv
, u
, v
, dimension
,
200 map
->Uorder
, map
->Vorder
);
202 CROSS3(normal
[i
], du
, dv
);
203 NORMALIZE_3FV(normal
[i
]);
206 obj_ptr
->size
= MAX2(obj_ptr
->size
, dimension
);
207 obj_ptr
->flags
|= dirty_flags
[dimension
];
211 static void eval2_4f( GLvector4f
*dest
,
215 struct gl_2d_map
*map
)
217 const GLfloat u1
= map
->u1
;
218 const GLfloat du
= map
->du
;
219 const GLfloat v1
= map
->v1
;
220 const GLfloat dv
= map
->dv
;
221 GLfloat (*to
)[4] = dest
->data
;
224 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++)
225 if (flags
[i
] & (VERT_EVAL_C2
|VERT_EVAL_P2
)) {
226 GLfloat u
= (coord
[i
][0] - u1
) * du
;
227 GLfloat v
= (coord
[i
][1] - v1
) * dv
;
228 _math_horner_bezier_surf(map
->Points
, to
[i
], u
, v
, dimension
,
229 map
->Uorder
, map
->Vorder
);
232 dest
->size
= MAX2(dest
->size
, dimension
);
233 dest
->flags
|= dirty_flags
[dimension
];
237 static void eval2_norm( GLvector3f
*dest
,
240 struct gl_2d_map
*map
)
242 const GLfloat u1
= map
->u1
;
243 const GLfloat du
= map
->du
;
244 const GLfloat v1
= map
->v1
;
245 const GLfloat dv
= map
->dv
;
246 GLfloat (*to
)[3] = dest
->data
;
249 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++)
250 if (flags
[i
] & (VERT_EVAL_C2
|VERT_EVAL_P2
)) {
251 GLfloat u
= (coord
[i
][0] - u1
) * du
;
252 GLfloat v
= (coord
[i
][1] - v1
) * dv
;
253 _math_horner_bezier_surf(map
->Points
, to
[i
], u
, v
, 3,
254 map
->Uorder
, map
->Vorder
);
260 static void eval2_1ui( GLvector1ui
*dest
,
263 struct gl_2d_map
*map
)
265 const GLfloat u1
= map
->u1
;
266 const GLfloat du
= map
->du
;
267 const GLfloat v1
= map
->v1
;
268 const GLfloat dv
= map
->dv
;
269 GLuint
*to
= dest
->data
;
272 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++)
273 if (flags
[i
] & (VERT_EVAL_C2
|VERT_EVAL_P2
)) {
274 GLfloat u
= (coord
[i
][0] - u1
) * du
;
275 GLfloat v
= (coord
[i
][1] - v1
) * dv
;
277 _math_horner_bezier_surf(map
->Points
, &tmp
, u
, v
, 1,
278 map
->Uorder
, map
->Vorder
);
280 to
[i
] = (GLuint
) (GLint
) tmp
;
286 static void eval2_color(
287 #if CHAN_TYPE == GL_UNSIGNED_BYTE
289 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
291 #elif CHAN_TYPE == GL_FLOAT
296 struct gl_2d_map
*map
)
298 const GLfloat u1
= map
->u1
;
299 const GLfloat du
= map
->du
;
300 const GLfloat v1
= map
->v1
;
301 const GLfloat dv
= map
->dv
;
302 GLchan (*to
)[4] = dest
->data
;
305 for (i
= 0 ; !(flags
[i
] & VERT_END_VB
) ; i
++) {
306 if (flags
[i
] & (VERT_EVAL_C2
|VERT_EVAL_P2
)) {
307 GLfloat u
= (coord
[i
][0] - u1
) * du
;
308 GLfloat v
= (coord
[i
][1] - v1
) * dv
;
310 _math_horner_bezier_surf(map
->Points
, fcolor
, u
, v
, 4,
311 map
->Uorder
, map
->Vorder
);
312 UNCLAMPED_FLOAT_TO_RGBA_CHAN(to
[i
], fcolor
);
319 static void copy_4f( GLfloat to
[][4], GLfloat from
[][4], GLuint count
)
321 MEMCPY( to
, from
, count
* sizeof(to
[0]));
324 static void copy_3f( GLfloat to
[][3], GLfloat from
[][3], GLuint count
)
326 MEMCPY( to
, from
, (count
) * sizeof(to
[0]));
329 static void copy_4chan( GLchan to
[][4], GLchan from
[][4], GLuint count
)
331 MEMCPY( to
, from
, (count
) * sizeof(to
[0]));
334 static void copy_1ui( GLuint to
[], GLuint from
[], GLuint count
)
336 MEMCPY( to
, from
, (count
) * sizeof(to
[0]));
341 /* Translate eval enabled flags to VERT_* flags.
343 static void update_eval( GLcontext
*ctx
)
345 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
346 GLuint eval1
= 0, eval2
= 0;
348 if (ctx
->Eval
.Map1Index
)
351 if (ctx
->Eval
.Map2Index
)
354 if (ctx
->Eval
.Map1Color4
)
357 if (ctx
->Eval
.Map2Color4
)
360 if (ctx
->Eval
.Map1Normal
)
363 if (ctx
->Eval
.Map2Normal
)
366 if (ctx
->Eval
.Map1TextureCoord4
||
367 ctx
->Eval
.Map1TextureCoord3
||
368 ctx
->Eval
.Map1TextureCoord2
||
369 ctx
->Eval
.Map1TextureCoord1
)
372 if (ctx
->Eval
.Map2TextureCoord4
||
373 ctx
->Eval
.Map2TextureCoord3
||
374 ctx
->Eval
.Map2TextureCoord2
||
375 ctx
->Eval
.Map2TextureCoord1
)
378 if (ctx
->Eval
.Map1Vertex4
)
379 eval1
|= VERT_OBJ_234
;
381 if (ctx
->Eval
.Map1Vertex3
)
382 eval1
|= VERT_OBJ_23
;
384 if (ctx
->Eval
.Map2Vertex4
) {
385 if (ctx
->Eval
.AutoNormal
)
386 eval2
|= VERT_OBJ_234
| VERT_NORM
;
388 eval2
|= VERT_OBJ_234
;
390 else if (ctx
->Eval
.Map2Vertex3
) {
391 if (ctx
->Eval
.AutoNormal
)
392 eval2
|= VERT_OBJ_23
| VERT_NORM
;
394 eval2
|= VERT_OBJ_23
;
397 tnl
->eval
.EvalMap1Flags
= eval1
;
398 tnl
->eval
.EvalMap2Flags
= eval2
;
399 tnl
->eval
.EvalNewState
= 0;
403 /* This looks a lot like a pipeline stage, but for various reasons is
404 * better handled outside the pipeline, and considered the final stage
405 * of fixing up an immediate struct for execution.
407 * Really want to cache the results of this function in display lists,
408 * at least for EvalMesh commands.
410 void _tnl_eval_vb( GLcontext
*ctx
,
415 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
416 struct vertex_arrays
*tmp
= &tnl
->imm_inputs
;
417 struct tnl_eval_store
*store
= &tnl
->eval
;
418 GLuint
*flags
= tnl
->vb
.Flag
;
419 GLuint count
= tnl
->vb
.Count
;
420 GLuint any_eval1
= orflag
& (VERT_EVAL_C1
|VERT_EVAL_P1
);
421 GLuint any_eval2
= orflag
& (VERT_EVAL_C2
|VERT_EVAL_P2
);
422 GLuint all_eval
= andflag
& VERT_EVAL_ANY
; /* may have false negatives */
424 GLuint purge_flags
= 0;
426 if (tnl
->eval
.EvalNewState
& _NEW_EVAL
)
429 /* Handle the degenerate cases.
431 if (any_eval1
&& !ctx
->Eval
.Map1Vertex4
&& !ctx
->Eval
.Map1Vertex3
)
432 purge_flags
= (VERT_EVAL_P1
|VERT_EVAL_C1
);
434 if (any_eval2
&& !ctx
->Eval
.Map2Vertex4
&& !ctx
->Eval
.Map2Vertex3
)
435 purge_flags
|= (VERT_EVAL_P1
|VERT_EVAL_C1
);
438 req
|= tnl
->pipeline
.inputs
& tnl
->eval
.EvalMap1Flags
;
441 req
|= tnl
->pipeline
.inputs
& tnl
->eval
.EvalMap2Flags
;
444 /* Translate points into coords. Use store->Coord to hold the
447 if (any_eval1
&& (orflag
& VERT_EVAL_P1
))
449 eval_points1( store
->Coord
, coord
, flags
,
450 ctx
->Eval
.MapGrid1du
,
451 ctx
->Eval
.MapGrid1u1
);
453 coord
= store
->Coord
;
456 if (any_eval2
&& (orflag
& VERT_EVAL_P2
))
458 eval_points2( store
->Coord
, coord
, flags
,
459 ctx
->Eval
.MapGrid2du
,
460 ctx
->Eval
.MapGrid2u1
,
461 ctx
->Eval
.MapGrid2dv
,
462 ctx
->Eval
.MapGrid2v1
);
464 coord
= store
->Coord
;
468 /* Perform the evaluations on active data elements.
470 if (req
& VERT_INDEX
)
473 copy_1ui( store
->Index
, tmp
->Index
.data
, count
);
475 tmp
->Index
.data
= store
->Index
;
476 tmp
->Index
.start
= store
->Index
;
478 if (ctx
->Eval
.Map1Index
&& any_eval1
)
479 eval1_1ui( &tmp
->Index
, coord
, flags
, &ctx
->EvalMap
.Map1Index
);
481 if (ctx
->Eval
.Map2Index
&& any_eval2
)
482 eval2_1ui( &tmp
->Index
, coord
, flags
, &ctx
->EvalMap
.Map2Index
);
489 copy_4chan( store
->Color
, tmp
->Color
.data
, count
);
491 tmp
->Color
.data
= store
->Color
;
492 tmp
->Color
.start
= (GLchan
*) store
->Color
;
494 if (ctx
->Eval
.Map1Color4
&& any_eval1
)
495 eval1_color( &tmp
->Color
, coord
, flags
, &ctx
->EvalMap
.Map1Color4
);
497 if (ctx
->Eval
.Map2Color4
&& any_eval2
)
498 eval2_color( &tmp
->Color
, coord
, flags
, &ctx
->EvalMap
.Map2Color4
);
502 if (req
& VERT_TEX(0))
505 copy_4f( store
->TexCoord
, tmp
->TexCoord
[0].data
, count
);
507 tmp
->TexCoord
[0].size
= 0;
509 tmp
->TexCoord
[0].data
= store
->TexCoord
;
510 tmp
->TexCoord
[0].start
= (GLfloat
*)store
->TexCoord
;
513 if (ctx
->Eval
.Map1TextureCoord4
) {
514 eval1_4f( &tmp
->TexCoord
[0], coord
, flags
, 4,
515 &ctx
->EvalMap
.Map1Texture4
);
517 else if (ctx
->Eval
.Map1TextureCoord3
) {
518 eval1_4f( &tmp
->TexCoord
[0], coord
, flags
, 3,
519 &ctx
->EvalMap
.Map1Texture3
);
521 else if (ctx
->Eval
.Map1TextureCoord2
) {
522 eval1_4f( &tmp
->TexCoord
[0], coord
, flags
, 2,
523 &ctx
->EvalMap
.Map1Texture2
);
525 else if (ctx
->Eval
.Map1TextureCoord1
) {
526 eval1_4f( &tmp
->TexCoord
[0], coord
, flags
, 1,
527 &ctx
->EvalMap
.Map1Texture1
);
532 if (ctx
->Eval
.Map2TextureCoord4
) {
533 eval2_4f( &tmp
->TexCoord
[0], coord
, flags
, 4,
534 &ctx
->EvalMap
.Map2Texture4
);
536 else if (ctx
->Eval
.Map2TextureCoord3
) {
537 eval2_4f( &tmp
->TexCoord
[0], coord
, flags
, 3,
538 &ctx
->EvalMap
.Map2Texture3
);
540 else if (ctx
->Eval
.Map2TextureCoord2
) {
541 eval2_4f( &tmp
->TexCoord
[0], coord
, flags
, 2,
542 &ctx
->EvalMap
.Map2Texture2
);
544 else if (ctx
->Eval
.Map2TextureCoord1
) {
545 eval2_4f( &tmp
->TexCoord
[0], coord
, flags
, 1,
546 &ctx
->EvalMap
.Map2Texture1
);
555 copy_3f( store
->Normal
, tmp
->Normal
.data
, count
);
557 tmp
->Normal
.data
= store
->Normal
;
558 tmp
->Normal
.start
= (GLfloat
*)store
->Normal
;
560 if (ctx
->Eval
.Map1Normal
&& any_eval1
)
561 eval1_norm( &tmp
->Normal
, coord
, flags
,
562 &ctx
->EvalMap
.Map1Normal
);
564 if (ctx
->Eval
.Map2Normal
&& any_eval2
)
565 eval2_norm( &tmp
->Normal
, coord
, flags
,
566 &ctx
->EvalMap
.Map2Normal
);
571 /* In the AutoNormal case, the copy and assignment of tmp->NormalPtr
577 copy_4f( store
->Obj
, tmp
->Obj
.data
, count
);
581 tmp
->Obj
.data
= store
->Obj
;
582 tmp
->Obj
.start
= (GLfloat
*)store
->Obj
;
585 if (ctx
->Eval
.Map1Vertex4
) {
586 eval1_4f( &tmp
->Obj
, coord
, flags
, 4,
587 &ctx
->EvalMap
.Map1Vertex4
);
589 else if (ctx
->Eval
.Map1Vertex3
) {
590 eval1_4f( &tmp
->Obj
, coord
, flags
, 3,
591 &ctx
->EvalMap
.Map1Vertex3
);
596 if (ctx
->Eval
.Map2Vertex4
)
598 if (ctx
->Eval
.AutoNormal
&& (req
& VERT_NORM
))
599 eval2_obj_norm( &tmp
->Obj
, &tmp
->Normal
, coord
, flags
, 4,
600 &ctx
->EvalMap
.Map2Vertex4
);
602 eval2_4f( &tmp
->Obj
, coord
, flags
, 4,
603 &ctx
->EvalMap
.Map2Vertex4
);
605 else if (ctx
->Eval
.Map2Vertex3
)
607 if (ctx
->Eval
.AutoNormal
&& (req
& VERT_NORM
))
608 eval2_obj_norm( &tmp
->Obj
, &tmp
->Normal
, coord
, flags
, 3,
609 &ctx
->EvalMap
.Map2Vertex3
);
611 eval2_4f( &tmp
->Obj
, coord
, flags
, 3,
612 &ctx
->EvalMap
.Map2Vertex3
);
620 copy_1ui( store
->Flag
, flags
, count
);
621 tnl
->vb
.Flag
= store
->Flag
;
623 /* This is overkill, but correct as fixup will have copied the
624 * values to all vertices in the VB - we may be falsely stating
625 * that some repeated values are new, but doing so is fairly
628 for (i
= 0 ; i
< count
; i
++)
629 store
->Flag
[i
] |= req
;