Move the transform and lighting code to two new directories
[mesa.git] / src / mesa / tnl / t_pipeline.c
1 /* $Id: t_pipeline.c,v 1.1 2000/11/16 21:05:42 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 /* 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 "types.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_fog.h"
45 #include "t_light.h"
46 #include "t_pipeline.h"
47 #include "t_shade.h"
48 #include "t_stages.h"
49 #include "t_vbcull.h"
50 #include "t_vbindirect.h"
51 #include "t_vbrender.h"
52 #include "t_vbxform.h"
53
54
55
56
57
58 void gl_print_pipe_ops( const char *msg, GLuint flags )
59 {
60 fprintf(stderr,
61 "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s\n",
62 msg,
63 flags,
64 (flags & PIPE_OP_CVA_PREPARE) ? "cva-prepare, " : "",
65 (flags & PIPE_OP_VERT_XFORM) ? "vert-xform, " : "",
66 (flags & PIPE_OP_NORM_XFORM) ? "norm-xform, " : "",
67 (flags & PIPE_OP_LIGHT) ? "light, " : "",
68 (flags & PIPE_OP_FOG) ? "fog, " : "",
69 (flags & PIPE_OP_TEX0) ? "tex-0, " : "",
70 (flags & PIPE_OP_TEX1) ? "tex-1, " : "",
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 gl_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 gl_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 < gl_default_nr_stages ; i++)
144 p->state_change |= gl_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 gl_default_pipeline,
154 sizeof(*gl_default_pipeline) * gl_default_nr_stages );
155
156 tnl->NrPipelineStages = gl_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_TEX0_4 | \
165 VERT_TEX1_4 | \
166 VERT_TEX2_4 | \
167 VERT_TEX3_4 | \
168 VERT_EVAL_ANY))
169
170 #define VERT_CURRENT_DATA (VERT_TEX0_1234 | \
171 VERT_TEX1_1234 | \
172 VERT_TEX2_1234 | \
173 VERT_TEX3_1234 | \
174 VERT_RGBA | \
175 VERT_SPEC_RGB | \
176 VERT_FOG_COORD | \
177 VERT_INDEX | \
178 VERT_EDGE | \
179 VERT_NORM | \
180 VERT_MATERIAL)
181
182 /* Called prior to every recomputation of the CVA precalc data, except where
183 * the driver is able to calculate the pipeline unassisted.
184 */
185 static void build_full_precalc_pipeline( GLcontext *ctx )
186 {
187 TNLcontext *tnl = TNL_CONTEXT(ctx);
188 struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
189 struct gl_cva *cva = &tnl->CVA;
190 struct gl_pipeline *pre = &cva->pre;
191 struct gl_pipeline_stage **stages = pre->stages;
192 GLuint i;
193 GLuint newstate = pre->new_state;
194 GLuint changed_ops = 0;
195 GLuint oldoutputs = pre->outputs;
196 GLuint oldinputs = pre->inputs;
197 GLuint fallback = (VERT_CURRENT_DATA & tnl->_CurrentFlag &
198 ~tnl->_ArraySummary);
199 GLuint changed_outputs = (tnl->_ArrayNewState |
200 (fallback & cva->orflag));
201 GLuint available = fallback | tnl->_ArrayFlags;
202
203 pre->cva_state_change = 0;
204 pre->ops = 0;
205 pre->outputs = 0;
206 pre->inputs = 0;
207 pre->forbidden_inputs = 0;
208 pre->fallback = 0;
209
210 /* KW: Disable data reuse during Mesa reorg. Make this more readable...
211 */
212 newstate = ~0;
213
214 if (tnl->_ArraySummary & VERT_ELT)
215 cva->orflag &= VERT_MATERIAL;
216
217 cva->orflag &= ~(tnl->_ArraySummary & ~VERT_OBJ_ANY);
218 available &= ~cva->orflag;
219
220 pre->outputs = available;
221 pre->inputs = available;
222
223 if (MESA_VERBOSE & VERBOSE_PIPELINE) {
224 fprintf(stderr, ": Rebuild pipeline\n");
225 gl_print_vert_flags("orflag", cva->orflag);
226 }
227
228
229
230 /* If something changes in the pipeline, tag all subsequent stages
231 * using this value for recalcuation. Also used to build the full
232 * pipeline by setting newstate and newinputs to ~0.
233 *
234 * Because all intermediate values are buffered, the new inputs
235 * are enough to fully specify what needs to be calculated, and a
236 * single pass identifies all stages requiring recalculation.
237 */
238 for (i = 0 ; i < tnl->NrPipelineStages ; i++)
239 {
240 pipeline[i].check(ctx, &pipeline[i]);
241
242 if (pipeline[i].type & PIPE_PRECALC)
243 {
244 if ((newstate & pipeline[i].cva_state_change) ||
245 (changed_outputs & pipeline[i].inputs) ||
246 !pipeline[i].inputs)
247 {
248 changed_ops |= pipeline[i].ops;
249 changed_outputs |= pipeline[i].outputs;
250 pipeline[i].active &= ~PIPE_PRECALC;
251
252 if ((pipeline[i].inputs & ~available) == 0 &&
253 (pipeline[i].ops & pre->ops) == 0)
254 {
255 pipeline[i].active |= PIPE_PRECALC;
256 *stages++ = &pipeline[i];
257 }
258 }
259
260 /* Incompatible with multiple stages structs implementing
261 * the same stage.
262 */
263 available &= ~pipeline[i].outputs;
264 pre->outputs &= ~pipeline[i].outputs;
265
266 if (pipeline[i].active & PIPE_PRECALC) {
267 pre->ops |= pipeline[i].ops;
268 pre->outputs |= pipeline[i].outputs;
269 available |= pipeline[i].outputs;
270 pre->forbidden_inputs |= pipeline[i].pre_forbidden_inputs;
271 }
272 }
273 else if (pipeline[i].active & PIPE_PRECALC)
274 {
275 pipeline[i].active &= ~PIPE_PRECALC;
276 changed_outputs |= pipeline[i].outputs;
277 changed_ops |= pipeline[i].ops;
278 }
279 }
280
281 *stages = 0;
282
283 pre->new_outputs = pre->outputs & (changed_outputs | ~oldoutputs);
284 pre->new_inputs = pre->inputs & ~oldinputs;
285 pre->fallback = pre->inputs & fallback;
286 pre->forbidden_inputs |= pre->inputs & fallback;
287
288 pre->changed_ops = changed_ops;
289 }
290
291 void gl_build_precalc_pipeline( GLcontext *ctx )
292 {
293 TNLcontext *tnl = TNL_CONTEXT(ctx);
294 struct gl_pipeline *pre = &tnl->CVA.pre;
295 struct gl_pipeline *elt = &tnl->CVA.elt;
296
297 if (!ctx->Driver.BuildPrecalcPipeline ||
298 !ctx->Driver.BuildPrecalcPipeline( ctx ))
299 build_full_precalc_pipeline( ctx );
300
301 pre->data_valid = 0;
302 pre->pipeline_valid = 1;
303 elt->pipeline_valid = 0;
304
305 tnl->CVA.orflag = 0;
306
307 if (MESA_VERBOSE&VERBOSE_PIPELINE)
308 gl_print_pipeline( ctx, pre );
309 }
310
311
312 static void build_full_immediate_pipeline( GLcontext *ctx )
313 {
314 TNLcontext *tnl = TNL_CONTEXT(ctx);
315 struct gl_pipeline_stage *pipeline = tnl->PipelineStage;
316 struct gl_cva *cva = &tnl->CVA;
317 struct gl_pipeline *pre = &cva->pre;
318 struct gl_pipeline *elt = &cva->elt;
319 struct gl_pipeline_stage **stages = elt->stages;
320 GLuint i;
321 GLuint newstate = elt->new_state;
322 GLuint active_ops = 0;
323 GLuint available = cva->orflag | MINIMAL_VERT_DATA;
324 GLuint generated = 0;
325 GLuint is_elt = 0;
326
327 if (pre->data_valid && tnl->CompileCVAFlag) {
328 is_elt = 1;
329 active_ops = cva->pre.ops;
330 available |= pre->outputs | VERT_PRECALC_DATA;
331 }
332
333
334 elt->outputs = 0; /* not used */
335 elt->inputs = 0;
336
337 for (i = 0 ; i < tnl->NrPipelineStages ; i++) {
338 pipeline[i].active &= ~PIPE_IMMEDIATE;
339
340 if ((pipeline[i].state_change & newstate) ||
341 (pipeline[i].elt_forbidden_inputs & available))
342 {
343 pipeline[i].check(ctx, &pipeline[i]);
344 }
345
346 if ((pipeline[i].type & PIPE_IMMEDIATE) &&
347 (pipeline[i].ops & active_ops) == 0 &&
348 (pipeline[i].elt_forbidden_inputs & available) == 0
349 )
350 {
351 if (pipeline[i].inputs & ~available)
352 elt->forbidden_inputs |= pipeline[i].inputs & ~available;
353 else
354 {
355 elt->inputs |= pipeline[i].inputs & ~generated;
356 elt->forbidden_inputs |= pipeline[i].elt_forbidden_inputs;
357 pipeline[i].active |= PIPE_IMMEDIATE;
358 *stages++ = &pipeline[i];
359 generated |= pipeline[i].outputs;
360 available |= pipeline[i].outputs;
361 active_ops |= pipeline[i].ops;
362 }
363 }
364 }
365
366 *stages = 0;
367
368 elt->copy_transformed_data = 1;
369 elt->replay_copied_vertices = 0;
370
371 if (is_elt) {
372 cva->merge = elt->inputs & pre->outputs;
373 elt->ops = active_ops & ~pre->ops;
374 }
375 }
376
377
378
379 void gl_build_immediate_pipeline( GLcontext *ctx )
380 {
381 TNLcontext *tnl = TNL_CONTEXT(ctx);
382 struct gl_pipeline *elt = &tnl->CVA.elt;
383
384 if (!ctx->Driver.BuildEltPipeline ||
385 !ctx->Driver.BuildEltPipeline( ctx )) {
386 build_full_immediate_pipeline( ctx );
387 }
388
389 elt->pipeline_valid = 1;
390 tnl->CVA.orflag = 0;
391
392 if (MESA_VERBOSE&VERBOSE_PIPELINE)
393 gl_print_pipeline( ctx, elt );
394 }
395
396 #define INTERESTED ~0
397
398 void gl_update_pipelines( GLcontext *ctx )
399 {
400 TNLcontext *tnl = TNL_CONTEXT(ctx);
401 GLuint newstate = ctx->NewState;
402 struct gl_cva *cva = &tnl->CVA;
403
404 newstate &= INTERESTED;
405
406 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_STATE))
407 gl_print_enable_flags("enabled", ctx->_Enabled);
408
409 if (newstate ||
410 cva->lock_changed ||
411 cva->orflag != cva->last_orflag ||
412 tnl->_ArrayFlags != cva->last_array_flags)
413 {
414 GLuint flags = VERT_WIN;
415
416 if (ctx->Visual.RGBAflag) {
417 flags |= VERT_RGBA;
418 if (ctx->_TriangleCaps && DD_SEPERATE_SPECULAR)
419 flags |= VERT_SPEC_RGB;
420 } else
421 flags |= VERT_INDEX;
422
423 if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY)
424 flags |= VERT_TEX0_ANY;
425
426 if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
427 flags |= VERT_TEX1_ANY;
428
429 #if MAX_TEXTURE_UNITS > 2
430 if (ctx->Texture._ReallyEnabled & TEXTURE2_ANY)
431 flags |= VERT_TEX2_ANY;
432 #endif
433 #if MAX_TEXTURE_UNITS > 3
434 if (ctx->Texture._ReallyEnabled & TEXTURE3_ANY)
435 flags |= VERT_TEX3_ANY;
436 #endif
437
438 if (ctx->Polygon._Unfilled)
439 flags |= VERT_EDGE;
440
441 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
442 flags |= VERT_FOG_COORD;
443
444 if (ctx->RenderMode==GL_FEEDBACK) {
445 flags = (VERT_WIN | VERT_RGBA | VERT_INDEX | VERT_NORM | VERT_EDGE
446 | VERT_TEX0_ANY
447 | VERT_TEX1_ANY
448 #if MAX_TEXTURE_UNITS > 2
449 | VERT_TEX2_ANY
450 #endif
451 #if MAX_TEXTURE_UNITS > 3
452 | VERT_TEX3_ANY
453 #endif
454 );
455 }
456
457 tnl->_RenderFlags = flags;
458
459 cva->elt.new_state |= newstate;
460 cva->elt.pipeline_valid = 0;
461
462 cva->pre.new_state |= newstate;
463 cva->pre.forbidden_inputs = 0;
464 cva->pre.pipeline_valid = 0;
465 cva->lock_changed = 0;
466 }
467
468 if (tnl->_ArrayNewState != cva->last_array_new_state)
469 cva->pre.pipeline_valid = 0;
470
471 cva->pre.data_valid = 0;
472 cva->last_array_new_state = tnl->_ArrayNewState;
473 cva->last_orflag = cva->orflag;
474 cva->last_array_flags = tnl->_ArrayFlags;
475 }
476
477 void gl_run_pipeline( struct vertex_buffer *VB )
478 {
479 struct gl_pipeline *pipe = VB->pipeline;
480 struct gl_pipeline_stage **stages = pipe->stages;
481 unsigned short x;
482
483 pipe->data_valid = 1; /* optimized stages might want to reset this. */
484
485 if (0) gl_print_pipeline( VB->ctx, pipe );
486
487 START_FAST_MATH(x);
488
489 for ( VB->Culled = 0; *stages && !VB->Culled ; stages++ )
490 (*stages)->run( VB );
491
492 END_FAST_MATH(x);
493
494 pipe->new_state = 0;
495 }
496