ff_fragment_shader.cpp revision 239617fbe22d4dd7b2794510a6665f09602b5adf
115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/**************************************************************************
215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
3f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * All Rights Reserved.
515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * copy of this software and associated documentation files (the
815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * "Software"), to deal in the Software without restriction, including
915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * without limitation the rights to use, copy, modify, merge, publish,
1015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * distribute, sub license, and/or sell copies of the Software, and to
1115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * permit persons to whom the Software is furnished to do so, subject to
1215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * the following conditions:
1315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * The above copyright notice and this permission notice (including the
1515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * next paragraph) shall be included in all copies or substantial portions
1615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * of the Software.
1715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
2615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell **************************************************************************/
2715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
2815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "glheader.h"
2915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "macros.h"
3015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "enums.h"
31c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_parameter.h"
32f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian#include "shader/prog_cache.h"
33c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_instruction.h"
34c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_print.h"
35c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_statevars.h"
3683fad68ec1989c719646a76f4cc5e0b3d23537edBrian#include "shader/programopt.h"
3715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "texenvprogram.h"
3815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul/**
403f99f501db2582e241851e63e432c18e2de415beBrian Paul * Up to nine instructions per tex unit, plus fog, specular color.
41e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul */
423f99f501db2582e241851e63e432c18e2de415beBrian Paul#define MAX_INSTRUCTIONS ((MAX_TEXTURE_UNITS * 9) + 12)
4315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
44269e3895d9837ac7303b91948f003ca5c12c0fe4Keith Whitwell#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
4515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
46ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct mode_opt {
476280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLubyte Source:4;
486280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLubyte Operand:3;
49ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
50ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
51ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct state_key {
526280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint nr_enabled_units:8;
536280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint enabled_units:8;
545d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint separate_specular:1;
555d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_enabled:1;
565d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_mode:2;
576280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint inputs_available:12;
58ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
59ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct {
605d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint enabled:1;
615d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
625d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftRGB:2;
635d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftA:2;
64ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
655d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsRGB:2;
665d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeRGB:4;
675d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsA:2;
685d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeA:4;
696280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell
706280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell      struct mode_opt OptRGB[3];
71ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      struct mode_opt OptA[3];
72ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } unit[8];
73ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
74ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
75ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_LINEAR  0
76ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP     1
77ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP2    2
78ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_UNKNOWN 3
79ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
80ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
81ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
82ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
83ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
84ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP: return FOG_EXP;
85ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP2: return FOG_EXP2;
86ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return FOG_UNKNOWN;
87ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
88ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
89ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
90ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_COLOR           0
91ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_COLOR 1
92ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_ALPHA           2
93ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_ALPHA	3
94ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ZERO                4
95ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE                 5
96ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_UNKNOWN             7
97ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
98ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_operand( GLenum operand )
99ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
100ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (operand) {
101ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_COLOR: return OPR_SRC_COLOR;
102ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
103ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
104ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
105ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ZERO: return OPR_ZERO;
106ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE: return OPR_ONE;
107ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:	return OPR_UNKNOWN;
108ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
109ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
110ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
111ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE  0
112ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE0 1
113ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE1 2
114ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE2 3
115ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE3 4
116ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE4 5
117ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE5 6
118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE6 7
119ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE7 8
120ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_CONSTANT 9
121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PRIMARY_COLOR 10
122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PREVIOUS 11
123ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_UNKNOWN  15
124ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
125ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_source( GLenum src )
126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (src) {
128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE: return SRC_TEXTURE;
129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE0:
130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE1:
131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE2:
132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE3:
133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE4:
134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE5:
135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE6:
136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_CONSTANT: return SRC_CONSTANT;
138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PREVIOUS: return SRC_PREVIOUS;
140ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return SRC_UNKNOWN;
141ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
142ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
143ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
144ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_REPLACE       0
145ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE      1
146ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD           2
147ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD_SIGNED    3
148ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_INTERPOLATE   4
149ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_SUBTRACT      5
150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB      6
151ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB_EXT  7
152ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA     8
153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA_EXT 9
154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_ADD_ATI           10
155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SIGNED_ADD_ATI    11
156ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SUBTRACT_ATI      12
157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_UNKNOWN       15
158ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
159ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_mode( GLenum mode )
160ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_REPLACE: return MODE_REPLACE;
163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE: return MODE_MODULATE;
164ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD: return MODE_ADD;
165ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
166ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_INTERPOLATE: return MODE_INTERPOLATE;
167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SUBTRACT: return MODE_SUBTRACT;
168ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB: return MODE_DOT3_RGB;
169ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
175ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return MODE_UNKNOWN;
176ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define TEXTURE_UNKNOWN_INDEX 7
180e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paulstatic GLuint translate_tex_src_bit( GLbitfield bit )
181ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
182ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (bit) {
183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
184ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
185ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
186ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
187ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return TEXTURE_UNKNOWN_INDEX;
189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
190ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
191ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1921680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
1931680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
1941680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
195239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
196239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Identify all possible varying inputs.  The fragment program will
1971680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * never reference non-varying inputs, but will track them via state
1981680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * constants instead.
1991680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell *
2001680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * This function figures out all the inputs that the fragment program
2011680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * has access to.  The bitmask is later reduced to just those which
2021680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * are actually referenced.
2031680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell */
204239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paulstatic GLbitfield get_fp_input_mask( GLcontext *ctx )
2051680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
206239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield fp_inputs = 0x0;
2071680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2086ff1cf5b82488dc5a07513b0806c23e70f7a665eKeith Whitwell   if (!ctx->VertexProgram._Enabled ||
2096ff1cf5b82488dc5a07513b0806c23e70f7a665eKeith Whitwell       !ctx->VertexProgram._Current) {
2106ff1cf5b82488dc5a07513b0806c23e70f7a665eKeith Whitwell
2116ff1cf5b82488dc5a07513b0806c23e70f7a665eKeith Whitwell      /* Fixed function logic */
212239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul      GLbitfield varying_inputs = ctx->varying_vp_inputs;
2131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2141680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* First look at what values may be computed by the generated
2151680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * vertex program:
2161680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
2171680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (ctx->Light.Enabled) {
2181680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         fp_inputs |= FRAG_BIT_COL0;
2191680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2201680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
2211680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell            fp_inputs |= FRAG_BIT_COL1;
2221680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      }
2231680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2241680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (ctx->Texture._TexGenEnabled |
2251680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
2261680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2271680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* Then look at what might be varying as a result of enabled
2281680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * arrays, etc:
2291680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
2301680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (varying_inputs & VERT_BIT_COLOR0) fp_inputs |= FRAG_BIT_COL0;
2311680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (varying_inputs & VERT_BIT_COLOR1) fp_inputs |= FRAG_BIT_COL1;
2321680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2331680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
2341680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    << FRAG_ATTRIB_TEX0);
2351680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2361680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
2371680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
2381680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* calculate from vp->outputs */
239239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul      GLbitfield vp_outputs = ctx->VertexProgram._Current->Base.OutputsWritten;
2401680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2411680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0;
2421680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1;
2431680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2440370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell      fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
2450370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell                    << FRAG_ATTRIB_TEX0);
2461680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
2471680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2481680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   return fp_inputs;
2491680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
2501680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2511680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
25222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
25322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Examine current texture environment state and generate a unique
25422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * key to identify it.
25522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
2568065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwellstatic void make_state_key( GLcontext *ctx,  struct state_key *key )
257ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
258ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint i, j;
259239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_referenced = FRAG_BIT_COL0;
260239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_available = get_fp_input_mask( ctx );
2611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2628065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memset(key, 0, sizeof(*key));
2638065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
264ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
265d9736db6676948e06712d4bcba46b7040452f870Brian Paul      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
266ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
2671680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (!texUnit->_ReallyEnabled)
268ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         continue;
269ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
270ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].enabled = 1;
271ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->enabled_units |= (1<<i);
2721680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      key->nr_enabled_units = i+1;
2731680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_TEX(i);
274ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
275ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].source_index =
276ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_tex_src_bit(texUnit->_ReallyEnabled);
277ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
278ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
279ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
280ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
281ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeRGB =
282ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
283ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeA =
284ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeA);
285ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
286ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
28764da16146fed68605f83ccf3b64075c0d5b6f052Keith Whitwell      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
288ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
289ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      for (j=0;j<3;j++) {
290ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Operand =
291ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
292ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Operand =
293ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
294ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Source =
295ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
296ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Source =
297ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
298ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      }
299ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
300ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
3011680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
302ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->separate_specular = 1;
3031680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_COL1;
3041680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
305ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
306ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->Fog.Enabled) {
307ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_enabled = 1;
308ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
3091680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
310ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
3111680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3121680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   key->inputs_available = (inputs_available & inputs_referenced);
313ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
314ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
315239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
316239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Use uregs to represent registers internally, translate to Mesa's
31715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * expected formats on emit.
31815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
31915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * NOTE: These are passed by value extensively in this file rather
32015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * than as usual by pointer reference.  If this disturbs you, try
32115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * remembering they are just 32bits in size.
32215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
32315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * GCC is smart enough to deal with these dword-sized structures in
32415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * much the same way as if I had defined them as dwords and was using
32515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * macros to access and set the fields.  This is much nicer and easier
32615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * to evolve.
32715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
32815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct ureg {
32915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint file:4;
33015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint idx:8;
33115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negatebase:1;
33215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint abs:1;
33315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negateabs:1;
33415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint swz:12;
33515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint pad:5;
33615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
33715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
33813abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paulstatic const struct ureg undef = {
3398d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   PROGRAM_UNDEFINED,
34015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   ~0,
34115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
34215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
34315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
34415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
34515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0
34615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
34715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
34815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
349239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/** State used to build the fragment program:
35015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
35115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct texenv_fragment_program {
352122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_fragment_program *program;
35315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLcontext *ctx;
354ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *state;
35515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
356239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield alu_temps;	/**< Track texture indirections, see spec. */
357239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temps_output;	/**< Track texture indirections, see spec. */
358239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temp_in_use;	/**< Tracks temporary regs which are in use. */
35915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLboolean error;
36015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
3612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg src_texture[MAX_TEXTURE_UNITS];
362ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   /* Reg containing each texture unit's sampled texture color,
363ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    * else undef.
364ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
36515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
366239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   struct ureg src_previous;	/**< Reg containing color from previous
36715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 * stage.  May need to be decl'd.
36815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 */
36915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
370239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLuint last_tex_stage;	/**< Number of last enabled texture unit */
3712dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
3722dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg half;
3732dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg one;
3742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg zero;
37515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
37615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
37715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
37815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
37915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
38015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
38115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg reg;
38215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.file = file;
38315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.idx = idx;
38415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negatebase = 0;
38515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.abs = 0;
38615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negateabs = 0;
38715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = SWIZZLE_NOOP;
38815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.pad = 0;
38915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
39015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
39115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
39315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
39415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
39515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, y),
39615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, z),
39715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, w));
39815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
40015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
40115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
40215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
40315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
40415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return swizzle(reg, x, x, x, x);
40515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
40615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4076fe176a64859798db17fbaed6858cccc646aae38Keith Whitwellstatic struct ureg negate( struct ureg reg )
4086fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell{
4096fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   reg.negatebase ^= 1;
4106fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   return reg;
4116fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell}
4126fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell
41315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic GLboolean is_undef( struct ureg reg )
41415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
4158d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   return reg.file == PROGRAM_UNDEFINED;
41615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
41715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
418ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
41915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_temp( struct texenv_fragment_program *p )
42015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
42113abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   GLint bit;
422ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
423cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try and reuse temps which have been used already:
424ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
425b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
426ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
427ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
428ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
429ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit)
430b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
431ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
432ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit) {
433bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
434b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
435ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   }
436ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
43713abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
438b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
439b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
44093cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
441ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
442ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell}
443ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
444ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwellstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
445ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell{
446ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   int bit;
447ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
448006fb638188f083d64a2427cd28979b432622f3eBrian Paul   /* First try to find available temp not previously used (to avoid
449cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * starting a new texture indirection).  According to the spec, the
450cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * ~p->temps_output isn't necessary, but will keep it there for
451cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * now:
452ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
453b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
454ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
455ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
456ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
457cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!bit)
458b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
459ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
46015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (!bit) {
461bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
462b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
46315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
46415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
46513abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
466b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
467b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
46893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
46915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
47015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
47115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
47215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4738fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul/** Mark a temp reg as being no longer allocatable. */
4748fd329d04885eba7587bbe7604d3a1088e35de40Brian Paulstatic void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
4758fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul{
4768fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul   if (r.file == PROGRAM_TEMPORARY)
4778fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul      p->temps_output |= (1 << r.idx);
4788fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul}
4798fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul
4808fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul
481f18d4e058ed979c6e42e868c7febde4fa62c5810Brianstatic void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
48215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
483f18d4e058ed979c6e42e868c7febde4fa62c5810Brian   GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
48493cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell
4852dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   /* KW: To support tex_env_crossbar, don't release the registers in
4862dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    * temps_output.
4872dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    */
48893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   if (max_temp >= sizeof(int) * 8)
4892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = p->temps_output;
49093cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   else
4912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
49215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
49315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
49415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4959fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brianstatic struct ureg register_param5( struct texenv_fragment_program *p,
496ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s0,
497ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s1,
498ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s2,
499ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s3,
5009fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian				    GLint s4)
50115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
5029fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian   gl_state_index tokens[STATE_LENGTH];
50347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint idx;
50447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[0] = s0;
50547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[1] = s1;
50647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[2] = s2;
50747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[3] = s3;
50847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[4] = s4;
509de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
51047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
51147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell}
51215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
51315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5149fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
5159fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
5169fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
5179fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
51847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
5191680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwellstatic GLuint frag_to_vert_attrib( GLuint attrib )
5201680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
5211680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   switch (attrib) {
5221680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
5231680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
5241680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   default:
5251680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib >= FRAG_ATTRIB_TEX0);
5261680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib <= FRAG_ATTRIB_TEX7);
5271680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
5281680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
5291680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
5301680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
53147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
53247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
53347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell{
5341680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (p->state->inputs_available & (1<<input)) {
5351680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      p->program->Base.InputsRead |= (1 << input);
5361680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return make_ureg(PROGRAM_INPUT, input);
5371680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
5381680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
5391680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      GLuint idx = frag_to_vert_attrib( input );
5401680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
5411680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
54215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
54315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
54447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
5457e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *reg,
54615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg )
54715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
54815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->File = ureg.file;
54915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Index = ureg.idx;
55015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Swizzle = ureg.swz;
551f2802c40fff686301a7ff99f0a0b1c57d5cf5625Keith Whitwell   reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
55215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Abs = ureg.abs;
55315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->NegateAbs = ureg.negateabs;
55415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
55515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5567e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
55715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg, GLuint mask )
55815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
55915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->File = ureg.file;
56015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->Index = ureg.idx;
56115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->WriteMask = mask;
562112a1580f658948e553fe04399a20958dca67c16Brian   dst->CondMask = COND_TR;  /* always pass cond test */
563112a1580f658948e553fe04399a20958dca67c16Brian   dst->CondSwizzle = SWIZZLE_NOOP;
56415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
56515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5667e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic struct prog_instruction *
56715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellemit_op(struct texenv_fragment_program *p,
5685d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul	enum prog_opcode op,
56915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg dest,
57015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	GLuint mask,
57122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	GLboolean saturate,
57215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src0,
57315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src1,
57415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src2 )
57515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
57647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
577de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
57815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
579e69943e6dda102df8418a8261b95155350181a2fBrian   assert(nr < MAX_INSTRUCTIONS);
580e69943e6dda102df8418a8261b95155350181a2fBrian
581d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul   _mesa_init_instructions(inst, 1);
58215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->Opcode = op;
58315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
58447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
58547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
58647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
58715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
588e31ac052236ea615b4995f9ec301d8af4b864531Brian Paul   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
58915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
59015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_dst( &inst->DstReg, dest, mask );
59115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5928fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul#if 0
593cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
594cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
595cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
596cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->temps_output |= 1 << dest.idx;
5978fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul#endif
598cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
59915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return inst;
60015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
60115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
60215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
60315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_arith( struct texenv_fragment_program *p,
6045d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
60547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg dest,
60647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       GLuint mask,
60722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			       GLboolean saturate,
60847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src0,
60947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src1,
61047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src2 )
61115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
61215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
61315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
614cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
615cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
616cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (src0.file == PROGRAM_TEMPORARY)
617cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src0.idx;
618cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
619cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
620cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src1.idx;
621cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
622cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
623cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src2.idx;
624cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
625cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
626cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << dest.idx;
627cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
62821f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumAluInstructions++;
62915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
63015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
63115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
63215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_texld( struct texenv_fragment_program *p,
6335d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
634ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg dest,
635ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint destmask,
636ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_unit,
637ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_idx,
638ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg coord )
63915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
6407e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   struct prog_instruction *inst = emit_op( p, op,
64115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  dest, destmask,
64222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul					  GL_FALSE,	/* don't saturate? */
64315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  coord, 	/* arg 0? */
64415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef,
64515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef);
64615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6477e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   inst->TexSrcTarget = tex_idx;
64815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->TexSrcUnit = tex_unit;
64915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
65021f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumTexInstructions++;
65115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6528fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul   /* Accounting for indirection tracking:
6538fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul    */
6548fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul   reserve_temp(p, dest);
6558fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul
656cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Is this a texture indirection?
657cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
658cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if ((coord.file == PROGRAM_TEMPORARY &&
659cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->temps_output & (1<<coord.idx))) ||
660cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       (dest.file == PROGRAM_TEMPORARY &&
661cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->alu_temps & (1<<dest.idx)))) {
66221f99792a916a62fcfae7c208f50f192d4ce5926Brian      p->program->Base.NumTexIndirections++;
6632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temps_output = 1<<coord.idx;
664cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps = 0;
6652dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(0);		/* KW: texture env crossbar */
66615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
66715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
66815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
66915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
67015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
67115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
67247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_const4f( struct texenv_fragment_program *p,
673ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s0,
674ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s1,
675ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s2,
676ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s3)
67715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
67847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLfloat values[4];
679a90046f1097ad95de2aa95ca65741dff5cddced9Brian   GLuint idx, swizzle;
680006fb638188f083d64a2427cd28979b432622f3eBrian Paul   struct ureg r;
68147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[0] = s0;
68247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[1] = s1;
68347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[2] = s2;
68447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[3] = s3;
685a90046f1097ad95de2aa95ca65741dff5cddced9Brian   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
686a90046f1097ad95de2aa95ca65741dff5cddced9Brian                                     &swizzle );
687006fb638188f083d64a2427cd28979b432622f3eBrian Paul   r = make_ureg(PROGRAM_CONSTANT, idx);
688006fb638188f083d64a2427cd28979b432622f3eBrian Paul   r.swz = swizzle;
689006fb638188f083d64a2427cd28979b432622f3eBrian Paul   return r;
69015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
69115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
692e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
69347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
69447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
69547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
69615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
69715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6982dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_one( struct texenv_fragment_program *p )
6992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->one))
7012dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->one = register_scalar_const(p, 1.0);
7022dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->one;
7032dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
7052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_half( struct texenv_fragment_program *p )
7062dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7072dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->half))
7084dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->half = register_scalar_const(p, 0.5);
7092dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->half;
7102dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7112dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
7122dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_zero( struct texenv_fragment_program *p )
7132dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7142dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->zero))
7154dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->zero = register_scalar_const(p, 0.0);
7162dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->zero;
7172dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7182dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
71915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void program_error( struct texenv_fragment_program *p, const char *msg )
72115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
722bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul   _mesa_problem(NULL, msg);
72315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p->error = 1;
72415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
72515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_source( struct texenv_fragment_program *p,
727ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint src, GLuint unit )
72815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
72915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (src) {
730ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE:
7312dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(!is_undef(p->src_texture[unit]));
7322dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return p->src_texture[unit];
73315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
734ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
735ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
736ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
737ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
738ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
739ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
740ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
741ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
742ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
743ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return p->src_texture[src - SRC_TEXTURE0];
744ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
745ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_CONSTANT:
74647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_param2(p, STATE_TEXENV_COLOR, unit);
7472dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
748ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PRIMARY_COLOR:
74947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_input(p, FRAG_ATTRIB_COL0);
7502dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
751ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PREVIOUS:
752ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:
75347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (is_undef(p->src_previous))
75447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return register_input(p, FRAG_ATTRIB_COL0);
75547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      else
75647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return p->src_previous;
75715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
75815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
7592dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
76015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine_source( struct texenv_fragment_program *p,
761ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint mask,
762ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint unit,
763ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint source,
764ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint operand )
76515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
76615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg arg, src, one;
76715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
76815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   src = get_source(p, source, unit);
76915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
77015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (operand) {
771ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_COLOR:
77215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
77315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.xyzw
77415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
77515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      arg = get_temp( p );
7762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one( p );
7777e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
77815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
779ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_ALPHA:
78015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_W)
78115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src;
78215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
78322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	 return swizzle1( src, SWIZZLE_W );
784ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_ALPHA:
78515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
78615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.wwww
78715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
7882dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      arg = get_temp(p);
7892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one(p);
7907e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
79122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			one, swizzle1(src, SWIZZLE_W), undef);
792ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ZERO:
7932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_zero(p);
794ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE:
7952dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_one(p);
796ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_COLOR:
79715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
79815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src;
79915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
80015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
80115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
802ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLboolean args_match( struct state_key *key, GLuint unit )
80315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
80422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i, nr = key->unit[unit].NumArgsRGB;
80515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
80615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0 ; i < nr ; i++) {
807ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
80815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;
80915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
810ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      switch(key->unit[unit].OptA[i].Operand) {
811ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_SRC_ALPHA:
812ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
813ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_COLOR:
814ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_ALPHA:
81515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
81615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
81715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
81815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
81915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
820ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_ONE_MINUS_SRC_ALPHA:
821ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
822ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_COLOR:
823ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_ALPHA:
82415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
82515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
82615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
82715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
82815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
82915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      default:
83015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;	/* impossible */
83115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
83215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
83315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
83415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return GL_TRUE;
83515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
83615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
83715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine( struct texenv_fragment_program *p,
838ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 struct ureg dest,
839ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mask,
84022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul				 GLboolean saturate,
841ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint unit,
842ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint nr,
843ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mode,
844d9736db6676948e06712d4bcba46b7040452f870Brian Paul				 const struct mode_opt *opt)
845ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
84615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg src[3];
847cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg tmp, half;
84822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i;
84915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
8500063084804d62402d80821a86978660663955442Brian Paul   tmp = undef; /* silence warning (bug 5318) */
8510063084804d62402d80821a86978660663955442Brian Paul
85215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0; i < nr; i++)
853ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
85415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
85515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (mode) {
856ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_REPLACE:
85715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_XYZW && !saturate)
85815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src[0];
85915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
8607e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
861ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE:
8627e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
8636fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
864ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD:
8657e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
8666fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
867ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD_SIGNED:
86815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp = arg0 + arg1
869cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       * result = tmp - .5
87015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
8712dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
87299da2d30eb08e50edf4b0067518af3acdf2dabc0Jerome Glisse      tmp = get_temp( p );
8737e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
8747e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
87515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
876ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_INTERPOLATE:
87715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
87815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
8797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
88015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
881ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_SUBTRACT:
8827e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
88315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
884ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA:
885ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
886ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
887ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB: {
88815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp0 = get_temp( p );
88915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp1 = get_temp( p );
890e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg neg1 = register_scalar_const(p, -1);
891e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg two  = register_scalar_const(p, 2);
89215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
89315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp0 = 2*src0 - 1
89415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * tmp1 = 2*src1 - 1
89515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       *
89615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * dst = tmp0 dot3 tmp1
89715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
8987e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
8996fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		  two, src[0], neg1);
90015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
901aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
90215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 tmp1 = tmp0;
90315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
9047e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
9056fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		     two, src[1], neg1);
9067e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
90715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
90815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
909ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_ADD_ATI:
9106fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 */
9117e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
9126fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[2], src[1] );
913ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SIGNED_ADD_ATI: {
9146fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 - 0.5 */
9156fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      struct ureg tmp0 = get_temp(p);
9162dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
9177e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
9187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
9196fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
9206fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   }
921ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SUBTRACT_ATI:
9226fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 - Arg1 */
9237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
9246fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
92515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
92615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src[0];
92715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
92815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
92915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
93015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
93122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
93222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for one texture unit's env/combiner mode.
93322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
93422db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic struct ureg
93522db53577603afef8fdf62c324ff5977de76b9d8Brian Paulemit_texenv(struct texenv_fragment_program *p, GLuint unit)
93615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
937ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
93822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLboolean saturate = (unit < p->last_tex_stage);
93915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint rgb_shift, alpha_shift;
94015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg out, shift;
941cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg dest;
94215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
943ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (!key->unit[unit].enabled) {
944ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return get_source(p, SRC_PREVIOUS, 0);
94515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
946ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
947ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (key->unit[unit].ModeRGB) {
948ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
949ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
95015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
95115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
952ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
95315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      alpha_shift = 0;
95415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
95515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
95615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
957ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      rgb_shift = key->unit[unit].ScaleShiftRGB;
958ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
95915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
96015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
961ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
962cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* If this is the very last calculation, emit direct to output reg:
963cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
964ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular ||
965cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       unit != p->last_tex_stage ||
966cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       alpha_shift ||
967cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       rgb_shift)
968cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      dest = get_temp( p );
969cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   else
97090ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
97115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
97215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Emit the RGB and A combine ops
97315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
974ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
975ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       args_match(key, unit)) {
97615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
97715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
978ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
979ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
980ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
98115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
982ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
9839a45176dd85a1cd523498efeebd0481950a1bf58Roland Scheidegger	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
98415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
98515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
98615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
987ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
988ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
989ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
99015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
99115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else {
99215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Need to do something to stop from re-emitting identical
99315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * argument calculations here:
99415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
99515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
99615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
997ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
998ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
999ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
100015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_W, saturate,
100115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1002ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsA,
1003ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeA,
1004ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptA);
100515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
100615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
100715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Deal with the final shift:
100815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
100915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (alpha_shift || rgb_shift) {
101015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (rgb_shift == alpha_shift) {
101153174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
101215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
101315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else {
10142dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell	 shift = register_const4f(p,
101553174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
101653174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
101753174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
101853174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<alpha_shift));
101915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
10207e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
102115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			 saturate, out, shift, undef );
102215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
102315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else
102415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return out;
102515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
102615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
102822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
102922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instruction for getting a texture source term.
103022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
10312dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic void load_texture( struct texenv_fragment_program *p, GLuint unit )
10322dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
10332dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->src_texture[unit])) {
1034ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      GLuint dim = p->state->unit[unit].source_index;
10352dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
10362dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg tmp = get_tex_temp( p );
10372dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1038bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      if (dim == TEXTURE_UNKNOWN_INDEX)
1039bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul         program_error(p, "TexSrcBit");
1040ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
10412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* TODO: Use D0_MASK_XY where possible.
10422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
10431e3b07f363e6bf512ab1a5c620656985aece40fdBrian      if (p->state->unit[unit].enabled) {
1044b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
1045b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    tmp, WRITEMASK_XYZW,
1046b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    unit, dim, texcoord );
10471e3b07f363e6bf512ab1a5c620656985aece40fdBrian         p->program->Base.SamplersUsed |= (1 << unit);
1048fce4612f8a29ee1798c9326a431a139d856c7a04Brian         /* This identity mapping should already be in place
1049fce4612f8a29ee1798c9326a431a139d856c7a04Brian          * (see _mesa_init_program_struct()) but let's be safe.
1050fce4612f8a29ee1798c9326a431a139d856c7a04Brian          */
1051fce4612f8a29ee1798c9326a431a139d856c7a04Brian         p->program->Base.SamplerUnits[unit] = unit;
10521e3b07f363e6bf512ab1a5c620656985aece40fdBrian      }
1053b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      else
1054b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = get_zero(p);
10552dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
10562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
10572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1058241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwellstatic GLboolean load_texenv_source( struct texenv_fragment_program *p,
1059ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLuint src, GLuint unit )
10602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
10612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   switch (src) {
10624dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola   case SRC_TEXTURE:
10632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      load_texture(p, unit);
10642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
10652dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1066ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
1067ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
1068ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
1069ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
1070ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
1071ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
1072ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
1073ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
1074ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      load_texture(p, src - SRC_TEXTURE0);
10752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
10762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
10772dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   default:
10782dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
10792dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1080241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell
1081241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
10822dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
10832dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
108422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
108522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
108622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for loading all texture source terms.
108722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
108822db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic GLboolean
108922db53577603afef8fdf62c324ff5977de76b9d8Brian Paulload_texunit_sources( struct texenv_fragment_program *p, int unit )
10902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
1091ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
1092b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   GLuint i;
1093b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1094b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
1095b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit);
1096b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   }
1097b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1098b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
1099b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
11002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1101b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1102241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
11032dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
11042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
110522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
110622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
110722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate a new fragment program which implements the context's
110822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * current texture env/combine mode.
110922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
111022db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic void
1111e998c346471142db91a1bcb6c61551b8247b87e7Brian Paulcreate_new_program(GLcontext *ctx, struct state_key *key,
1112122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                   struct gl_fragment_program *program)
111315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1114e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
111515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct texenv_fragment_program p;
111615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint unit;
111715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg cf, out;
1118276330b2412910777f7016f427909085f02acbb8Keith Whitwell
1119e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell   _mesa_memset(&p, 0, sizeof(p));
112015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.ctx = ctx;
1121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.state = key;
1122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.program = program;
112315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1124e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* During code generation, use locally-allocated instruction buffer,
1125e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    * then alloc dynamic storage below.
1126e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    */
1127e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.Instructions = instBuffer;
1128276330b2412910777f7016f427909085f02acbb8Keith Whitwell   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
112921f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexIndirections = 1;	/* correct? */
113021f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexInstructions = 0;
113121f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumAluInstructions = 0;
11321240eb2683043ba81e81378807170d0d7045581dBrian   p.program->Base.String = NULL;
11339ca8815d3ba56ad718ba1c48c73aae3cdc0b8db0Keith Whitwell   p.program->Base.NumInstructions =
1134e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumTemporaries =
1135e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumParameters =
1136e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1137de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1138dbeea25bb834479a29712100888c862348112018Keith Whitwell
1139de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.InputsRead = 0;
1140de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
114115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
11422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
11432dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p.src_texture[unit] = undef;
11442dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
114547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   p.src_previous = undef;
11465ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.half = undef;
11475ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.zero = undef;
11485ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.one = undef;
11495ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
115015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.last_tex_stage = 0;
1151f18d4e058ed979c6e42e868c7febde4fa62c5810Brian   release_temps(ctx, &p);
115215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->enabled_units) {
11542dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* First pass - to support texture_env_crossbar, first identify
11552dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * all referenced texture sources and emit texld instructions
11562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * for each:
11572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
115815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1159ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->unit[unit].enabled) {
1160b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    load_texunit_sources( &p, unit );
1161b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    p.last_tex_stage = unit;
116215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
116315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
11642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* Second pass - emit combine instructions to build final color:
11652dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
116615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
1167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->enabled_units & (1<<unit)) {
116815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    p.src_previous = emit_texenv( &p, unit );
11698fd329d04885eba7587bbe7604d3a1088e35de40Brian Paul            reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
1170f18d4e058ed979c6e42e868c7febde4fa62c5810Brian	    release_temps(ctx, &p);	/* release all temps */
117115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
117215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
117315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   cf = get_source( &p, SRC_PREVIOUS, 0 );
117590ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
117615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular) {
117815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Emit specular add.
117915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
118047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
11817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
11827e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
118315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1184aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
118515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Will wind up in here if no texture enabled or a couple of
118615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * other scenarios (GL_REPLACE for instance).
118715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
11887e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
118915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
119015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
119147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   /* Finish up:
119247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell    */
11937e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
119447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1195ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->fog_enabled) {
1196ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      /* Pull fog mode from GLcontext, the value in the state key is
1197ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       * a reduced value and not what is expected in FogOption
1198ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       */
1199276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = ctx->Fog.Mode;
120063be96bdc7e9f388a5c49295bd7e150462fd003aBrian      p.program->Base.InputsRead |= FRAG_BIT_FOGC; /* XXX new */
1201ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } else
1202276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = GL_NONE;
120347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
120421f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
120515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max nr indirect texture lookups");
120615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
120721f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
120815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max TEX instructions");
120915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
121021f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
121115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max ALU instructions");
121215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12135d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
12148b88f62fbd62153500fc3483003f438561366a00Keith Whitwell
1215e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* Allocate final instruction array */
12163bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   p.program->Base.Instructions
12173bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      = _mesa_alloc_instructions(p.program->Base.NumInstructions);
12183bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   if (!p.program->Base.Instructions) {
1219e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1220e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                  "generating tex env program");
1221e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      return;
1222e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
12233bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
12243bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian                           p.program->Base.NumInstructions);
12253bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian
12263bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   if (p.program->FogOption) {
12273bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      _mesa_append_fog_code(ctx, p.program);
12283bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      p.program->FogOption = GL_NONE;
12293bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   }
12303bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian
1231e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1232dbeea25bb834479a29712100888c862348112018Keith Whitwell   /* Notify driver the fragment program has (actually) changed.
12338b88f62fbd62153500fc3483003f438561366a00Keith Whitwell    */
1234e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (ctx->Driver.ProgramStringNotify) {
1235e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1236e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                                       &p.program->Base );
1237e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1238e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1239e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (DISASSEM) {
1240e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_print_program(&p.program->Base);
1241e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_printf("\n");
1242dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
124315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
124415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12455d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul
1246a90046f1097ad95de2aa95ca65741dff5cddced9Brian/**
124783ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian * Return a fragment program which implements the current
124883ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian * fixed-function texture, fog and color-sum operations.
124983ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian */
125083ce6c51d7189094cf2a13fdcc0882a051a3bd41Brianstruct gl_fragment_program *
125183ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
125283ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian{
125383ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   struct gl_fragment_program *prog;
125483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   struct state_key key;
125583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
125683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   make_state_key(ctx, &key);
125783ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
1258f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian   prog = (struct gl_fragment_program *)
1259f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
1260f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian                                 &key, sizeof(key));
126183ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
126283ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   if (!prog) {
126383ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian      prog = (struct gl_fragment_program *)
126483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
126583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
126683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian      create_new_program(ctx, &key, prog);
126783ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
1268f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1269f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian                                 &key, sizeof(key), &prog->Base);
127083ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   }
127183ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
127283ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   return prog;
127383ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian}
127483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
127583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
127683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
127783ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian/**
1278a90046f1097ad95de2aa95ca65741dff5cddced9Brian * If _MaintainTexEnvProgram is set we'll generate a fragment program that
1279a90046f1097ad95de2aa95ca65741dff5cddced9Brian * implements the current texture env/combine mode.
1280a90046f1097ad95de2aa95ca65741dff5cddced9Brian * This function generates that program and puts it into effect.
1281a90046f1097ad95de2aa95ca65741dff5cddced9Brian */
1282a90046f1097ad95de2aa95ca65741dff5cddced9Brianvoid
1283a90046f1097ad95de2aa95ca65741dff5cddced9Brian_mesa_UpdateTexEnvProgram( GLcontext *ctx )
1284ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
1285122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
1286ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1287a90046f1097ad95de2aa95ca65741dff5cddced9Brian   ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
1288a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1289a90046f1097ad95de2aa95ca65741dff5cddced9Brian   /* If a conventional fragment program/shader isn't in effect... */
1290efcfdbd4d16071088e60a59cb966abd730d9d111Brian   if (!ctx->FragmentProgram._Enabled &&
1291d781cdc8fadc802a1f2edbeb13ccb1ee768ce803Brian       (!ctx->Shader.CurrentProgram ||
1292d781cdc8fadc802a1f2edbeb13ccb1ee768ce803Brian        !ctx->Shader.CurrentProgram->FragmentProgram) ) {
1293a90046f1097ad95de2aa95ca65741dff5cddced9Brian
129483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian      ctx->FragmentProgram._Current
129583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian         = ctx->FragmentProgram._TexEnvProgram
129683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian         = _mesa_get_fixed_func_fragment_program(ctx);
1297c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   }
1298c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1299c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* Tell the driver about the change.  Could define a new target for
1300c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    * this?
1301c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    */
13025d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
13035d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
1304a90046f1097ad95de2aa95ca65741dff5cddced9Brian                         (struct gl_program *) ctx->FragmentProgram._Current);
13055d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   }
1306ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1307