programopt.c revision f5eea0cc7a8c568b00035427294812712c6c6081
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Mesa 3-D graphics library 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: 6.5.2 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to deal in the Software without restriction, including without limitation 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software is furnished to do so, subject to the following conditions: 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice shall be included 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in all copies or substantial portions of the Software. 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */ 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/** 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * \file programopt.c 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Vertex/Fragment program optimizations and transformations for program 28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * options, etc. 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * \author Brian Paul 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "glheader.h" 35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "context.h" 36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "imports.h" 37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "mtypes.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "programopt.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program_instruction.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This function inserts instructions for coordinate modelview * projection 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * into a vertex program. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * May be used to implement the position_invariant option. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct prog_instruction *newInst; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GLuint origLen = vprog->Base.NumInstructions; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GLuint newLen = origLen + 4; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint i; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Setup state references for the modelview/projection matrix. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * XXX we should check if these state vars are already declared. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const GLint mvpState[4][5] = { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { STATE_MATRIX, STATE_MVP, 0, 0, 0 }, /* state.matrix.mvp.row[0] */ 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { STATE_MATRIX, STATE_MVP, 0, 1, 1 }, /* state.matrix.mvp.row[1] */ 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { STATE_MATRIX, STATE_MVP, 0, 2, 2 }, /* state.matrix.mvp.row[2] */ 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { STATE_MATRIX, STATE_MVP, 0, 3, 3 }, /* state.matrix.mvp.row[3] */ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint mvpRef[4]; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < 4; i++) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mvpState[i]); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Alloc storage for new instructions */ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst = _mesa_alloc_instructions(newLen); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!newInst) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_error(ctx, GL_OUT_OF_MEMORY, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "glProgramString(inserting position_invariant code)"); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generated instructions: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < 4; i++) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_init_instruction(newInst + i); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].Opcode = OPCODE_DP4; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].DstReg.File = PROGRAM_OUTPUT; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].DstReg.Index = VERT_RESULT_HPOS; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].DstReg.WriteMask = (WRITEMASK_X << i); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[0].Index = mvpRef[i]; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[1].File = PROGRAM_INPUT; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Append original instructions after new instructions */ 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_memcpy(newInst + 4, vprog->Base.Instructions, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origLen * sizeof(struct prog_instruction)); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* free old instructions */ 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_free(vprog->Base.Instructions); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* install new instructions */ 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vprog->Base.Instructions = newInst; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vprog->Base.NumInstructions = newLen; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vprog->Base.InputsRead |= VERT_BIT_POS; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Append extra instructions onto the given fragment program to implement 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the fog mode specified by fprog->FogOption. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The fragment.fogcoord input is used to compute the fog blend factor. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * XXX with a little work, this function could be adapted to add fog code 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to vertex programs too. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const GLint fogParamsState[] = { STATE_FOG_PARAMS, 0, 0, 0, 0 }; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const GLint fogColorState[] = { STATE_FOG_COLOR, 0, 0, 0, 0 }; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct prog_instruction *newInst, *inst; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GLuint origLen = fprog->Base.NumInstructions; 133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const GLuint newLen = origLen + 6; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint i; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLint fogParamsRef, fogColorRef; /* state references */ 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint colorTemp, fogFactorTemp; /* temporary registerss */ 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLfloat fogVals[4]; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint fogConsts; /* constant values for EXP, EXP2 mode */ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fprog->FogOption != GL_NONE) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program" 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " with FogOption == GL_NONE"); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Alloc storage for new instructions */ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newInst = _mesa_alloc_instructions(newLen); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!newInst) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_error(ctx, GL_OUT_OF_MEMORY, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "glProgramString(inserting fog_option code)"); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Copy orig instructions into new instruction buffer */ 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _mesa_memcpy(newInst, fprog->Base.Instructions, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origLen * sizeof(struct prog_instruction)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* PARAM fogParamsRef = state.fog.params; */ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogParamsRef 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = _mesa_add_state_reference(fprog->Base.Parameters, fogParamsState); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* PARAM fogColorRef = state.fog.color; */ 162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fogColorRef 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch /* TEMP colorTemp; */ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) colorTemp = fprog->Base.NumTemporaries++; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* TEMP fogFactorTemp; */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogFactorTemp = fprog->Base.NumTemporaries++; 169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* PARAM fogVals = { 1/ln(2), 1/sqrt(ln(2), 0, 0 }; */ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogVals[0] = 1.0 / log(2.0); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogVals[1] = 1.0 / SQRTF(log(2.0)); 173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch fogVals[2] = 0.0; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogVals[3] = 0.0; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fogConsts = _mesa_add_unnamed_constant(fprog->Base.Parameters, fogVals); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 177c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch /* Scan program to find where result.color is written */ 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inst = newInst; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < fprog->Base.NumInstructions; i++) { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inst->Opcode == OPCODE_END) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 182 if (inst->DstReg.File == PROGRAM_OUTPUT && 183 inst->DstReg.Index == FRAG_RESULT_COLR) { 184 /* change the instruction to write to colorTemp w/ clamping */ 185 inst->DstReg.File = PROGRAM_TEMPORARY; 186 inst->DstReg.Index = colorTemp; 187 inst->SaturateMode = SATURATE_ZERO_ONE; 188 /* don't break (may be several writes to result.color) */ 189 } 190 inst++; 191 } 192 assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */ 193 194 for (i = 0; i < 6; i++) 195 _mesa_init_instruction(inst + i); 196 197 /* emit instructions to compute fog blending factor */ 198 if (fprog->FogOption == GL_LINEAR) { 199 /* SUB fogFactorTemp.x, fogParamsRef.z, fragment.fogcoord.x; */ 200 inst->Opcode = OPCODE_SUB; 201 inst->DstReg.File = PROGRAM_TEMPORARY; 202 inst->DstReg.Index = fogFactorTemp; 203 inst->DstReg.WriteMask = WRITEMASK_X; 204 inst->SrcReg[0].File = PROGRAM_STATE_VAR; 205 inst->SrcReg[0].Index = fogParamsRef; 206 inst->SrcReg[0].Swizzle = SWIZZLE_Z; 207 inst->SrcReg[1].File = PROGRAM_INPUT; 208 inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; 209 inst++; 210 /* MUL fogFactorTemp.x, fogFactorTemp, fogParamsRef.w; */ 211 inst->Opcode = OPCODE_MUL; 212 inst->DstReg.File = PROGRAM_TEMPORARY; 213 inst->DstReg.Index = fogFactorTemp; 214 inst->DstReg.WriteMask = WRITEMASK_X; 215 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 216 inst->SrcReg[0].Index = fogFactorTemp; 217 inst->SrcReg[1].File = PROGRAM_STATE_VAR; 218 inst->SrcReg[1].Index = fogParamsRef; 219 inst->SrcReg[1].Swizzle = SWIZZLE_W; 220 inst++; 221 } 222 else { 223 ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2); 224 /* MUL fogFactorTemp.x, fogParamsRef.x, fragment.fogcoord; */ 225 inst->Opcode = OPCODE_MUL; 226 inst->DstReg.File = PROGRAM_TEMPORARY; 227 inst->DstReg.Index = fogFactorTemp; 228 inst->DstReg.WriteMask = WRITEMASK_X; 229 inst->SrcReg[0].File = PROGRAM_STATE_VAR; 230 inst->SrcReg[0].Index = fogParamsRef; 231 inst->SrcReg[0].Swizzle = SWIZZLE_X; /* X=density */ 232 inst->SrcReg[1].File = PROGRAM_INPUT; 233 inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; 234 inst->SrcReg[1].Swizzle = SWIZZLE_X; 235 inst++; 236 if (fprog->FogOption == GL_EXP2) { 237 /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */ 238 inst->Opcode = OPCODE_MUL; 239 inst->DstReg.File = PROGRAM_TEMPORARY; 240 inst->DstReg.Index = fogFactorTemp; 241 inst->DstReg.WriteMask = WRITEMASK_X; 242 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 243 inst->SrcReg[0].Index = fogFactorTemp; 244 inst->SrcReg[1].File = PROGRAM_TEMPORARY; 245 inst->SrcReg[1].Index = fogFactorTemp; 246 inst++; 247 } 248 /* EXP: MUL fogFactorTemp.x, fogFactorTemp.x, {1/ln(2)}; */ 249 /* EXP2: MUL fogFactorTemp.x, fogFactorTemp.x, {1/sqrt(ln(2))}; */ 250 inst->Opcode = OPCODE_MUL; 251 inst->DstReg.File = PROGRAM_TEMPORARY; 252 inst->DstReg.Index = fogFactorTemp; 253 inst->DstReg.WriteMask = WRITEMASK_X; 254 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 255 inst->SrcReg[0].Index = fogFactorTemp; 256 inst->SrcReg[1].File = PROGRAM_CONSTANT; 257 inst->SrcReg[1].Index = fogConsts; 258 inst->SrcReg[1].Swizzle 259 = (fprog->FogOption == GL_EXP) ? SWIZZLE_X : SWIZZLE_Y; 260 inst++; 261 /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */ 262 inst->Opcode = OPCODE_EX2; 263 inst->DstReg.File = PROGRAM_TEMPORARY; 264 inst->DstReg.Index = fogFactorTemp; 265 inst->DstReg.WriteMask = WRITEMASK_X; 266 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 267 inst->SrcReg[0].Index = fogFactorTemp; 268 inst->SrcReg[0].NegateBase = GL_TRUE; 269 inst->SaturateMode = SATURATE_ZERO_ONE; 270 inst++; 271 } 272 /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */ 273 inst->Opcode = OPCODE_LRP; 274 inst->DstReg.File = PROGRAM_OUTPUT; 275 inst->DstReg.Index = FRAG_RESULT_COLR; 276 inst->DstReg.WriteMask = WRITEMASK_XYZ; 277 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 278 inst->SrcReg[0].Index = fogFactorTemp; 279 inst->SrcReg[0].Swizzle 280 = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); 281 inst->SrcReg[1].File = PROGRAM_TEMPORARY; 282 inst->SrcReg[1].Index = colorTemp; 283 inst->SrcReg[2].File = PROGRAM_STATE_VAR; 284 inst->SrcReg[2].Index = fogColorRef; 285 inst++; 286 /* MOV result.color.w, colorTemp.x; # copy alpha */ 287 inst->Opcode = OPCODE_MOV; 288 inst->DstReg.File = PROGRAM_OUTPUT; 289 inst->DstReg.Index = FRAG_RESULT_COLR; 290 inst->DstReg.WriteMask = WRITEMASK_W; 291 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 292 inst->SrcReg[0].Index = colorTemp; 293 inst++; 294 /* END; */ 295 inst->Opcode = OPCODE_END; 296 inst++; 297 298 /* free old instructions */ 299 _mesa_free(fprog->Base.Instructions); 300 301 /* install new instructions */ 302 fprog->Base.Instructions = newInst; 303 fprog->Base.NumInstructions = inst - newInst; 304 fprog->Base.InputsRead |= FRAG_BIT_FOGC; 305 /* XXX do this? fprog->FogOption = GL_NONE; */ 306} 307