diff options
Diffstat (limited to 'src/mesa/tnl/t_imm_eval.c')
-rw-r--r-- | src/mesa/tnl/t_imm_eval.c | 623 |
1 files changed, 623 insertions, 0 deletions
diff --git a/src/mesa/tnl/t_imm_eval.c b/src/mesa/tnl/t_imm_eval.c new file mode 100644 index 00000000000..ed8af649aad --- /dev/null +++ b/src/mesa/tnl/t_imm_eval.c @@ -0,0 +1,623 @@ +/* $Id: t_imm_eval.c,v 1.1 2000/12/26 05:09:32 keithw Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "macros.h" +#include "mem.h" +#include "mmath.h" +#include "mtypes.h" +#include "math/m_eval.h" + +#include "t_context.h" +#include "t_imm_eval.h" +#include "t_imm_exec.h" +#include "t_imm_fixup.h" + + +static void eval_points1( GLfloat outcoord[][4], + GLfloat coord[][4], + const GLuint *flags, + GLfloat du, GLfloat u1 ) +{ + GLuint i; + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & VERT_EVAL_ANY) { + outcoord[i][0] = coord[i][0]; + outcoord[i][1] = coord[i][1]; + if (flags[i] & VERT_EVAL_P1) + outcoord[i][0] = coord[i][0] * du + u1; + } +} + +static void eval_points2( GLfloat outcoord[][4], + GLfloat coord[][4], + const GLuint *flags, + GLfloat du, GLfloat u1, + GLfloat dv, GLfloat v1 ) +{ + GLuint i; + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) { + if (flags[i] & VERT_EVAL_ANY) { + outcoord[i][0] = coord[i][0]; + outcoord[i][1] = coord[i][1]; + if (flags[i] & VERT_EVAL_P2) { + outcoord[i][0] = coord[i][0] * du + u1; + outcoord[i][1] = coord[i][1] * dv + v1; + } + } + } +} + +static const GLubyte dirty_flags[5] = { + 0, /* not possible */ + VEC_DIRTY_0, + VEC_DIRTY_1, + VEC_DIRTY_2, + VEC_DIRTY_3 +}; + + +static void eval1_4f( GLvector4f *dest, + GLfloat coord[][4], + const GLuint *flags, + GLuint dimension, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLfloat (*to)[4] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + ASSIGN_4V(to[i], 0,0,0,1); + _math_horner_bezier_curve(map->Points, to[i], u, + dimension, map->Order); + } + + dest->size = MAX2(dest->size, dimension); + dest->flags |= dirty_flags[dimension]; +} + + +static void eval1_1ui( GLvector1ui *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLuint *to = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat tmp; + _math_horner_bezier_curve(map->Points, &tmp, u, 1, map->Order); + to[i] = (GLuint) (GLint) tmp; + } + +} + +static void eval1_norm( GLvector3f *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLfloat (*to)[3] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + _math_horner_bezier_curve(map->Points, to[i], u, 3, map->Order); + } +} + +static void eval1_color( GLvector4ub *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_1d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + GLubyte (*to)[4] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat fcolor[4]; + _math_horner_bezier_curve(map->Points, fcolor, u, 4, map->Order); + FLOAT_RGBA_TO_CHAN_RGBA(to[i], fcolor); + } +} + + + + +static void eval2_obj_norm( GLvector4f *obj_ptr, + GLvector3f *norm_ptr, + GLfloat coord[][4], + GLuint *flags, + GLuint dimension, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*obj)[4] = obj_ptr->data; + GLfloat (*normal)[3] = norm_ptr->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat du[4], dv[4]; + + ASSIGN_4V(obj[i], 0,0,0,1); + _math_de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension, + map->Uorder, map->Vorder); + + CROSS3(normal[i], du, dv); + NORMALIZE_3FV(normal[i]); + } + + obj_ptr->size = MAX2(obj_ptr->size, dimension); + obj_ptr->flags |= dirty_flags[dimension]; +} + + +static void eval2_4f( GLvector4f *dest, + GLfloat coord[][4], + const GLuint *flags, + GLuint dimension, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*to)[4] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + _math_horner_bezier_surf(map->Points, to[i], u, v, dimension, + map->Uorder, map->Vorder); + } + + dest->size = MAX2(dest->size, dimension); + dest->flags |= dirty_flags[dimension]; +} + + +static void eval2_norm( GLvector3f *dest, + GLfloat coord[][4], + GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLfloat (*to)[3] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + _math_horner_bezier_surf(map->Points, to[i], u, v, 3, + map->Uorder, map->Vorder); + } + +} + + +static void eval2_1ui( GLvector1ui *dest, + GLfloat coord[][4], + const GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLuint *to = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat tmp; + _math_horner_bezier_surf(map->Points, &tmp, u, v, 1, + map->Uorder, map->Vorder); + + to[i] = (GLuint) (GLint) tmp; + } +} + + + +static void eval2_color( GLvector4ub *dest, + GLfloat coord[][4], + GLuint *flags, + struct gl_2d_map *map ) +{ + const GLfloat u1 = map->u1; + const GLfloat du = map->du; + const GLfloat v1 = map->v1; + const GLfloat dv = map->dv; + GLubyte (*to)[4] = dest->data; + GLuint i; + + for (i = 0 ; !(flags[i] & VERT_END_VB) ; i++) + if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) { + GLfloat u = (coord[i][0] - u1) * du; + GLfloat v = (coord[i][1] - v1) * dv; + GLfloat fcolor[4]; + _math_horner_bezier_surf(map->Points, fcolor, u, v, 4, + map->Uorder, map->Vorder); + FLOAT_RGBA_TO_CHAN_RGBA(to[i], fcolor); + } + +} + + + +static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count ) +{ + MEMCPY( to, from, count * sizeof(to[0])); +} + +static void copy_3f( GLfloat to[][3], GLfloat from[][3], GLuint count ) +{ + MEMCPY( to, from, (count) * sizeof(to[0])); +} + +static void copy_4ub( GLubyte to[][4], GLubyte from[][4], GLuint count ) +{ + MEMCPY( to, from, (count) * sizeof(to[0])); +} + +static void copy_1ui( GLuint to[], GLuint from[], GLuint count ) +{ + MEMCPY( to, from, (count) * sizeof(to[0])); +} + + + +/* Translate eval enabled flags to VERT_* flags. + */ +static void update_eval( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint eval1 = 0, eval2 = 0; + + if (ctx->Eval.Map1Index) + eval1 |= VERT_INDEX; + + if (ctx->Eval.Map2Index) + eval2 |= VERT_INDEX; + + if (ctx->Eval.Map1Color4) + eval1 |= VERT_RGBA; + + if (ctx->Eval.Map2Color4) + eval2 |= VERT_RGBA; + + if (ctx->Eval.Map1Normal) + eval1 |= VERT_NORM; + + if (ctx->Eval.Map2Normal) + eval2 |= VERT_NORM; + + if (ctx->Eval.Map1TextureCoord4 || + ctx->Eval.Map1TextureCoord3 || + ctx->Eval.Map1TextureCoord2 || + ctx->Eval.Map1TextureCoord1) + eval1 |= VERT_TEX0; + + if (ctx->Eval.Map2TextureCoord4 || + ctx->Eval.Map2TextureCoord3 || + ctx->Eval.Map2TextureCoord2 || + ctx->Eval.Map2TextureCoord1) + eval2 |= VERT_TEX0; + + if (ctx->Eval.Map1Vertex4) + eval1 |= VERT_OBJ_234; + + if (ctx->Eval.Map1Vertex3) + eval1 |= VERT_OBJ_23; + + if (ctx->Eval.Map2Vertex4) { + if (ctx->Eval.AutoNormal) + eval2 |= VERT_OBJ_234 | VERT_NORM; + else + eval2 |= VERT_OBJ_234; + } + else if (ctx->Eval.Map2Vertex3) { + if (ctx->Eval.AutoNormal) + eval2 |= VERT_OBJ_23 | VERT_NORM; + else + eval2 |= VERT_OBJ_23; + } + + tnl->eval.EvalMap1Flags = eval1; + tnl->eval.EvalMap2Flags = eval2; + tnl->eval.EvalNewState = 0; +} + + +/* This looks a lot like a pipeline stage, but for various reasons is + * better handled outside the pipeline, and considered the final stage + * of fixing up an immediate struct for execution. + * + * Really want to cache the results of this function in display lists, + * at least for EvalMesh commands. + */ +void _tnl_eval_vb( GLcontext *ctx, + GLfloat (*coord)[4], + GLuint orflag, + GLuint andflag ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_arrays *tmp = &tnl->imm_inputs; + struct tnl_eval_store *store = &tnl->eval; + GLuint *flags = tnl->vb.Flag; + GLuint count = tnl->vb.Count; + GLuint any_eval1 = orflag & (VERT_EVAL_C1|VERT_EVAL_P1); + GLuint any_eval2 = orflag & (VERT_EVAL_C2|VERT_EVAL_P2); + GLuint all_eval = andflag & VERT_EVAL_ANY; /* may have false negatives */ + GLuint req = 0; + GLuint purge_flags = 0; + + if (tnl->eval.EvalNewState & _NEW_EVAL) + update_eval( ctx ); + + /* Handle the degenerate cases. + */ + if (any_eval1 && !ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) + purge_flags = (VERT_EVAL_P1|VERT_EVAL_C1); + + if (any_eval2 && !ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) + purge_flags |= (VERT_EVAL_P1|VERT_EVAL_C1); + + if (any_eval1) + req |= tnl->pipeline.inputs & tnl->eval.EvalMap1Flags; + + if (any_eval2) + req |= tnl->pipeline.inputs & tnl->eval.EvalMap2Flags; + + + /* Translate points into coords. Use store->Obj to hold the + * new data. + */ + if (any_eval1 && (orflag & VERT_EVAL_P1)) + { + eval_points1( store->Obj, coord, flags, + ctx->Eval.MapGrid1du, + ctx->Eval.MapGrid1u1); + + coord = store->Obj; + } + + if (any_eval2 && (orflag & VERT_EVAL_P2)) + { + eval_points2( store->Obj, coord, flags, + ctx->Eval.MapGrid2du, + ctx->Eval.MapGrid2u1, + ctx->Eval.MapGrid2dv, + ctx->Eval.MapGrid2v1 ); + + coord = store->Obj; + } + + + /* Perform the evaluations on active data elements. + */ + if (req & VERT_INDEX) + { + if (!all_eval) + copy_1ui( store->Index, tmp->Index.data, count ); + + tmp->Index.data = store->Index; + tmp->Index.start = store->Index; + + if (ctx->Eval.Map1Index && any_eval1) + eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index ); + + if (ctx->Eval.Map2Index && any_eval2) + eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index ); + + } + + if (req & VERT_RGBA) + { + if (!all_eval) + copy_4ub( store->Color, tmp->Color.data, count ); + + tmp->Color.data = store->Color; + tmp->Color.start = (GLubyte *)store->Color; + + if (ctx->Eval.Map1Color4 && any_eval1) + eval1_color( &tmp->Color, coord, flags, &ctx->EvalMap.Map1Color4 ); + + if (ctx->Eval.Map2Color4 && any_eval2) + eval2_color( &tmp->Color, coord, flags, &ctx->EvalMap.Map2Color4 ); + } + + + if (req & VERT_TEX(0)) + { + if (!all_eval) + copy_4f( store->TexCoord, tmp->TexCoord[0].data, count ); + else + tmp->TexCoord[0].size = 0; + + tmp->TexCoord[0].data = store->TexCoord; + tmp->TexCoord[0].start = (GLfloat *)store->TexCoord; + + if (any_eval1) { + if (ctx->Eval.Map1TextureCoord4) { + eval1_4f( &tmp->TexCoord[0], coord, flags, 4, + &ctx->EvalMap.Map1Texture4 ); + } + else if (ctx->Eval.Map1TextureCoord3) { + eval1_4f( &tmp->TexCoord[0], coord, flags, 3, + &ctx->EvalMap.Map1Texture3 ); + } + else if (ctx->Eval.Map1TextureCoord2) { + eval1_4f( &tmp->TexCoord[0], coord, flags, 2, + &ctx->EvalMap.Map1Texture2 ); + } + else if (ctx->Eval.Map1TextureCoord1) { + eval1_4f( &tmp->TexCoord[0], coord, flags, 1, + &ctx->EvalMap.Map1Texture1 ); + } + } + + if (any_eval2) { + if (ctx->Eval.Map2TextureCoord4) { + eval2_4f( &tmp->TexCoord[0], coord, flags, 4, + &ctx->EvalMap.Map2Texture4 ); + } + else if (ctx->Eval.Map2TextureCoord3) { + eval2_4f( &tmp->TexCoord[0], coord, flags, 3, + &ctx->EvalMap.Map2Texture3 ); + } + else if (ctx->Eval.Map2TextureCoord2) { + eval2_4f( &tmp->TexCoord[0], coord, flags, 2, + &ctx->EvalMap.Map2Texture2 ); + } + else if (ctx->Eval.Map2TextureCoord1) { + eval2_4f( &tmp->TexCoord[0], coord, flags, 1, + &ctx->EvalMap.Map2Texture1 ); + } + } + } + + + if (req & VERT_NORM) + { + if (!all_eval) + copy_3f( store->Normal, tmp->Normal.data, count ); + + tmp->Normal.data = store->Normal; + tmp->Normal.start = (GLfloat *)store->Normal; + + if (ctx->Eval.Map1Normal && any_eval1) + eval1_norm( &tmp->Normal, coord, flags, + &ctx->EvalMap.Map1Normal ); + + if (ctx->Eval.Map2Normal && any_eval2) + eval2_norm( &tmp->Normal, coord, flags, + &ctx->EvalMap.Map2Normal ); + } + + + + /* In the AutoNormal case, the copy and assignment of tmp->NormalPtr + * are done above. + */ + if (req & VERT_OBJ) + { + if (!all_eval) { + copy_4f( store->Obj, tmp->Obj.data, count ); + } else + tmp->Obj.size = 0; + + tmp->Obj.data = store->Obj; + tmp->Obj.start = (GLfloat *)store->Obj; + + if (any_eval1) { + if (ctx->Eval.Map1Vertex4) { + eval1_4f( &tmp->Obj, coord, flags, 4, + &ctx->EvalMap.Map1Vertex4 ); + } + else if (ctx->Eval.Map1Vertex3) { + eval1_4f( &tmp->Obj, coord, flags, 3, + &ctx->EvalMap.Map1Vertex3 ); + } + } + + if (any_eval2) { + if (ctx->Eval.Map2Vertex4) + { + if (ctx->Eval.AutoNormal && (req & VERT_NORM)) + eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4, + &ctx->EvalMap.Map2Vertex4 ); + else + eval2_4f( &tmp->Obj, coord, flags, 4, + &ctx->EvalMap.Map2Vertex4 ); + } + else if (ctx->Eval.Map2Vertex3) + { + if (ctx->Eval.AutoNormal && (req & VERT_NORM)) + eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3, + &ctx->EvalMap.Map2Vertex3 ); + else + eval2_4f( &tmp->Obj, coord, flags, 3, + &ctx->EvalMap.Map2Vertex3 ); + } + } + } + + + { + GLuint i; + copy_1ui( store->Flag, flags, count ); + tnl->vb.Flag = store->Flag; + + /* This is overkill, but correct as fixup will have copied the + * values to all vertices in the VB - we may be falsely stating + * that some repeated values are new, but doing so is fairly + * harmless. + */ + for (i = 0 ; i < count ; i++) + store->Flag[i] |= req; + } +} + + + + + + + |