t_vb_program.c revision 3c63452e64df7e10aa073c6c3b9492b1d7dabbb8
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 */ 126struct 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 */ 146static 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 */ 304static 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 */ 352static 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 */ 368static 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 */ 408static 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 */ 440static 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 */ 463const 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}; 479