Header file clean-up:
[mesa.git] / src / mesa / tnl / t_vb_program.c
1 /* $Id: t_vb_program.c,v 1.15 2002/10/24 23:57:25 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 4.1
6 *
7 * Copyright (C) 1999-2002 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 /*
28 * -------- Regarding NV_vertex_program --------
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions are met:
31 *
32 * o Redistribution of the source code must contain a copyright notice
33 * and this list of conditions;
34 *
35 * o Redistribution in binary and source code form must contain the
36 * following Notice in the software and any documentation and/or other
37 * materials provided with the distribution; and
38 *
39 * o The name of Nvidia may not be used to promote or endorse software
40 * derived from the software.
41 *
42 * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
43 * royalty free patent license under patent claims that are licensable by
44 * Nvidia and which are necessarily required and for which no commercially
45 * viable non infringing alternative exists to make, use, sell, offer to sell,
46 * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
47 * Library as distributed in source code and object code form. No hardware or
48 * hardware implementation (including a semiconductor implementation and chips)
49 * are licensed hereunder. If a recipient makes a patent claim or institutes
50 * patent litigation against Nvidia or Nvidia's customers for use or sale of
51 * Nvidia products, then this license grant as to such recipient shall
52 * immediately terminate and recipient immediately agrees to cease use and
53 * distribution of the Mesa Program and derivatives thereof.
54 *
55 * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
56 * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
57 * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
58 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
59 *
60 * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
61 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
62 * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
65 * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
66 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 *
68 * If you do not comply with this agreement, then Nvidia may cancel the license
69 * and rights granted herein.
70 * ---------------------------------------------
71 */
72
73 /**
74 * \file tnl/t_vb_program.c
75 * \brief Pipeline stage for executing vertex programs
76 * \author Brian Paul, Keith Whitwell
77 */
78
79
80 #include "glheader.h"
81 #include "api_noop.h"
82 #include "colormac.h"
83 #include "context.h"
84 #include "dlist.h"
85 #include "hash.h"
86 #include "light.h"
87 #include "macros.h"
88 #include "imports.h"
89 #include "mmath.h"
90 #include "simple_list.h"
91 #include "mtypes.h"
92 #include "vpexec.h"
93
94 #include "math/m_translate.h"
95
96 #include "t_context.h"
97 #include "t_pipeline.h"
98 #include "t_imm_api.h"
99 #include "t_imm_exec.h"
100
101
102 /**
103 * \warning These values _MUST_ match the values in the OutputRegisters[]
104 * array in vpparse.c!!!
105 */
106 #define VERT_RESULT_HPOS 0
107 #define VERT_RESULT_COL0 1
108 #define VERT_RESULT_COL1 2
109 #define VERT_RESULT_BFC0 3
110 #define VERT_RESULT_BFC1 4
111 #define VERT_RESULT_FOGC 5
112 #define VERT_RESULT_PSIZ 6
113 #define VERT_RESULT_TEX0 7
114 #define VERT_RESULT_TEX1 8
115 #define VERT_RESULT_TEX2 9
116 #define VERT_RESULT_TEX3 10
117 #define VERT_RESULT_TEX4 11
118 #define VERT_RESULT_TEX5 12
119 #define VERT_RESULT_TEX6 13
120 #define VERT_RESULT_TEX7 14
121
122
123 /*!
124 * Private storage for the vertex program pipeline stage.
125 */
126 struct vp_stage_data {
127 /** The results of running the vertex program go into these arrays. */
128 GLvector4f attribs[15];
129
130 /* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */
131 struct gl_client_array color0[2]; /**< diffuse front and back */
132 struct gl_client_array color1[2]; /**< specular front and back */
133
134 GLvector4f ndcCoords; /**< normalized device coords */
135 GLubyte *clipmask; /**< clip flags */
136 GLubyte ormask, andmask; /**< for clipping */
137 };
138
139
140 #define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
141
142
143 /**
144 * This function executes vertex programs
145 */
146 static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
147 {
148 TNLcontext *tnl = TNL_CONTEXT(ctx);
149 struct vp_stage_data *store = VP_STAGE_DATA(stage);
150 struct vertex_buffer *VB = &tnl->vb;
151 struct vp_machine *machine = &(ctx->VertexProgram.Machine);
152 struct vp_program *program = ctx->VertexProgram.Current;
153 GLuint i;
154
155 _mesa_init_tracked_matrices(ctx); /* load registers with matrices */
156 _mesa_init_vp_registers(ctx); /* init temp and result regs */
157
158 for (i = 0; i < VB->Count; i++) {
159 GLuint attr;
160
161 #if 0
162 printf("Input %d: %f, %f, %f, %f\n", i,
163 VB->AttribPtr[0]->data[i][0],
164 VB->AttribPtr[0]->data[i][1],
165 VB->AttribPtr[0]->data[i][2],
166 VB->AttribPtr[0]->data[i][3]);
167 printf(" color: %f, %f, %f, %f\n",
168 VB->AttribPtr[3]->data[i][0],
169 VB->AttribPtr[3]->data[i][1],
170 VB->AttribPtr[3]->data[i][2],
171 VB->AttribPtr[3]->data[i][3]);
172 printf(" normal: %f, %f, %f, %f\n",
173 VB->AttribPtr[2]->data[i][0],
174 VB->AttribPtr[2]->data[i][1],
175 VB->AttribPtr[2]->data[i][2],
176 VB->AttribPtr[2]->data[i][3]);
177 #endif
178
179 /* load the input attribute registers */
180 if (VB->Flag) {
181 /* the traditional glBegin/glVertex/glEnd case */
182 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
183 if (VB->Flag[i] & (1 << attr)) {
184 COPY_4V(machine->Registers[VP_INPUT_REG_START + attr],
185 VB->AttribPtr[attr]->data[i]);
186 }
187 }
188 }
189 else {
190 /* the vertex array case */
191 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
192 if (program->InputsRead & (1 << attr)) {
193 const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
194 const GLuint stride = VB->AttribPtr[attr]->stride;
195 const GLfloat *data = (GLfloat *) (ptr + stride * i);
196 COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], data);
197 /*ASSERT(VB->AttribPtr[attr]->size == 4);*/
198 ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0);
199 }
200 }
201 }
202
203 /* execute the program */
204 ASSERT(program);
205 _mesa_exec_program(ctx, program);
206
207 #if 0
208 printf("Output %d: %f, %f, %f, %f\n", i,
209 machine->Registers[VP_OUTPUT_REG_START + 0][0],
210 machine->Registers[VP_OUTPUT_REG_START + 0][1],
211 machine->Registers[VP_OUTPUT_REG_START + 0][2],
212 machine->Registers[VP_OUTPUT_REG_START + 0][3]);
213 printf(" color: %f, %f, %f, %f\n",
214 machine->Registers[VP_OUTPUT_REG_START +_1][0],
215 machine->Registers[VP_OUTPUT_REG_START + 1][1],
216 machine->Registers[VP_OUTPUT_REG_START + 1][2],
217 machine->Registers[VP_OUTPUT_REG_START + 1][3]);
218 printf("PointSize[%d]: %g\n", i,
219 machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]);
220 #endif
221
222 /* Fixup fog an point size results if needed */
223 if (ctx->Fog.Enabled &&
224 (program->OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) {
225 machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_FOGC][0] = 1.0;
226 }
227
228 if (ctx->VertexProgram.PointSizeEnabled &&
229 (program->OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) {
230 machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]
231 = ctx->Point.Size;
232 }
233
234 /* copy the output registers into the VB->attribs arrays */
235 /* XXX (optimize) could use a conditional and smaller loop limit here */
236 for (attr = 0; attr < 15; attr++) {
237 COPY_4V( store->attribs[attr].data[i],
238 machine->Registers[VP_OUTPUT_REG_START + attr] );
239 }
240 }
241
242 /* Setup the VB pointers so that the next pipeline stages get
243 * their data from the right place (the program output arrays).
244 */
245 VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
246 VB->ClipPtr->size = 4;
247 VB->ClipPtr->count = VB->Count;
248 VB->ColorPtr[0] = &store->color0[0];
249 VB->ColorPtr[1] = &store->color0[1];
250 VB->SecondaryColorPtr[0] = &store->color1[0];
251 VB->SecondaryColorPtr[1] = &store->color1[1];
252 VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
253 VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ];
254 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
255 VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i];
256
257 /* Cliptest and perspective divide. Clip functions must clear
258 * the clipmask.
259 */
260 store->ormask = 0;
261 store->andmask = CLIP_ALL_BITS;
262
263 if (tnl->NeedNdcCoords) {
264 VB->NdcPtr =
265 _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
266 &store->ndcCoords,
267 store->clipmask,
268 &store->ormask,
269 &store->andmask );
270
271 }
272 else {
273 VB->NdcPtr = 0;
274 _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
275 0,
276 store->clipmask,
277 &store->ormask,
278 &store->andmask );
279 }
280
281 if (store->andmask) /* All vertices are outside the frustum */
282 return GL_FALSE;
283
284
285 /* This is where we'd do clip testing against the user-defined
286 * clipping planes, but they're not supported by vertex programs.
287 */
288
289 VB->ClipOrMask = store->ormask;
290 VB->ClipMask = store->clipmask;
291
292 /* XXXX what's this?
293 if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
294 VB->importable_data |= VERT_BIT_CLIP;
295 */
296
297 return GL_TRUE;
298 }
299
300
301 /**
302 * This function validates stuff.
303 */
304 static GLboolean run_validate_program( GLcontext *ctx,
305 struct gl_pipeline_stage *stage )
306 {
307 #if 000
308 /* XXX do we need any validation for vertex programs? */
309 GLuint ind = 0;
310 light_func *tab;
311
312 if (ctx->Visual.rgbMode) {
313 if (ctx->Light._NeedVertices) {
314 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
315 tab = _tnl_light_spec_tab;
316 else
317 tab = _tnl_light_tab;
318 }
319 else {
320 if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
321 tab = _tnl_light_fast_single_tab;
322 else
323 tab = _tnl_light_fast_tab;
324 }
325 }
326 else
327 tab = _tnl_light_ci_tab;
328
329 if (ctx->Light.ColorMaterialEnabled)
330 ind |= LIGHT_COLORMATERIAL;
331
332 if (ctx->Light.Model.TwoSide)
333 ind |= LIGHT_TWOSIDE;
334
335 VP_STAGE_DATA(stage)->light_func_tab = &tab[ind];
336
337 /* This and the above should only be done on _NEW_LIGHT:
338 */
339 _mesa_validate_all_lighting_tables( ctx );
340 #endif
341
342 /* Now run the stage...
343 */
344 stage->run = run_vp;
345 return stage->run( ctx, stage );
346 }
347
348
349 /**
350 * Initialize a gl_client_array to point into a GLvector4f color vector.
351 */
352 static void init_color_array( struct gl_client_array *a, GLvector4f *vec )
353 {
354 a->Ptr = vec->data;
355 a->Size = 4;
356 a->Type = GL_FLOAT;
357 a->Stride = 0;
358 a->StrideB = sizeof(GLfloat) * 4;
359 a->Enabled = 0;
360 a->Flags = 0;
361 }
362
363
364 /**
365 * Called the first time stage->run is called. In effect, don't
366 * allocate data until the first time the stage is run.
367 */
368 static GLboolean run_init_vp( GLcontext *ctx,
369 struct gl_pipeline_stage *stage )
370 {
371 TNLcontext *tnl = TNL_CONTEXT(ctx);
372 struct vertex_buffer *VB = &(tnl->vb);
373 struct vp_stage_data *store;
374 const GLuint size = VB->Size;
375 GLuint i;
376
377 stage->privatePtr = MALLOC(sizeof(*store));
378 store = VP_STAGE_DATA(stage);
379 if (!store)
380 return GL_FALSE;
381
382 /* Allocate arrays of vertex output values */
383 for (i = 0; i < 15; i++)
384 _mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 );
385
386 /* Make the color0[] and color1[] arrays point into the attribs[] arrays */
387 init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] );
388 init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] );
389 init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] );
390 init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] );
391
392 /* a few other misc allocations */
393 _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
394 store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
395
396 /* Now validate the stage derived data...
397 */
398 stage->run = run_validate_program;
399 return stage->run( ctx, stage );
400 }
401
402
403
404 /**
405 * Check if vertex program mode is enabled.
406 * If so, configure the pipeline stage's type, inputs, and outputs.
407 */
408 static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
409 {
410 stage->active = ctx->VertexProgram.Enabled;
411
412 if (stage->active) {
413 /* I believe this is right - Keith?
414 * Set stage->inputs equal to the bitmask of vertex attributes
415 * which the program needs for inputs.
416 */
417
418 stage->inputs = ctx->VertexProgram.Current->InputsRead;
419
420 #if 000
421 if (stage->privatePtr)
422 stage->run = run_validate_program;
423 stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
424 if (ctx->Light._NeedVertices)
425 stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
426 if (ctx->Light.ColorMaterialEnabled)
427 stage->inputs |= VERT_BIT_COLOR0;
428
429 stage->outputs = VERT_BIT_COLOR0;
430 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
431 stage->outputs |= VERT_BIT_COLOR1;
432 #endif
433 }
434 }
435
436
437 /**
438 * Destructor for this pipeline stage.
439 */
440 static void dtr( struct gl_pipeline_stage *stage )
441 {
442 struct vp_stage_data *store = VP_STAGE_DATA(stage);
443
444 if (store) {
445 GLuint i;
446
447 /* free the vertex program result arrays */
448 for (i = 0; i < 15; i++)
449 _mesa_vector4f_free( &store->attribs[i] );
450
451 /* free misc arrays */
452 _mesa_vector4f_free( &store->ndcCoords );
453 ALIGN_FREE( store->clipmask );
454
455 FREE( store );
456 stage->privatePtr = 0;
457 }
458 }
459
460 /**
461 * Public description of this pipeline stage.
462 */
463 const struct gl_pipeline_stage _tnl_vertex_program_stage =
464 {
465 "vertex-program",
466 _NEW_ALL, /*XXX FIX */ /* recheck */
467 _NEW_ALL, /*XXX FIX */ /* recalc -- modelview dependency
468 * otherwise not captured by inputs
469 * (which may be VERT_BIT_POS) */
470 GL_FALSE, /* active */
471 /*0*/ VERT_BIT_POS, /* inputs XXX OK? */
472 VERT_BIT_CLIP | VERT_BIT_COLOR0, /* outputs XXX OK? */
473 0, /* changed_inputs */
474 NULL, /* private_data */
475 dtr, /* destroy */
476 check_vp, /* check */
477 run_init_vp /* run -- initially set to ctr */
478 };