1824fc3fa9ec73939209d5b842f9016c46d7b0c4
[mesa.git] / src / mesa / tnl / t_eval_api.c
1 /* $Id: t_eval_api.c,v 1.13 2003/03/01 01:50:26 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 5.1
6 *
7 * Copyright (C) 1999-2003 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 - original code
28 * Brian Paul - vertex program updates
29 */
30
31
32 #include "glheader.h"
33 #include "colormac.h"
34 #include "context.h"
35 #include "macros.h"
36 #include "imports.h"
37 #include "mtypes.h"
38 #include "math/m_eval.h"
39
40 #include "t_eval_api.h"
41 #include "t_imm_api.h"
42 #include "t_imm_alloc.h"
43 #include "t_imm_exec.h"
44
45
46 /* KW: If are compiling, we don't know whether eval will produce a
47 * vertex when it is run in the future. If this is pure immediate
48 * mode, eval is a noop if neither vertex map is enabled.
49 *
50 * Thus we need to have a check in the display list code or
51 * elsewhere for eval(1,2) vertices in the case where
52 * map(1,2)_vertex is disabled, and to purge those vertices from
53 * the vb.
54 */
55 void
56 _tnl_exec_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
57 {
58 GET_CURRENT_CONTEXT(ctx);
59 GLint i;
60 GLfloat u, du;
61 GLenum prim;
62 ASSERT_OUTSIDE_BEGIN_END(ctx);
63
64 if (MESA_VERBOSE & VERBOSE_API)
65 _mesa_debug(ctx, "glEvalMesh1()");
66
67 switch (mode) {
68 case GL_POINT:
69 prim = GL_POINTS;
70 break;
71 case GL_LINE:
72 prim = GL_LINE_STRIP;
73 break;
74 default:
75 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
76 return;
77 }
78
79 /* No effect if vertex maps disabled.
80 */
81 if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3 &&
82 (!ctx->VertexProgram.Enabled || !ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]))
83 return;
84
85 du = ctx->Eval.MapGrid1du;
86 u = ctx->Eval.MapGrid1u1 + i1 * du;
87
88 /* Need to turn off compilation -- this is already saved, and the
89 * coordinates generated and the test above depend on state that
90 * may change before the list is executed.
91 *
92 * TODO: Anaylse display lists to determine if this state is
93 * constant.
94 *
95 * State to watch:
96 * - enabled maps
97 * - map state for each enabled map, including control points
98 * - grid state
99 *
100 * Could alternatively cache individual maps in arrays, rather than
101 * building immediates.
102 */
103 {
104 GLboolean compiling = ctx->CompileFlag;
105 TNLcontext *tnl = TNL_CONTEXT(ctx);
106 struct immediate *im = TNL_CURRENT_IM(ctx);
107 GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p);
108
109 NotifyBegin = tnl->Driver.NotifyBegin;
110 tnl->Driver.NotifyBegin = 0;
111
112 if (compiling) {
113 struct immediate *tmp = _tnl_alloc_immediate( ctx );
114 FLUSH_VERTICES( ctx, 0 );
115 SET_IMMEDIATE( ctx, tmp );
116 TNL_CURRENT_IM(ctx)->ref_count++;
117 ctx->CompileFlag = GL_FALSE;
118 }
119
120 _tnl_Begin( prim );
121 for (i=i1;i<=i2;i++,u+=du) {
122 _tnl_eval_coord1f( ctx, u );
123 }
124 _tnl_end(ctx);
125
126 /* Need this for replay *and* compile:
127 */
128 FLUSH_VERTICES( ctx, 0 );
129 tnl->Driver.NotifyBegin = NotifyBegin;
130
131 if (compiling) {
132 TNL_CURRENT_IM(ctx)->ref_count--;
133 ASSERT( TNL_CURRENT_IM(ctx)->ref_count == 0 );
134 _tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
135 SET_IMMEDIATE( ctx, im );
136 ctx->CompileFlag = GL_TRUE;
137 }
138 }
139 }
140
141
142
143 void
144 _tnl_exec_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
145 {
146 GET_CURRENT_CONTEXT(ctx);
147 GLint i, j;
148 GLfloat u, du, v, dv, v1, u1;
149 ASSERT_OUTSIDE_BEGIN_END(ctx);
150
151 if (MESA_VERBOSE & VERBOSE_API)
152 _mesa_debug(ctx, "glEvalMesh2()");
153
154 /* No effect if vertex maps disabled.
155 */
156 if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3 &&
157 (!ctx->VertexProgram.Enabled || !ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]))
158 return;
159
160 du = ctx->Eval.MapGrid2du;
161 dv = ctx->Eval.MapGrid2dv;
162 v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
163 u1 = ctx->Eval.MapGrid2u1 + i1 * du;
164
165 /* Need to turn off compilation -- this is already saved, and the
166 * coordinates generated and the test above depend on state that
167 * may change before the list is executed.
168 */
169 {
170 GLboolean compiling = ctx->CompileFlag;
171 struct immediate *im = TNL_CURRENT_IM(ctx);
172 TNLcontext *tnl = TNL_CONTEXT(ctx);
173 GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p);
174
175 NotifyBegin = tnl->Driver.NotifyBegin;
176 tnl->Driver.NotifyBegin = 0;
177
178 if (compiling) {
179 struct immediate *tmp = _tnl_alloc_immediate( ctx );
180 FLUSH_VERTICES( ctx, 0 );
181 SET_IMMEDIATE( ctx, tmp );
182 TNL_CURRENT_IM(ctx)->ref_count++;
183 ctx->CompileFlag = GL_FALSE;
184 }
185
186 switch (mode) {
187 case GL_POINT:
188 _tnl_Begin( GL_POINTS );
189 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
190 for (u=u1,i=i1;i<=i2;i++,u+=du) {
191 _tnl_eval_coord2f( ctx, u, v );
192 }
193 }
194 _tnl_end(ctx);
195 break;
196 case GL_LINE:
197 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
198 _tnl_Begin( GL_LINE_STRIP );
199 for (u=u1,i=i1;i<=i2;i++,u+=du) {
200 _tnl_eval_coord2f( ctx, u, v );
201 }
202 _tnl_end(ctx);
203 }
204 for (u=u1,i=i1;i<=i2;i++,u+=du) {
205 _tnl_Begin( GL_LINE_STRIP );
206 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
207 _tnl_eval_coord2f( ctx, u, v );
208 }
209 _tnl_end(ctx);
210 }
211 break;
212 case GL_FILL:
213 for (v=v1,j=j1;j<j2;j++,v+=dv) {
214 _tnl_Begin( GL_TRIANGLE_STRIP );
215 for (u=u1,i=i1;i<=i2;i++,u+=du) {
216 _tnl_eval_coord2f( ctx, u, v );
217 _tnl_eval_coord2f( ctx, u, v+dv );
218 }
219 _tnl_end(ctx);
220 }
221 break;
222 default:
223 _mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
224 return;
225 }
226
227 /* Need this for replay *and* compile:
228 */
229 FLUSH_VERTICES( ctx, 0 );
230 tnl->Driver.NotifyBegin = NotifyBegin;
231
232 if (compiling) {
233 TNL_CURRENT_IM(ctx)->ref_count--;
234 _tnl_free_immediate( ctx, TNL_CURRENT_IM( ctx ) );
235 SET_IMMEDIATE( ctx, im );
236 ctx->CompileFlag = GL_TRUE;
237 }
238 }
239 }
240
241
242 void _tnl_eval_init( GLcontext *ctx )
243 {
244 GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
245 vfmt->EvalMesh1 = _tnl_exec_EvalMesh1;
246 vfmt->EvalMesh2 = _tnl_exec_EvalMesh2;
247 }