ff_fragment_shader.cpp revision 9a45176dd85a1cd523498efeebd0481950a1bf58
115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/**************************************************************************
215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * Copyright 2003 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"
31a90046f1097ad95de2aa95ca65741dff5cddced9Brian#include "prog_parameter.h"
32a90046f1097ad95de2aa95ca65741dff5cddced9Brian#include "prog_instruction.h"
33a90046f1097ad95de2aa95ca65741dff5cddced9Brian#include "prog_print.h"
34a90046f1097ad95de2aa95ca65741dff5cddced9Brian#include "prog_statevars.h"
3515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "texenvprogram.h"
3615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
37e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul/**
38e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul * According to Glean's texCombine test, no more than 21 instructions
39e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul * are needed.  Allow a few extra just in case.
40e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul */
41e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul#define MAX_INSTRUCTIONS 24
4215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
43269e3895d9837ac7303b91948f003ca5c12c0fe4Keith Whitwell#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
4415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
45ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct mode_opt {
465d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint Source:4;
475d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint Operand:3;
48ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
49ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
50ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct state_key {
515d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLbitfield enabled_units;
525d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint separate_specular:1;
535d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_enabled:1;
545d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_mode:2;
55ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
56ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct {
575d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint enabled:1;
585d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
595d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftRGB:2;
605d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftA:2;
61ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
625d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsRGB:2;
635d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeRGB:4;
64ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      struct mode_opt OptRGB[3];
65ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
665d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsA:2;
675d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeA:4;
68ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      struct mode_opt OptA[3];
69ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } unit[8];
70ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
71ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
72ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_LINEAR  0
73ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP     1
74ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP2    2
75ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_UNKNOWN 3
76ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
77ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
78ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
79ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
80ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
81ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP: return FOG_EXP;
82ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP2: return FOG_EXP2;
83ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return FOG_UNKNOWN;
84ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
85ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
86ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
87ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_COLOR           0
88ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_COLOR 1
89ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_ALPHA           2
90ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_ALPHA	3
91ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ZERO                4
92ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE                 5
93ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_UNKNOWN             7
94ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
95ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_operand( GLenum operand )
96ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
97ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (operand) {
98ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_COLOR: return OPR_SRC_COLOR;
99ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
100ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
101ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
102ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ZERO: return OPR_ZERO;
103ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE: return OPR_ONE;
104ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:	return OPR_UNKNOWN;
105ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
106ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
107ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
108ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE  0
109ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE0 1
110ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE1 2
111ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE2 3
112ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE3 4
113ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE4 5
114ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE5 6
115ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE6 7
116ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE7 8
117ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_CONSTANT 9
118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PRIMARY_COLOR 10
119ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PREVIOUS 11
120ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_UNKNOWN  15
121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_source( GLenum src )
123ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
124ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (src) {
125ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE: return SRC_TEXTURE;
126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE0:
127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE1:
128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE2:
129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE3:
130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE4:
131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE5:
132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE6:
133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_CONSTANT: return SRC_CONSTANT;
135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PREVIOUS: return SRC_PREVIOUS;
137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return SRC_UNKNOWN;
138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
140ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
141ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_REPLACE       0
142ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE      1
143ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD           2
144ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD_SIGNED    3
145ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_INTERPOLATE   4
146ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_SUBTRACT      5
147ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB      6
148ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB_EXT  7
149ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA     8
150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA_EXT 9
151ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_ADD_ATI           10
152ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SIGNED_ADD_ATI    11
153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SUBTRACT_ATI      12
154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_UNKNOWN       15
155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
156ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_mode( GLenum mode )
157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
158ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
159ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_REPLACE: return MODE_REPLACE;
160ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE: return MODE_MODULATE;
161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD: return MODE_ADD;
162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_INTERPOLATE: return MODE_INTERPOLATE;
164ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SUBTRACT: return MODE_SUBTRACT;
165ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB: return MODE_DOT3_RGB;
166ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
168ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
169ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return MODE_UNKNOWN;
173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
175ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
176ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define TEXTURE_UNKNOWN_INDEX 7
177e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paulstatic GLuint translate_tex_src_bit( GLbitfield bit )
178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (bit) {
180ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
181ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
182ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
184ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
185ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return TEXTURE_UNKNOWN_INDEX;
186ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
187ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
18922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
19022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Examine current texture environment state and generate a unique
19122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * key to identify it.
19222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
1938065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwellstatic void make_state_key( GLcontext *ctx,  struct state_key *key )
194ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
195ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint i, j;
196ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1978065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memset(key, 0, sizeof(*key));
1988065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
199ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
200d9736db6676948e06712d4bcba46b7040452f870Brian Paul      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
201ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
202ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (!texUnit->_ReallyEnabled)
203ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         continue;
204ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
205ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].enabled = 1;
206ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->enabled_units |= (1<<i);
207ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
208ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].source_index =
209ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_tex_src_bit(texUnit->_ReallyEnabled);
210ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
211ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
212ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
213ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
214ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeRGB =
215ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
216ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeA =
217ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeA);
218ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
219ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
22064da16146fed68605f83ccf3b64075c0d5b6f052Keith Whitwell      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
221ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
222ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      for (j=0;j<3;j++) {
223ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Operand =
224ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
225ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Operand =
226ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
227ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Source =
228ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
229ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Source =
230ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
231ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      }
232ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
233ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
234ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
235ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->separate_specular = 1;
236ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
237ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->Fog.Enabled) {
238ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_enabled = 1;
239ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
240ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
241ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
242ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
24315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/* Use uregs to represent registers internally, translate to Mesa's
24415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * expected formats on emit.
24515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
24615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * NOTE: These are passed by value extensively in this file rather
24715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * than as usual by pointer reference.  If this disturbs you, try
24815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * remembering they are just 32bits in size.
24915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
25015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * GCC is smart enough to deal with these dword-sized structures in
25115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * much the same way as if I had defined them as dwords and was using
25215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * macros to access and set the fields.  This is much nicer and easier
25315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * to evolve.
25415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
25515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct ureg {
25615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint file:4;
25715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint idx:8;
25815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negatebase:1;
25915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint abs:1;
26015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negateabs:1;
26115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint swz:12;
26215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint pad:5;
26315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
26415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
26513abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paulstatic const struct ureg undef = {
2668d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   PROGRAM_UNDEFINED,
26715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   ~0,
26815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
26915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
27015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
27115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
27215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0
27315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
27415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
27515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
27615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/* State used to build the fragment program:
27715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
27815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct texenv_fragment_program {
279122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_fragment_program *program;
28015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLcontext *ctx;
281ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *state;
28215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
283c8d1741b78eda547762b35a6e4dea7ccb563ffa5Brian Paul   GLbitfield alu_temps;	/* Track texture indirections, see spec. */
284c8d1741b78eda547762b35a6e4dea7ccb563ffa5Brian Paul   GLbitfield temps_output;	/* Track texture indirections, see spec. */
285c8d1741b78eda547762b35a6e4dea7ccb563ffa5Brian Paul   GLbitfield temp_in_use;	/* Tracks temporary regs which are in use. */
28615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLboolean error;
28715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
2882dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg src_texture[MAX_TEXTURE_UNITS];
289ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   /* Reg containing each texture unit's sampled texture color,
290ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    * else undef.
291ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
29215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
29315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg src_previous;	/* Reg containing color from previous
29415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 * stage.  May need to be decl'd.
29515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 */
29615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
29715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint last_tex_stage;	/* Number of last enabled texture unit */
2982dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
2992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg half;
3002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg one;
3012dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg zero;
30215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
30315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
30415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
30515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
30615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
30715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
30815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg reg;
30915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.file = file;
31015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.idx = idx;
31115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negatebase = 0;
31215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.abs = 0;
31315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negateabs = 0;
31415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = SWIZZLE_NOOP;
31515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.pad = 0;
31615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
31715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
31815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
31915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
32015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
32115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
32215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, y),
32315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, z),
32415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, w));
32515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
32615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
32715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
32815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
32915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
33015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
33115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return swizzle(reg, x, x, x, x);
33215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
33315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
3346fe176a64859798db17fbaed6858cccc646aae38Keith Whitwellstatic struct ureg negate( struct ureg reg )
3356fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell{
3366fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   reg.negatebase ^= 1;
3376fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   return reg;
3386fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell}
3396fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell
34015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic GLboolean is_undef( struct ureg reg )
34115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
3428d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   return reg.file == PROGRAM_UNDEFINED;
34315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
34415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
345ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
34615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_temp( struct texenv_fragment_program *p )
34715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
34813abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   GLint bit;
349ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
350cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try and reuse temps which have been used already:
351ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
352b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
353ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
354ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
355ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
356ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit)
357b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
358ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
359ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit) {
360bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
361b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
362ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   }
363ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
36413abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
365b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
366b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
36793cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
368ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
369ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell}
370ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
371ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwellstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
372ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell{
373ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   int bit;
374ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
375cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try to find availble temp not previously used (to avoid
376cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * starting a new texture indirection).  According to the spec, the
377cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * ~p->temps_output isn't necessary, but will keep it there for
378cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * now:
379ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
380b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
381ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
382ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
383ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
384cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!bit)
385b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
386ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
38715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (!bit) {
388bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
389b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
39015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
39115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39213abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
393b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
394b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
39593cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
39615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
39715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
39815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
40015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void release_temps( struct texenv_fragment_program *p )
40115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
40205051037101dfa053798cf5ad91d1975fd1aa6a7Brian Paul   GLuint max_temp = p->ctx->Const.FragmentProgram.MaxTemps;
40393cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell
4042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   /* KW: To support tex_env_crossbar, don't release the registers in
4052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    * temps_output.
4062dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    */
40793cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   if (max_temp >= sizeof(int) * 8)
4082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = p->temps_output;
40993cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   else
4102dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
41115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
41215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
41315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4149fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brianstatic struct ureg register_param5( struct texenv_fragment_program *p,
415ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s0,
416ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s1,
417ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s2,
418ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s3,
4199fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian				    GLint s4)
42015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
4219fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian   gl_state_index tokens[STATE_LENGTH];
42247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint idx;
42347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[0] = s0;
42447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[1] = s1;
42547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[2] = s2;
42647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[3] = s3;
42747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[4] = s4;
428de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
42947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
43047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell}
43115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
43215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4339fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
4349fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
4359fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
4369fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
43747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
43847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
43947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
44047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell{
441de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p->program->Base.InputsRead |= (1 << input);
44247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_INPUT, input);
44315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
44415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
44547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
4467e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *reg,
44715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg )
44815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
44915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->File = ureg.file;
45015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Index = ureg.idx;
45115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Swizzle = ureg.swz;
452f2802c40fff686301a7ff99f0a0b1c57d5cf5625Keith Whitwell   reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
45315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Abs = ureg.abs;
45415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->NegateAbs = ureg.negateabs;
45515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
45615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4577e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
45815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg, GLuint mask )
45915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
46015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->File = ureg.file;
46115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->Index = ureg.idx;
46215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->WriteMask = mask;
46315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->CondMask = 0;
46415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->CondSwizzle = 0;
46515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
46615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4677e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic struct prog_instruction *
46815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellemit_op(struct texenv_fragment_program *p,
4695d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul	enum prog_opcode op,
47015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg dest,
47115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	GLuint mask,
47222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	GLboolean saturate,
47315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src0,
47415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src1,
47515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src2 )
47615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
47747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
478de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
47915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
480d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul   _mesa_init_instructions(inst, 1);
48115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->Opcode = op;
48215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
48347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
48447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
48547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
48615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
487e31ac052236ea615b4995f9ec301d8af4b864531Brian Paul   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
48815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
48915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_dst( &inst->DstReg, dest, mask );
49015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
491cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
492cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
493cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
494cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->temps_output |= 1 << dest.idx;
495cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
49615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return inst;
49715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
49815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
49915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
50015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_arith( struct texenv_fragment_program *p,
5015d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
50247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg dest,
50347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       GLuint mask,
50422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			       GLboolean saturate,
50547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src0,
50647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src1,
50747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src2 )
50815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
50915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
51015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
511cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
512cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
513cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (src0.file == PROGRAM_TEMPORARY)
514cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src0.idx;
515cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
516cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
517cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src1.idx;
518cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
519cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
520cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src2.idx;
521cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
522cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
523cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << dest.idx;
524cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
52521f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumAluInstructions++;
52615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
52715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
52815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
52915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_texld( struct texenv_fragment_program *p,
5305d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
531ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg dest,
532ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint destmask,
533ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_unit,
534ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_idx,
535ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg coord )
53615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
5377e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   struct prog_instruction *inst = emit_op( p, op,
53815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  dest, destmask,
53922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul					  GL_FALSE,	/* don't saturate? */
54015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  coord, 	/* arg 0? */
54115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef,
54215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef);
54315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5447e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   inst->TexSrcTarget = tex_idx;
54515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->TexSrcUnit = tex_unit;
54615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
54721f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumTexInstructions++;
54815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
549cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Is this a texture indirection?
550cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
551cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if ((coord.file == PROGRAM_TEMPORARY &&
552cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->temps_output & (1<<coord.idx))) ||
553cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       (dest.file == PROGRAM_TEMPORARY &&
554cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->alu_temps & (1<<dest.idx)))) {
55521f99792a916a62fcfae7c208f50f192d4ce5926Brian      p->program->Base.NumTexIndirections++;
5562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temps_output = 1<<coord.idx;
557cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps = 0;
5582dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(0);		/* KW: texture env crossbar */
55915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
56015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
56215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
56315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_const4f( struct texenv_fragment_program *p,
566ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s0,
567ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s1,
568ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s2,
569ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s3)
57015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
57147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLfloat values[4];
572a90046f1097ad95de2aa95ca65741dff5cddced9Brian   GLuint idx, swizzle;
57347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[0] = s0;
57447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[1] = s1;
57547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[2] = s2;
57647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[3] = s3;
577a90046f1097ad95de2aa95ca65741dff5cddced9Brian   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
578a90046f1097ad95de2aa95ca65741dff5cddced9Brian                                     &swizzle );
579a90046f1097ad95de2aa95ca65741dff5cddced9Brian   ASSERT(swizzle == SWIZZLE_NOOP);
58047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
58115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
58215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
583e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
58447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
58547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
58647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
58715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
58815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_one( struct texenv_fragment_program *p )
5902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
5912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->one))
5922dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->one = register_scalar_const(p, 1.0);
5932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->one;
5942dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
5952dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
5962dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_half( struct texenv_fragment_program *p )
5972dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
5982dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->half))
5994dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->half = register_scalar_const(p, 0.5);
6002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->half;
6012dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
6022dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
6032dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_zero( struct texenv_fragment_program *p )
6042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
6052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->zero))
6064dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->zero = register_scalar_const(p, 0.0);
6072dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->zero;
6082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
6092dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
61015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
61115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void program_error( struct texenv_fragment_program *p, const char *msg )
61215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
613bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul   _mesa_problem(NULL, msg);
61415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p->error = 1;
61515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
61615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
61715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_source( struct texenv_fragment_program *p,
618ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint src, GLuint unit )
61915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
62015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (src) {
621ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE:
6222dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(!is_undef(p->src_texture[unit]));
6232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return p->src_texture[unit];
62415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
625ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
626ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
627ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
628ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
629ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
630ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
631ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
632ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
633ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
634ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return p->src_texture[src - SRC_TEXTURE0];
635ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
636ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_CONSTANT:
63747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_param2(p, STATE_TEXENV_COLOR, unit);
6382dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
639ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PRIMARY_COLOR:
64047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_input(p, FRAG_ATTRIB_COL0);
6412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
642ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PREVIOUS:
643ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:
64447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (is_undef(p->src_previous))
64547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return register_input(p, FRAG_ATTRIB_COL0);
64647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      else
64747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return p->src_previous;
64815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
64915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
6502dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
65115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine_source( struct texenv_fragment_program *p,
652ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint mask,
653ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint unit,
654ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint source,
655ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint operand )
65615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
65715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg arg, src, one;
65815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
65915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   src = get_source(p, source, unit);
66015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
66115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (operand) {
662ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_COLOR:
66315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
66415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.xyzw
66515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
66615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      arg = get_temp( p );
6672dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one( p );
6687e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
66915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
670ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_ALPHA:
67115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_W)
67215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src;
67315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
67422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	 return swizzle1( src, SWIZZLE_W );
675ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_ALPHA:
67615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
67715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.wwww
67815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
6792dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      arg = get_temp(p);
6802dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one(p);
6817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
68222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			one, swizzle1(src, SWIZZLE_W), undef);
683ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ZERO:
6842dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_zero(p);
685ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE:
6862dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_one(p);
687ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_COLOR:
68815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
68915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src;
69015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
69115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
69215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
693ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLboolean args_match( struct state_key *key, GLuint unit )
69415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
69522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i, nr = key->unit[unit].NumArgsRGB;
69615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
69715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0 ; i < nr ; i++) {
698ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
69915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;
70015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
701ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      switch(key->unit[unit].OptA[i].Operand) {
702ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_SRC_ALPHA:
703ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
704ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_COLOR:
705ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_ALPHA:
70615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
70715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
70815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
70915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
71015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
711ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_ONE_MINUS_SRC_ALPHA:
712ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
713ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_COLOR:
714ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_ALPHA:
71515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
71615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
71715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
71815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
71915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
72015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      default:
72115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;	/* impossible */
72215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
72315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
72415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return GL_TRUE;
72615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
72715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine( struct texenv_fragment_program *p,
729ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 struct ureg dest,
730ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mask,
73122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul				 GLboolean saturate,
732ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint unit,
733ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint nr,
734ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mode,
735d9736db6676948e06712d4bcba46b7040452f870Brian Paul				 const struct mode_opt *opt)
736ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
73715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg src[3];
738cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg tmp, half;
73922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i;
74015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7410063084804d62402d80821a86978660663955442Brian Paul   tmp = undef; /* silence warning (bug 5318) */
7420063084804d62402d80821a86978660663955442Brian Paul
74315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0; i < nr; i++)
744ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
74515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
74615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (mode) {
747ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_REPLACE:
74815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_XYZW && !saturate)
74915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src[0];
75015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
7517e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
752ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE:
7537e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
7546fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
755ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD:
7567e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
7576fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
758ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD_SIGNED:
75915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp = arg0 + arg1
760cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       * result = tmp - .5
76115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
7622dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
76399da2d30eb08e50edf4b0067518af3acdf2dabc0Jerome Glisse      tmp = get_temp( p );
7647e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
7657e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
76615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
767ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_INTERPOLATE:
76815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
76915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
7707e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
77115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
772ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_SUBTRACT:
7737e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
77415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
775ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA:
776ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
777ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
778ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB: {
77915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp0 = get_temp( p );
78015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp1 = get_temp( p );
781e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg neg1 = register_scalar_const(p, -1);
782e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg two  = register_scalar_const(p, 2);
78315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
78415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp0 = 2*src0 - 1
78515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * tmp1 = 2*src1 - 1
78615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       *
78715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * dst = tmp0 dot3 tmp1
78815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
7897e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
7906fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		  two, src[0], neg1);
79115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
792aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
79315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 tmp1 = tmp0;
79415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
7957e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
7966fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		     two, src[1], neg1);
7977e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
79815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
79915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
800ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_ADD_ATI:
8016fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 */
8027e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
8036fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[2], src[1] );
804ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SIGNED_ADD_ATI: {
8056fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 - 0.5 */
8066fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      struct ureg tmp0 = get_temp(p);
8072dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
8087e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
8097e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
8106fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
8116fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   }
812ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SUBTRACT_ATI:
8136fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 - Arg1 */
8147e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
8156fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
81615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
81715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src[0];
81815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
81915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
82015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
82322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for one texture unit's env/combiner mode.
82422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
82522db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic struct ureg
82622db53577603afef8fdf62c324ff5977de76b9d8Brian Paulemit_texenv(struct texenv_fragment_program *p, GLuint unit)
82715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
828ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
82922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLboolean saturate = (unit < p->last_tex_stage);
83015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint rgb_shift, alpha_shift;
83115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg out, shift;
832cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg dest;
83315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
834ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (!key->unit[unit].enabled) {
835ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return get_source(p, SRC_PREVIOUS, 0);
83615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
837ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
838ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (key->unit[unit].ModeRGB) {
839ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
840ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
84115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
84215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
843ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
84415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      alpha_shift = 0;
84515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
84615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
84715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
848ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      rgb_shift = key->unit[unit].ScaleShiftRGB;
849ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
85015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
85115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
852ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
853cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* If this is the very last calculation, emit direct to output reg:
854cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
855ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular ||
856cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       unit != p->last_tex_stage ||
857cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       alpha_shift ||
858cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       rgb_shift)
859cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      dest = get_temp( p );
860cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   else
86190ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
86215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Emit the RGB and A combine ops
86415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
865ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
866ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       args_match(key, unit)) {
86715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
86815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
869ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
870ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
871ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
87215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
873ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
8749a45176dd85a1cd523498efeebd0481950a1bf58Roland Scheidegger	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
87515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
87615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
87715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
878ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
879ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
880ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
88115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
88215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else {
88315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Need to do something to stop from re-emitting identical
88415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * argument calculations here:
88515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
88615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
88715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
888ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
889ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
890ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
89115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_W, saturate,
89215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
893ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsA,
894ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeA,
895ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptA);
89615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
89715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
89815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Deal with the final shift:
89915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
90015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (alpha_shift || rgb_shift) {
90115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (rgb_shift == alpha_shift) {
902e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell	 shift = register_scalar_const(p, 1<<rgb_shift);
90315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
90415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else {
9052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell	 shift = register_const4f(p,
9062dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell				  1<<rgb_shift,
9072dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell				  1<<rgb_shift,
9082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell				  1<<rgb_shift,
9092dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell				  1<<alpha_shift);
91015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
9117e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
91215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			 saturate, out, shift, undef );
91315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
91415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else
91515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return out;
91615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
91715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
9182dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
91922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
92022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instruction for getting a texture source term.
92122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
9222dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic void load_texture( struct texenv_fragment_program *p, GLuint unit )
9232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
9242dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->src_texture[unit])) {
925ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      GLuint dim = p->state->unit[unit].source_index;
9262dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
9272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg tmp = get_tex_temp( p );
9282dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
929bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      if (dim == TEXTURE_UNKNOWN_INDEX)
930bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul         program_error(p, "TexSrcBit");
931ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
9322dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* TODO: Use D0_MASK_XY where possible.
9332dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
934b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      if (p->state->unit[unit].enabled)
935b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
936b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    tmp, WRITEMASK_XYZW,
937b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    unit, dim, texcoord );
938b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      else
939b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = get_zero(p);
9402dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
9412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
9422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
943241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwellstatic GLboolean load_texenv_source( struct texenv_fragment_program *p,
944ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLuint src, GLuint unit )
9452dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
9462dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   switch (src) {
9474dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola   case SRC_TEXTURE:
9482dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      load_texture(p, unit);
9492dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
9502dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
951ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
952ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
953ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
954ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
955ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
956ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
957ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
958ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
959ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      load_texture(p, src - SRC_TEXTURE0);
9602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
9612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
9622dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   default:
9632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
9642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
965241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell
966241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
9672dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
9682dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
96922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
97022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
97122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for loading all texture source terms.
97222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
97322db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic GLboolean
97422db53577603afef8fdf62c324ff5977de76b9d8Brian Paulload_texunit_sources( struct texenv_fragment_program *p, int unit )
9752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
976ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
977b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   GLuint i;
978b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
979b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
980b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit);
981b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   }
982b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
983b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
984b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
9852dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
986b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
987241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
9882dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
9892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
99022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
99122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
99222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate a new fragment program which implements the context's
99322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * current texture env/combine mode.
99422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
99522db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic void
996e998c346471142db91a1bcb6c61551b8247b87e7Brian Paulcreate_new_program(GLcontext *ctx, struct state_key *key,
997122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                   struct gl_fragment_program *program)
99815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
999e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
100015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct texenv_fragment_program p;
100115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint unit;
100215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg cf, out;
1003276330b2412910777f7016f427909085f02acbb8Keith Whitwell
1004e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell   _mesa_memset(&p, 0, sizeof(p));
100515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.ctx = ctx;
1006ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.state = key;
1007ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.program = program;
100815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1009e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* During code generation, use locally-allocated instruction buffer,
1010e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    * then alloc dynamic storage below.
1011e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    */
1012e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.Instructions = instBuffer;
1013276330b2412910777f7016f427909085f02acbb8Keith Whitwell   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
101421f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexIndirections = 1;	/* correct? */
101521f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexInstructions = 0;
101621f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumAluInstructions = 0;
10171240eb2683043ba81e81378807170d0d7045581dBrian   p.program->Base.String = NULL;
10189ca8815d3ba56ad718ba1c48c73aae3cdc0b8db0Keith Whitwell   p.program->Base.NumInstructions =
1019e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumTemporaries =
1020e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumParameters =
1021e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1022de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1023dbeea25bb834479a29712100888c862348112018Keith Whitwell
1024de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.InputsRead = 0;
1025de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
102615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
10282dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p.src_texture[unit] = undef;
10292dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
103047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   p.src_previous = undef;
10315ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.half = undef;
10325ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.zero = undef;
10335ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.one = undef;
10345ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
103515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.last_tex_stage = 0;
103693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   release_temps(&p);
103715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1038ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->enabled_units) {
10392dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* First pass - to support texture_env_crossbar, first identify
10402dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * all referenced texture sources and emit texld instructions
10412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * for each:
10422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
104315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1044ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->unit[unit].enabled) {
1045b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    load_texunit_sources( &p, unit );
1046b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    p.last_tex_stage = unit;
104715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
104815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10492dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* Second pass - emit combine instructions to build final color:
10502dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
105115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
1052ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->enabled_units & (1<<unit)) {
105315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    p.src_previous = emit_texenv( &p, unit );
105493cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell	    release_temps(&p);	/* release all temps */
105515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
105615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
105715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1058ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   cf = get_source( &p, SRC_PREVIOUS, 0 );
105990ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
106015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1061ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular) {
106215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Emit specular add.
106315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
106447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
10657e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
10667e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
106715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1068aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
106915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Will wind up in here if no texture enabled or a couple of
107015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * other scenarios (GL_REPLACE for instance).
107115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10727e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
107315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
107415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
107547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   /* Finish up:
107647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell    */
10777e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
107847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1079ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->fog_enabled) {
1080ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      /* Pull fog mode from GLcontext, the value in the state key is
1081ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       * a reduced value and not what is expected in FogOption
1082ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       */
1083276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = ctx->Fog.Mode;
1084ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } else
1085276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = GL_NONE;
108647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
108721f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
108815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max nr indirect texture lookups");
108915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
109021f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
109115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max TEX instructions");
109215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
109321f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
109415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max ALU instructions");
109515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10965d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
10978b88f62fbd62153500fc3483003f438561366a00Keith Whitwell
1098e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* Allocate final instruction array */
1099e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   program->Base.Instructions
1100e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      = _mesa_alloc_instructions(program->Base.NumInstructions);
1101e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (!program->Base.Instructions) {
1102e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1103e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                  "generating tex env program");
1104e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      return;
1105e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
11061240eb2683043ba81e81378807170d0d7045581dBrian   _mesa_copy_instructions(program->Base.Instructions, instBuffer,
11071240eb2683043ba81e81378807170d0d7045581dBrian                           program->Base.NumInstructions);
1108e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1109dbeea25bb834479a29712100888c862348112018Keith Whitwell   /* Notify driver the fragment program has (actually) changed.
11108b88f62fbd62153500fc3483003f438561366a00Keith Whitwell    */
1111e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (ctx->Driver.ProgramStringNotify) {
1112e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1113e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                                       &p.program->Base );
1114e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1115e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1116e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (DISASSEM) {
1117e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_print_program(&p.program->Base);
1118e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_printf("\n");
1119dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
112015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
112115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
11225d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul
1123122629f27925a9dc50029bebc5079f87f416a7e1Brian Paulstatic struct gl_fragment_program *
1124d9736db6676948e06712d4bcba46b7040452f870Brian Paulsearch_cache(const struct texenvprog_cache *cache,
1125d9736db6676948e06712d4bcba46b7040452f870Brian Paul             GLuint hash,
1126e4cb9cd167b2993a4d73871b80216af9766f130bBrian Paul             const void *key,
1127d9736db6676948e06712d4bcba46b7040452f870Brian Paul             GLuint keysize)
1128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
11295ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   struct texenvprog_cache_item *c;
1130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
11315ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   for (c = cache->items[hash % cache->size]; c; c = c->next) {
11325ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell      if (c->hash == hash && memcmp(c->key, key, keysize) == 0)
1133122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul	 return (struct gl_fragment_program *) c->data;
1134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
1135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   return NULL;
1137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
11395ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwellstatic void rehash( struct texenvprog_cache *cache )
11405ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell{
11415ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   struct texenvprog_cache_item **items;
11425ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   struct texenvprog_cache_item *c, *next;
11435ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   GLuint size, i;
11445ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
11455ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   size = cache->size * 3;
11465ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   items = (struct texenvprog_cache_item**) _mesa_malloc(size * sizeof(*items));
11475ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   _mesa_memset(items, 0, size * sizeof(*items));
11485ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
11495ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   for (i = 0; i < cache->size; i++)
11505ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell      for (c = cache->items[i]; c; c = next) {
11515ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell	 next = c->next;
11525ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell	 c->next = items[c->hash % size];
11535ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell	 items[c->hash % size] = c;
11545ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell      }
11555ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
11565ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   _mesa_free(cache->items);
11575ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   cache->items = items;
11585ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   cache->size = size;
11595ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell}
11605ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
11618065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwellstatic void clear_cache( struct texenvprog_cache *cache )
11628065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell{
11638065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   struct texenvprog_cache_item *c, *next;
11648065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   GLuint i;
11658065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11668065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   for (i = 0; i < cache->size; i++) {
11678065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      for (c = cache->items[i]; c; c = next) {
11688065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell	 next = c->next;
11698065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell	 _mesa_free(c->key);
1170122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul	 cache->ctx->Driver.DeleteProgram(cache->ctx,
1171122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                                          (struct gl_program *) c->data);
11728065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell	 _mesa_free(c);
11738065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      }
11748065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      cache->items[i] = NULL;
11758065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
11768065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11778065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11788065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   cache->n_items = 0;
11798065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell}
11808065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11818065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11825ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwellstatic void cache_item( struct texenvprog_cache *cache,
1183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			GLuint hash,
1184b8f2f6fee147f423438ef7044984b1d7cfb5a428Brian Paul			const struct state_key *key,
1185ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			void *data )
1186ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
118718d1fdebebcb52e7fcf50e62c4c02862d173af51Brian   struct texenvprog_cache_item *c
118818d1fdebebcb52e7fcf50e62c4c02862d173af51Brian      = (struct texenvprog_cache_item *) MALLOC(sizeof(*c));
1189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   c->hash = hash;
11908065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
11918065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   c->key = _mesa_malloc(sizeof(*key));
11928065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memcpy(c->key, key, sizeof(*key));
11938065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
119418d1fdebebcb52e7fcf50e62c4c02862d173af51Brian   c->data = (struct gl_fragment_program *) data;
11955ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
11968065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   if (cache->n_items > cache->size * 1.5) {
11978065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      if (cache->size < 1000)
11988065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell	 rehash(cache);
11998065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      else
12008065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell	 clear_cache(cache);
12018065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
12025ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
12038065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   cache->n_items++;
12045ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   c->next = cache->items[hash % cache->size];
12055ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   cache->items[hash % cache->size] = c;
1206ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1207ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1208d9736db6676948e06712d4bcba46b7040452f870Brian Paulstatic GLuint hash_key( const struct state_key *key )
1209ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
1210ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint *ikey = (GLuint *)key;
1211ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint hash = 0, i;
1212ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
12138065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   /* Make a slightly better attempt at a hash function:
1214ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
12158065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   for (i = 0; i < sizeof(*key)/sizeof(*ikey); i++)
12168065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   {
12178065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      hash += ikey[i];
12188065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      hash += (hash << 10);
12198065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      hash ^= (hash >> 6);
12208065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
1221ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1222ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   return hash;
1223ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1224ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1225a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1226a90046f1097ad95de2aa95ca65741dff5cddced9Brian/**
1227a90046f1097ad95de2aa95ca65741dff5cddced9Brian * If _MaintainTexEnvProgram is set we'll generate a fragment program that
1228a90046f1097ad95de2aa95ca65741dff5cddced9Brian * implements the current texture env/combine mode.
1229a90046f1097ad95de2aa95ca65741dff5cddced9Brian * This function generates that program and puts it into effect.
1230a90046f1097ad95de2aa95ca65741dff5cddced9Brian */
1231a90046f1097ad95de2aa95ca65741dff5cddced9Brianvoid
1232a90046f1097ad95de2aa95ca65741dff5cddced9Brian_mesa_UpdateTexEnvProgram( GLcontext *ctx )
1233ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
12348065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   struct state_key key;
1235ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint hash;
1236122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
1237ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1238a90046f1097ad95de2aa95ca65741dff5cddced9Brian   ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
1239a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1240a90046f1097ad95de2aa95ca65741dff5cddced9Brian   /* If a conventional fragment program/shader isn't in effect... */
1241efcfdbd4d16071088e60a59cb966abd730d9d111Brian   if (!ctx->FragmentProgram._Enabled &&
1242efcfdbd4d16071088e60a59cb966abd730d9d111Brian       !ctx->Shader.CurrentProgram) {
12438065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      make_state_key(ctx, &key);
12448065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell      hash = hash_key(&key);
1245c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1246d9736db6676948e06712d4bcba46b7040452f870Brian Paul      ctx->FragmentProgram._Current =
1247a90046f1097ad95de2aa95ca65741dff5cddced9Brian      ctx->FragmentProgram._TexEnvProgram =
1248a90046f1097ad95de2aa95ca65741dff5cddced9Brian         search_cache(&ctx->Texture.env_fp_cache, hash, &key, sizeof(key));
1249a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1250a90046f1097ad95de2aa95ca65741dff5cddced9Brian      if (!ctx->FragmentProgram._TexEnvProgram) {
1251a90046f1097ad95de2aa95ca65741dff5cddced9Brian         if (0)
1252a90046f1097ad95de2aa95ca65741dff5cddced9Brian            _mesa_printf("Building new texenv proggy for key %x\n", hash);
1253a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1254a90046f1097ad95de2aa95ca65741dff5cddced9Brian         /* create new tex env program */
1255efcfdbd4d16071088e60a59cb966abd730d9d111Brian	 ctx->FragmentProgram._Current =
1256efcfdbd4d16071088e60a59cb966abd730d9d111Brian         ctx->FragmentProgram._TexEnvProgram =
1257efcfdbd4d16071088e60a59cb966abd730d9d111Brian            (struct gl_fragment_program *)
1258a90046f1097ad95de2aa95ca65741dff5cddced9Brian            ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
1259ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1260a90046f1097ad95de2aa95ca65741dff5cddced9Brian         create_new_program(ctx, &key, ctx->FragmentProgram._TexEnvProgram);
1261ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1262a90046f1097ad95de2aa95ca65741dff5cddced9Brian         cache_item(&ctx->Texture.env_fp_cache, hash, &key,
1263a90046f1097ad95de2aa95ca65741dff5cddced9Brian                    ctx->FragmentProgram._TexEnvProgram);
1264c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1265a90046f1097ad95de2aa95ca65741dff5cddced9Brian      else {
1266a90046f1097ad95de2aa95ca65741dff5cddced9Brian         if (0)
1267a90046f1097ad95de2aa95ca65741dff5cddced9Brian            _mesa_printf("Found existing texenv program for key %x\n", hash);
1268c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      }
1269c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   }
1270c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   else {
1271c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell      ctx->FragmentProgram._Current = ctx->FragmentProgram.Current;
1272ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
1273c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1274c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* Tell the driver about the change.  Could define a new target for
1275c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    * this?
1276c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    */
12775d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
12785d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
1279a90046f1097ad95de2aa95ca65741dff5cddced9Brian                         (struct gl_program *) ctx->FragmentProgram._Current);
12805d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   }
1281ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1282ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
12835ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
12845ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwellvoid _mesa_TexEnvProgramCacheInit( GLcontext *ctx )
12855ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell{
12868065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   ctx->Texture.env_fp_cache.ctx = ctx;
12875ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   ctx->Texture.env_fp_cache.size = 17;
12885ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   ctx->Texture.env_fp_cache.n_items = 0;
12895ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   ctx->Texture.env_fp_cache.items = (struct texenvprog_cache_item **)
12905ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell      _mesa_calloc(ctx->Texture.env_fp_cache.size *
12915ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell		   sizeof(struct texenvprog_cache_item));
12925ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell}
12935ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
12945ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
1295ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellvoid _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
1296ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
12978065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   clear_cache(&ctx->Texture.env_fp_cache);
12985ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   _mesa_free(ctx->Texture.env_fp_cache.items);
1299ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1300