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 341f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul#include "main/glheader.h" 351f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul#include "main/context.h" 3657d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_parameter.h" 3757d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_statevars.h" 386ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul#include "program.h" 39c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul#include "programopt.h" 4057d9531cd644226d15be4a09ad1492ab647165dcBrian#include "prog_instruction.h" 41c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 42c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 43c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/** 443c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * This function inserts instructions for coordinate modelview * projection 453c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * into a vertex program. 463c54e8376d639465277fac745b0b8134d2918a9fBrian Paul * May be used to implement the position_invariant option. 47c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 48b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwellstatic void 49f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_insert_mvp_dp4_code(struct gl_context *ctx, struct gl_vertex_program *vprog) 50c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul{ 513c54e8376d639465277fac745b0b8134d2918a9fBrian Paul struct prog_instruction *newInst; 52c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul const GLuint origLen = vprog->Base.NumInstructions; 533c54e8376d639465277fac745b0b8134d2918a9fBrian Paul const GLuint newLen = origLen + 4; 54c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul GLuint i; 55c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 56c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul /* 57c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Setup state references for the modelview/projection matrix. 58c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * XXX we should check if these state vars are already declared. 59c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 60aa9d22a1c0f3256497088985c290d4046e089456Brian static const gl_state_index mvpState[4][STATE_LENGTH] = { 616531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 0, 0, 0 }, /* state.matrix.mvp.row[0] */ 626531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 1, 1, 0 }, /* state.matrix.mvp.row[1] */ 636531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 2, 2, 0 }, /* state.matrix.mvp.row[2] */ 646531952b3c979be0dc95704beb3c3b9dad1dc37bBrian { STATE_MVP_MATRIX, 0, 3, 3, 0 }, /* state.matrix.mvp.row[3] */ 65c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul }; 66c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul GLint mvpRef[4]; 67c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 68c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul for (i = 0; i < 4; i++) { 69c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, 70c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul mvpState[i]); 71c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 72c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 733c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* Alloc storage for new instructions */ 743c54e8376d639465277fac745b0b8134d2918a9fBrian Paul newInst = _mesa_alloc_instructions(newLen); 753c54e8376d639465277fac745b0b8134d2918a9fBrian Paul if (!newInst) { 763c54e8376d639465277fac745b0b8134d2918a9fBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, 773c54e8376d639465277fac745b0b8134d2918a9fBrian Paul "glProgramString(inserting position_invariant code)"); 783c54e8376d639465277fac745b0b8134d2918a9fBrian Paul return; 793c54e8376d639465277fac745b0b8134d2918a9fBrian Paul } 803c54e8376d639465277fac745b0b8134d2918a9fBrian Paul 81c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul /* 82c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * Generated instructions: 83c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position; 84c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position; 85c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position; 86c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position; 87c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 88d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul _mesa_init_instructions(newInst, 4); 89c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul for (i = 0; i < 4; i++) { 90c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].Opcode = OPCODE_DP4; 91c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.File = PROGRAM_OUTPUT; 92c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.Index = VERT_RESULT_HPOS; 93c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].DstReg.WriteMask = (WRITEMASK_X << i); 94c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR; 95c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].Index = mvpRef[i]; 96c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; 97c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].File = PROGRAM_INPUT; 98c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS; 99c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 100c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 101c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 1023c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* Append original instructions after new instructions */ 103cfe984dbd0c478906785dbf8a9430504173ae952Oliver McFadden _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen); 1043c54e8376d639465277fac745b0b8134d2918a9fBrian Paul 1053c54e8376d639465277fac745b0b8134d2918a9fBrian Paul /* free old instructions */ 1066ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul _mesa_free_instructions(vprog->Base.Instructions, origLen); 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; 1125606dfb572bf4b89b4882265924705bacc8c182bIan Romanick vprog->Base.OutputsWritten |= BITFIELD64_BIT(VERT_RESULT_HPOS); 113c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul} 114c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 115c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 116b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwellstatic void 117f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_insert_mvp_mad_code(struct gl_context *ctx, struct gl_vertex_program *vprog) 118b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell{ 119b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell struct prog_instruction *newInst; 120b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell const GLuint origLen = vprog->Base.NumInstructions; 121b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell const GLuint newLen = origLen + 4; 122b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell GLuint hposTemp; 123b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell GLuint i; 124b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 125b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* 126b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * Setup state references for the modelview/projection matrix. 127b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * XXX we should check if these state vars are already declared. 128b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell */ 129b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell static const gl_state_index mvpState[4][STATE_LENGTH] = { 130b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell { STATE_MVP_MATRIX, 0, 0, 0, STATE_MATRIX_TRANSPOSE }, 131b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell { STATE_MVP_MATRIX, 0, 1, 1, STATE_MATRIX_TRANSPOSE }, 132b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell { STATE_MVP_MATRIX, 0, 2, 2, STATE_MATRIX_TRANSPOSE }, 133b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell { STATE_MVP_MATRIX, 0, 3, 3, STATE_MATRIX_TRANSPOSE }, 134b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell }; 135b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell GLint mvpRef[4]; 136b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 137b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell for (i = 0; i < 4; i++) { 138b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, 139b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell mvpState[i]); 140b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell } 141b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 142b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* Alloc storage for new instructions */ 143b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst = _mesa_alloc_instructions(newLen); 144b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell if (!newInst) { 145b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_error(ctx, GL_OUT_OF_MEMORY, 146b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell "glProgramString(inserting position_invariant code)"); 147b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell return; 148b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell } 149b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 150b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* TEMP hposTemp; */ 151b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell hposTemp = vprog->Base.NumTemporaries++; 152b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 153b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* 154b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * Generated instructions: 155b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * emit_op2(p, OPCODE_MUL, tmp, 0, swizzle1(src,X), mat[0]); 156b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Y), mat[1], tmp); 157b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * emit_op3(p, OPCODE_MAD, tmp, 0, swizzle1(src,Z), mat[2], tmp); 158b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell * emit_op3(p, OPCODE_MAD, dest, 0, swizzle1(src,W), mat[3], tmp); 159b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell */ 160b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_init_instructions(newInst, 4); 161b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 162b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].Opcode = OPCODE_MUL; 163b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].DstReg.File = PROGRAM_TEMPORARY; 164b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].DstReg.Index = hposTemp; 165b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].DstReg.WriteMask = WRITEMASK_XYZW; 166b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[0].File = PROGRAM_INPUT; 167b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[0].Index = VERT_ATTRIB_POS; 168b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[0].Swizzle = SWIZZLE_XXXX; 169b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[1].File = PROGRAM_STATE_VAR; 170b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[1].Index = mvpRef[0]; 171b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[0].SrcReg[1].Swizzle = SWIZZLE_NOOP; 172b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 173b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell for (i = 1; i <= 2; i++) { 174b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].Opcode = OPCODE_MAD; 175b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].DstReg.File = PROGRAM_TEMPORARY; 176b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].DstReg.Index = hposTemp; 177b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].DstReg.WriteMask = WRITEMASK_XYZW; 178b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[0].File = PROGRAM_INPUT; 179b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[0].Index = VERT_ATTRIB_POS; 180b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[0].Swizzle = MAKE_SWIZZLE4(i,i,i,i); 181b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[1].File = PROGRAM_STATE_VAR; 182b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[1].Index = mvpRef[i]; 183b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 184b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[2].File = PROGRAM_TEMPORARY; 185b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[i].SrcReg[2].Index = hposTemp; 186b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[1].SrcReg[2].Swizzle = SWIZZLE_NOOP; 187b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell } 188b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 189b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].Opcode = OPCODE_MAD; 190b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].DstReg.File = PROGRAM_OUTPUT; 191b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].DstReg.Index = VERT_RESULT_HPOS; 192b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].DstReg.WriteMask = WRITEMASK_XYZW; 193b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[0].File = PROGRAM_INPUT; 194b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[0].Index = VERT_ATTRIB_POS; 195b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[0].Swizzle = SWIZZLE_WWWW; 196b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[1].File = PROGRAM_STATE_VAR; 197b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[1].Index = mvpRef[3]; 198b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[1].Swizzle = SWIZZLE_NOOP; 199b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[2].File = PROGRAM_TEMPORARY; 200b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[2].Index = hposTemp; 201b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell newInst[3].SrcReg[2].Swizzle = SWIZZLE_NOOP; 202b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 203b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 204b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* Append original instructions after new instructions */ 205b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen); 206b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 207b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* free old instructions */ 208b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_free_instructions(vprog->Base.Instructions, origLen); 209b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 210b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell /* install new instructions */ 211b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell vprog->Base.Instructions = newInst; 212b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell vprog->Base.NumInstructions = newLen; 213b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell vprog->Base.InputsRead |= VERT_BIT_POS; 2145606dfb572bf4b89b4882265924705bacc8c182bIan Romanick vprog->Base.OutputsWritten |= BITFIELD64_BIT(VERT_RESULT_HPOS); 215b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell} 216b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 217b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 218b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwellvoid 219f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_insert_mvp_code(struct gl_context *ctx, struct gl_vertex_program *vprog) 220b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell{ 221b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell if (ctx->mvp_with_dp4) 222b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_insert_mvp_dp4_code( ctx, vprog ); 223b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell else 224b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell _mesa_insert_mvp_mad_code( ctx, vprog ); 225b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell} 226b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 227b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 228b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 229b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 230b6e8256899a9a93c665c34e10efcc918f2fcc095Keith Whitwell 231c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 232c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul/** 2334d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * Append instructions to implement fog 234f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * 2354d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * The \c fragment.fogcoord input is used to compute the fog blend factor. 2364d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * 2374d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \param ctx The GL context 2384d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \param fprog Fragment program that fog instructions will be appended to. 2394d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \param fog_mode Fog mode. One of \c GL_EXP, \c GL_EXP2, or \c GL_LINEAR. 2404d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \param saturate True if writes to color outputs should be clamped to [0, 1] 2414d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * 2424d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \note 2434d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * This function sets \c FRAG_BIT_FOGC in \c fprog->Base.InputsRead. 2444d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * 2454d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick * \todo With a little work, this function could be adapted to add fog code 246f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul * to vertex programs too. 247c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul */ 248c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paulvoid 2494d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick_mesa_append_fog_code(struct gl_context *ctx, 2504d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick struct gl_fragment_program *fprog, GLenum fog_mode, 2514d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick GLboolean saturate) 252c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul{ 253aa9d22a1c0f3256497088985c290d4046e089456Brian static const gl_state_index fogPStateOpt[STATE_LENGTH] 254776bc9cf55b116e17dddde4d097985b51879c83fBrian = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 }; 255aa9d22a1c0f3256497088985c290d4046e089456Brian static const gl_state_index fogColorState[STATE_LENGTH] 256776bc9cf55b116e17dddde4d097985b51879c83fBrian = { STATE_FOG_COLOR, 0, 0, 0, 0}; 257f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul struct prog_instruction *newInst, *inst; 258f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul const GLuint origLen = fprog->Base.NumInstructions; 259b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger const GLuint newLen = origLen + 5; 260f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul GLuint i; 261b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger GLint fogPRefOpt, fogColorRef; /* state references */ 262f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul GLuint colorTemp, fogFactorTemp; /* temporary registerss */ 263f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 2644d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick if (fog_mode == GL_NONE) { 265f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program" 2664d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick " with fog_mode == GL_NONE"); 267c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul return; 268f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 269f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 2707a271151a5d6990c8325008f19ab621d730d06c4José Fonseca if (!(fprog->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR))) { 2717a271151a5d6990c8325008f19ab621d730d06c4José Fonseca /* program doesn't output color, so nothing to do */ 2727a271151a5d6990c8325008f19ab621d730d06c4José Fonseca return; 2737a271151a5d6990c8325008f19ab621d730d06c4José Fonseca } 2747a271151a5d6990c8325008f19ab621d730d06c4José Fonseca 275f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Alloc storage for new instructions */ 276f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul newInst = _mesa_alloc_instructions(newLen); 277f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (!newInst) { 278f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, 279f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul "glProgramString(inserting fog_option code)"); 280c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul return; 281c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul } 282c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 283f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Copy orig instructions into new instruction buffer */ 28412229f119d754715e0315846fdd8d6e9213e8edfBrian _mesa_copy_instructions(newInst, fprog->Base.Instructions, origLen); 285f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 286b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* PARAM fogParamsRefOpt = internal optimized fog params; */ 287b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger fogPRefOpt 288b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger = _mesa_add_state_reference(fprog->Base.Parameters, fogPStateOpt); 289f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* PARAM fogColorRef = state.fog.color; */ 290f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fogColorRef 291f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState); 292c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 293f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* TEMP colorTemp; */ 294f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul colorTemp = fprog->Base.NumTemporaries++; 295f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* TEMP fogFactorTemp; */ 296f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fogFactorTemp = fprog->Base.NumTemporaries++; 297c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul 298f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* Scan program to find where result.color is written */ 299f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst = newInst; 300f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul for (i = 0; i < fprog->Base.NumInstructions; i++) { 301f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (inst->Opcode == OPCODE_END) 302f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul break; 303f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul if (inst->DstReg.File == PROGRAM_OUTPUT && 3048d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul inst->DstReg.Index == FRAG_RESULT_COLOR) { 305f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* change the instruction to write to colorTemp w/ clamping */ 306f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 307f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = colorTemp; 308e5c6a92a12b5cd7db205d72039f58d302b0be9d5Marek Olšák inst->SaturateMode = saturate; 309f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* don't break (may be several writes to result.color) */ 310f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 311f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 312f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 313f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */ 314f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 315b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger _mesa_init_instructions(inst, 5); 316f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 317f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* emit instructions to compute fog blending factor */ 318e5c6a92a12b5cd7db205d72039f58d302b0be9d5Marek Olšák /* this is always clamped to [0, 1] regardless of fragment clamping */ 3194d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick if (fog_mode == GL_LINEAR) { 320b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */ 321b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->Opcode = OPCODE_MAD; 322f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 323f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 324f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 325b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].File = PROGRAM_INPUT; 326b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Index = FRAG_ATTRIB_FOGC; 327e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 328f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_STATE_VAR; 329b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Index = fogPRefOpt; 330e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 331b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].File = PROGRAM_STATE_VAR; 332b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].Index = fogPRefOpt; 333e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[2].Swizzle = SWIZZLE_YYYY; 3341560de2c3c7f9d4e07b34e805e649769ca5a0cbeBrian inst->SaturateMode = SATURATE_ZERO_ONE; 335f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 336f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 337f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul else { 3384d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick ASSERT(fog_mode == GL_EXP || fog_mode == GL_EXP2); 339b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */ 340b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */ 341b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger /* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */ 342f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MUL; 343f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 344f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 345f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 346f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_STATE_VAR; 347b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Index = fogPRefOpt; 348b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle 3494d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick = (fog_mode == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW; 350f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_INPUT; 351f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; 352e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 353f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 3544d203a01e20dedcfaab09c18922e8ed9dcb39729Ian Romanick if (fog_mode == GL_EXP2) { 355f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */ 356f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MUL; 357f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 358f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 359f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 360f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 361f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 362e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 363f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_TEMPORARY; 364f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = fogFactorTemp; 365e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 366f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 367f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 368f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */ 369f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_EX2; 370f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 371f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.Index = fogFactorTemp; 372f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_X; 373f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 374f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 3757db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul inst->SrcReg[0].Negate = NEGATE_XYZW; 376e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 377f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SaturateMode = SATURATE_ZERO_ONE; 378f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 379f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul } 380f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */ 381f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_LRP; 382f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_OUTPUT; 3838d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul inst->DstReg.Index = FRAG_RESULT_COLOR; 384f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_XYZ; 385f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 386f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = fogFactorTemp; 387e0f160663e50d0481afd8a9e1ec90c334be489e1Brian Paul inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 388f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].File = PROGRAM_TEMPORARY; 389f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[1].Index = colorTemp; 390b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[1].Swizzle = SWIZZLE_NOOP; 391f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[2].File = PROGRAM_STATE_VAR; 392f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[2].Index = fogColorRef; 393b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[2].Swizzle = SWIZZLE_NOOP; 394f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 395f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* MOV result.color.w, colorTemp.x; # copy alpha */ 396f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_MOV; 397f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.File = PROGRAM_OUTPUT; 3988d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul inst->DstReg.Index = FRAG_RESULT_COLOR; 399f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->DstReg.WriteMask = WRITEMASK_W; 400f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 401f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->SrcReg[0].Index = colorTemp; 402b2d30ca0cb01a80ff440a4a07b293daa16486e12Roland Scheidegger inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; 403f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 404f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* END; */ 405f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst->Opcode = OPCODE_END; 406f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul inst++; 407f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 408f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* free old instructions */ 4096ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul _mesa_free_instructions(fprog->Base.Instructions, origLen); 410f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul 411f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul /* install new instructions */ 412f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.Instructions = newInst; 413f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.NumInstructions = inst - newInst; 414f5eea0cc7a8c568b00035427294812712c6c6081Brian Paul fprog->Base.InputsRead |= FRAG_BIT_FOGC; 4157a271151a5d6990c8325008f19ab621d730d06c4José Fonseca assert(fprog->Base.OutputsWritten & (1 << FRAG_RESULT_COLOR)); 416c6511ab950e2865e606ff13ce87f0ffc782c57adBrian Paul} 417048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 418048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 419048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 420048412473bda3db3e58b9840de5ef82d2ecce3c0Brianstatic GLboolean 421048412473bda3db3e58b9840de5ef82d2ecce3c0Brianis_texture_instruction(const struct prog_instruction *inst) 422048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 423048412473bda3db3e58b9840de5ef82d2ecce3c0Brian switch (inst->Opcode) { 424048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TEX: 425048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXB: 426048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXD: 427048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXL: 428048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXP: 429048412473bda3db3e58b9840de5ef82d2ecce3c0Brian case OPCODE_TXP_NV: 430048412473bda3db3e58b9840de5ef82d2ecce3c0Brian return GL_TRUE; 431048412473bda3db3e58b9840de5ef82d2ecce3c0Brian default: 432048412473bda3db3e58b9840de5ef82d2ecce3c0Brian return GL_FALSE; 433048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 434048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 435048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 436048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 437048412473bda3db3e58b9840de5ef82d2ecce3c0Brian/** 438048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Count the number of texure indirections in the given program. 439048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * The program's NumTexIndirections field will be updated. 440048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * See the GL_ARB_fragment_program spec (issue 24) for details. 441048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * XXX we count texture indirections in texenvprogram.c (maybe use this code 442048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * instead and elsewhere). 443048412473bda3db3e58b9840de5ef82d2ecce3c0Brian */ 444048412473bda3db3e58b9840de5ef82d2ecce3c0Brianvoid 445048412473bda3db3e58b9840de5ef82d2ecce3c0Brian_mesa_count_texture_indirections(struct gl_program *prog) 446048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 447048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint indirections = 1; 448048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLbitfield tempsOutput = 0x0; 449048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLbitfield aluTemps = 0x0; 450048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint i; 451048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 452048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (i = 0; i < prog->NumInstructions; i++) { 453048412473bda3db3e58b9840de5ef82d2ecce3c0Brian const struct prog_instruction *inst = prog->Instructions + i; 454048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 455048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (is_texture_instruction(inst)) { 456048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (((inst->SrcReg[0].File == PROGRAM_TEMPORARY) && 457048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (tempsOutput & (1 << inst->SrcReg[0].Index))) || 458048412473bda3db3e58b9840de5ef82d2ecce3c0Brian ((inst->Opcode != OPCODE_KIL) && 459048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (inst->DstReg.File == PROGRAM_TEMPORARY) && 460048412473bda3db3e58b9840de5ef82d2ecce3c0Brian (aluTemps & (1 << inst->DstReg.Index)))) 461048412473bda3db3e58b9840de5ef82d2ecce3c0Brian { 462048412473bda3db3e58b9840de5ef82d2ecce3c0Brian indirections++; 463048412473bda3db3e58b9840de5ef82d2ecce3c0Brian tempsOutput = 0x0; 464048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps = 0x0; 465048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 466048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 467048412473bda3db3e58b9840de5ef82d2ecce3c0Brian else { 468048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint j; 469048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (j = 0; j < 3; j++) { 470048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) 471048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps |= (1 << inst->SrcReg[j].Index); 472048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 473048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if (inst->DstReg.File == PROGRAM_TEMPORARY) 474048412473bda3db3e58b9840de5ef82d2ecce3c0Brian aluTemps |= (1 << inst->DstReg.Index); 475048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 476048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 477048412473bda3db3e58b9840de5ef82d2ecce3c0Brian if ((inst->Opcode != OPCODE_KIL) && (inst->DstReg.File == PROGRAM_TEMPORARY)) 478048412473bda3db3e58b9840de5ef82d2ecce3c0Brian tempsOutput |= (1 << inst->DstReg.Index); 479048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 480048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 481048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexIndirections = indirections; 482048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 483048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 484048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 485048412473bda3db3e58b9840de5ef82d2ecce3c0Brian/** 486048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * Count number of texture instructions in given program and update the 487048412473bda3db3e58b9840de5ef82d2ecce3c0Brian * program's NumTexInstructions field. 488048412473bda3db3e58b9840de5ef82d2ecce3c0Brian */ 489048412473bda3db3e58b9840de5ef82d2ecce3c0Brianvoid 490048412473bda3db3e58b9840de5ef82d2ecce3c0Brian_mesa_count_texture_instructions(struct gl_program *prog) 491048412473bda3db3e58b9840de5ef82d2ecce3c0Brian{ 492048412473bda3db3e58b9840de5ef82d2ecce3c0Brian GLuint i; 493048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexInstructions = 0; 494048412473bda3db3e58b9840de5ef82d2ecce3c0Brian for (i = 0; i < prog->NumInstructions; i++) { 495048412473bda3db3e58b9840de5ef82d2ecce3c0Brian prog->NumTexInstructions += is_texture_instruction(prog->Instructions + i); 496048412473bda3db3e58b9840de5ef82d2ecce3c0Brian } 497048412473bda3db3e58b9840de5ef82d2ecce3c0Brian} 498048412473bda3db3e58b9840de5ef82d2ecce3c0Brian 4996ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5006ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul/** 501928ec5cd3be5c7d6f3d9df0ace18371b1ec8c68cZack Rusin * Scan/rewrite program to remove reads of custom (output) registers. 5021f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul * The passed type has to be either PROGRAM_OUTPUT or PROGRAM_VARYING 5031f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul * (for vertex shaders). 5041f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul * In GLSL shaders, varying vars can be read and written. 5056ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * On some hardware, trying to read an output register causes trouble. 5066ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul * So, rewrite the program to use a temporary register in this case. 5076ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul */ 5086ca948a303e1af7ae66ea7082af741f6880887f2Brian Paulvoid 509b4026d9be828bd0b6f60158456edf24994efb053Brian Paul_mesa_remove_output_reads(struct gl_program *prog, gl_register_file type) 5106ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul{ 5116ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul GLuint i; 5126ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul GLint outputMap[VERT_RESULT_MAX]; 5136ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul GLuint numVaryingReads = 0; 514a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul GLboolean usedTemps[MAX_PROGRAM_TEMPS]; 515a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul GLuint firstTemp = 0; 516a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul 517a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul _mesa_find_used_registers(prog, PROGRAM_TEMPORARY, 518a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul usedTemps, MAX_PROGRAM_TEMPS); 5196ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 52095b34baa8f981b08e21a36f9163d98a426559839Zack Rusin assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT); 5211f4997c2aaf424c8a12cc6fdb1dd994f66074a1dBrian Paul assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING); 5226ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5236ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (i = 0; i < VERT_RESULT_MAX; i++) 5246ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul outputMap[i] = -1; 5256ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5266ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* look for instructions which read from varying vars */ 5276ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (i = 0; i < prog->NumInstructions; i++) { 5286ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul struct prog_instruction *inst = prog->Instructions + i; 5296ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); 5306ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul GLuint j; 5316ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (j = 0; j < numSrc; j++) { 532928ec5cd3be5c7d6f3d9df0ace18371b1ec8c68cZack Rusin if (inst->SrcReg[j].File == type) { 5336ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* replace the read with a temp reg */ 5346ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul const GLuint var = inst->SrcReg[j].Index; 5356ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul if (outputMap[var] == -1) { 5366ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul numVaryingReads++; 537a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul outputMap[var] = _mesa_find_free_register(usedTemps, 538a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul MAX_PROGRAM_TEMPS, 539a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul firstTemp); 540a2ddb3d20964e562e3dcb0e973f300362a9d5d69Brian Paul firstTemp = outputMap[var] + 1; 5416ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5426ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->SrcReg[j].File = PROGRAM_TEMPORARY; 5436ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->SrcReg[j].Index = outputMap[var]; 5446ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5456ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5466ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5476ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5486ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul if (numVaryingReads == 0) 5496ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul return; /* nothing to be done */ 5506ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5516ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* look for instructions which write to the varying vars identified above */ 5526ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (i = 0; i < prog->NumInstructions; i++) { 5536ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul struct prog_instruction *inst = prog->Instructions + i; 554d8f8eca9efaf2f537cf9218e4dd1d742e19ffc76Brian Paul if (inst->DstReg.File == type && 555d8f8eca9efaf2f537cf9218e4dd1d742e19ffc76Brian Paul outputMap[inst->DstReg.Index] >= 0) { 556d8f8eca9efaf2f537cf9218e4dd1d742e19ffc76Brian Paul /* change inst to write to the temp reg, instead of the varying */ 557d8f8eca9efaf2f537cf9218e4dd1d742e19ffc76Brian Paul inst->DstReg.File = PROGRAM_TEMPORARY; 558d8f8eca9efaf2f537cf9218e4dd1d742e19ffc76Brian Paul inst->DstReg.Index = outputMap[inst->DstReg.Index]; 5596ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5606ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5616ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5626ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* insert new instructions to copy the temp vars to the varying vars */ 5636ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul { 5646ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul struct prog_instruction *inst; 5656ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul GLint endPos, var; 5666ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5676ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* Look for END instruction and insert the new varying writes */ 5686ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul endPos = -1; 5696ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (i = 0; i < prog->NumInstructions; i++) { 5706ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul struct prog_instruction *inst = prog->Instructions + i; 5716ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul if (inst->Opcode == OPCODE_END) { 5726ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul endPos = i; 5736ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul _mesa_insert_instructions(prog, i, numVaryingReads); 5746ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul break; 5756ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5766ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5776ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5786ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul assert(endPos >= 0); 5796ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul 5806ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* insert new MOV instructions here */ 5816ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst = prog->Instructions + endPos; 5826ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul for (var = 0; var < VERT_RESULT_MAX; var++) { 5836ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul if (outputMap[var] >= 0) { 5846ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul /* MOV VAR[var], TEMP[tmp]; */ 5856ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->Opcode = OPCODE_MOV; 586928ec5cd3be5c7d6f3d9df0ace18371b1ec8c68cZack Rusin inst->DstReg.File = type; 5876ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->DstReg.Index = var; 5886ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->SrcReg[0].File = PROGRAM_TEMPORARY; 5896ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst->SrcReg[0].Index = outputMap[var]; 5906ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul inst++; 5916ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5926ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5936ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul } 5946ca948a303e1af7ae66ea7082af741f6880887f2Brian Paul} 595c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 596c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 597c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul/** 598c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * Make the given fragment program into a "no-op" shader. 599c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * Actually, just copy the incoming fragment color (or texcoord) 600c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * to the output color. 601c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * This is for debug/test purposes. 602c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul */ 603c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paulvoid 604f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_nop_fragment_program(struct gl_context *ctx, struct gl_fragment_program *prog) 605c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul{ 606c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul struct prog_instruction *inst; 607c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul GLuint inputAttr; 608c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 609c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst = _mesa_alloc_instructions(2); 610c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul if (!inst) { 611c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_fragment_program"); 612c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul return; 613c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul } 614c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 615c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_init_instructions(inst, 2); 616c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 617c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].Opcode = OPCODE_MOV; 618c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].DstReg.File = PROGRAM_OUTPUT; 619c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].DstReg.Index = FRAG_RESULT_COLOR; 620c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].SrcReg[0].File = PROGRAM_INPUT; 621c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul if (prog->Base.InputsRead & FRAG_BIT_COL0) 622c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inputAttr = FRAG_ATTRIB_COL0; 623c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul else 624c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inputAttr = FRAG_ATTRIB_TEX0; 625c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].SrcReg[0].Index = inputAttr; 626c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 627c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[1].Opcode = OPCODE_END; 628c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 629c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_free_instructions(prog->Base.Instructions, 630c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.NumInstructions); 631c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 632c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.Instructions = inst; 633c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.NumInstructions = 2; 634dca6a28a14f22d77273d79d44f57b0d853c0242dMathias Fröhlich prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); 6355606dfb572bf4b89b4882265924705bacc8c182bIan Romanick prog->Base.OutputsWritten = BITFIELD64_BIT(FRAG_RESULT_COLOR); 636c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul} 637c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 638c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 639c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul/** 640c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * \sa _mesa_nop_fragment_program 641c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * Replace the given vertex program with a "no-op" program that just 642c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * transforms vertex position and emits color. 643c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul */ 644c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paulvoid 645f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_nop_vertex_program(struct gl_context *ctx, struct gl_vertex_program *prog) 646c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul{ 647c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul struct prog_instruction *inst; 648c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul GLuint inputAttr; 649c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 650c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul /* 651c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * Start with a simple vertex program that emits color. 652c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul */ 653c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst = _mesa_alloc_instructions(2); 654c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul if (!inst) { 655c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "_mesa_nop_vertex_program"); 656c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul return; 657c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul } 658c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 659c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_init_instructions(inst, 2); 660c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 661c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].Opcode = OPCODE_MOV; 662c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].DstReg.File = PROGRAM_OUTPUT; 663c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].DstReg.Index = VERT_RESULT_COL0; 664c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].SrcReg[0].File = PROGRAM_INPUT; 665c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul if (prog->Base.InputsRead & VERT_BIT_COLOR0) 666c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inputAttr = VERT_ATTRIB_COLOR0; 667c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul else 668c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inputAttr = VERT_ATTRIB_TEX0; 669c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[0].SrcReg[0].Index = inputAttr; 670c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 671c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul inst[1].Opcode = OPCODE_END; 672c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 673c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_free_instructions(prog->Base.Instructions, 674c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.NumInstructions); 675c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 676c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.Instructions = inst; 677c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul prog->Base.NumInstructions = 2; 678dca6a28a14f22d77273d79d44f57b0d853c0242dMathias Fröhlich prog->Base.InputsRead = BITFIELD64_BIT(inputAttr); 6795606dfb572bf4b89b4882265924705bacc8c182bIan Romanick prog->Base.OutputsWritten = BITFIELD64_BIT(VERT_RESULT_COL0); 680c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul 681c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul /* 682c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul * Now insert code to do standard modelview/projection transformation. 683c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul */ 684c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul _mesa_insert_mvp_code(ctx, prog); 685c7aee65bb96df3f8e8421b5125dca84c028e9073Brian Paul} 686