programopt.c revision 776bc9cf55b116e17dddde4d097985b51879c83f
1c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/* 2c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Mesa 3-D graphics library 3048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Version: 6.5.3 4c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * 5048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * 7c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Permission is hereby granted, free of charge, to any person obtaining a 8c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * copy of this software and associated documentation files (the "Software"), 9c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * to deal in the Software without restriction, including without limitation 10c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * and/or sell copies of the Software, and to permit persons to whom the 12c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Software is furnished to do so, subject to the following conditions: 13c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * 14c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * The above copyright notice and this permission notice shall be included 15c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * in all copies or substantial portions of the Software. 16c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * 17c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 24c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 25c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/** 26c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * \file programopt.c 27c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Vertex/Fragment program optimizations and transformations for program 28c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * options, etc. 29c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * 30c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * \author Brian Paul 31c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 32c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 33c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 34c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul#include "glheader.h" 35c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul#include "context.h" 3657d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_parameter.h" 3757d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_statevars.h" 38c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul#include "programopt.h" 3957d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_instruction.h" 40c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 41c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 42c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/** 433c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * This function inserts instructions for coordinate modelview * projection 443c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * into a vertex program. 453c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * May be used to implement the position_invariant option. 46c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 47c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paulvoid 483c54e8376d639465277fac745b0b8134d2918a9fBrian Paul_mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) 49c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul{ 503c54e8376d639465277fac745b0b8134d2918a9fBrian Paul struct prog_instruction *newInst; 51c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul const GLuint origLen = vprog->Base.NumInstructions; 523c54e8376d639465277fac745b0b8134d2918a9fBrian Paul const GLuint newLen = origLen + 4; 53c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul GLuint i; 54c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 55c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul /* 56c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Setup state references for the modelview/projection matrix. 57c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * XXX we should check if these state vars are already declared. 58c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 59776bc9cf55b116e17dddde4d097985b51879c83fBrian static const GLint mvpState[4][STATE_LENGTH] = { 606531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 0, 0, 0 }, /* state.matrix.mvp.row[0] */ 616531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 1, 1, 0 }, /* state.matrix.mvp.row[1] */ 626531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 2, 2, 0 }, /* state.matrix.mvp.row[2] */ 636531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 3, 3, 0 }, /* state.matrix.mvp.row[3] */ 64c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul }; 65c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul GLint mvpRef[4]; 66c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 67c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul for (i = 0; i < 4; i++) { 68c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, 69c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul mvpState[i]); 70c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 71c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 723c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* Alloc storage for new instructions */ 733c54e8376d639465277fac745b0b8134d2918a9fBrian Paul newInst = _mesa_alloc_instructions(newLen); 743c54e8376d639465277fac745b0b8134d2918a9fBrian Paul if (!newInst) { 753c54e8376d639465277fac745b0b8134d2918a9fBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, 763c54e8376d639465277fac745b0b8134d2918a9fBrian Paul "glProgramString(inserting position_invariant code)"); 773c54e8376d639465277fac745b0b8134d2918a9fBrian Paul return; 783c54e8376d639465277fac745b0b8134d2918a9fBrian Paul } 793c54e8376d639465277fac745b0b8134d2918a9fBrian Paul 80c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul /* 81c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Generated instructions: 82c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position; 83c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position; 84c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position; 85c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position; 86c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 87d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul _mesa_init_instructions(newInst, 4); 88c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul for (i = 0; i < 4; i++) { 89c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].Opcode = OPCODE_DP4; 90c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.File = PROGRAM_OUTPUT; 91c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.Index = VERT_RESULT_HPOS; 92c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.WriteMask = (WRITEMASK_X << i); 93c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR; 94c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].Index = mvpRef[i]; 95c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; 96c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].File = PROGRAM_INPUT; 97c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS; 98c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 99c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 100c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 1013c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* Append original instructions after new instructions */ 1023c54e8376d639465277fac745b0b8134d2918a9fBrian Paul _mesa_memcpy(newInst + 4, vprog->Base.Instructions, 1033c54e8376d639465277fac745b0b8134d2918a9fBrian Paul origLen * sizeof(struct prog_instruction)); 1043c54e8376d639465277fac745b0b8134d2918a9fBrian Paul 1053c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* free old instructions */ 1063c54e8376d639465277fac745b0b8134d2918a9fBrian Paul _mesa_free(vprog->Base.Instructions); 107c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 1083c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* install new instructions */ 1093c54e8376d639465277fac745b0b8134d2918a9fBrian Paul vprog->Base.Instructions = newInst; 1103c54e8376d639465277fac745b0b8134d2918a9fBrian Paul vprog->Base.NumInstructions = newLen; 111c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul vprog->Base.InputsRead |= VERT_BIT_POS; 112c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); 113c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul} 114c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 115c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 116c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 117c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/** 118c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Append extra instructions onto the given fragment program to implement 119f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * the fog mode specified by fprog->FogOption. 120f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * The fragment.fogcoord input is used to compute the fog blend factor. 121f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * 122f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * XXX with a little work, this function could be adapted to add fog code 123f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * to vertex programs too. 124c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 125c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paulvoid 126c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul_mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) 127c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul{ 128776bc9cf55b116e17dddde4d097985b51879c83fBrian static const GLint fogPStateOpt[STATE_LENGTH] 129776bc9cf55b116e17dddde4d097985b51879c83fBrian = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 }; 130776bc9cf55b116e17dddde4d097985b51879c83fBrian static const GLint fogColorState[STATE_LENGTH] 131776bc9cf55b116e17dddde4d097985b51879c83fBrian = { STATE_FOG_COLOR, 0, 0, 0, 0}; 132f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul struct prog_instruction *newInst, *inst; 133f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul const GLuint origLen = fprog->Base.NumInstructions; 134b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger const GLuint newLen = origLen + 5; 135f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul GLuint i; 136b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger GLint fogPRefOpt, fogColorRef; /* state references */ 137f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul GLuint colorTemp, fogFactorTemp; /* temporary registerss */ 138f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 139abb1430c79024198bdc9816465d3c8bc963adf8bBrian Paul if (fprog->FogOption == GL_NONE) { 140f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program" 141f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul " with FogOption == GL_NONE"); 142c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul return; 143f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 144f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 145f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Alloc storage for new instructions */ 146f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul newInst = _mesa_alloc_instructions(newLen); 147f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (!newInst) { 148f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, 149f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul "glProgramString(inserting fog_option code)"); 150c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul return; 151c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 152c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 153f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Copy orig instructions into new instruction buffer */ 154f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_memcpy(newInst, fprog->Base.Instructions, 155f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul origLen * sizeof(struct prog_instruction)); 156f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 157b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* PARAM fogParamsRefOpt = internal optimized fog params; */ 158b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger fogPRefOpt 159b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger = _mesa_add_state_reference(fprog->Base.Parameters, fogPStateOpt); 160f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* PARAM fogColorRef = state.fog.color; */ 161f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fogColorRef 162f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState); 163c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 164f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* TEMP colorTemp; */ 165f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul colorTemp = fprog->Base.NumTemporaries++; 166f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* TEMP fogFactorTemp; */ 167f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fogFactorTemp = fprog->Base.NumTemporaries++; 168c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 169f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Scan program to find where result.color is written */ 170f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst = newInst; 171f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul for (i = 0; i < fprog->Base.NumInstructions; i++) { 172f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (inst->Opcode == OPCODE_END) 173f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul break; 174f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (inst->DstReg.File == PROGRAM_OUTPUT && 175f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index == FRAG_RESULT_COLR) { 176f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* change the instruction to write to colorTemp w/ clamping */ 177f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 178f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = colorTemp; 179f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SaturateMode = SATURATE_ZERO_ONE; 180f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* don't break (may be several writes to result.color) */ 181f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 182f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 183f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 184f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */ 185f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 186b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger _mesa_init_instructions(inst, 5); 187f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 188f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* emit instructions to compute fog blending factor */ 189f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (fprog->FogOption == GL_LINEAR) { 190b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */ 191b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->Opcode = OPCODE_MAD; 192f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 193f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 194f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 195b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].File = PROGRAM_INPUT; 196b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Index = FRAG_ATTRIB_FOGC; 197b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle = SWIZZLE_X; 198f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_STATE_VAR; 199b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Index = fogPRefOpt; 200b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Swizzle = SWIZZLE_X; 201b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].File = PROGRAM_STATE_VAR; 202b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].Index = fogPRefOpt; 203b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].Swizzle = SWIZZLE_Y; 204f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 205f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 206f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul else { 207f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2); 208b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */ 209b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */ 210b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */ 211f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MUL; 212f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 213f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 214f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 215f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_STATE_VAR; 216b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Index = fogPRefOpt; 217b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle 218b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger = (fprog->FogOption == GL_EXP) ? SWIZZLE_Z : SWIZZLE_W; 219f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_INPUT; 220f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; 221f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Swizzle = SWIZZLE_X; 222f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 223f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (fprog->FogOption == GL_EXP2) { 224f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */ 225f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MUL; 226f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 227f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 228f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 229f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 230f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 231b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle = SWIZZLE_X; 232f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_TEMPORARY; 233f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = fogFactorTemp; 234b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Swizzle = SWIZZLE_X; 235f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 236f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 237f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */ 238f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_EX2; 239f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 240f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 241f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 242f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 243f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 244f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].NegateBase = GL_TRUE; 245b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle = SWIZZLE_X; 246f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SaturateMode = SATURATE_ZERO_ONE; 247f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 248f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 249f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */ 250f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_LRP; 251f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_OUTPUT; 252f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = FRAG_RESULT_COLR; 253f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_XYZ; 254f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 255f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 256f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Swizzle 257f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); 258f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_TEMPORARY; 259f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = colorTemp; 260b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Swizzle = SWIZZLE_NOOP; 261f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[2].File = PROGRAM_STATE_VAR; 262f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[2].Index = fogColorRef; 263b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].Swizzle = SWIZZLE_NOOP; 264f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 265f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* MOV result.color.w, colorTemp.x; # copy alpha */ 266f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MOV; 267f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_OUTPUT; 268f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = FRAG_RESULT_COLR; 269f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_W; 270f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 271f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = colorTemp; 272b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; 273f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 274f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* END; */ 275f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_END; 276f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 277f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 278f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* free old instructions */ 279f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_free(fprog->Base.Instructions); 280f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 281f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* install new instructions */ 282f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.Instructions = newInst; 283f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.NumInstructions = inst - newInst; 284f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.InputsRead |= FRAG_BIT_FOGC; 285f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* XXX do this? fprog->FogOption = GL_NONE; */ 286c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul} 287048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 288048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 289048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 290048412473bda3db3e58b9840de5ef82d2ecce3c0Brianstatic GLboolean 291048412473bda3db3e58b9840de5ef82d2ecce3c0Brianis_texture_instruction(const struct prog_instruction *inst) 292048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 293048412473bda3db3e58b9840de5ef82d2ecce3c0Brian switch (inst->Opcode) { 294048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TEX: 295048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXB: 296048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXD: 297048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXL: 298048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXP: 299048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXP_NV: 300048412473bda3db3e58b9840de5ef82d2ecce3c0Brian return GL_TRUE; 301048412473bda3db3e58b9840de5ef82d2ecce3c0Brian default: 302048412473bda3db3e58b9840de5ef82d2ecce3c0Brian return GL_FALSE; 303048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 304048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 305048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 306048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 307048412473bda3db3e58b9840de5ef82d2ecce3c0Brian/** 308048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Count the number of texure indirections in the given program. 309048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * The program's NumTexIndirections field will be updated. 310048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * See the GL_ARB_fragment_program spec (issue 24) for details. 311048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * XXX we count texture indirections in texenvprogram.c (maybe use this code 312048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * instead and elsewhere). 313048412473bda3db3e58b9840de5ef82d2ecce3c0Brian */ 314048412473bda3db3e58b9840de5ef82d2ecce3c0Brianvoid 315048412473bda3db3e58b9840de5ef82d2ecce3c0Brian_mesa_count_texture_indirections(struct gl_program *prog) 316048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 317048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint indirections = 1; 318048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLbitfield tempsOutput = 0x0; 319048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLbitfield aluTemps = 0x0; 320048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint i; 321048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 322048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (i = 0; i < prog->NumInstructions; i++) { 323048412473bda3db3e58b9840de5ef82d2ecce3c0Brian const struct prog_instruction *inst = prog->Instructions + i; 324048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 325048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (is_texture_instruction(inst)) { 326048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (((inst->SrcReg[0].File == PROGRAM_TEMPORARY) && 327048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (tempsOutput & (1 << inst->SrcReg[0].Index))) || 328048412473bda3db3e58b9840de5ef82d2ecce3c0Brian ((inst->Opcode != OPCODE_KIL) && 329048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (inst->DstReg.File == PROGRAM_TEMPORARY) && 330048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (aluTemps & (1 << inst->DstReg.Index)))) 331048412473bda3db3e58b9840de5ef82d2ecce3c0Brian { 332048412473bda3db3e58b9840de5ef82d2ecce3c0Brian indirections++; 333048412473bda3db3e58b9840de5ef82d2ecce3c0Brian tempsOutput = 0x0; 334048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps = 0x0; 335048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 336048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 337048412473bda3db3e58b9840de5ef82d2ecce3c0Brian else { 338048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint j; 339048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (j = 0; j < 3; j++) { 340048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) 341048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps |= (1 << inst->SrcReg[j].Index); 342048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 343048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (inst->DstReg.File == PROGRAM_TEMPORARY) 344048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps |= (1 << inst->DstReg.Index); 345048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 346048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 347048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if ((inst->Opcode != OPCODE_KIL) && (inst->DstReg.File == PROGRAM_TEMPORARY)) 348048412473bda3db3e58b9840de5ef82d2ecce3c0Brian tempsOutput |= (1 << inst->DstReg.Index); 349048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 350048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 351048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexIndirections = indirections; 352048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 353048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 354048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 355048412473bda3db3e58b9840de5ef82d2ecce3c0Brian/** 356048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Count number of texture instructions in given program and update the 357048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * program's NumTexInstructions field. 358048412473bda3db3e58b9840de5ef82d2ecce3c0Brian */ 359048412473bda3db3e58b9840de5ef82d2ecce3c0Brianvoid 360048412473bda3db3e58b9840de5ef82d2ecce3c0Brian_mesa_count_texture_instructions(struct gl_program *prog) 361048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 362048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint i; 363048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexInstructions = 0; 364048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (i = 0; i < prog->NumInstructions; i++) { 365048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexInstructions += is_texture_instruction(prog->Instructions + i); 366048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 367048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 368048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 369