ff_fragment_shader.cpp revision 4dd8a8907e40126e42131a400b59e7d5da5e302a
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**************************************************************************
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * All Rights Reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copy of this software and associated documentation files (the
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the following conditions:
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * The above copyright notice and this permission notice (including the
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * of the Software.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) **************************************************************************/
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "glheader.h"
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "macros.h"
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "enums.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "texenvprogram.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "shader/program.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "shader/program_instruction.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MAX_INSTRUCTIONS 100
3753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)struct mode_opt {
4153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint Source:4;
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint Operand:3;
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)};
4453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
4553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)struct state_key {
4653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLbitfield enabled_units;
4753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint separate_specular:1;
4853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint fog_enabled:1;
4953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint fog_mode:2;
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   struct {
5253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint enabled:1;
5353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
5453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint ScaleShiftRGB:2;
5553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint ScaleShiftA:2;
5653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
5753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint NumArgsRGB:2;
5853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint ModeRGB:4;
5953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      struct mode_opt OptRGB[3];
6053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint NumArgsA:2;
6253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      GLuint ModeA:4;
6353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      struct mode_opt OptA[3];
6453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   } unit[8];
6553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)};
6653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
6753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define FOG_LINEAR  0
6853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define FOG_EXP     1
6953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define FOG_EXP2    2
7053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define FOG_UNKNOWN 3
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
7253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static GLuint translate_fog_mode( GLenum mode )
7353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
7453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   switch (mode) {
7553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case GL_LINEAR: return FOG_LINEAR;
7653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case GL_EXP: return FOG_EXP;
7753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case GL_EXP2: return FOG_EXP2;
7853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   default: return FOG_UNKNOWN;
7953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   }
8053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
8153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
8253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#define OPR_SRC_COLOR           0
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_ONE_MINUS_SRC_COLOR 1
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_SRC_ALPHA           2
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_ONE_MINUS_SRC_ALPHA	3
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_ZERO                4
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_ONE                 5
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define OPR_UNKNOWN             7
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GLuint translate_operand( GLenum operand )
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   switch (operand) {
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_SRC_COLOR: return OPR_SRC_COLOR;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ZERO: return OPR_ZERO;
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ONE: return OPR_ONE;
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   default:	return OPR_UNKNOWN;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE  0
104926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define SRC_TEXTURE0 1
105926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define SRC_TEXTURE1 2
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE2 3
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE3 4
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE4 5
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE5 6
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE6 7
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_TEXTURE7 8
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_CONSTANT 9
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define SRC_PRIMARY_COLOR 10
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_PREVIOUS 11
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define SRC_UNKNOWN  15
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GLuint translate_source( GLenum src )
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   switch (src) {
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE: return SRC_TEXTURE;
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE0:
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE1:
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE2:
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE3:
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE4:
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE5:
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE6:
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_CONSTANT: return SRC_CONSTANT;
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_PREVIOUS: return SRC_PREVIOUS;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   default: return SRC_UNKNOWN;
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_REPLACE       0
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_MODULATE      1
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_ADD           2
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_ADD_SIGNED    3
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_INTERPOLATE   4
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_SUBTRACT      5
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_DOT3_RGB      6
143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define MODE_DOT3_RGB_EXT  7
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_DOT3_RGBA     8
145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define MODE_DOT3_RGBA_EXT 9
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_MODULATE_ADD_ATI           10
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_MODULATE_SIGNED_ADD_ATI    11
148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)#define MODE_MODULATE_SUBTRACT_ATI      12
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define MODE_UNKNOWN       15
150926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
151926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static GLuint translate_mode( GLenum mode )
152926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
153926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   switch (mode) {
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_REPLACE: return MODE_REPLACE;
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_MODULATE: return MODE_MODULATE;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ADD: return MODE_ADD;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_INTERPOLATE: return MODE_INTERPOLATE;
159926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   case GL_SUBTRACT: return MODE_SUBTRACT;
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_DOT3_RGB: return MODE_DOT3_RGB;
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   default: return MODE_UNKNOWN;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define TEXTURE_UNKNOWN_INDEX 7
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GLuint translate_tex_src_bit( GLbitfield bit )
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   switch (bit) {
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   default: return TEXTURE_UNKNOWN_INDEX;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Examine current texture environment state and generate a unique
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * key to identify it.
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct state_key *
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)make_state_key(GLcontext *ctx)
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct state_key *key = CALLOC_STRUCT(state_key);
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint i, j;
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (!texUnit->_ReallyEnabled)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         continue;
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].enabled = 1;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->enabled_units |= (1<<i);
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].source_index =
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 translate_tex_src_bit(texUnit->_ReallyEnabled);
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].ModeRGB =
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].ModeA =
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 translate_mode(texUnit->_CurrentCombine->ModeA);
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftRGB;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      for (j=0;j<3;j++) {
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         key->unit[i].OptRGB[j].Operand =
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         key->unit[i].OptA[j].Operand =
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         key->unit[i].OptRGB[j].Source =
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)         key->unit[i].OptA[j].Source =
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      }
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->separate_specular = 1;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (ctx->Fog.Enabled) {
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->fog_enabled = 1;
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return key;
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* Use uregs to represent registers internally, translate to Mesa's
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * expected formats on emit.
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * NOTE: These are passed by value extensively in this file rather
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * than as usual by pointer reference.  If this disturbs you, try
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * remembering they are just 32bits in size.
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * GCC is smart enough to deal with these dword-sized structures in
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * much the same way as if I had defined them as dwords and was using
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * macros to access and set the fields.  This is much nicer and easier
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * to evolve.
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct ureg {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint file:4;
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint idx:8;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint negatebase:1;
256926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   GLuint abs:1;
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint negateabs:1;
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint swz:12;
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint pad:5;
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
262926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)const static struct ureg undef = {
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   ~0,
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   ~0,
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   0,
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   0,
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   0,
26853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   0,
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   0
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* State used to build the fragment program:
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct texenv_fragment_program {
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct fragment_program *program;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLcontext *ctx;
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct state_key *state;
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLbitfield alu_temps;	/* Track texture indirections, see spec. */
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLbitfield temps_output;	/* Track texture indirections, see spec. */
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLbitfield temp_in_use;	/* Tracks temporary regs which are in use. */
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLboolean error;
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg src_texture[MAX_TEXTURE_UNITS];
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Reg containing each texture unit's sampled texture color,
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    * else undef.
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg src_previous;	/* Reg containing color from previous
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				 * stage.  May need to be decl'd.
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				 */
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint last_tex_stage;	/* Number of last enabled texture unit */
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg half;
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg one;
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg zero;
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg make_ureg(GLuint file, GLuint idx)
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct ureg reg;
3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.file = file;
3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.idx = idx;
3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.negatebase = 0;
3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.abs = 0;
3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.negateabs = 0;
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.swz = SWIZZLE_NOOP;
3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.pad = 0;
3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return reg;
3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
31753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			   GET_SWZ(reg.swz, y),
3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			   GET_SWZ(reg.swz, z),
3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			   GET_SWZ(reg.swz, w));
3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
323926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   return reg;
3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg swizzle1( struct ureg reg, int x )
3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return swizzle(reg, x, x, x, x);
3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg negate( struct ureg reg )
3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg.negatebase ^= 1;
3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return reg;
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
336926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static GLboolean is_undef( struct ureg reg )
338926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return reg.file == 0xf;
340926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_temp( struct texenv_fragment_program *p )
3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   int bit;
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* First try and reuse temps which have been used already:
3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Then any unused temporary:
3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!bit)
3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      bit = _mesa_ffs( ~p->temp_in_use );
35553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!bit) {
3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      _mesa_exit(1);
3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (bit > p->program->Base.NumTemporaries)
3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->program->Base.NumTemporaries = bit;
3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->temp_in_use |= 1<<(bit-1);
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
36753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_tex_temp( struct texenv_fragment_program *p )
3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   int bit;
3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* First try to find availble temp not previously used (to avoid
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    * starting a new texture indirection).  According to the spec, the
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    * ~p->temps_output isn't necessary, but will keep it there for
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    * now:
3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Then any unused temporary:
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!bit)
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      bit = _mesa_ffs( ~p->temp_in_use );
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!bit) {
3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      _mesa_exit(1);
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
389926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   if (bit > p->program->Base.NumTemporaries)
390926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      p->program->Base.NumTemporaries = bit;
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->temp_in_use |= 1<<(bit-1);
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void release_temps( struct texenv_fragment_program *p )
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint max_temp = p->ctx->Const.FragmentProgram.MaxTemps;
4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* KW: To support tex_env_crossbar, don't release the registers in
402926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    * temps_output.
403926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    */
40453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   if (max_temp >= sizeof(int) * 8)
405926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      p->temp_in_use = p->temps_output;
406926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   else
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
409926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
410926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
411926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static struct ureg register_param6( struct texenv_fragment_program *p,
412926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s0,
413926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s1,
414926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s2,
415926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s3,
416926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s4,
417926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)				    GLint s5)
418926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
419926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   GLint tokens[6];
420926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   GLuint idx;
421926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   tokens[0] = s0;
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   tokens[1] = s1;
423926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   tokens[2] = s2;
424926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   tokens[3] = s3;
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   tokens[4] = s4;
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   tokens[5] = s5;
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return make_ureg(PROGRAM_STATE_VAR, idx);
429926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_param1(p,s0)          register_param6(p,s0,0,0,0,0,0)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_param2(p,s0,s1)       register_param6(p,s0,s1,0,0,0,0)
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_param3(p,s0,s1,s2)    register_param6(p,s0,s1,s2,0,0,0)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_param4(p,s0,s1,s2,s3) register_param6(p,s0,s1,s2,s3,0,0)
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
437926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->program->Base.InputsRead |= (1 << input);
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return make_ureg(PROGRAM_INPUT, input);
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void emit_arg( struct prog_src_register *reg,
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		      struct ureg ureg )
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->File = ureg.file;
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->Index = ureg.idx;
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->Swizzle = ureg.swz;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->Abs = ureg.abs;
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   reg->NegateAbs = ureg.negateabs;
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
455926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void emit_dst( struct prog_dst_register *dst,
4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)		      struct ureg ureg, GLuint mask )
4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   dst->File = ureg.file;
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   dst->Index = ureg.idx;
4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   dst->WriteMask = mask;
4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   dst->CondMask = 0;
4635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   dst->CondSwizzle = 0;
4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct prog_instruction *
4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)emit_op(struct texenv_fragment_program *p,
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	enum prog_opcode op,
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	struct ureg dest,
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	GLuint mask,
47153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	GLboolean saturate,
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	struct ureg src0,
473926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)	struct ureg src1,
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	struct ureg src2 )
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint nr = p->program->Base.NumInstructions++;
4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   _mesa_init_instruction(inst);
48053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   inst->Opcode = op;
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   emit_arg( &inst->SrcReg[0], src0 );
48353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   emit_arg( &inst->SrcReg[1], src1 );
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   emit_arg( &inst->SrcReg[2], src2 );
4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   emit_dst( &inst->DstReg, dest, mask );
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Accounting for indirection tracking:
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (dest.file == PROGRAM_TEMPORARY)
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->temps_output |= 1 << dest.idx;
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return inst;
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg emit_arith( struct texenv_fragment_program *p,
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       enum prog_opcode op,
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg dest,
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       GLuint mask,
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       GLboolean saturate,
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg src0,
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg src1,
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg src2 )
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Accounting for indirection tracking:
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
5125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (src0.file == PROGRAM_TEMPORARY)
5135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->alu_temps |= 1 << src0.idx;
5145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
5165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->alu_temps |= 1 << src1.idx;
5175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
5195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->alu_temps |= 1 << src2.idx;
5205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (dest.file == PROGRAM_TEMPORARY)
5225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->alu_temps |= 1 << dest.idx;
5235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->program->NumAluInstructions++;
5255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return dest;
5265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg emit_texld( struct texenv_fragment_program *p,
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       enum prog_opcode op,
5305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg dest,
5315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       GLuint destmask,
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       GLuint tex_unit,
5335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       GLuint tex_idx,
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)			       struct ureg coord )
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   struct prog_instruction *inst = emit_op( p, op,
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					  dest, destmask,
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					  GL_FALSE,	/* don't saturate? */
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					  coord, 	/* arg 0? */
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					  undef,
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					  undef);
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   inst->TexSrcTarget = tex_idx;
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   inst->TexSrcUnit = tex_unit;
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->program->NumTexInstructions++;
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   /* Is this a texture indirection?
5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    */
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if ((coord.file == PROGRAM_TEMPORARY &&
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	(p->temps_output & (1<<coord.idx))) ||
5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       (dest.file == PROGRAM_TEMPORARY &&
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	(p->alu_temps & (1<<dest.idx)))) {
5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->program->NumTexIndirections++;
5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->temps_output = 1<<coord.idx;
5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->alu_temps = 0;
5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      assert(0);		/* KW: texture env crossbar */
5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return dest;
561926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg register_const4f( struct texenv_fragment_program *p,
5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				     GLfloat s0,
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				     GLfloat s1,
5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				     GLfloat s2,
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)				     GLfloat s3)
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLfloat values[4];
5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   GLuint idx;
5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   values[0] = s0;
5735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   values[1] = s1;
5745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   values[2] = s2;
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   values[3] = s3;
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values );
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return make_ureg(PROGRAM_STATE_VAR, idx);
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
5835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
5845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_one( struct texenv_fragment_program *p )
5875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (is_undef(p->one))
5895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->one = register_scalar_const(p, 1.0);
5905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return p->one;
5915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_half( struct texenv_fragment_program *p )
5945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (is_undef(p->half))
5965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->half = register_scalar_const(p, 0.5);
5975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return p->half;
5985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_zero( struct texenv_fragment_program *p )
60153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   if (is_undef(p->zero))
6035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      p->zero = register_scalar_const(p, 0.0);
6045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   return p->zero;
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static void program_error( struct texenv_fragment_program *p, const char *msg )
60953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   _mesa_problem(NULL, msg);
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   p->error = 1;
6125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static struct ureg get_source( struct texenv_fragment_program *p,
615926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)			       GLuint src, GLuint unit )
616926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){
617926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)   switch (src) {
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE:
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      assert(!is_undef(p->src_texture[unit]));
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return p->src_texture[unit];
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE0:
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE1:
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE2:
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE3:
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE4:
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE5:
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE6:
6295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_TEXTURE7:
630926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return p->src_texture[src - SRC_TEXTURE0];
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_CONSTANT:
63453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return register_param2(p, STATE_TEXENV_COLOR, unit);
6355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_PRIMARY_COLOR:
63753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return register_input(p, FRAG_ATTRIB_COL0);
6385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case SRC_PREVIOUS:
6405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   default:
6415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (is_undef(p->src_previous))
6425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 return register_input(p, FRAG_ATTRIB_COL0);
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else
6445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 return p->src_previous;
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   }
6465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
64853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static struct ureg emit_combine_source( struct texenv_fragment_program *p,
64953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)					GLuint mask,
6505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					GLuint unit,
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					GLuint source,
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)					GLuint operand )
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
65453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   struct ureg arg, src, one;
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   src = get_source(p, source, unit);
6575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   switch (operand) {
6595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case OPR_ONE_MINUS_SRC_COLOR:
6605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      /* Get unused tmp,
6615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       * Emit tmp = 1.0 - arg.xyzw
6625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       */
6635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      arg = get_temp( p );
6645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      one = get_one( p );
6655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
6665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case OPR_SRC_ALPHA:
6685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      if (mask == WRITEMASK_W)
6695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 return src;
6705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      else
6715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)	 return swizzle1( src, SWIZZLE_W );
6725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)   case OPR_ONE_MINUS_SRC_ALPHA:
6735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      /* Get unused tmp,
6745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       * Emit tmp = 1.0 - arg.wwww
6755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       */
6765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)      arg = get_temp(p);
67753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      one = get_one(p);
67853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
67953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			one, swizzle1(src, SWIZZLE_W), undef);
68053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case OPR_ZERO:
68153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return get_zero(p);
68253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case OPR_ONE:
68353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return get_one(p);
68453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case OPR_SRC_COLOR:
68553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   default:
68653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return src;
68753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   }
68853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
68953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
69053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static GLboolean args_match( struct state_key *key, GLuint unit )
69153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
69253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint i, nr = key->unit[unit].NumArgsRGB;
69353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
69453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   for (i = 0 ; i < nr ; i++) {
69553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
69653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 return GL_FALSE;
69753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
69853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      switch(key->unit[unit].OptA[i].Operand) {
69953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      case OPR_SRC_ALPHA:
70053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 switch(key->unit[unit].OptRGB[i].Operand) {
70153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 case OPR_SRC_COLOR:
70253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 case OPR_SRC_ALPHA:
70353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    break;
70453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 default:
70553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    return GL_FALSE;
70653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 }
70753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 break;
70853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      case OPR_ONE_MINUS_SRC_ALPHA:
70953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 switch(key->unit[unit].OptRGB[i].Operand) {
71053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 case OPR_ONE_MINUS_SRC_COLOR:
71153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 case OPR_ONE_MINUS_SRC_ALPHA:
71253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    break;
71353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 default:
71453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	    return GL_FALSE;
71553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 }
71653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 break;
71753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      default:
71853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 return GL_FALSE;	/* impossible */
71953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      }
72053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   }
72153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
72253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   return GL_TRUE;
72353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
72453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
72553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)static struct ureg emit_combine( struct texenv_fragment_program *p,
72653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 struct ureg dest,
72753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 GLuint mask,
72853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 GLboolean saturate,
72953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 GLuint unit,
73053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 GLuint nr,
73153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 GLuint mode,
73253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)				 struct mode_opt *opt)
73353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){
73453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   struct ureg src[3];
73553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   struct ureg tmp, half;
73653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   GLuint i;
73753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
73853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   tmp = undef; /* silence warning (bug 5318) */
73953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
74053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   for (i = 0; i < nr; i++)
74153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
74253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
74353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   switch (mode) {
74453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case MODE_REPLACE:
74553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      if (mask == WRITEMASK_XYZW && !saturate)
74653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 return src[0];
74753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      else
74853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
74953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case MODE_MODULATE:
75053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
75153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 src[0], src[1], undef );
75253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case MODE_ADD:
75353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
75453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)			 src[0], src[1], undef );
75553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)   case MODE_ADD_SIGNED:
75653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)      /* tmp = arg0 + arg1
7575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)       * result = tmp - .5
758       */
759      half = get_half(p);
760      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
761      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
762      return dest;
763   case MODE_INTERPOLATE:
764      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
765       */
766      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
767
768   case MODE_SUBTRACT:
769      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
770
771   case MODE_DOT3_RGBA:
772   case MODE_DOT3_RGBA_EXT:
773   case MODE_DOT3_RGB_EXT:
774   case MODE_DOT3_RGB: {
775      struct ureg tmp0 = get_temp( p );
776      struct ureg tmp1 = get_temp( p );
777      struct ureg neg1 = register_scalar_const(p, -1);
778      struct ureg two  = register_scalar_const(p, 2);
779
780      /* tmp0 = 2*src0 - 1
781       * tmp1 = 2*src1 - 1
782       *
783       * dst = tmp0 dot3 tmp1
784       */
785      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
786		  two, src[0], neg1);
787
788      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
789	 tmp1 = tmp0;
790      else
791	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
792		     two, src[1], neg1);
793      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
794      return dest;
795   }
796   case MODE_MODULATE_ADD_ATI:
797      /* Arg0 * Arg2 + Arg1 */
798      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
799			 src[0], src[2], src[1] );
800   case MODE_MODULATE_SIGNED_ADD_ATI: {
801      /* Arg0 * Arg2 + Arg1 - 0.5 */
802      struct ureg tmp0 = get_temp(p);
803      half = get_half(p);
804      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
805      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
806      return dest;
807   }
808   case MODE_MODULATE_SUBTRACT_ATI:
809      /* Arg0 * Arg2 - Arg1 */
810      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
811      return dest;
812   default:
813      return src[0];
814   }
815}
816
817
818/**
819 * Generate instructions for one texture unit's env/combiner mode.
820 */
821static struct ureg
822emit_texenv(struct texenv_fragment_program *p, GLuint unit)
823{
824   struct state_key *key = p->state;
825   GLboolean saturate = (unit < p->last_tex_stage);
826   GLuint rgb_shift, alpha_shift;
827   struct ureg out, shift;
828   struct ureg dest;
829
830   if (!key->unit[unit].enabled) {
831      return get_source(p, SRC_PREVIOUS, 0);
832   }
833
834   switch (key->unit[unit].ModeRGB) {
835   case MODE_DOT3_RGB_EXT:
836      alpha_shift = key->unit[unit].ScaleShiftA;
837      rgb_shift = 0;
838      break;
839   case MODE_DOT3_RGBA_EXT:
840      alpha_shift = 0;
841      rgb_shift = 0;
842      break;
843   default:
844      rgb_shift = key->unit[unit].ScaleShiftRGB;
845      alpha_shift = key->unit[unit].ScaleShiftA;
846      break;
847   }
848
849   /* If this is the very last calculation, emit direct to output reg:
850    */
851   if (key->separate_specular ||
852       unit != p->last_tex_stage ||
853       alpha_shift ||
854       rgb_shift)
855      dest = get_temp( p );
856   else
857      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
858
859   /* Emit the RGB and A combine ops
860    */
861   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
862       args_match(key, unit)) {
863      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
864			  unit,
865			  key->unit[unit].NumArgsRGB,
866			  key->unit[unit].ModeRGB,
867			  key->unit[unit].OptRGB);
868   }
869   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
870	    key->unit[unit].ModeA == MODE_DOT3_RGBA) {
871
872      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
873			  unit,
874			  key->unit[unit].NumArgsRGB,
875			  key->unit[unit].ModeRGB,
876			  key->unit[unit].OptRGB);
877   }
878   else {
879      /* Need to do something to stop from re-emitting identical
880       * argument calculations here:
881       */
882      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
883			  unit,
884			  key->unit[unit].NumArgsRGB,
885			  key->unit[unit].ModeRGB,
886			  key->unit[unit].OptRGB);
887      out = emit_combine( p, dest, WRITEMASK_W, saturate,
888			  unit,
889			  key->unit[unit].NumArgsA,
890			  key->unit[unit].ModeA,
891			  key->unit[unit].OptA);
892   }
893
894   /* Deal with the final shift:
895    */
896   if (alpha_shift || rgb_shift) {
897      if (rgb_shift == alpha_shift) {
898	 shift = register_scalar_const(p, 1<<rgb_shift);
899      }
900      else {
901	 shift = register_const4f(p,
902				  1<<rgb_shift,
903				  1<<rgb_shift,
904				  1<<rgb_shift,
905				  1<<alpha_shift);
906      }
907      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
908			 saturate, out, shift, undef );
909   }
910   else
911      return out;
912}
913
914
915/**
916 * Generate instruction for getting a texture source term.
917 */
918static void load_texture( struct texenv_fragment_program *p, GLuint unit )
919{
920   if (is_undef(p->src_texture[unit])) {
921      GLuint dim = p->state->unit[unit].source_index;
922      struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
923      struct ureg tmp = get_tex_temp( p );
924
925      if (dim == TEXTURE_UNKNOWN_INDEX)
926         program_error(p, "TexSrcBit");
927
928      /* TODO: Use D0_MASK_XY where possible.
929       */
930      p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
931					 tmp, WRITEMASK_XYZW,
932					 unit, dim, texcoord );
933   }
934}
935
936static GLboolean load_texenv_source( struct texenv_fragment_program *p,
937				     GLuint src, GLuint unit )
938{
939   switch (src) {
940   case SRC_TEXTURE:
941      load_texture(p, unit);
942      break;
943
944   case SRC_TEXTURE0:
945   case SRC_TEXTURE1:
946   case SRC_TEXTURE2:
947   case SRC_TEXTURE3:
948   case SRC_TEXTURE4:
949   case SRC_TEXTURE5:
950   case SRC_TEXTURE6:
951   case SRC_TEXTURE7:
952      if (!p->state->unit[src - SRC_TEXTURE0].enabled)
953	 return GL_FALSE;
954      load_texture(p, src - SRC_TEXTURE0);
955      break;
956
957   default:
958      break;
959   }
960
961   return GL_TRUE;
962}
963
964
965/**
966 * Generate instructions for loading all texture source terms.
967 */
968static GLboolean
969load_texunit_sources( struct texenv_fragment_program *p, int unit )
970{
971   struct state_key *key = p->state;
972   int i, nr = key->unit[unit].NumArgsRGB;
973   for (i = 0; i < nr; i++) {
974      if (!load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit) ||
975	  !load_texenv_source( p, key->unit[unit].OptA[i].Source, unit ))
976	 return GL_FALSE;
977   }
978   return GL_TRUE;
979}
980
981
982/**
983 * Generate a new fragment program which implements the context's
984 * current texture env/combine mode.
985 */
986static void
987create_new_program(struct state_key *key, GLcontext *ctx,
988                   struct fragment_program *program)
989{
990   struct texenv_fragment_program p;
991   GLuint unit;
992   struct ureg cf, out;
993
994   _mesa_memset(&p, 0, sizeof(p));
995   p.ctx = ctx;
996   p.state = key;
997   p.program = program;
998
999   p.program->Base.Instructions =
1000      (struct prog_instruction*) _mesa_malloc(sizeof(struct prog_instruction) * MAX_INSTRUCTIONS);
1001   p.program->Base.NumInstructions = 0;
1002   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
1003   p.program->NumTexIndirections = 1;	/* correct? */
1004   p.program->NumTexInstructions = 0;
1005   p.program->NumAluInstructions = 0;
1006   p.program->Base.String = 0;
1007   p.program->Base.NumInstructions =
1008      p.program->Base.NumTemporaries =
1009      p.program->Base.NumParameters =
1010      p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1011   p.program->Base.Parameters = _mesa_new_parameter_list();
1012
1013   p.program->Base.InputsRead = 0;
1014   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
1015
1016   for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
1017      p.src_texture[unit] = undef;
1018
1019   p.src_previous = undef;
1020   p.last_tex_stage = 0;
1021   release_temps(&p);
1022
1023   if (key->enabled_units) {
1024      /* First pass - to support texture_env_crossbar, first identify
1025       * all referenced texture sources and emit texld instructions
1026       * for each:
1027       */
1028      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1029	 if (key->unit[unit].enabled) {
1030	    if (load_texunit_sources( &p, unit ))
1031	       p.last_tex_stage = unit;
1032	 }
1033
1034      /* Second pass - emit combine instructions to build final color:
1035       */
1036      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
1037	 if (key->enabled_units & (1<<unit)) {
1038	    p.src_previous = emit_texenv( &p, unit );
1039	    release_temps(&p);	/* release all temps */
1040	 }
1041   }
1042
1043   cf = get_source( &p, SRC_PREVIOUS, 0 );
1044   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
1045
1046   if (key->separate_specular) {
1047      /* Emit specular add.
1048       */
1049      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
1050      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
1051      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
1052   }
1053   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
1054      /* Will wind up in here if no texture enabled or a couple of
1055       * other scenarios (GL_REPLACE for instance).
1056       */
1057      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
1058   }
1059
1060   /* Finish up:
1061    */
1062   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
1063
1064   if (key->fog_enabled) {
1065      /* Pull fog mode from GLcontext, the value in the state key is
1066       * a reduced value and not what is expected in FogOption
1067       */
1068      p.program->FogOption = ctx->Fog.Mode;
1069   } else
1070      p.program->FogOption = GL_NONE;
1071
1072   if (p.program->NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
1073      program_error(&p, "Exceeded max nr indirect texture lookups");
1074
1075   if (p.program->NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
1076      program_error(&p, "Exceeded max TEX instructions");
1077
1078   if (p.program->NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
1079      program_error(&p, "Exceeded max ALU instructions");
1080
1081   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
1082
1083   /* Notify driver the fragment program has (actually) changed.
1084    */
1085   if (ctx->Driver.ProgramStringNotify || DISASSEM) {
1086      if (ctx->Driver.ProgramStringNotify)
1087	 ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1088					  &p.program->Base );
1089
1090      if (DISASSEM) {
1091	 _mesa_print_program(&p.program->Base);
1092	 _mesa_printf("\n");
1093      }
1094   }
1095}
1096
1097
1098static void *search_cache( struct texenvprog_cache *cache,
1099			   GLuint hash,
1100			   const void *key,
1101			   GLuint keysize)
1102{
1103   struct texenvprog_cache *c;
1104
1105   for (c = cache; c; c = c->next) {
1106      if (c->hash == hash && _mesa_memcmp(c->key, key, keysize) == 0)
1107	 return c->data;
1108   }
1109
1110   return NULL;
1111}
1112
1113static void cache_item( struct texenvprog_cache **cache,
1114			GLuint hash,
1115			void *key,
1116			void *data )
1117{
1118   struct texenvprog_cache *c = CALLOC_STRUCT(texenvprog_cache);
1119   c->hash = hash;
1120   c->key = key;
1121   c->data = data;
1122   c->next = *cache;
1123   *cache = c;
1124}
1125
1126static GLuint hash_key( struct state_key *key )
1127{
1128   GLuint *ikey = (GLuint *)key;
1129   GLuint hash = 0, i;
1130
1131   /* I'm sure this can be improved on, but speed is important:
1132    */
1133   for (i = 0; i < sizeof(*key)/sizeof(GLuint); i++)
1134      hash ^= ikey[i];
1135
1136   return hash;
1137}
1138
1139void _mesa_UpdateTexEnvProgram( GLcontext *ctx )
1140{
1141   struct state_key *key;
1142   GLuint hash;
1143   struct fragment_program *prev = ctx->FragmentProgram._Current;
1144
1145   if (!ctx->FragmentProgram._Enabled) {
1146      key = make_state_key(ctx);
1147      hash = hash_key(key);
1148
1149      ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
1150	 (struct fragment_program *)
1151	 search_cache(ctx->Texture.env_fp_cache, hash, key, sizeof(*key));
1152
1153      if (!ctx->_TexEnvProgram) {
1154	 if (0) _mesa_printf("Building new texenv proggy for key %x\n", hash);
1155
1156	 ctx->FragmentProgram._Current = ctx->_TexEnvProgram =
1157	    (struct fragment_program *)
1158	    ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
1159
1160	 create_new_program(key, ctx, ctx->_TexEnvProgram);
1161
1162	 cache_item(&ctx->Texture.env_fp_cache, hash, key, ctx->_TexEnvProgram);
1163      } else {
1164	 _mesa_free(key);
1165	 if (0) _mesa_printf("Found existing texenv program for key %x\n", hash);
1166      }
1167   }
1168   else {
1169      ctx->FragmentProgram._Current = ctx->FragmentProgram.Current;
1170   }
1171
1172   /* Tell the driver about the change.  Could define a new target for
1173    * this?
1174    */
1175   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
1176      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
1177                             (struct program *) ctx->FragmentProgram._Current);
1178   }
1179}
1180
1181void _mesa_TexEnvProgramCacheDestroy( GLcontext *ctx )
1182{
1183   struct texenvprog_cache *a, *tmp;
1184
1185   for (a = ctx->Texture.env_fp_cache; a; a = tmp) {
1186      tmp = a->next;
1187      _mesa_free(a->key);
1188      ctx->Driver.DeleteProgram(ctx, (struct program *) a->data);
1189      _mesa_free(a);
1190   }
1191}
1192