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