ff_fragment_shader.cpp revision 2389c055ed4c26ba5f3979c4a7871a333725dd88
115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/**************************************************************************
215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
3f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * All Rights Reserved.
515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * copy of this software and associated documentation files (the
815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * "Software"), to deal in the Software without restriction, including
915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * without limitation the rights to use, copy, modify, merge, publish,
1015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * distribute, sub license, and/or sell copies of the Software, and to
1115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * permit persons to whom the Software is furnished to do so, subject to
1215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * the following conditions:
1315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * The above copyright notice and this permission notice (including the
1515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * next paragraph) shall be included in all copies or substantial portions
1615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * of the Software.
1715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
2615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell **************************************************************************/
2715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
2815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "glheader.h"
2915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "macros.h"
3015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "enums.h"
315b5c9315275752add1215dba0f86d5f5068d856bBrian Paul#include "shader/program.h"
32c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_parameter.h"
33f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian#include "shader/prog_cache.h"
34c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_instruction.h"
35c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_print.h"
36c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_statevars.h"
3783fad68ec1989c719646a76f4cc5e0b3d23537edBrian#include "shader/programopt.h"
3815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "texenvprogram.h"
3915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
405b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
415b5c9315275752add1215dba0f86d5f5068d856bBrian Paulstruct texenvprog_cache_item
425b5c9315275752add1215dba0f86d5f5068d856bBrian Paul{
435b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   GLuint hash;
445b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   void *key;
455b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct gl_fragment_program *data;
465b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct texenvprog_cache_item *next;
475b5c9315275752add1215dba0f86d5f5068d856bBrian Paul};
485b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
495b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
50e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul/**
51b5e1a93036b22bd30738abccbb8a2645a515667fBrian Paul * Up to nine instructions per tex unit, plus fog, specular color.
52e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul */
53b5e1a93036b22bd30738abccbb8a2645a515667fBrian Paul#define MAX_INSTRUCTIONS ((MAX_TEXTURE_UNITS * 9) + 12)
5415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
55269e3895d9837ac7303b91948f003ca5c12c0fe4Keith Whitwell#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
5615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
57ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct mode_opt {
586280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLubyte Source:4;
596280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLubyte Operand:3;
60ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
61ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
62ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct state_key {
636280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint nr_enabled_units:8;
646280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint enabled_units:8;
655d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint separate_specular:1;
665d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_enabled:1;
675d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_mode:2;
686280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint inputs_available:12;
69ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
70ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct {
715d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint enabled:1;
725d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
7383ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      GLuint shadow:1;
745d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftRGB:2;
755d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftA:2;
76ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
775d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsRGB:2;
785d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeRGB:4;
795d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint NumArgsA:2;
805d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ModeA:4;
816280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell
826280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell      struct mode_opt OptRGB[3];
83ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      struct mode_opt OptA[3];
84ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } unit[8];
85ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
86ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
87ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_LINEAR  0
88ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP     1
89ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP2    2
90ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_UNKNOWN 3
91ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
92ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
93ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
94ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
95ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
96ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP: return FOG_EXP;
97ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP2: return FOG_EXP2;
98ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return FOG_UNKNOWN;
99ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
100ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
101ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
102ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_COLOR           0
103ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_COLOR 1
104ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_ALPHA           2
105ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_ALPHA	3
106ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ZERO                4
107ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE                 5
108ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_UNKNOWN             7
109ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
110ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_operand( GLenum operand )
111ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
112ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (operand) {
113ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_COLOR: return OPR_SRC_COLOR;
114ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
115ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
116ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
117ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ZERO: return OPR_ZERO;
118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE: return OPR_ONE;
119ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:	return OPR_UNKNOWN;
120ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
123ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE  0
124ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE0 1
125ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE1 2
126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE2 3
127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE3 4
128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE4 5
129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE5 6
130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE6 7
131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE7 8
132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_CONSTANT 9
133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PRIMARY_COLOR 10
134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PREVIOUS 11
135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_UNKNOWN  15
136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_source( GLenum src )
138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (src) {
140ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE: return SRC_TEXTURE;
141ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE0:
142ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE1:
143ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE2:
144ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE3:
145ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE4:
146ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE5:
147ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE6:
148ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
149ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_CONSTANT: return SRC_CONSTANT;
150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
151ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PREVIOUS: return SRC_PREVIOUS;
152ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return SRC_UNKNOWN;
153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
156ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_REPLACE       0
157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE      1
158ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD           2
159ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_ADD_SIGNED    3
160ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_INTERPOLATE   4
161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_SUBTRACT      5
162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB      6
163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGB_EXT  7
164ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA     8
165ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_DOT3_RGBA_EXT 9
166ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_ADD_ATI           10
167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SIGNED_ADD_ATI    11
168ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_MODULATE_SUBTRACT_ATI      12
169ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define MODE_UNKNOWN       15
170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_mode( GLenum mode )
172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_REPLACE: return MODE_REPLACE;
175ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE: return MODE_MODULATE;
176ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD: return MODE_ADD;
177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_INTERPOLATE: return MODE_INTERPOLATE;
179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SUBTRACT: return MODE_SUBTRACT;
180ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB: return MODE_DOT3_RGB;
181ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
182ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
184ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
185ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
186ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
187ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return MODE_UNKNOWN;
188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
190ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
191ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define TEXTURE_UNKNOWN_INDEX 7
192e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paulstatic GLuint translate_tex_src_bit( GLbitfield bit )
193ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
1941519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   /* make sure number of switch cases is correct */
1951519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   assert(NUM_TEXTURE_TARGETS == 7);
196ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (bit) {
1971519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_1D_BIT:         return TEXTURE_1D_INDEX;
1981519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_2D_BIT:         return TEXTURE_2D_INDEX;
1991519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_3D_BIT:         return TEXTURE_3D_INDEX;
2001519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_CUBE_BIT:       return TEXTURE_CUBE_INDEX;
2011519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_RECT_BIT:       return TEXTURE_RECT_INDEX;
2021519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_1D_ARRAY_BIT:   return TEXTURE_1D_ARRAY_INDEX;
2031519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   case TEXTURE_2D_ARRAY_BIT:   return TEXTURE_2D_ARRAY_INDEX;
2041519b93b7bc519e187d98f99715a01ba866286b1Brian Paul   default:                     return TEXTURE_UNKNOWN_INDEX;
205ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
206ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
207ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
2081680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
2091680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
2101680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
211239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
212239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Identify all possible varying inputs.  The fragment program will
2131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * never reference non-varying inputs, but will track them via state
2141680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * constants instead.
2151680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell *
2161680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * This function figures out all the inputs that the fragment program
2171680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * has access to.  The bitmask is later reduced to just those which
2181680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * are actually referenced.
2191680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell */
220239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paulstatic GLbitfield get_fp_input_mask( GLcontext *ctx )
2211680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
222f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
223f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul                                   ctx->Shader.CurrentProgram->VertexProgram);
224f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
225239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield fp_inputs = 0x0;
2261680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2276d4d51d647c27288aa625560bc080231099c0b01Brian Paul   if (ctx->VertexProgram._Overriden) {
2286d4d51d647c27288aa625560bc080231099c0b01Brian Paul      /* Somebody's messing with the vertex program and we don't have
2296d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * a clue what's happening.  Assume that it could be producing
2306d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * all possible outputs.
2316d4d51d647c27288aa625560bc080231099c0b01Brian Paul       */
2326d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = ~0;
2336d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
2346d4d51d647c27288aa625560bc080231099c0b01Brian Paul   else if (ctx->RenderMode == GL_FEEDBACK) {
2356d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
2366d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
237f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   else if (!(vertexProgram || vertexShader) ||
238d7296a1a8e846bc4d41ded1c2406b6f5c658188aBrian Paul            !ctx->VertexProgram._Current) {
239f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul      /* Fixed function vertex logic */
240239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul      GLbitfield varying_inputs = ctx->varying_vp_inputs;
2411680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
24297e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
24397e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
24497e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
24597e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
24697e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         varying_inputs |= FRAG_BITS_TEX_ANY;
24797e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
2481680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* First look at what values may be computed by the generated
2491680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * vertex program:
2501680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
2511680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (ctx->Light.Enabled) {
2521680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         fp_inputs |= FRAG_BIT_COL0;
2531680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2541680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
2551680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell            fp_inputs |= FRAG_BIT_COL1;
2561680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      }
2571680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2581680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (ctx->Texture._TexGenEnabled |
2591680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
2601680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* Then look at what might be varying as a result of enabled
2621680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * arrays, etc:
2631680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
2641680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (varying_inputs & VERT_BIT_COLOR0) fp_inputs |= FRAG_BIT_COL0;
2651680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (varying_inputs & VERT_BIT_COLOR1) fp_inputs |= FRAG_BIT_COL1;
2661680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2671680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
2681680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    << FRAG_ATTRIB_TEX0);
2691680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2701680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
2711680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
2721680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* calculate from vp->outputs */
2732389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      struct gl_vertex_program *vprog;
2742389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      GLbitfield vp_outputs;
2752389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
2762389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      /* Choose GLSL vertex shader over ARB vertex program.  Need this
2772389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * since vertex shader state validation comes after fragment state
2782389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * validation (see additional comments in state.c).
2792389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       */
2802389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      if (vertexShader)
2812389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul         vprog = ctx->Shader.CurrentProgram->VertexProgram;
2822389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      else
2832389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul         vprog = ctx->VertexProgram._Current;
2842389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
2852389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      vp_outputs = vprog->Base.OutputsWritten;
2861680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
28797e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
28897e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
28997e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
29097e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
29197e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         vp_outputs |= FRAG_BITS_TEX_ANY;
29297e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
2931680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (vp_outputs & (1 << VERT_RESULT_COL0)) fp_inputs |= FRAG_BIT_COL0;
2941680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (vp_outputs & (1 << VERT_RESULT_COL1)) fp_inputs |= FRAG_BIT_COL1;
2951680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2960370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell      fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
2970370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell                    << FRAG_ATTRIB_TEX0);
2981680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
2991680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3001680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   return fp_inputs;
3011680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
3021680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3031680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
30422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
30522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Examine current texture environment state and generate a unique
30622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * key to identify it.
30722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
3088065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwellstatic void make_state_key( GLcontext *ctx,  struct state_key *key )
309ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
310ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint i, j;
311239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_referenced = FRAG_BIT_COL0;
312239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_available = get_fp_input_mask( ctx );
3131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3148065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memset(key, 0, sizeof(*key));
3158065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
316ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
317d9736db6676948e06712d4bcba46b7040452f870Brian Paul      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
318b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao      GLenum format;
319bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger
320bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger      if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
321ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         continue;
322ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
323b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao      format = texUnit->_Current->Image[0][texUnit->_Current->BaseLevel]->_BaseFormat;
324b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao
325ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].enabled = 1;
326ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->enabled_units |= (1<<i);
3271680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      key->nr_enabled_units = i+1;
3281680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_TEX(i);
329ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
330ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].source_index =
331ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_tex_src_bit(texUnit->_ReallyEnabled);
332b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao      key->unit[i].shadow = ((texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
333b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                             ((format == GL_DEPTH_COMPONENT) ||
334b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                              (format == GL_DEPTH_STENCIL_EXT)));
335ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
336ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
337ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
338ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
339ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeRGB =
340ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
341ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeA =
342ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 translate_mode(texUnit->_CurrentCombine->ModeA);
343ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
344ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
34564da16146fed68605f83ccf3b64075c0d5b6f052Keith Whitwell      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
346ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
347ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      for (j=0;j<3;j++) {
348ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Operand =
349ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
350ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Operand =
351ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
352ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptRGB[j].Source =
353ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
354ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         key->unit[i].OptA[j].Source =
355ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
356ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      }
357ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
358ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
3591680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
360ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->separate_specular = 1;
3611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_COL1;
3621680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
363ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
364ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->Fog.Enabled) {
365ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_enabled = 1;
366ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
3671680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
368ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
3691680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3701680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   key->inputs_available = (inputs_available & inputs_referenced);
371ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
372ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
373239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
374239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Use uregs to represent registers internally, translate to Mesa's
37515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * expected formats on emit.
37615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
37715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * NOTE: These are passed by value extensively in this file rather
37815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * than as usual by pointer reference.  If this disturbs you, try
37915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * remembering they are just 32bits in size.
38015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
38115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * GCC is smart enough to deal with these dword-sized structures in
38215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * much the same way as if I had defined them as dwords and was using
38315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * macros to access and set the fields.  This is much nicer and easier
38415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * to evolve.
38515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
38615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct ureg {
38715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint file:4;
38815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint idx:8;
38915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negatebase:1;
39015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint abs:1;
39115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negateabs:1;
39215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint swz:12;
39315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint pad:5;
39415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
39515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
39613abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paulstatic const struct ureg undef = {
3978d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   PROGRAM_UNDEFINED,
39815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   ~0,
39915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
40015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
40115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
40215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
40315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0
40415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
40515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
40615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
407239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/** State used to build the fragment program:
40815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
40915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct texenv_fragment_program {
410122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_fragment_program *program;
41115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLcontext *ctx;
412ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *state;
41315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
414239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield alu_temps;	/**< Track texture indirections, see spec. */
415239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temps_output;	/**< Track texture indirections, see spec. */
416239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temp_in_use;	/**< Tracks temporary regs which are in use. */
41715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLboolean error;
41815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4192dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg src_texture[MAX_TEXTURE_UNITS];
420ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   /* Reg containing each texture unit's sampled texture color,
421ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    * else undef.
422ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
42315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
424239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   struct ureg src_previous;	/**< Reg containing color from previous
42515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 * stage.  May need to be decl'd.
42615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 */
42715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
428239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLuint last_tex_stage;	/**< Number of last enabled texture unit */
4292dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
4302dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg half;
4312dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg one;
4322dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg zero;
43315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
43415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
43515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
43615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
43715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
43815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
43915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg reg;
44015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.file = file;
44115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.idx = idx;
44215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negatebase = 0;
44315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.abs = 0;
44415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negateabs = 0;
44515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = SWIZZLE_NOOP;
44615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.pad = 0;
44715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
44815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
44915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
45015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
45115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
45215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
45315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, y),
45415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, z),
45515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, w));
45615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
45715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
45815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
45915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
46015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
46115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
46215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return swizzle(reg, x, x, x, x);
46315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
46415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
4656fe176a64859798db17fbaed6858cccc646aae38Keith Whitwellstatic struct ureg negate( struct ureg reg )
4666fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell{
4676fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   reg.negatebase ^= 1;
4686fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   return reg;
4696fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell}
4706fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell
47115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic GLboolean is_undef( struct ureg reg )
47215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
4738d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   return reg.file == PROGRAM_UNDEFINED;
47415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
47515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
476ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
47715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_temp( struct texenv_fragment_program *p )
47815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
47913abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   GLint bit;
480ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
481cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try and reuse temps which have been used already:
482ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
483b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
484ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
485ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
486ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
487ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit)
488b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
489ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
490ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit) {
491bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
492b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
493ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   }
494ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
49513abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
496b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
497b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
49893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
499ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
500ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell}
501ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
502ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwellstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
503ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell{
504ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   int bit;
505ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
506d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   /* First try to find available temp not previously used (to avoid
507cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * starting a new texture indirection).  According to the spec, the
508cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * ~p->temps_output isn't necessary, but will keep it there for
509cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * now:
510ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
511b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
512ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
513ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
514ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
515cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!bit)
516b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
517ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
51815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (!bit) {
519bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
520b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
52115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
52215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
52313abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
524b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
525b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
52693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
52715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
52815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
52915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
53015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5315620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul/** Mark a temp reg as being no longer allocatable. */
5325620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paulstatic void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
5335620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul{
5345620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   if (r.file == PROGRAM_TEMPORARY)
5355620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul      p->temps_output |= (1 << r.idx);
5365620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul}
5375620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
5385620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
539f18d4e058ed979c6e42e868c7febde4fa62c5810Brianstatic void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
54015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
541f18d4e058ed979c6e42e868c7febde4fa62c5810Brian   GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
54293cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell
5432dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   /* KW: To support tex_env_crossbar, don't release the registers in
5442dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    * temps_output.
5452dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    */
54693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   if (max_temp >= sizeof(int) * 8)
5472dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = p->temps_output;
54893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   else
5492dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
55015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
55115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
55215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5539fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brianstatic struct ureg register_param5( struct texenv_fragment_program *p,
554ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s0,
555ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s1,
556ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s2,
557ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s3,
5589fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian				    GLint s4)
55915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
5609fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian   gl_state_index tokens[STATE_LENGTH];
56147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint idx;
56247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[0] = s0;
56347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[1] = s1;
56447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[2] = s2;
56547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[3] = s3;
56647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[4] = s4;
567de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
56847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
56947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell}
57015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
57115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5729fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
5739fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
5749fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
5759fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
57647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
5771680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwellstatic GLuint frag_to_vert_attrib( GLuint attrib )
5781680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
5791680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   switch (attrib) {
5801680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
5811680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
5821680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   default:
5831680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib >= FRAG_ATTRIB_TEX0);
5841680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib <= FRAG_ATTRIB_TEX7);
5851680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
5861680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
5871680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
5881680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
58947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
59047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
59147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell{
5921680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (p->state->inputs_available & (1<<input)) {
5931680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      p->program->Base.InputsRead |= (1 << input);
5941680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return make_ureg(PROGRAM_INPUT, input);
5951680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
5961680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
5971680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      GLuint idx = frag_to_vert_attrib( input );
5981680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
5991680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
60015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
60115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
60247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
6037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *reg,
60415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg )
60515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
60615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->File = ureg.file;
60715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Index = ureg.idx;
60815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Swizzle = ureg.swz;
609f2802c40fff686301a7ff99f0a0b1c57d5cf5625Keith Whitwell   reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
61015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Abs = ureg.abs;
61115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->NegateAbs = ureg.negateabs;
61215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
61315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6147e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
61515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg, GLuint mask )
61615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
61715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->File = ureg.file;
61815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->Index = ureg.idx;
61915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->WriteMask = mask;
620c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondMask = COND_TR;  /* always pass cond test */
621c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondSwizzle = SWIZZLE_NOOP;
62215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
62315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic struct prog_instruction *
62515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellemit_op(struct texenv_fragment_program *p,
6265d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul	enum prog_opcode op,
62715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg dest,
62815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	GLuint mask,
62922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	GLboolean saturate,
63015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src0,
63115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src1,
63215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src2 )
63315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
63447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint nr = p->program->Base.NumInstructions++;
635de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
6362a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
6372a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian   assert(nr < MAX_INSTRUCTIONS);
6382a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
639d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul   _mesa_init_instructions(inst, 1);
64015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->Opcode = op;
64115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
64247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
64347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
64447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
64515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
646e31ac052236ea615b4995f9ec301d8af4b864531Brian Paul   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
64715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
64815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_dst( &inst->DstReg, dest, mask );
64915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6505620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#if 0
651cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
652cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
653cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
654cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->temps_output |= 1 << dest.idx;
6555620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#endif
656cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
65715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return inst;
65815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
65915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
66015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
66115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_arith( struct texenv_fragment_program *p,
6625d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
66347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg dest,
66447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       GLuint mask,
66522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			       GLboolean saturate,
66647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src0,
66747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src1,
66847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src2 )
66915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
67015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
67115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
672cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
673cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
674cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (src0.file == PROGRAM_TEMPORARY)
675cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src0.idx;
676cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
677cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
678cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src1.idx;
679cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
680cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
681cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src2.idx;
682cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
683cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
684cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << dest.idx;
685cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
68621f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumAluInstructions++;
68715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
68815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
68915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
69015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_texld( struct texenv_fragment_program *p,
6915d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
692ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg dest,
693ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint destmask,
694ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_unit,
695ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_idx,
696ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg coord )
69715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
6987e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   struct prog_instruction *inst = emit_op( p, op,
69915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  dest, destmask,
70022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul					  GL_FALSE,	/* don't saturate? */
70115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  coord, 	/* arg 0? */
70215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef,
70315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef);
70415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7057e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   inst->TexSrcTarget = tex_idx;
70615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->TexSrcUnit = tex_unit;
70715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
70821f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumTexInstructions++;
70915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7105620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   /* Accounting for indirection tracking:
7115620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul    */
7125620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   reserve_temp(p, dest);
7135620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
714cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Is this a texture indirection?
715cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
716cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if ((coord.file == PROGRAM_TEMPORARY &&
717cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->temps_output & (1<<coord.idx))) ||
718cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       (dest.file == PROGRAM_TEMPORARY &&
719cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->alu_temps & (1<<dest.idx)))) {
72021f99792a916a62fcfae7c208f50f192d4ce5926Brian      p->program->Base.NumTexIndirections++;
7212dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temps_output = 1<<coord.idx;
722cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps = 0;
7232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(0);		/* KW: texture env crossbar */
72415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
72515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
72715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
72815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
73047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_const4f( struct texenv_fragment_program *p,
731ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s0,
732ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s1,
733ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s2,
734ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s3)
73515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
73647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLfloat values[4];
737a90046f1097ad95de2aa95ca65741dff5cddced9Brian   GLuint idx, swizzle;
738d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   struct ureg r;
73947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[0] = s0;
74047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[1] = s1;
74147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[2] = s2;
74247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[3] = s3;
743a90046f1097ad95de2aa95ca65741dff5cddced9Brian   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
744a90046f1097ad95de2aa95ca65741dff5cddced9Brian                                     &swizzle );
745d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r = make_ureg(PROGRAM_CONSTANT, idx);
746d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r.swz = swizzle;
747d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   return r;
74815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
74915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
750e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
75147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
75247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
75347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
75415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
75515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_one( struct texenv_fragment_program *p )
7572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7582dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->one))
7592dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->one = register_scalar_const(p, 1.0);
7602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->one;
7612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7622dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
7632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_half( struct texenv_fragment_program *p )
7642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7652dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->half))
7664dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->half = register_scalar_const(p, 0.5);
7672dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->half;
7682dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7692dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
7702dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_zero( struct texenv_fragment_program *p )
7712dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
7722dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->zero))
7734dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->zero = register_scalar_const(p, 0.0);
7742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->zero;
7752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
7762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
77715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
77815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void program_error( struct texenv_fragment_program *p, const char *msg )
77915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
780bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul   _mesa_problem(NULL, msg);
78115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p->error = 1;
78215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
78315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
78415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_source( struct texenv_fragment_program *p,
785ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint src, GLuint unit )
78615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
78715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (src) {
788ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE:
7892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(!is_undef(p->src_texture[unit]));
7902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return p->src_texture[unit];
79115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
792ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
793ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
794ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
795ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
796ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
797ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
798ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
799ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
800ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
801ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return p->src_texture[src - SRC_TEXTURE0];
802ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
803ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_CONSTANT:
80447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_param2(p, STATE_TEXENV_COLOR, unit);
8052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
806ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PRIMARY_COLOR:
80747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_input(p, FRAG_ATTRIB_COL0);
8082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
809ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PREVIOUS:
810ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default:
81147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (is_undef(p->src_previous))
81247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return register_input(p, FRAG_ATTRIB_COL0);
81347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      else
81447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return p->src_previous;
81515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
81615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
8172dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
81815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine_source( struct texenv_fragment_program *p,
819ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint mask,
820ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint unit,
821ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint source,
822ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint operand )
82315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
82415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg arg, src, one;
82515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   src = get_source(p, source, unit);
82715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (operand) {
829ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_COLOR:
83015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
83115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.xyzw
83215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
83315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      arg = get_temp( p );
8342dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one( p );
8357e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
83615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
837ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_ALPHA:
83815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_W)
83915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src;
84015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
84122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	 return swizzle1( src, SWIZZLE_W );
842ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_ALPHA:
84315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
84415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.wwww
84515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
8462dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      arg = get_temp(p);
8472dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one(p);
8487e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
84922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			one, swizzle1(src, SWIZZLE_W), undef);
850ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ZERO:
8512dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_zero(p);
852ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE:
8532dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_one(p);
854ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_COLOR:
85515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
85615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src;
85715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
85815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
85915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
860ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLboolean args_match( struct state_key *key, GLuint unit )
86115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
86222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i, nr = key->unit[unit].NumArgsRGB;
86315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0 ; i < nr ; i++) {
865ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
86615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;
86715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
868ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      switch(key->unit[unit].OptA[i].Operand) {
869ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_SRC_ALPHA:
870ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
871ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_COLOR:
872ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_ALPHA:
87315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
87415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
87515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
87615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
87715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
878ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_ONE_MINUS_SRC_ALPHA:
879ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 switch(key->unit[unit].OptRGB[i].Operand) {
880ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_COLOR:
881ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_ALPHA:
88215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
88315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
88415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
88515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
88615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
88715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      default:
88815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;	/* impossible */
88915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
89015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
89115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
89215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return GL_TRUE;
89315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
89415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
89515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine( struct texenv_fragment_program *p,
896ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 struct ureg dest,
897ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mask,
89822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul				 GLboolean saturate,
899ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint unit,
900ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint nr,
901ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mode,
902d9736db6676948e06712d4bcba46b7040452f870Brian Paul				 const struct mode_opt *opt)
903ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
90415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg src[3];
905cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg tmp, half;
90622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i;
90715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
9080063084804d62402d80821a86978660663955442Brian Paul   tmp = undef; /* silence warning (bug 5318) */
9090063084804d62402d80821a86978660663955442Brian Paul
91015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0; i < nr; i++)
911ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
91215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
91315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (mode) {
914ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_REPLACE:
91515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_XYZW && !saturate)
91615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src[0];
91715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
9187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
919ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE:
9207e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
9216fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
922ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD:
9237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
9246fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
925ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD_SIGNED:
92615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp = arg0 + arg1
927cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       * result = tmp - .5
92815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
9292dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
93099da2d30eb08e50edf4b0067518af3acdf2dabc0Jerome Glisse      tmp = get_temp( p );
9317e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
9327e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
93315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
934ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_INTERPOLATE:
93515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
93615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
9377e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
93815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
939ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_SUBTRACT:
9407e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
94115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
942ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA:
943ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
944ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
945ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB: {
94615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp0 = get_temp( p );
94715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp1 = get_temp( p );
948e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg neg1 = register_scalar_const(p, -1);
949e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg two  = register_scalar_const(p, 2);
95015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
95115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp0 = 2*src0 - 1
95215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * tmp1 = 2*src1 - 1
95315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       *
95415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * dst = tmp0 dot3 tmp1
95515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
9567e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
9576fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		  two, src[0], neg1);
95815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
959aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
96015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 tmp1 = tmp0;
96115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
9627e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
9636fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		     two, src[1], neg1);
9647e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
96515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
96615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
967ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_ADD_ATI:
9686fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 */
9697e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
9706fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[2], src[1] );
971ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SIGNED_ADD_ATI: {
9726fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 - 0.5 */
9736fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      struct ureg tmp0 = get_temp(p);
9742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
9757e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
9767e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
9776fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
9786fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   }
979ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SUBTRACT_ATI:
9806fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 - Arg1 */
9817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
9826fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
98315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
98415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src[0];
98515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
98615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
98715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
98815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
98922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
99022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for one texture unit's env/combiner mode.
99122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
99222db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic struct ureg
99322db53577603afef8fdf62c324ff5977de76b9d8Brian Paulemit_texenv(struct texenv_fragment_program *p, GLuint unit)
99415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
995ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
99622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLboolean saturate = (unit < p->last_tex_stage);
99715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint rgb_shift, alpha_shift;
99815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg out, shift;
999cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg dest;
100015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1001ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (!key->unit[unit].enabled) {
1002ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return get_source(p, SRC_PREVIOUS, 0);
100315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1004ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1005ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (key->unit[unit].ModeRGB) {
1006ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
1007ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
100815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
100915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
1010ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
101115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      alpha_shift = 0;
101215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
101315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
101415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
1015ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      rgb_shift = key->unit[unit].ScaleShiftRGB;
1016ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
101715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
101815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1019ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1020cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* If this is the very last calculation, emit direct to output reg:
1021cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
1022ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular ||
1023cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       unit != p->last_tex_stage ||
1024cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       alpha_shift ||
1025cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       rgb_shift)
1026cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      dest = get_temp( p );
1027cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   else
102890ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
102915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
103015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Emit the RGB and A combine ops
103115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
1032ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
1033ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       args_match(key, unit)) {
103415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
103515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1036ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1037ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1038ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
103915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1040ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
10419a45176dd85a1cd523498efeebd0481950a1bf58Roland Scheidegger	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
104215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
104315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
104415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1045ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1046ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1047ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
104815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
104915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else {
105015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Need to do something to stop from re-emitting identical
105115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * argument calculations here:
105215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
105315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
105415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1055ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1056ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1057ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
105815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_W, saturate,
105915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1060ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsA,
1061ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeA,
1062ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptA);
106315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
106415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
106515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Deal with the final shift:
106615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
106715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (alpha_shift || rgb_shift) {
106815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (rgb_shift == alpha_shift) {
106953174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
107015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
107115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else {
10722dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell	 shift = register_const4f(p,
107353174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
107453174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
107553174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<rgb_shift),
107653174afeeb68a79e471185cb463c13ff90af698fJosé Fonseca				  (GLfloat)(1<<alpha_shift));
107715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
10787e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
107915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			 saturate, out, shift, undef );
108015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
108115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else
108215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return out;
108315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
108415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10852dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
108622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
108722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instruction for getting a texture source term.
108822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
10892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic void load_texture( struct texenv_fragment_program *p, GLuint unit )
10902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
10912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->src_texture[unit])) {
1092ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      GLuint dim = p->state->unit[unit].source_index;
10932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
10942dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg tmp = get_tex_temp( p );
10952dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1096bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      if (dim == TEXTURE_UNKNOWN_INDEX)
1097bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul         program_error(p, "TexSrcBit");
1098ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
10992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* TODO: Use D0_MASK_XY where possible.
11002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
110183ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      if (p->state->unit[unit].enabled) {
1102b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
1103b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    tmp, WRITEMASK_XYZW,
1104b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola					    unit, dim, texcoord );
11050397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell
110683ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle	 if (p->state->unit[unit].shadow)
110783ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle	    p->program->Base.ShadowSamplers |= 1 << unit;
11080397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell
11091e3b07f363e6bf512ab1a5c620656985aece40fdBrian         p->program->Base.SamplersUsed |= (1 << unit);
1110fce4612f8a29ee1798c9326a431a139d856c7a04Brian         /* This identity mapping should already be in place
1111fce4612f8a29ee1798c9326a431a139d856c7a04Brian          * (see _mesa_init_program_struct()) but let's be safe.
1112fce4612f8a29ee1798c9326a431a139d856c7a04Brian          */
1113fce4612f8a29ee1798c9326a431a139d856c7a04Brian         p->program->Base.SamplerUnits[unit] = unit;
11141e3b07f363e6bf512ab1a5c620656985aece40fdBrian      }
1115b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      else
1116b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = get_zero(p);
11172dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
11182dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
11192dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1120241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwellstatic GLboolean load_texenv_source( struct texenv_fragment_program *p,
1121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLuint src, GLuint unit )
11222dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
11232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   switch (src) {
11244dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola   case SRC_TEXTURE:
11252dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      load_texture(p, unit);
11262dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
11272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
1129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
1130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
1131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
1132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
1133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
1134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
1135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
1136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      load_texture(p, src - SRC_TEXTURE0);
11372dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
11382dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
11392dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   default:
11402dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
11412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1142241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell
1143241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
11442dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
11452dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
114622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
114722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
114822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for loading all texture source terms.
114922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
115022db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic GLboolean
115122db53577603afef8fdf62c324ff5977de76b9d8Brian Paulload_texunit_sources( struct texenv_fragment_program *p, int unit )
11522dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
1153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *key = p->state;
1154b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   GLuint i;
1155b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1156b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
1157b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit);
1158b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   }
1159b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1160b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
1161b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
11622dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1163b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1164241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
11652dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
11662dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
116722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
116822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
116922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate a new fragment program which implements the context's
117022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * current texture env/combine mode.
117122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
117222db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic void
1173e998c346471142db91a1bcb6c61551b8247b87e7Brian Paulcreate_new_program(GLcontext *ctx, struct state_key *key,
1174122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                   struct gl_fragment_program *program)
117515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1176e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
117715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct texenv_fragment_program p;
117815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint unit;
117915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg cf, out;
1180276330b2412910777f7016f427909085f02acbb8Keith Whitwell
1181e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell   _mesa_memset(&p, 0, sizeof(p));
118215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.ctx = ctx;
1183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.state = key;
1184ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.program = program;
118515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1186e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* During code generation, use locally-allocated instruction buffer,
1187e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    * then alloc dynamic storage below.
1188e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    */
1189e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.Instructions = instBuffer;
1190276330b2412910777f7016f427909085f02acbb8Keith Whitwell   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
119121f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexIndirections = 1;	/* correct? */
119221f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexInstructions = 0;
119321f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumAluInstructions = 0;
11941240eb2683043ba81e81378807170d0d7045581dBrian   p.program->Base.String = NULL;
11959ca8815d3ba56ad718ba1c48c73aae3cdc0b8db0Keith Whitwell   p.program->Base.NumInstructions =
1196e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumTemporaries =
1197e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumParameters =
1198e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1199de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1200dbeea25bb834479a29712100888c862348112018Keith Whitwell
1201de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.InputsRead = 0;
1202de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
120315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
12052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p.src_texture[unit] = undef;
12062dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
120747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   p.src_previous = undef;
12085ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.half = undef;
12095ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.zero = undef;
12105ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.one = undef;
12115ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
121215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.last_tex_stage = 0;
1213f18d4e058ed979c6e42e868c7febde4fa62c5810Brian   release_temps(ctx, &p);
121415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1215ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->enabled_units) {
12162dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* First pass - to support texture_env_crossbar, first identify
12172dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * all referenced texture sources and emit texld instructions
12182dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * for each:
12192dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
122015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1221ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->unit[unit].enabled) {
1222b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    load_texunit_sources( &p, unit );
1223b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    p.last_tex_stage = unit;
122415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
122515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12262dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* Second pass - emit combine instructions to build final color:
12272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
122815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
1229ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->enabled_units & (1<<unit)) {
123015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    p.src_previous = emit_texenv( &p, unit );
12315620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul            reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
1232f18d4e058ed979c6e42e868c7febde4fa62c5810Brian	    release_temps(ctx, &p);	/* release all temps */
123315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
123415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
123515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1236ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   cf = get_source( &p, SRC_PREVIOUS, 0 );
123790ebb581e60d29bd565ad4d8a49e642de7b0ce5dBrian Paul   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
123815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1239ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular) {
124015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Emit specular add.
124115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
124247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
12437e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
12447e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
124515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1246aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
124715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Will wind up in here if no texture enabled or a couple of
124815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * other scenarios (GL_REPLACE for instance).
124915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
12507e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
125115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
125215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
125347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   /* Finish up:
125447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell    */
12557e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
125647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1257ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->fog_enabled) {
1258ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      /* Pull fog mode from GLcontext, the value in the state key is
1259ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       * a reduced value and not what is expected in FogOption
1260ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       */
1261276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = ctx->Fog.Mode;
126263be96bdc7e9f388a5c49295bd7e150462fd003aBrian      p.program->Base.InputsRead |= FRAG_BIT_FOGC; /* XXX new */
1263ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   } else
1264276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = GL_NONE;
126547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
126621f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
126715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max nr indirect texture lookups");
126815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
126921f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
127015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max TEX instructions");
127115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
127221f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
127315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max ALU instructions");
127415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12755d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
12768b88f62fbd62153500fc3483003f438561366a00Keith Whitwell
1277e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* Allocate final instruction array */
12783bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   p.program->Base.Instructions
12793bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      = _mesa_alloc_instructions(p.program->Base.NumInstructions);
12803bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   if (!p.program->Base.Instructions) {
1281e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1282e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                  "generating tex env program");
1283e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      return;
1284e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
12853bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
12863bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian                           p.program->Base.NumInstructions);
12873bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian
12883bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   if (p.program->FogOption) {
12893bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      _mesa_append_fog_code(ctx, p.program);
12903bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian      p.program->FogOption = GL_NONE;
12913bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian   }
12923bf8d2ac7108a7f0f1722e411161e013bb8573f0Brian
1293e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1294dbeea25bb834479a29712100888c862348112018Keith Whitwell   /* Notify driver the fragment program has (actually) changed.
12958b88f62fbd62153500fc3483003f438561366a00Keith Whitwell    */
1296e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (ctx->Driver.ProgramStringNotify) {
1297e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1298e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                                       &p.program->Base );
1299e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1300e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1301e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (DISASSEM) {
1302e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_print_program(&p.program->Base);
1303e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_printf("\n");
1304dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
130515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
130615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
13075d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul
1308a90046f1097ad95de2aa95ca65741dff5cddced9Brian/**
130983ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian * Return a fragment program which implements the current
131083ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian * fixed-function texture, fog and color-sum operations.
131183ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian */
131283ce6c51d7189094cf2a13fdcc0882a051a3bd41Brianstruct gl_fragment_program *
131383ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
1314ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
131583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   struct gl_fragment_program *prog;
131683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   struct state_key key;
131783ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
131883ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   make_state_key(ctx, &key);
131983ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian
1320f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian   prog = (struct gl_fragment_program *)
1321f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
1322f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian                                 &key, sizeof(key));
13238065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
132483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   if (!prog) {
132583ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian      prog = (struct gl_fragment_program *)
132683ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
13278065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
132883ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian      create_new_program(ctx, &key, prog);
13295ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
1330f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1331f4a5ea2ccb472958a4635c606e9510011bceaa3dBrian                                 &key, sizeof(key), &prog->Base);
13328065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
13335ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
133483ce6c51d7189094cf2a13fdcc0882a051a3bd41Brian   return prog;
1335ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1336ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1337ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1338a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1339a90046f1097ad95de2aa95ca65741dff5cddced9Brian/**
1340a90046f1097ad95de2aa95ca65741dff5cddced9Brian * If _MaintainTexEnvProgram is set we'll generate a fragment program that
1341a90046f1097ad95de2aa95ca65741dff5cddced9Brian * implements the current texture env/combine mode.
1342a90046f1097ad95de2aa95ca65741dff5cddced9Brian * This function generates that program and puts it into effect.
1343af74abab6b9a1e32a1cc5cac7e547b953dcee0abKeith Whitwell *
1344af74abab6b9a1e32a1cc5cac7e547b953dcee0abKeith Whitwell * XXX: remove this function.  currently only called by some drivers,
1345af74abab6b9a1e32a1cc5cac7e547b953dcee0abKeith Whitwell * not by mesa core.  We now handle this properly from inside mesa.
1346a90046f1097ad95de2aa95ca65741dff5cddced9Brian */
1347a90046f1097ad95de2aa95ca65741dff5cddced9Brianvoid
1348a90046f1097ad95de2aa95ca65741dff5cddced9Brian_mesa_UpdateTexEnvProgram( GLcontext *ctx )
1349ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
1350122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
1351ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1352a90046f1097ad95de2aa95ca65741dff5cddced9Brian   ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
1353a90046f1097ad95de2aa95ca65741dff5cddced9Brian
1354a90046f1097ad95de2aa95ca65741dff5cddced9Brian   /* If a conventional fragment program/shader isn't in effect... */
1355efcfdbd4d16071088e60a59cb966abd730d9d111Brian   if (!ctx->FragmentProgram._Enabled &&
1356d781cdc8fadc802a1f2edbeb13ccb1ee768ce803Brian       (!ctx->Shader.CurrentProgram ||
13570397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell        !ctx->Shader.CurrentProgram->FragmentProgram) )
13580397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell   {
13595b5c9315275752add1215dba0f86d5f5068d856bBrian Paul      struct gl_fragment_program *newProg;
13605b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
13610397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell      newProg = _mesa_get_fixed_func_fragment_program(ctx);
13625b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
13635b5c9315275752add1215dba0f86d5f5068d856bBrian Paul      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg);
13645b5c9315275752add1215dba0f86d5f5068d856bBrian Paul      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg);
1365c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   }
1366c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell
1367c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell   /* Tell the driver about the change.  Could define a new target for
1368c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    * this?
1369c3626a91cee5034528f3f92c802a8e5947ea5f92Keith Whitwell    */
13705d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
13715d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
1372a90046f1097ad95de2aa95ca65741dff5cddced9Brian                         (struct gl_program *) ctx->FragmentProgram._Current);
13735d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   }
1374ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
1375