Modified Files:
[mesa.git] / src / mesa / tnl / t_pipeline.c
1 /* $Id: t_pipeline.c,v 1.6 2000/11/27 09:05:52 joukj 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 /* Dynamic pipelines, support for CVA.
28 * Copyright (C) 1999 Keith Whitwell.
29 */
30
31 #include "glheader.h"
32 #include "context.h"
33 #include "mem.h"
34 #include "mmath.h"
35 #include "state.h"
36 #include "mtypes.h"
37
38 #include "math/m_translate.h"
39 #include "math/m_xform.h"
40
41 #include "t_bbox.h"
42 #include "t_clip.h"
43 #include "t_cva.h"
44 #include "t_debug.h"
45 #include "t_fog.h"
46 #include "t_light.h"
47 #include "t_pipeline.h"
48 #include "t_shade.h"
49 #include "t_stages.h"
50 #include "t_vbcull.h"
51 #include "t_vbindirect.h"
52 #include "t_vbrender.h"
53 #include "t_vbxform.h"
54
55
56
57
58
59 void _tnl_print_pipe_ops( const char *msg, GLuint flags )
60 {
61 fprintf(stderr,
62 "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
63 msg,
64 flags,
65 (flags & PIPE_OP_CVA_PREPARE) ? "cva-prepare, " : "",
66 (flags & PIPE_OP_VERT_XFORM) ? "vert-xform, " : "",
67 (flags & PIPE_OP_NORM_XFORM) ? "norm-xform, " : "",
68 (flags & PIPE_OP_LIGHT) ? "light, " : "",
69 (flags & PIPE_OP_FOG) ? "fog, " : "",
70 (flags & PIPE_OP_TEX) ? "tex-gen/tex-mat, " : "",
71 (flags & PIPE_OP_RAST_SETUP_0) ? "rast-0, " : "",
72 (flags & PIPE_OP_RAST_SETUP_1) ? "rast-1, " : "",
73 (flags & PIPE_OP_RENDER) ? "render, " : "");
74
75 }
76
77
78
79 /* Have to reset only those parts of the vb which are being recalculated.
80 */
81 void _tnl_reset_cva_vb( struct vertex_buffer *VB, GLuint stages )
82 {
83 GLcontext *ctx = VB->ctx;
84 TNLcontext *tnl = TNL_CONTEXT(ctx);
85
86 if (MESA_VERBOSE&VERBOSE_PIPELINE)
87 _tnl_print_pipe_ops( "reset cva vb", stages );
88
89 if (stages & PIPE_OP_VERT_XFORM)
90 {
91 if (VB->ClipOrMask & CLIP_USER_BIT)
92 MEMSET(VB->UserClipMask, 0, VB->Count);
93
94 VB->ClipOrMask = 0;
95 VB->ClipAndMask = CLIP_ALL_BITS;
96 VB->CullMode = 0;
97 VB->CullFlag[0] = VB->CullFlag[1] = 0;
98 VB->Culled = 0;
99 }
100
101 if (stages & PIPE_OP_NORM_XFORM) {
102 VB->NormalPtr = &tnl->CVA.v.Normal;
103 }
104
105 if (stages & PIPE_OP_LIGHT)
106 {
107 VB->ColorPtr = VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
108 VB->IndexPtr = VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
109 }
110 else if (stages & PIPE_OP_FOG)
111 {
112 if (ctx->Light.Enabled) {
113 VB->Color[0] = VB->LitColor[0];
114 VB->Color[1] = VB->LitColor[1];
115 VB->Index[0] = VB->LitIndex[0];
116 VB->Index[1] = VB->LitIndex[1];
117 } else {
118 VB->Color[0] = VB->Color[1] = &tnl->CVA.v.Color;
119 VB->Index[0] = VB->Index[1] = &tnl->CVA.v.Index;
120 }
121 VB->ColorPtr = VB->Color[0];
122 VB->IndexPtr = VB->Index[0];
123 }
124 }
125
126
127
128
129
130
131 static void pipeline_ctr( struct gl_pipeline *p, GLcontext *ctx, GLuint type )
132 {
133 GLuint i;
134 (void) ctx;
135
136 p->state_change = 0;
137 p->cva_state_change = 0;
138 p->inputs = 0;
139 p->outputs = 0;
140 p->type = type;
141 p->ops = 0;
142
143 for (i = 0 ; i < _tnl_default_nr_stages ; i++)
144 p->state_change |= _tnl_default_pipeline[i].state_change;
145 }
146
147
148 void _tnl_pipeline_init( GLcontext *ctx )
149 {
150 TNLcontext *tnl = TNL_CONTEXT(ctx);
151
152 MEMCPY( tnl->PipelineStage,
153 _tnl_default_pipeline,
154 sizeof(*_tnl_default_pipeline) * _tnl_default_nr_stages );
155
156 tnl->NrPipelineStages = _tnl_default_nr_stages;
157
158 pipeline_ctr( &tnl->CVA.elt, ctx, PIPE_IMMEDIATE);
159 pipeline_ctr( &tnl->CVA.pre, ctx, PIPE_PRECALC );
160 }
161
162
163
164 #define MINIMAL_VERT_DATA (VERT_DATA & ~VERT_EVAL_ANY)
165
166 #define VERT_CURRENT_DATA (VERT_TEX_ANY | \
167 VERT_RGBA | \
168 VERT_SPEC_RGB | \
169 VERT_FOG_COORD | \
170 VERT_INDEX | \
171 VERT_EDGE | \
172 VERT_NORM | \
173 VERT_MATERIAL)
174
175 /* Called prior to every recomputation of the CVA precalc data, except where
176 * the driver is able to calculate the pipeline unassisted.
177 */
178 static void build_full_precalc_pipeline( GLcontext *ctx )
179 {
180 TNLcontext *tnl = TNL_CONTEXT(ctx);
181 struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
182 struct gl_cva *cva = &tnl->CVA;
183 struct gl_pipeline *pre = &cva->pre;
184 struct gl_pipeline_stage **stages = pre->stages;
185 GLuint i;
186 GLuint newstate = pre->new_state;
187 GLuint changed_ops = 0;
188 GLuint oldoutputs = pre->outputs;
189 GLuint oldinputs = pre->inputs;
190 GLuint fallback = (VERT_CURRENT_DATA &
191 ~tnl->_ArraySummary);
192 GLuint changed_outputs = (tnl->_ArrayNewState |
193 (fallback & cva->orflag));
194 GLuint available = fallback | tnl->_ArrayFlags;
195
196 pre->cva_state_change = 0;
197 pre->ops = 0;
198 pre->outputs = 0;
199 pre->inputs = 0;
200 pre->forbidden_inputs = 0;
201 pre->fallback = 0;
202
203 /* KW: Disable data reuse during Mesa reorg. Make this more readable...
204 */
205 newstate = ~0;
206
207 if (tnl->_ArraySummary & VERT_ELT)
208 cva->orflag &= VERT_MATERIAL;
209
210 cva->orflag &= ~(tnl->_ArraySummary & ~VERT_OBJ_ANY);
211 available &= ~cva->orflag;
212
213 pre->outputs = available;
214 pre->inputs = available;
215
216 if (MESA_VERBOSE & VERBOSE_PIPELINE) {
217 fprintf(stderr, ": Rebuild pipeline\n");
218 _tnl_print_vert_flags("orflag", cva->orflag);
219 }
220
221
222
223 /* If something changes in the pipeline, tag all subsequent stages
224 * using this value for recalcuation. Also used to build the full
225 * pipeline by setting newstate and newinputs to ~0.
226 *
227 * Because all intermediate values are buffered, the new inputs
228 * are enough to fully specify what needs to be calculated, and a
229 * single pass identifies all stages requiring recalculation.
230 */
231 for (i = 0 ; i < tnl->NrPipelineStages ; i++)
232 {
233 pipeline[i].check(ctx, &pipeline[i]);
234
235 if (pipeline[i].type & PIPE_PRECALC)
236 {
237 if ((newstate & pipeline[i].cva_state_change) ||
238 (changed_outputs & pipeline[i].inputs) ||
239 !pipeline[i].inputs)
240 {
241 changed_ops |= pipeline[i].ops;
242 changed_outputs |= pipeline[i].outputs;
243 pipeline[i].active &= ~PIPE_PRECALC;
244
245 if ((pipeline[i].inputs & ~available) == 0 &&
246 (pipeline[i].ops & pre->ops) == 0)
247 {
248 pipeline[i].active |= PIPE_PRECALC;
249 *stages++ = &pipeline[i];
250 }
251 }
252
253 /* Incompatible with multiple stages structs implementing
254 * the same stage.
255 */
256 available &= ~pipeline[i].outputs;
257 pre->outputs &= ~pipeline[i].outputs;
258
259 if (pipeline[i].active & PIPE_PRECALC) {
260 pre->ops |= pipeline[i].ops;
261 pre->outputs |= pipeline[i].outputs;
262 available |= pipeline[i].outputs;
263 pre->forbidden_inputs |= pipeline[i].pre_forbidden_inputs;
264 }
265 }
266 else if (pipeline[i].active & PIPE_PRECALC)
267 {
268 pipeline[i].active &= ~PIPE_PRECALC;
269 changed_outputs |= pipeline[i].outputs;
270 changed_ops |= pipeline[i].ops;
271 }
272 }
273
274 *stages = 0;
275
276 pre->new_outputs = pre->outputs & (changed_outputs | ~oldoutputs);
277 pre->new_inputs = pre->inputs & ~oldinputs;
278 pre->fallback = pre->inputs & fallback;
279 pre->forbidden_inputs |= pre->inputs & fallback;
280
281 pre->changed_ops = changed_ops;
282 }
283
284 void _tnl_build_precalc_pipeline( GLcontext *ctx )
285 {
286 TNLcontext *tnl = TNL_CONTEXT(ctx);
287 struct gl_pipeline *pre = &tnl->CVA.pre;
288 struct gl_pipeline *elt = &tnl->CVA.elt;
289
290 if (!ctx->Driver.BuildPrecalcPipeline ||
291 !ctx->Driver.BuildPrecalcPipeline( ctx ))
292 build_full_precalc_pipeline( ctx );
293
294 pre->data_valid = 0;
295 pre->pipeline_valid = 1;
296 elt->pipeline_valid = 0;
297
298 tnl->CVA.orflag = 0;
299
300 if (MESA_VERBOSE&VERBOSE_PIPELINE)
301 _tnl_print_pipeline( ctx, pre );
302 }
303
304
305 static void build_full_immediate_pipeline( GLcontext *ctx )
306 {
307 TNLcontext *tnl = TNL_CONTEXT(ctx);
308 struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
309 struct gl_cva *cva = &tnl->CVA;
310 struct gl_pipeline *pre = &cva->pre;
311 struct gl_pipeline *elt = &cva->elt;
312 struct gl_pipeline_stage **stages = elt->stages;
313 GLuint i;
314 GLuint newstate = elt->new_state;
315 GLuint active_ops = 0;
316 GLuint available = cva->orflag | MINIMAL_VERT_DATA;
317 GLuint generated = 0;
318 GLuint is_elt = 0;
319
320 if (pre->data_valid && tnl->CompileCVAFlag) {
321 is_elt = 1;
322 active_ops = cva->pre.ops;
323 available |= pre->outputs | VERT_PRECALC_DATA;
324 }
325
326
327 elt->outputs = 0; /* not used */
328 elt->inputs = 0;
329
330 for (i = 0 ; i < tnl->NrPipelineStages ; i++) {
331 pipeline[i].active &= ~PIPE_IMMEDIATE;
332
333 if ((pipeline[i].state_change & newstate) ||
334 (pipeline[i].elt_forbidden_inputs & available))
335 {
336 pipeline[i].check(ctx, &pipeline[i]);
337 }
338
339 if ((pipeline[i].type & PIPE_IMMEDIATE) &&
340 (pipeline[i].ops & active_ops) == 0 &&
341 (pipeline[i].elt_forbidden_inputs & available) == 0
342 )
343 {
344 if (pipeline[i].inputs & ~available)
345 elt->forbidden_inputs |= pipeline[i].inputs & ~available;
346 else
347 {
348 elt->inputs |= pipeline[i].inputs & ~generated;
349 elt->forbidden_inputs |= pipeline[i].elt_forbidden_inputs;
350 pipeline[i].active |= PIPE_IMMEDIATE;
351 *stages++ = &pipeline[i];
352 generated |= pipeline[i].outputs;
353 available |= pipeline[i].outputs;
354 active_ops |= pipeline[i].ops;
355 }
356 }
357 }
358
359 *stages = 0;
360
361 elt->copy_transformed_data = 1;
362 elt->replay_copied_vertices = 0;
363
364 if (is_elt) {
365 cva->merge = elt->inputs & pre->outputs;
366 elt->ops = active_ops & ~pre->ops;
367 }
368 }
369
370
371
372 void _tnl_build_immediate_pipeline( GLcontext *ctx )
373 {
374 TNLcontext *tnl = TNL_CONTEXT(ctx);
375 struct gl_pipeline *elt = &tnl->CVA.elt;
376
377 if (!ctx->Driver.BuildEltPipeline ||
378 !ctx->Driver.BuildEltPipeline( ctx )) {
379 build_full_immediate_pipeline( ctx );
380 }
381
382 elt->pipeline_valid = 1;
383 tnl->CVA.orflag = 0;
384
385 if (MESA_VERBOSE&VERBOSE_PIPELINE)
386 _tnl_print_pipeline( ctx, elt );
387 }
388
389 #define INTERESTED ~0
390
391 void _tnl_update_pipelines( GLcontext *ctx )
392 {
393 TNLcontext *tnl = TNL_CONTEXT(ctx);
394 GLuint newstate = ctx->NewState;
395 struct gl_cva *cva = &tnl->CVA;
396
397 newstate &= INTERESTED;
398
399 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_STATE))
400 gl_print_enable_flags("enabled", ctx->_Enabled);
401
402 if (newstate ||
403 cva->lock_changed ||
404 cva->orflag != cva->last_orflag ||
405 tnl->_ArrayFlags != cva->last_array_flags)
406 {
407 GLuint j;
408 GLuint flags = VERT_WIN;
409
410 if (ctx->Visual.RGBAflag) {
411 flags |= VERT_RGBA;
412 if (ctx->_TriangleCaps && DD_SEPERATE_SPECULAR)
413 flags |= VERT_SPEC_RGB;
414 } else
415 flags |= VERT_INDEX;
416
417 for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) {
418 if (ctx->Texture.Unit[j]._ReallyEnabled)
419 flags |= VERT_TEX(j);
420 }
421
422 if (ctx->Polygon._Unfilled)
423 flags |= VERT_EDGE;
424
425 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
426 flags |= VERT_FOG_COORD;
427
428 if (ctx->RenderMode==GL_FEEDBACK) {
429 flags = (VERT_WIN | VERT_RGBA | VERT_INDEX | VERT_NORM |
430 VERT_EDGE | VERT_TEX_ANY);
431 }
432
433 tnl->_RenderFlags = flags;
434
435 cva->elt.new_state |= newstate;
436 cva->elt.pipeline_valid = 0;
437
438 cva->pre.new_state |= newstate;
439 cva->pre.forbidden_inputs = 0;
440 cva->pre.pipeline_valid = 0;
441 cva->lock_changed = 0;
442 }
443
444 if (tnl->_ArrayNewState != cva->last_array_new_state)
445 cva->pre.pipeline_valid = 0;
446
447 cva->pre.data_valid = 0;
448 cva->last_array_new_state = tnl->_ArrayNewState;
449 cva->last_orflag = cva->orflag;
450 cva->last_array_flags = tnl->_ArrayFlags;
451 }
452
453 void _tnl_run_pipeline( struct vertex_buffer *VB )
454 {
455 struct gl_pipeline *pipe = VB->pipeline;
456 struct gl_pipeline_stage **stages = pipe->stages;
457 unsigned short x;
458
459 pipe->data_valid = 1; /* optimized stages might want to reset this. */
460
461 if (0) _tnl_print_pipeline( VB->ctx, pipe );
462
463 START_FAST_MATH(x);
464
465 for ( VB->Culled = 0; *stages && !VB->Culled ; stages++ )
466 (*stages)->run( VB );
467
468 END_FAST_MATH(x);
469
470 pipe->new_state = 0;
471 }
472