Vertex program attribute arrays seem to work now. This includes fallbacks
[mesa.git] / src / mesa / tnl / t_vb_program.c
1 /* $Id: t_vb_program.c,v 1.12 2002/04/21 20:37:04 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 "mem.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);
156 _mesa_init_vp_registers(ctx); /* init temp and result regs */
157 /* XXX if GL_FOG is enabled but the program doesn't write to the
158 * o[FOGC] register, set the fog result to 1.0
159 */
160 /* XXX if GL_VERTEX_PROGRAM_POINT_SIZE_NV is enabled but the program
161 * doesn't write the PSIZ variable then use ctx->Point.Size
162 */
163
164 for (i = 0; i < VB->Count; i++) {
165 GLuint attr;
166
167 #if 0
168 printf("Input %d: %f, %f, %f, %f\n", i,
169 VB->AttribPtr[0]->data[i][0],
170 VB->AttribPtr[0]->data[i][1],
171 VB->AttribPtr[0]->data[i][2],
172 VB->AttribPtr[0]->data[i][3]);
173 printf(" color: %f, %f, %f, %f\n",
174 VB->AttribPtr[3]->data[i][0],
175 VB->AttribPtr[3]->data[i][1],
176 VB->AttribPtr[3]->data[i][2],
177 VB->AttribPtr[3]->data[i][3]);
178 printf(" normal: %f, %f, %f, %f\n",
179 VB->AttribPtr[2]->data[i][0],
180 VB->AttribPtr[2]->data[i][1],
181 VB->AttribPtr[2]->data[i][2],
182 VB->AttribPtr[2]->data[i][3]);
183 #endif
184
185 /* load the input attribute registers */
186 if (VB->Flag) {
187 /* the traditional glBegin/glVertex/glEnd case */
188 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
189 if (VB->Flag[i] & (1 << attr)) {
190 COPY_4V(machine->Registers[VP_INPUT_REG_START + attr],
191 VB->AttribPtr[attr]->data[i]);
192 }
193 }
194 }
195 else {
196 /* the vertex array case */
197 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
198 if (program->InputsRead & (1 << attr)) {
199 const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
200 const GLuint stride = VB->AttribPtr[attr]->stride;
201 const GLfloat *data = (GLfloat *) (ptr + stride * i);
202 COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], data);
203 /*ASSERT(VB->AttribPtr[attr]->size == 4);*/
204 ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0);
205 }
206 }
207 }
208
209 /* execute the program */
210 ASSERT(program);
211 _mesa_exec_program(ctx, program);
212 #if 0
213 printf("Output %d: %f, %f, %f, %f\n", i,
214 machine->Registers[VP_OUT_HPOS][0],
215 machine->Registers[VP_OUT_HPOS][1],
216 machine->Registers[VP_OUT_HPOS][2],
217 machine->Registers[VP_OUT_HPOS][3]);
218 printf(" color: %f, %f, %f, %f\n",
219 machine->Registers[VP_OUT_COL0][0],
220 machine->Registers[VP_OUT_COL0][1],
221 machine->Registers[VP_OUT_COL0][2],
222 machine->Registers[VP_OUT_COL0][3]);
223 printf("PointSize[%d]: %g\n", i,
224 machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]);
225 #endif
226
227 /* copy the output registers into the VB->attribs arrays */
228 /* XXX (optimize) could use a conditional and smaller loop limit here */
229 for (attr = 0; attr < 15; attr++) {
230 COPY_4V( store->attribs[attr].data[i],
231 machine->Registers[VP_OUTPUT_REG_START + attr] );
232 }
233 }
234
235 /* Setup the VB pointers so that the next pipeline stages get
236 * their data from the right place (the program output arrays).
237 */
238 VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
239 VB->ClipPtr->size = 4;
240 VB->ClipPtr->count = VB->Count;
241 VB->ColorPtr[0] = &store->color0[0];
242 VB->ColorPtr[1] = &store->color0[1];
243 VB->SecondaryColorPtr[0] = &store->color1[0];
244 VB->SecondaryColorPtr[1] = &store->color1[1];
245 VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
246 VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ];
247 for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
248 VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i];
249
250 /* Cliptest and perspective divide. Clip functions must clear
251 * the clipmask.
252 */
253 store->ormask = 0;
254 store->andmask = CLIP_ALL_BITS;
255
256 if (tnl->NeedNdcCoords) {
257 VB->NdcPtr =
258 _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
259 &store->ndcCoords,
260 store->clipmask,
261 &store->ormask,
262 &store->andmask );
263
264 }
265 else {
266 VB->NdcPtr = 0;
267 _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
268 0,
269 store->clipmask,
270 &store->ormask,
271 &store->andmask );
272 }
273
274 if (store->andmask) /* All vertices are outside the frustum */
275 return GL_FALSE;
276
277
278 /* This is where we'd do clip testing against the user-defined
279 * clipping planes, but they're not supported by vertex programs.
280 */
281
282 VB->ClipOrMask = store->ormask;
283 VB->ClipMask = store->clipmask;
284
285 /* XXXX what's this?
286 if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
287 VB->importable_data |= VERT_BIT_CLIP;
288 */
289
290 return GL_TRUE;
291 }
292
293
294 /**
295 * This function validates stuff.
296 */
297 static GLboolean run_validate_program( GLcontext *ctx,
298 struct gl_pipeline_stage *stage )
299 {
300 #if 000
301 /* XXX do we need any validation for vertex programs? */
302 GLuint ind = 0;
303 light_func *tab;
304
305 if (ctx->Visual.rgbMode) {
306 if (ctx->Light._NeedVertices) {
307 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
308 tab = _tnl_light_spec_tab;
309 else
310 tab = _tnl_light_tab;
311 }
312 else {
313 if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
314 tab = _tnl_light_fast_single_tab;
315 else
316 tab = _tnl_light_fast_tab;
317 }
318 }
319 else
320 tab = _tnl_light_ci_tab;
321
322 if (ctx->Light.ColorMaterialEnabled)
323 ind |= LIGHT_COLORMATERIAL;
324
325 if (ctx->Light.Model.TwoSide)
326 ind |= LIGHT_TWOSIDE;
327
328 VP_STAGE_DATA(stage)->light_func_tab = &tab[ind];
329
330 /* This and the above should only be done on _NEW_LIGHT:
331 */
332 _mesa_validate_all_lighting_tables( ctx );
333 #endif
334
335 /* Now run the stage...
336 */
337 stage->run = run_vp;
338 return stage->run( ctx, stage );
339 }
340
341
342 /**
343 * Initialize a gl_client_array to point into a GLvector4f color vector.
344 */
345 static void init_color_array( struct gl_client_array *a, GLvector4f *vec )
346 {
347 a->Ptr = vec->data;
348 a->Size = 4;
349 a->Type = GL_FLOAT;
350 a->Stride = 0;
351 a->StrideB = sizeof(GLfloat) * 4;
352 a->Enabled = 0;
353 a->Flags = 0;
354 }
355
356
357 /**
358 * Called the first time stage->run is called. In effect, don't
359 * allocate data until the first time the stage is run.
360 */
361 static GLboolean run_init_vp( GLcontext *ctx,
362 struct gl_pipeline_stage *stage )
363 {
364 TNLcontext *tnl = TNL_CONTEXT(ctx);
365 struct vertex_buffer *VB = &(tnl->vb);
366 struct vp_stage_data *store;
367 const GLuint size = VB->Size;
368 GLuint i;
369
370 stage->privatePtr = MALLOC(sizeof(*store));
371 store = VP_STAGE_DATA(stage);
372 if (!store)
373 return GL_FALSE;
374
375 /* Allocate arrays of vertex output values */
376 for (i = 0; i < 15; i++)
377 _mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 );
378
379 /* Make the color0[] and color1[] arrays point into the attribs[] arrays */
380 init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] );
381 init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] );
382 init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] );
383 init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] );
384
385 /* a few other misc allocations */
386 _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
387 store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
388
389 /* Now validate the stage derived data...
390 */
391 stage->run = run_validate_program;
392 return stage->run( ctx, stage );
393 }
394
395
396
397 /**
398 * Check if vertex program mode is enabled.
399 * If so, configure the pipeline stage's type, inputs, and outputs.
400 */
401 static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
402 {
403 stage->active = ctx->VertexProgram.Enabled;
404
405 if (stage->active) {
406 /* XXX what do we need here???
407 *
408 * I think that:
409 * stage->inputs = ctx->VertexProgram.Current->InputsRead;
410 * would be correct, and something similar for the outputs.
411 */
412
413 #if 000
414 if (stage->privatePtr)
415 stage->run = run_validate_program;
416 stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
417 if (ctx->Light._NeedVertices)
418 stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
419 if (ctx->Light.ColorMaterialEnabled)
420 stage->inputs |= VERT_BIT_COLOR0;
421
422 stage->outputs = VERT_BIT_COLOR0;
423 if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
424 stage->outputs |= VERT_BIT_COLOR1;
425 #endif
426 }
427 }
428
429
430 /**
431 * Destructor for this pipeline stage.
432 */
433 static void dtr( struct gl_pipeline_stage *stage )
434 {
435 struct vp_stage_data *store = VP_STAGE_DATA(stage);
436
437 if (store) {
438 GLuint i;
439
440 /* free the vertex program result arrays */
441 for (i = 0; i < 15; i++)
442 _mesa_vector4f_free( &store->attribs[i] );
443
444 /* free misc arrays */
445 _mesa_vector4f_free( &store->ndcCoords );
446 ALIGN_FREE( store->clipmask );
447
448 FREE( store );
449 stage->privatePtr = 0;
450 }
451 }
452
453 /**
454 * Public description of this pipeline stage.
455 */
456 const struct gl_pipeline_stage _tnl_vertex_program_stage =
457 {
458 "vertex-program",
459 _NEW_ALL, /*XXX FIX */ /* recheck */
460 _NEW_ALL, /*XXX FIX */ /* recalc -- modelview dependency
461 * otherwise not captured by inputs
462 * (which may be VERT_BIT_POS) */
463 GL_FALSE, /* active */
464 /*0*/ VERT_BIT_POS, /* inputs XXX OK? */
465 VERT_BIT_CLIP | VERT_BIT_COLOR0, /* outputs XXX OK? */
466 0, /* changed_inputs */
467 NULL, /* private_data */
468 dtr, /* destroy */
469 check_vp, /* check */
470 run_init_vp /* run -- initially set to ctr */
471 };