17117f1b4Smrg/* 27117f1b4Smrg * Mesa 3-D graphics library 37117f1b4Smrg * 44a49301eSmrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 54a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 247117f1b4Smrg */ 257117f1b4Smrg 267117f1b4Smrg 277117f1b4Smrg/** 287117f1b4Smrg * \file tnl/t_vb_program.c 297117f1b4Smrg * \brief Pipeline stage for executing vertex programs. 307117f1b4Smrg * \author Brian Paul, Keith Whitwell 317117f1b4Smrg */ 327117f1b4Smrg 337117f1b4Smrg 347117f1b4Smrg#include "main/glheader.h" 357117f1b4Smrg#include "main/macros.h" 36af69d88dSmrg#include "main/samplerobj.h" 3701e04c3fSmrg#include "main/state.h" 383464ebd5Sriastradh#include "math/m_xform.h" 393464ebd5Sriastradh#include "program/prog_instruction.h" 403464ebd5Sriastradh#include "program/prog_statevars.h" 413464ebd5Sriastradh#include "program/prog_execute.h" 427117f1b4Smrg#include "swrast/s_context.h" 4301e04c3fSmrg#include "util/bitscan.h" 447ec681f3Smrg#include "util/u_memory.h" 457117f1b4Smrg 467117f1b4Smrg#include "tnl/tnl.h" 477117f1b4Smrg#include "tnl/t_context.h" 487117f1b4Smrg#include "tnl/t_pipeline.h" 497117f1b4Smrg 507117f1b4Smrg 514a49301eSmrg#ifdef NAN_CHECK 524a49301eSmrg/** Check for NaNs and very large values */ 53af69d88dSmrgstatic inline void 544a49301eSmrgcheck_float(float x) 554a49301eSmrg{ 567ec681f3Smrg assert(!util_is_inf_or_nan(x)); 574a49301eSmrg assert(1.0e-15 <= x && x <= 1.0e15); 584a49301eSmrg} 594a49301eSmrg#endif 604a49301eSmrg 617117f1b4Smrg 627117f1b4Smrg/*! 637117f1b4Smrg * Private storage for the vertex program pipeline stage. 647117f1b4Smrg */ 657117f1b4Smrgstruct vp_stage_data { 667117f1b4Smrg /** The results of running the vertex program go into these arrays. */ 67af69d88dSmrg GLvector4f results[VARYING_SLOT_MAX]; 687117f1b4Smrg 697117f1b4Smrg GLvector4f ndcCoords; /**< normalized device coords */ 707117f1b4Smrg GLubyte *clipmask; /**< clip flags */ 717117f1b4Smrg GLubyte ormask, andmask; /**< for clipping */ 723464ebd5Sriastradh 73af69d88dSmrg GLboolean vertex_textures; 74af69d88dSmrg 753464ebd5Sriastradh struct gl_program_machine machine; 767117f1b4Smrg}; 777117f1b4Smrg 787117f1b4Smrg 797117f1b4Smrg#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr)) 807117f1b4Smrg 817117f1b4Smrg 827117f1b4Smrgstatic void 833464ebd5Sriastradhuserclip( struct gl_context *ctx, 847117f1b4Smrg GLvector4f *clip, 857117f1b4Smrg GLubyte *clipmask, 867117f1b4Smrg GLubyte *clipormask, 877117f1b4Smrg GLubyte *clipandmask ) 887117f1b4Smrg{ 8901e04c3fSmrg GLbitfield mask = ctx->Transform.ClipPlanesEnabled; 9001e04c3fSmrg while (mask) { 9101e04c3fSmrg const int p = u_bit_scan(&mask); 9201e04c3fSmrg GLuint nr, i; 9301e04c3fSmrg const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; 9401e04c3fSmrg const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; 9501e04c3fSmrg const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; 9601e04c3fSmrg const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; 9701e04c3fSmrg GLfloat *coord = (GLfloat *)clip->data; 9801e04c3fSmrg GLuint stride = clip->stride; 9901e04c3fSmrg GLuint count = clip->count; 10001e04c3fSmrg 10101e04c3fSmrg for (nr = 0, i = 0 ; i < count ; i++) { 10201e04c3fSmrg GLfloat dp = (coord[0] * a + 10301e04c3fSmrg coord[1] * b + 10401e04c3fSmrg coord[2] * c + 10501e04c3fSmrg coord[3] * d); 10601e04c3fSmrg 10701e04c3fSmrg if (dp < 0) { 10801e04c3fSmrg nr++; 10901e04c3fSmrg clipmask[i] |= CLIP_USER_BIT; 11001e04c3fSmrg } 11101e04c3fSmrg 11201e04c3fSmrg STRIDE_F(coord, stride); 11301e04c3fSmrg } 1147117f1b4Smrg 11501e04c3fSmrg if (nr > 0) { 11601e04c3fSmrg *clipormask |= CLIP_USER_BIT; 11701e04c3fSmrg if (nr == count) { 11801e04c3fSmrg *clipandmask |= CLIP_USER_BIT; 11901e04c3fSmrg return; 12001e04c3fSmrg } 1217117f1b4Smrg } 1227117f1b4Smrg } 1237117f1b4Smrg} 1247117f1b4Smrg 1257117f1b4Smrg 1267117f1b4Smrgstatic GLboolean 1273464ebd5Sriastradhdo_ndc_cliptest(struct gl_context *ctx, struct vp_stage_data *store) 1287117f1b4Smrg{ 1297117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 1307117f1b4Smrg struct vertex_buffer *VB = &tnl->vb; 1317117f1b4Smrg /* Cliptest and perspective divide. Clip functions must clear 1327117f1b4Smrg * the clipmask. 1337117f1b4Smrg */ 1347117f1b4Smrg store->ormask = 0; 1357117f1b4Smrg store->andmask = CLIP_FRUSTUM_BITS; 1367117f1b4Smrg 1374a49301eSmrg tnl_clip_prepare(ctx); 1384a49301eSmrg 1397117f1b4Smrg if (tnl->NeedNdcCoords) { 1407117f1b4Smrg VB->NdcPtr = 1417117f1b4Smrg _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, 1427117f1b4Smrg &store->ndcCoords, 1437117f1b4Smrg store->clipmask, 1447117f1b4Smrg &store->ormask, 1454a49301eSmrg &store->andmask, 14601e04c3fSmrg !(ctx->Transform.DepthClampNear && 14701e04c3fSmrg ctx->Transform.DepthClampFar) ); 1487117f1b4Smrg } 1497117f1b4Smrg else { 1507117f1b4Smrg VB->NdcPtr = NULL; 1517117f1b4Smrg _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr, 1527117f1b4Smrg NULL, 1537117f1b4Smrg store->clipmask, 1547117f1b4Smrg &store->ormask, 1554a49301eSmrg &store->andmask, 15601e04c3fSmrg !(ctx->Transform.DepthClampNear && 15701e04c3fSmrg ctx->Transform.DepthClampFar) ); 1587117f1b4Smrg } 1597117f1b4Smrg 1607117f1b4Smrg if (store->andmask) { 1617117f1b4Smrg /* All vertices are outside the frustum */ 1627117f1b4Smrg return GL_FALSE; 1637117f1b4Smrg } 1647117f1b4Smrg 1657117f1b4Smrg /* Test userclip planes. This contributes to VB->ClipMask. 1667117f1b4Smrg */ 1677117f1b4Smrg /** XXX NEW_SLANG _Enabled ??? */ 16801e04c3fSmrg if (ctx->Transform.ClipPlanesEnabled && 16901e04c3fSmrg (!_mesa_arb_vertex_program_enabled(ctx) || 17001e04c3fSmrg ctx->VertexProgram.Current->arb.IsPositionInvariant)) { 1717117f1b4Smrg userclip( ctx, 1727117f1b4Smrg VB->ClipPtr, 1737117f1b4Smrg store->clipmask, 1747117f1b4Smrg &store->ormask, 1757117f1b4Smrg &store->andmask ); 1767117f1b4Smrg 1777117f1b4Smrg if (store->andmask) { 1787117f1b4Smrg return GL_FALSE; 1797117f1b4Smrg } 1807117f1b4Smrg } 1817117f1b4Smrg 1827117f1b4Smrg VB->ClipAndMask = store->andmask; 1837117f1b4Smrg VB->ClipOrMask = store->ormask; 1847117f1b4Smrg VB->ClipMask = store->clipmask; 1857117f1b4Smrg 1867117f1b4Smrg return GL_TRUE; 1877117f1b4Smrg} 1887117f1b4Smrg 1897117f1b4Smrg 1907117f1b4Smrg/** 1917117f1b4Smrg * XXX the texture sampling code in this module is a bit of a hack. 1927117f1b4Smrg * The texture sampling code is in swrast, though it doesn't have any 1937117f1b4Smrg * real dependencies on the rest of swrast. It should probably be 1947117f1b4Smrg * moved into main/ someday. 1957117f1b4Smrg */ 1967117f1b4Smrgstatic void 1973464ebd5Sriastradhvp_fetch_texel(struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda, 1987117f1b4Smrg GLuint unit, GLfloat color[4]) 1997117f1b4Smrg{ 2007117f1b4Smrg SWcontext *swrast = SWRAST_CONTEXT(ctx); 2017117f1b4Smrg 2027117f1b4Smrg /* XXX use a float-valued TextureSample routine here!!! */ 203af69d88dSmrg swrast->TextureSample[unit](ctx, _mesa_get_samplerobj(ctx, unit), 204af69d88dSmrg ctx->Texture.Unit[unit]._Current, 2057117f1b4Smrg 1, (const GLfloat (*)[4]) texcoord, 2064a49301eSmrg &lambda, (GLfloat (*)[4]) color); 2077117f1b4Smrg} 2087117f1b4Smrg 2097117f1b4Smrg 2107117f1b4Smrg/** 2117117f1b4Smrg * Called via ctx->Driver.ProgramStringNotify() after a new vertex program 2127117f1b4Smrg * string has been parsed. 2137117f1b4Smrg */ 214cdc920a0SmrgGLboolean 2153464ebd5Sriastradh_tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program) 2167117f1b4Smrg{ 2177117f1b4Smrg /* No-op. 2187117f1b4Smrg * If we had derived anything from the program that was private to this 2197117f1b4Smrg * stage we'd recompute/validate it here. 2207117f1b4Smrg */ 221cdc920a0Smrg return GL_TRUE; 2227117f1b4Smrg} 2237117f1b4Smrg 2247117f1b4Smrg 2257117f1b4Smrg/** 2267117f1b4Smrg * Initialize virtual machine state prior to executing vertex program. 2277117f1b4Smrg */ 2287117f1b4Smrgstatic void 2293464ebd5Sriastradhinit_machine(struct gl_context *ctx, struct gl_program_machine *machine, 2303464ebd5Sriastradh GLuint instID) 2317117f1b4Smrg{ 2327117f1b4Smrg /* Input registers get initialized from the current vertex attribs */ 233cdc920a0Smrg memcpy(machine->VertAttribs, ctx->Current.Attrib, 2344a49301eSmrg MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat)); 2357117f1b4Smrg 2367117f1b4Smrg machine->NumDeriv = 0; 2377117f1b4Smrg 2387117f1b4Smrg /* init call stack */ 2397117f1b4Smrg machine->StackDepth = 0; 2407117f1b4Smrg 2417117f1b4Smrg machine->FetchTexelLod = vp_fetch_texel; 2427117f1b4Smrg machine->FetchTexelDeriv = NULL; /* not used by vertex programs */ 243c1f859d4Smrg 24401e04c3fSmrg machine->Samplers = ctx->VertexProgram._Current->SamplerUnits; 2453464ebd5Sriastradh 2463464ebd5Sriastradh machine->SystemValues[SYSTEM_VALUE_INSTANCE_ID][0] = (GLfloat) instID; 2477117f1b4Smrg} 2487117f1b4Smrg 2497117f1b4Smrg 2507117f1b4Smrg/** 2517117f1b4Smrg * Map the texture images which the vertex program will access (if any). 2527117f1b4Smrg */ 2537117f1b4Smrgstatic void 25401e04c3fSmrgmap_textures(struct gl_context *ctx, const struct gl_program *vp) 2557117f1b4Smrg{ 2567117f1b4Smrg GLuint u; 2577117f1b4Smrg 258af69d88dSmrg for (u = 0; u < ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits; u++) { 25901e04c3fSmrg if (vp->TexturesUsed[u]) { 2607117f1b4Smrg /* Note: _Current *should* correspond to the target indicated 2617117f1b4Smrg * in TexturesUsed[u]. 2627117f1b4Smrg */ 263af69d88dSmrg _swrast_map_texture(ctx, ctx->Texture.Unit[u]._Current); 2647117f1b4Smrg } 2657117f1b4Smrg } 2667117f1b4Smrg} 2677117f1b4Smrg 2687117f1b4Smrg 2697117f1b4Smrg/** 2707117f1b4Smrg * Unmap the texture images which were used by the vertex program (if any). 2717117f1b4Smrg */ 2727117f1b4Smrgstatic void 27301e04c3fSmrgunmap_textures(struct gl_context *ctx, const struct gl_program *vp) 2747117f1b4Smrg{ 2757117f1b4Smrg GLuint u; 2767117f1b4Smrg 277af69d88dSmrg for (u = 0; u < ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits; u++) { 27801e04c3fSmrg if (vp->TexturesUsed[u]) { 2797117f1b4Smrg /* Note: _Current *should* correspond to the target indicated 2807117f1b4Smrg * in TexturesUsed[u]. 2817117f1b4Smrg */ 282af69d88dSmrg _swrast_unmap_texture(ctx, ctx->Texture.Unit[u]._Current); 2837117f1b4Smrg } 2847117f1b4Smrg } 2857117f1b4Smrg} 2867117f1b4Smrg 2877117f1b4Smrg 2887117f1b4Smrg/** 2897117f1b4Smrg * This function executes vertex programs 2907117f1b4Smrg */ 2917117f1b4Smrgstatic GLboolean 2923464ebd5Sriastradhrun_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage ) 2937117f1b4Smrg{ 2947117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 2957117f1b4Smrg struct vp_stage_data *store = VP_STAGE_DATA(stage); 2967117f1b4Smrg struct vertex_buffer *VB = &tnl->vb; 29701e04c3fSmrg struct gl_program *program = ctx->VertexProgram._Current; 2983464ebd5Sriastradh struct gl_program_machine *machine = &store->machine; 299af69d88dSmrg GLuint outputs[VARYING_SLOT_MAX], numOutputs; 3007117f1b4Smrg GLuint i, j; 3017117f1b4Smrg 3027117f1b4Smrg if (!program) 3037117f1b4Smrg return GL_TRUE; 3047117f1b4Smrg 305af69d88dSmrg /* ARB program or vertex shader */ 30601e04c3fSmrg _mesa_load_state_parameters(ctx, program->Parameters); 3077117f1b4Smrg 3087117f1b4Smrg /* make list of outputs to save some time below */ 3097117f1b4Smrg numOutputs = 0; 310af69d88dSmrg for (i = 0; i < VARYING_SLOT_MAX; i++) { 31101e04c3fSmrg if (program->info.outputs_written & BITFIELD64_BIT(i)) { 3127117f1b4Smrg outputs[numOutputs++] = i; 3137117f1b4Smrg } 3147117f1b4Smrg } 3157117f1b4Smrg 316af69d88dSmrg /* Allocate result vectors. We delay this until now to avoid allocating 317af69d88dSmrg * memory that would never be used if we don't run the software tnl pipeline. 318af69d88dSmrg */ 319af69d88dSmrg if (!store->results[0].storage) { 320af69d88dSmrg for (i = 0; i < VARYING_SLOT_MAX; i++) { 321af69d88dSmrg assert(!store->results[i].storage); 322af69d88dSmrg _mesa_vector4f_alloc( &store->results[i], 0, VB->Size, 32 ); 323af69d88dSmrg store->results[i].size = 4; 324af69d88dSmrg } 325af69d88dSmrg } 326af69d88dSmrg 3277117f1b4Smrg map_textures(ctx, program); 3287117f1b4Smrg 3297117f1b4Smrg for (i = 0; i < VB->Count; i++) { 3307117f1b4Smrg GLuint attr; 3317117f1b4Smrg 3323464ebd5Sriastradh init_machine(ctx, machine, tnl->CurInstance); 3337117f1b4Smrg 3347117f1b4Smrg#if 0 3357117f1b4Smrg printf("Input %d: %f, %f, %f, %f\n", i, 3367117f1b4Smrg VB->AttribPtr[0]->data[i][0], 3377117f1b4Smrg VB->AttribPtr[0]->data[i][1], 3387117f1b4Smrg VB->AttribPtr[0]->data[i][2], 3397117f1b4Smrg VB->AttribPtr[0]->data[i][3]); 3407117f1b4Smrg printf(" color: %f, %f, %f, %f\n", 3417117f1b4Smrg VB->AttribPtr[3]->data[i][0], 3427117f1b4Smrg VB->AttribPtr[3]->data[i][1], 3437117f1b4Smrg VB->AttribPtr[3]->data[i][2], 3447117f1b4Smrg VB->AttribPtr[3]->data[i][3]); 3457117f1b4Smrg printf(" normal: %f, %f, %f, %f\n", 3467117f1b4Smrg VB->AttribPtr[2]->data[i][0], 3477117f1b4Smrg VB->AttribPtr[2]->data[i][1], 3487117f1b4Smrg VB->AttribPtr[2]->data[i][2], 3497117f1b4Smrg VB->AttribPtr[2]->data[i][3]); 3507117f1b4Smrg#endif 3517117f1b4Smrg 3527117f1b4Smrg /* the vertex array case */ 3537117f1b4Smrg for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { 35401e04c3fSmrg if (program->info.inputs_read & BITFIELD64_BIT(attr)) { 3557117f1b4Smrg const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data; 3567117f1b4Smrg const GLuint size = VB->AttribPtr[attr]->size; 3577117f1b4Smrg const GLuint stride = VB->AttribPtr[attr]->stride; 3587117f1b4Smrg const GLfloat *data = (GLfloat *) (ptr + stride * i); 3594a49301eSmrg#ifdef NAN_CHECK 3604a49301eSmrg check_float(data[0]); 3614a49301eSmrg check_float(data[1]); 3624a49301eSmrg check_float(data[2]); 3634a49301eSmrg check_float(data[3]); 3644a49301eSmrg#endif 3653464ebd5Sriastradh COPY_CLEAN_4V(machine->VertAttribs[attr], size, data); 3667117f1b4Smrg } 3677117f1b4Smrg } 3687117f1b4Smrg 3697117f1b4Smrg /* execute the program */ 37001e04c3fSmrg _mesa_execute_program(ctx, program, machine); 3717117f1b4Smrg 3727117f1b4Smrg /* copy the output registers into the VB->attribs arrays */ 3737117f1b4Smrg for (j = 0; j < numOutputs; j++) { 3747117f1b4Smrg const GLuint attr = outputs[j]; 3754a49301eSmrg#ifdef NAN_CHECK 3763464ebd5Sriastradh check_float(machine->Outputs[attr][0]); 3773464ebd5Sriastradh check_float(machine->Outputs[attr][1]); 3783464ebd5Sriastradh check_float(machine->Outputs[attr][2]); 3793464ebd5Sriastradh check_float(machine->Outputs[attr][3]); 3804a49301eSmrg#endif 3813464ebd5Sriastradh COPY_4V(store->results[attr].data[i], machine->Outputs[attr]); 3827117f1b4Smrg } 3834a49301eSmrg 3844a49301eSmrg /* FOGC is a special case. Fragment shader expects (f,0,0,1) */ 38501e04c3fSmrg if (program->info.outputs_written & BITFIELD64_BIT(VARYING_SLOT_FOGC)) { 386af69d88dSmrg store->results[VARYING_SLOT_FOGC].data[i][1] = 0.0; 387af69d88dSmrg store->results[VARYING_SLOT_FOGC].data[i][2] = 0.0; 388af69d88dSmrg store->results[VARYING_SLOT_FOGC].data[i][3] = 1.0; 3894a49301eSmrg } 3904a49301eSmrg#ifdef NAN_CHECK 39101e04c3fSmrg assert(machine->Outputs[0][3] != 0.0F); 3924a49301eSmrg#endif 3937117f1b4Smrg#if 0 3947117f1b4Smrg printf("HPOS: %f %f %f %f\n", 3957ec681f3Smrg machine->Outputs[0][0], 3967ec681f3Smrg machine->Outputs[0][1], 3977ec681f3Smrg machine->Outputs[0][2], 3983464ebd5Sriastradh machine->Outputs[0][3]); 3997117f1b4Smrg#endif 4007117f1b4Smrg } 4017117f1b4Smrg 4027117f1b4Smrg unmap_textures(ctx, program); 4037117f1b4Smrg 40401e04c3fSmrg if (program->arb.IsPositionInvariant) { 4057ec681f3Smrg /* make sure the inverse is up to date */ 4067ec681f3Smrg _math_matrix_analyse(&ctx->_ModelProjectMatrix); 4077ec681f3Smrg 4087117f1b4Smrg /* We need the exact same transform as in the fixed function path here 4097117f1b4Smrg * to guarantee invariance, depending on compiler optimization flags 4107117f1b4Smrg * results could be different otherwise. 4117117f1b4Smrg */ 4127117f1b4Smrg VB->ClipPtr = TransformRaw( &store->results[0], 4137117f1b4Smrg &ctx->_ModelProjectMatrix, 4147117f1b4Smrg VB->AttribPtr[0] ); 4157117f1b4Smrg 4167117f1b4Smrg /* Drivers expect this to be clean to element 4... 4177117f1b4Smrg */ 4187117f1b4Smrg switch (VB->ClipPtr->size) { 4197117f1b4Smrg case 1: 4207117f1b4Smrg /* impossible */ 4217117f1b4Smrg case 2: 4227117f1b4Smrg _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); 4237ec681f3Smrg FALLTHROUGH; 4247117f1b4Smrg case 3: 4257117f1b4Smrg _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 ); 4267ec681f3Smrg FALLTHROUGH; 4277117f1b4Smrg case 4: 4287117f1b4Smrg break; 4297117f1b4Smrg } 4307117f1b4Smrg } 4317117f1b4Smrg else { 4327117f1b4Smrg /* Setup the VB pointers so that the next pipeline stages get 4337117f1b4Smrg * their data from the right place (the program output arrays). 4347117f1b4Smrg */ 435af69d88dSmrg VB->ClipPtr = &store->results[VARYING_SLOT_POS]; 4367117f1b4Smrg VB->ClipPtr->size = 4; 4377117f1b4Smrg VB->ClipPtr->count = VB->Count; 4387117f1b4Smrg } 4397117f1b4Smrg 440af69d88dSmrg VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VARYING_SLOT_COL0]; 441af69d88dSmrg VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VARYING_SLOT_COL1]; 442af69d88dSmrg VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VARYING_SLOT_FOGC]; 443af69d88dSmrg VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VARYING_SLOT_PSIZ]; 444af69d88dSmrg VB->BackfaceColorPtr = &store->results[VARYING_SLOT_BFC0]; 445af69d88dSmrg VB->BackfaceSecondaryColorPtr = &store->results[VARYING_SLOT_BFC1]; 4467117f1b4Smrg 4477117f1b4Smrg for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { 4487117f1b4Smrg VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] 449af69d88dSmrg = &store->results[VARYING_SLOT_TEX0 + i]; 4507117f1b4Smrg } 4517117f1b4Smrg 4527117f1b4Smrg for (i = 0; i < ctx->Const.MaxVarying; i++) { 45301e04c3fSmrg if (program->info.outputs_written & 45401e04c3fSmrg BITFIELD64_BIT(VARYING_SLOT_VAR0 + i)) { 4557117f1b4Smrg /* Note: varying results get put into the generic attributes */ 4567117f1b4Smrg VB->AttribPtr[VERT_ATTRIB_GENERIC0+i] 457af69d88dSmrg = &store->results[VARYING_SLOT_VAR0 + i]; 4587117f1b4Smrg } 4597117f1b4Smrg } 4607117f1b4Smrg 4617117f1b4Smrg 4627117f1b4Smrg /* Perform NDC and cliptest operations: 4637117f1b4Smrg */ 4647117f1b4Smrg return do_ndc_cliptest(ctx, store); 4657117f1b4Smrg} 4667117f1b4Smrg 4677117f1b4Smrg 4687117f1b4Smrg/** 4697117f1b4Smrg * Called the first time stage->run is called. In effect, don't 4707117f1b4Smrg * allocate data until the first time the stage is run. 4717117f1b4Smrg */ 4727117f1b4Smrgstatic GLboolean 4733464ebd5Sriastradhinit_vp(struct gl_context *ctx, struct tnl_pipeline_stage *stage) 4747117f1b4Smrg{ 4757117f1b4Smrg TNLcontext *tnl = TNL_CONTEXT(ctx); 4767117f1b4Smrg struct vertex_buffer *VB = &(tnl->vb); 4777117f1b4Smrg struct vp_stage_data *store; 4787117f1b4Smrg const GLuint size = VB->Size; 4797117f1b4Smrg 480af69d88dSmrg stage->privatePtr = calloc(1, sizeof(*store)); 4817117f1b4Smrg store = VP_STAGE_DATA(stage); 4827117f1b4Smrg if (!store) 4837117f1b4Smrg return GL_FALSE; 4847117f1b4Smrg 4857117f1b4Smrg /* a few other misc allocations */ 4867117f1b4Smrg _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 ); 4877ec681f3Smrg store->clipmask = align_malloc(sizeof(GLubyte)*size, 32 ); 4887117f1b4Smrg 4897117f1b4Smrg return GL_TRUE; 4907117f1b4Smrg} 4917117f1b4Smrg 4927117f1b4Smrg 4937117f1b4Smrg/** 4947117f1b4Smrg * Destructor for this pipeline stage. 4957117f1b4Smrg */ 4967117f1b4Smrgstatic void 4977117f1b4Smrgdtr(struct tnl_pipeline_stage *stage) 4987117f1b4Smrg{ 4997117f1b4Smrg struct vp_stage_data *store = VP_STAGE_DATA(stage); 5007117f1b4Smrg 5017117f1b4Smrg if (store) { 5027117f1b4Smrg GLuint i; 5037117f1b4Smrg 5047117f1b4Smrg /* free the vertex program result arrays */ 505af69d88dSmrg for (i = 0; i < VARYING_SLOT_MAX; i++) 5067117f1b4Smrg _mesa_vector4f_free( &store->results[i] ); 5077117f1b4Smrg 5087117f1b4Smrg /* free misc arrays */ 5097117f1b4Smrg _mesa_vector4f_free( &store->ndcCoords ); 5107ec681f3Smrg align_free( store->clipmask ); 5117117f1b4Smrg 512af69d88dSmrg free( store ); 5137117f1b4Smrg stage->privatePtr = NULL; 5147117f1b4Smrg } 5157117f1b4Smrg} 5167117f1b4Smrg 5177117f1b4Smrg 5187117f1b4Smrgstatic void 5193464ebd5Sriastradhvalidate_vp_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage) 5207117f1b4Smrg{ 5217117f1b4Smrg if (ctx->VertexProgram._Current) { 5227117f1b4Smrg _swrast_update_texture_samplers(ctx); 5237117f1b4Smrg } 5247117f1b4Smrg} 5257117f1b4Smrg 5267117f1b4Smrg 5277117f1b4Smrg 5287117f1b4Smrg/** 5297117f1b4Smrg * Public description of this pipeline stage. 5307117f1b4Smrg */ 5317117f1b4Smrgconst struct tnl_pipeline_stage _tnl_vertex_program_stage = 5327117f1b4Smrg{ 5337117f1b4Smrg "vertex-program", 5347117f1b4Smrg NULL, /* private_data */ 5357117f1b4Smrg init_vp, /* create */ 5367117f1b4Smrg dtr, /* destroy */ 5377117f1b4Smrg validate_vp_stage, /* validate */ 5387117f1b4Smrg run_vp /* run -- initially set to ctr */ 5397117f1b4Smrg}; 540