misc updates to match latest device driver changes
[mesa.git] / src / mesa / tnl / t_imm_exec.c
1 /* $Id: t_imm_exec.c,v 1.9 2001/01/24 00:04:59 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 <keithw@valinux.com>
28 */
29
30
31 #include "glheader.h"
32 #include "context.h"
33 #include "enums.h"
34 #include "dlist.h"
35 #include "macros.h"
36 #include "mem.h"
37 #include "mmath.h"
38 #include "light.h"
39 #include "state.h"
40 #include "texture.h"
41 #include "mtypes.h"
42
43 #include "math/m_matrix.h"
44 #include "math/m_xform.h"
45
46 #include "t_context.h"
47 #include "t_array_import.h"
48 #include "t_imm_alloc.h"
49 #include "t_imm_api.h"
50 #include "t_imm_debug.h"
51 #include "t_imm_dlist.h"
52 #include "t_imm_eval.h"
53 #include "t_imm_elt.h"
54 #include "t_imm_exec.h"
55 #include "t_imm_fixup.h"
56 #include "t_pipeline.h"
57
58
59
60 /* Called to initialize new buffers, and to recycle old ones.
61 */
62 void _tnl_reset_input( GLcontext *ctx,
63 GLuint start,
64 GLuint beginstate,
65 GLuint savedbeginstate )
66 {
67 struct immediate *IM = TNL_CURRENT_IM(ctx);
68
69 /* Clear the dirty part of the flag array.
70 */
71 if (start < IM->Count+2)
72 MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
73
74 IM->CopyStart = IM->Start = IM->Count = start;
75 IM->Primitive[IM->Start] = (ctx->Driver.CurrentExecPrimitive | PRIM_LAST);
76 IM->LastPrimitive = IM->Start;
77 IM->BeginState = beginstate;
78 IM->SavedBeginState = savedbeginstate;
79 IM->TexSize = 0;
80
81 IM->ArrayEltFlags = ~ctx->Array._Enabled;
82 IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
83 IM->ArrayEltFlush = !ctx->Array.LockCount;
84 }
85
86
87
88 static void copy_to_current( GLcontext *ctx, struct immediate *IM,
89 GLuint flag )
90 {
91 GLuint count = IM->LastData;
92
93 if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
94 _tnl_print_vert_flags("copy to current", flag);
95
96 if (flag & VERT_NORM)
97 COPY_3FV( ctx->Current.Normal, IM->Normal[count]);
98
99 if (flag & VERT_INDEX)
100 ctx->Current.Index = IM->Index[count];
101
102 if (flag & VERT_EDGE)
103 ctx->Current.EdgeFlag = IM->EdgeFlag[count];
104
105 if (flag & VERT_RGBA)
106 COPY_4UBV(ctx->Current.Color, IM->Color[count]);
107
108 if (flag & VERT_SPEC_RGB)
109 COPY_4UBV(ctx->Current.SecondaryColor, IM->SecondaryColor[count]);
110
111 if (flag & VERT_FOG_COORD)
112 ctx->Current.FogCoord = IM->FogCoord[count];
113
114 if (flag & VERT_TEX_ANY) {
115 GLuint i;
116 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
117 if (flag & VERT_TEX(i)) {
118 COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]);
119 }
120 }
121 }
122 }
123
124
125
126 void _tnl_compute_orflag( struct immediate *IM )
127 {
128 GLuint count = IM->Count;
129 GLuint orflag = 0;
130 GLuint andflag = ~0U;
131 GLuint i;
132
133 IM->LastData = count-1;
134
135
136 /* Compute the flags for the whole buffer.
137 */
138 for (i = IM->CopyStart ; i < count ; i++) {
139 andflag &= IM->Flag[i];
140 orflag |= IM->Flag[i];
141 }
142
143 /* It is possible there will be data in the buffer arising from
144 * calls like 'glNormal', 'glMaterial' that occur after the final
145 * glVertex, glEval, etc. Additionally, a buffer can consist of
146 * only a single glMaterial call, in which case IM->Start ==
147 * IM->Count, but the buffer is definitely not empty.
148 */
149 if (IM->Flag[i] & VERT_DATA) {
150 IM->LastData++;
151 orflag |= IM->Flag[i];
152 }
153
154 IM->Flag[IM->LastData+1] |= VERT_END_VB;
155 IM->CopyAndFlag = IM->AndFlag = andflag;
156 IM->CopyOrFlag = IM->OrFlag = orflag;
157 }
158
159
160
161
162
163 /* Note: The 'start' member of the GLvector structs is now redundant
164 * because we always re-transform copied vertices, and the vectors
165 * below are set up so that the first copied vertex (if any) appears
166 * at position zero.
167 */
168 static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
169 {
170 TNLcontext *tnl = TNL_CONTEXT(ctx);
171 struct vertex_buffer *VB = &tnl->vb;
172 struct vertex_arrays *tmp = &tnl->imm_inputs;
173 GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
174 GLuint start = IM->CopyStart;
175 GLuint count = IM->Count - start;
176
177 /* TODO: optimize the case where nothing has changed. (Just bind
178 * tmp to vb).
179 */
180
181 /* Setup constant data in the VB.
182 */
183 VB->Count = count;
184 VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
185 VB->import_data = 0;
186 VB->importable_data = 0;
187
188 /* Need an IM->FirstPrimitive?
189 */
190 VB->Primitive = IM->Primitive + IM->CopyStart;
191 VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
192 VB->FirstPrimitive = 0;
193
194 VB->Flag = IM->Flag + start;
195
196 /* TexCoordPtr's are zeroed in loop below.
197 */
198 VB->NormalPtr = 0;
199 VB->NormalLengthPtr = 0;
200 VB->FogCoordPtr = 0;
201 VB->EdgeFlag = 0;
202 VB->IndexPtr[0] = 0;
203 VB->IndexPtr[1] = 0;
204 VB->ColorPtr[0] = 0;
205 VB->ColorPtr[1] = 0;
206 VB->SecondaryColorPtr[0] = 0;
207 VB->SecondaryColorPtr[1] = 0;
208 VB->Elts = 0;
209 VB->MaterialMask = 0;
210 VB->Material = 0;
211
212 /* _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
213 /* _tnl_print_vert_flags("orflag", IM->OrFlag); */
214 /* _tnl_print_vert_flags("inputs", inputs); */
215
216 /* Setup the initial values of array pointers in the vb.
217 */
218 if (inputs & VERT_OBJ) {
219 tmp->Obj.data = IM->Obj + start;
220 tmp->Obj.start = (GLfloat *)(IM->Obj + start);
221 tmp->Obj.count = count;
222 VB->ObjPtr = &tmp->Obj;
223 if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_234)
224 tmp->Obj.size = 4;
225 else if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_23)
226 tmp->Obj.size = 3;
227 else
228 tmp->Obj.size = 2;
229 }
230
231 if (inputs & VERT_NORM) {
232 tmp->Normal.data = IM->Normal + start;
233 tmp->Normal.start = (GLfloat *)(IM->Normal + start);
234 tmp->Normal.count = count;
235 VB->NormalPtr = &tmp->Normal;
236 if (IM->NormalLengths)
237 VB->NormalLengthPtr = IM->NormalLengths + start;
238 }
239
240 if (inputs & VERT_INDEX) {
241 tmp->Index.count = count;
242 tmp->Index.data = IM->Index + start;
243 tmp->Index.start = IM->Index + start;
244 VB->IndexPtr[0] = &tmp->Index;
245 }
246
247 if (inputs & VERT_FOG_COORD) {
248 tmp->FogCoord.data = IM->FogCoord + start;
249 tmp->FogCoord.start = IM->FogCoord + start;
250 tmp->FogCoord.count = count;
251 VB->FogCoordPtr = &tmp->FogCoord;
252 }
253
254 if (inputs & VERT_SPEC_RGB) {
255 tmp->SecondaryColor.data = IM->SecondaryColor + start;
256 tmp->SecondaryColor.start = (GLchan *)(IM->SecondaryColor + start);
257 tmp->SecondaryColor.count = count;
258 VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
259 }
260
261 if (inputs & VERT_EDGE) {
262 VB->EdgeFlag = IM->EdgeFlag + start;
263 }
264
265 if (inputs & VERT_RGBA) {
266 tmp->Color.data = IM->Color + start;
267 tmp->Color.start = (GLchan *)(IM->Color + start);
268 tmp->Color.count = count;
269 VB->ColorPtr[0] = &tmp->Color;
270 }
271
272 if (inputs & VERT_TEX_ANY) {
273 GLuint i;
274 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
275 VB->TexCoordPtr[i] = 0;
276 if (inputs & VERT_TEX(i)) {
277 tmp->TexCoord[i].count = count;
278 tmp->TexCoord[i].data = IM->TexCoord[i] + start;
279 tmp->TexCoord[i].start = (GLfloat *)(IM->TexCoord[i] + start);
280 tmp->TexCoord[i].size = 2;
281 if (IM->TexSize & TEX_SIZE_3(i)) {
282 tmp->TexCoord[i].size = 3;
283 if (IM->TexSize & TEX_SIZE_4(i))
284 tmp->TexCoord[i].size = 4;
285 }
286 VB->TexCoordPtr[i] = &tmp->TexCoord[i];
287 }
288 }
289 }
290
291 if ((inputs & VERT_MATERIAL) && IM->Material) {
292 VB->MaterialMask = IM->MaterialMask + start;
293 VB->Material = IM->Material + start;
294 }
295 }
296
297
298
299
300 /* Called by exec_cassette and execute_compiled_cassette.
301 */
302 void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
303 {
304 TNLcontext *tnl = TNL_CONTEXT(ctx);
305
306 _tnl_vb_bind_immediate( ctx, IM );
307
308 if (IM->CopyOrFlag & VERT_EVAL_ANY)
309 _tnl_eval_vb( ctx,
310 IM->Obj + IM->CopyStart,
311 IM->CopyOrFlag,
312 IM->CopyAndFlag );
313
314
315 /* Invalidate all stored data before and after run:
316 */
317 tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
318 _tnl_run_pipeline( ctx );
319 tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
320
321 copy_to_current( ctx, IM, IM->OrFlag );
322 }
323
324
325
326
327 /* Called for pure, locked VERT_ELT cassettes instead of
328 * _tnl_run_cassette.
329 */
330 static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
331 {
332 TNLcontext *tnl = TNL_CONTEXT(ctx);
333 struct vertex_buffer *VB = &tnl->vb;
334
335 _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
336
337 VB->Elts = IM->Elt + IM->CopyStart;
338 VB->Primitive = IM->Primitive + IM->CopyStart;
339 VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
340 VB->FirstPrimitive = 0;
341
342 /* Run the pipeline. No input changes as a result of this action.
343 */
344 _tnl_run_pipeline( ctx );
345
346 /* Still need to update current values: (TODO - copy from VB)
347 * TODO: delay this until FlushVertices
348 */
349 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
350 _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
351 copy_to_current( ctx, IM, ctx->Array._Enabled );
352 }
353 }
354
355 /* Called for cassettes where CopyStart == Count -- no need to run the
356 * pipeline.
357 */
358 void _tnl_run_empty_cassette( GLcontext *ctx, struct immediate *IM )
359 {
360 copy_to_current( ctx, IM, IM->OrFlag );
361
362 if (IM->OrFlag & (VERT_RGBA|VERT_MATERIAL)) {
363 GLuint start = IM->CopyStart;
364
365 if (IM->OrFlag & VERT_MATERIAL)
366 gl_update_material( ctx, IM->Material[start],
367 IM->MaterialMask[start] );
368
369 if (IM->OrFlag & VERT_RGBA)
370 if (ctx->Light.ColorMaterialEnabled)
371 gl_update_color_material( ctx, ctx->Current.Color );
372
373 gl_validate_all_lighting_tables( ctx );
374 }
375 }
376
377
378 /* Called for regular vertex cassettes.
379 */
380 static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
381 {
382 if (IM->OrFlag & VERT_ELT) {
383 GLuint andflag = ~0;
384 GLuint i;
385 GLuint start = IM->FlushElt ? IM->LastPrimitive : IM->CopyStart;
386 _tnl_translate_array_elts( ctx, IM, start, IM->Count );
387
388 /* Need to recompute andflag.
389 */
390 if (IM->CopyAndFlag & VERT_ELT)
391 IM->CopyAndFlag |= ctx->Array._Enabled;
392 else {
393 for (i = IM->CopyStart ; i < IM->Count ; i++)
394 andflag &= IM->Flag[i];
395 IM->CopyAndFlag = andflag;
396 }
397 }
398
399 _tnl_fixup_input( ctx, IM );
400 /* _tnl_print_cassette( IM ); */
401 _tnl_run_cassette( ctx, IM );
402 }
403
404
405
406 /* Called for all cassettes when not compiling or playing a display
407 * list.
408 */
409 void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
410 {
411 TNLcontext *tnl = TNL_CONTEXT(ctx);
412
413 ASSERT(tnl->ExecCopySource == IM);
414
415 _tnl_compute_orflag( IM );
416
417 /* _tnl_print_cassette( IM ); */
418
419 /* Mark the last primitive:
420 */
421 IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
422 ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
423
424
425 if (tnl->pipeline.build_state_changes)
426 _tnl_validate_pipeline( ctx );
427
428 _tnl_get_exec_copy_verts( ctx, IM );
429
430 if (IM->CopyStart == IM->Count) {
431 if (IM->OrFlag & VERT_ELT)
432 _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
433
434 _tnl_fixup_input( ctx, IM ); /* shouldn't be needed? (demos/fire) */
435 _tnl_run_empty_cassette( ctx, IM );
436 }
437 else if ((IM->OrFlag & VERT_DATA) == VERT_ELT &&
438 ctx->Array.LockCount &&
439 ctx->Array.Vertex.Enabled) {
440 exec_elt_cassette( ctx, IM );
441 }
442 else {
443 exec_vert_cassette( ctx, IM );
444 }
445
446 _tnl_reset_input( ctx,
447 IMM_MAX_COPIED_VERTS,
448 IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1),
449 IM->SavedBeginState );
450
451 /* Copy vertices and primitive information to immediate before it
452 * can be overwritten.
453 */
454 _tnl_copy_immediate_vertices( ctx, IM );
455
456 if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
457 ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
458 }
459
460
461
462
463 /* Setup vector pointers that will be used to bind immediates to VB's.
464 */
465 void _tnl_imm_init( GLcontext *ctx )
466 {
467 TNLcontext *tnl = TNL_CONTEXT(ctx);
468 struct vertex_arrays *tmp = &tnl->imm_inputs;
469 GLuint i;
470 static int firsttime = 1;
471
472 if (firsttime) {
473 firsttime = 0;
474 _tnl_imm_elt_init();
475 }
476
477 ctx->swtnl_im = _tnl_alloc_immediate( ctx );
478 TNL_CURRENT_IM(ctx)->ref_count++;
479
480 tnl->ExecCopyTexSize = 0;
481 tnl->ExecCopyCount = 0;
482 tnl->ExecCopySource = TNL_CURRENT_IM(ctx);
483 TNL_CURRENT_IM(ctx)->ref_count++;
484
485 TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
486
487 gl_vector4f_init( &tmp->Obj, 0, 0 );
488 gl_vector3f_init( &tmp->Normal, 0, 0 );
489 #if CHAN_TYPE == GL_UNSIGNED_BYTE
490 gl_vector4ub_init( &tmp->Color, 0, 0 );
491 gl_vector4ub_init( &tmp->SecondaryColor, 0, 0 );
492 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
493 gl_vector4us_init( &tmp->Color, 0, 0 );
494 gl_vector4us_init( &tmp->SecondaryColor, 0, 0 );
495 #elif CHAN_TYPE == GL_FLOAT
496 gl_vector4f_init( &tmp->Color, 0, 0 );
497 gl_vector4f_init( &tmp->SecondaryColor, 0, 0 );
498 #endif
499 gl_vector1f_init( &tmp->FogCoord, 0, 0 );
500 gl_vector1ui_init( &tmp->Index, 0, 0 );
501 gl_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
502
503 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
504 gl_vector4f_init( &tmp->TexCoord[i], 0, 0);
505
506 /* Install the first immediate. Intially outside begin/end.
507 */
508 _tnl_reset_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
509 tnl->ReplayHardBeginEnd = 0;
510
511 _tnl_imm_vtxfmt_init( ctx );
512 }
513
514
515 void _tnl_imm_destroy( GLcontext *ctx )
516 {
517 if (TNL_CURRENT_IM(ctx))
518 _tnl_free_immediate( TNL_CURRENT_IM(ctx) );
519
520 }