ff_fragment_shader.cpp revision a46e32787d98192d35bf2834011cfa5537e0e703
115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell/**************************************************************************
215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * All Rights Reserved.
56947f85cb5fbc433ba7763530285e470745b009bBrian Paul * Copyright 2009 VMware, Inc.  All Rights Reserved.
615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * Permission is hereby granted, free of charge, to any person obtaining a
815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * copy of this software and associated documentation files (the
915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * "Software"), to deal in the Software without restriction, including
1015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * without limitation the rights to use, copy, modify, merge, publish,
1115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * distribute, sub license, and/or sell copies of the Software, and to
1215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * permit persons to whom the Software is furnished to do so, subject to
1315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * the following conditions:
1415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * The above copyright notice and this permission notice (including the
1615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * next paragraph) shall be included in all copies or substantial portions
1715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * of the Software.
1815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
1915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
2715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell **************************************************************************/
2815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
2915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "glheader.h"
3025e5a6f279cec0863dcc341805aa7ca71189b626Brian Paul#include "imports.h"
315b5c9315275752add1215dba0f86d5f5068d856bBrian Paul#include "shader/program.h"
32c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_parameter.h"
3332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell#include "shader/prog_cache.h"
34c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_instruction.h"
35c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_print.h"
36c223c6b663cd5db39ba19c2be74b88cc3b8f53f3Brian#include "shader/prog_statevars.h"
37fb3c41f5044bc0e228470ebf9f2cfdf2c53f191fBrian#include "shader/programopt.h"
3815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "texenvprogram.h"
3915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
405b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
41e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul/*
42e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * Note on texture units:
43e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
44e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * The number of texture units supported by fixed-function fragment
45e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
46e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * That's because there's a one-to-one correspondence between texture
47e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * coordinates and samplers in fixed-function processing.
48e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
49e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
50e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * sets of texcoords, so is fixed-function fragment processing.
51e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
52e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
53e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul */
54e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul
55e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul
565b5c9315275752add1215dba0f86d5f5068d856bBrian Paulstruct texenvprog_cache_item
575b5c9315275752add1215dba0f86d5f5068d856bBrian Paul{
585b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   GLuint hash;
595b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   void *key;
605b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct gl_fragment_program *data;
615b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct texenvprog_cache_item *next;
625b5c9315275752add1215dba0f86d5f5068d856bBrian Paul};
635b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
649cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholtstatic GLboolean
659cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholttexenv_doing_secondary_color(GLcontext *ctx)
669cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt{
679cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (ctx->Light.Enabled &&
689cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt       (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
699cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt      return GL_TRUE;
709cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt
719cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (ctx->Fog.ColorSumEnabled)
729cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt      return GL_TRUE;
739cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt
749cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   return GL_FALSE;
759cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt}
765b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
77e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul/**
78b5e1a93036b22bd30738abccbb8a2645a515667fBrian Paul * Up to nine instructions per tex unit, plus fog, specular color.
79e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul */
800815ebccfc0a12d8f3e831928f1c4210b7f75ad8Brian Paul#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
8115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82269e3895d9837ac7303b91948f003ca5c12c0fe4Keith Whitwell#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
8315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
84ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct mode_opt {
85a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson   GLubyte Source:4;  /**< SRC_x */
86a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson   GLubyte Operand:3; /**< OPR_x */
87ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
88ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
89ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct state_key {
906280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint nr_enabled_units:8;
916280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint enabled_units:8;
925d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint separate_specular:1;
935d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_enabled:1;
949ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   GLuint fog_mode:2;          /**< FOG_x */
956280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint inputs_available:12;
96ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
97ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct {
985d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint enabled:1;
999ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint source_index:3;   /**< TEXTURE_x_INDEX */
10083ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      GLuint shadow:1;
1015d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftRGB:2;
1025d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftA:2;
103ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1049ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint NumArgsRGB:3;  /**< up to MAX_COMBINER_TERMS */
105f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      GLuint ModeRGB:5;     /**< MODE_x */
106ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1079ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint NumArgsA:3;  /**< up to MAX_COMBINER_TERMS */
108f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      GLuint ModeA:5;     /**< MODE_x */
109a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson
110a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson      struct mode_opt OptRGB[MAX_COMBINER_TERMS];
111bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul      struct mode_opt OptA[MAX_COMBINER_TERMS];
112d55a28e3dc712342e4a2f25aa9b661add7461e82Brian Paul   } unit[MAX_TEXTURE_UNITS];
113ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
114ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
115ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_LINEAR  0
116ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP     1
117ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP2    2
118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_UNKNOWN 3
119ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
120ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
121ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
123ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
124ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP: return FOG_EXP;
125ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP2: return FOG_EXP2;
126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return FOG_UNKNOWN;
127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_COLOR           0
131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_COLOR 1
132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_ALPHA           2
133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_ALPHA	3
134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ZERO                4
135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE                 5
136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_UNKNOWN             7
137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_operand( GLenum operand )
139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
140ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (operand) {
141ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_COLOR: return OPR_SRC_COLOR;
142ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
143ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
144ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
145ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ZERO: return OPR_ZERO;
146ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE: return OPR_ONE;
1476947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
1486947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
1496947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return OPR_UNKNOWN;
150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
151ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
152ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE  0
154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE0 1
155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE1 2
156ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE2 3
157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE3 4
158ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE4 5
159ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE5 6
160ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE6 7
161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE7 8
162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_CONSTANT 9
163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PRIMARY_COLOR 10
164ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PREVIOUS 11
1656947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define SRC_ZERO     12
166ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_UNKNOWN  15
167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
168ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_source( GLenum src )
169ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (src) {
171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE: return SRC_TEXTURE;
172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE0:
173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE1:
174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE2:
175ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE3:
176ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE4:
177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE5:
178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE6:
179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
180ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_CONSTANT: return SRC_CONSTANT;
181ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
182ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PREVIOUS: return SRC_PREVIOUS;
1836947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ZERO:
1846947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return SRC_ZERO;
1856947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
1866947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
1876947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return SRC_UNKNOWN;
188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
190ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1916947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_REPLACE                     0  /* r = a0 */
1926947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE                    1  /* r = a0 * a1 */
1936947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD                         2  /* r = a0 + a1 */
1946947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_SIGNED                  3  /* r = a0 + a1 - 0.5 */
1956947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_INTERPOLATE                 4  /* r = a0 * a2 + a1 * (1 - a2) */
1966947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_SUBTRACT                    5  /* r = a0 - a1 */
1976947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGB                    6  /* r = a0 . a1 */
1986947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGB_EXT                7  /* r = a0 . a1 */
1996947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGBA                   8  /* r = a0 . a1 */
2006947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGBA_EXT               9  /* r = a0 . a1 */
2016947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_ADD_ATI           10  /* r = a0 * a2 + a1 */
2026947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_SIGNED_ADD_ATI    11  /* r = a0 * a2 + a1 - 0.5 */
2036947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_SUBTRACT_ATI      12  /* r = a0 * a2 - a1 */
2046947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_PRODUCTS               13  /* r = a0 * a1 + a2 * a3 */
2056947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_PRODUCTS_SIGNED        14  /* r = a0 * a1 + a2 * a3 - 0.5 */
206114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#define MODE_BUMP_ENVMAP_ATI            15  /* special */
207114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#define MODE_UNKNOWN                    16
2086947f85cb5fbc433ba7763530285e470745b009bBrian Paul
2096947f85cb5fbc433ba7763530285e470745b009bBrian Paul/**
2106947f85cb5fbc433ba7763530285e470745b009bBrian Paul * Translate GL combiner state into a MODE_x value
2116947f85cb5fbc433ba7763530285e470745b009bBrian Paul */
2126947f85cb5fbc433ba7763530285e470745b009bBrian Paulstatic GLuint translate_mode( GLenum envMode, GLenum mode )
213ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
214ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
215ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_REPLACE: return MODE_REPLACE;
216ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE: return MODE_MODULATE;
2176947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ADD:
2186947f85cb5fbc433ba7763530285e470745b009bBrian Paul      if (envMode == GL_COMBINE4_NV)
2196947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_PRODUCTS;
2206947f85cb5fbc433ba7763530285e470745b009bBrian Paul      else
2216947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD;
2226947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ADD_SIGNED:
2236947f85cb5fbc433ba7763530285e470745b009bBrian Paul      if (envMode == GL_COMBINE4_NV)
2246947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_PRODUCTS_SIGNED;
2256947f85cb5fbc433ba7763530285e470745b009bBrian Paul      else
2266947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_SIGNED;
227ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_INTERPOLATE: return MODE_INTERPOLATE;
228ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SUBTRACT: return MODE_SUBTRACT;
229ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB: return MODE_DOT3_RGB;
230ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
231ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
232ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
233ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
234ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
235ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
236114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
2376947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
2386947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
2396947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return MODE_UNKNOWN;
240ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
241ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
242ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
243f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
244f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul/**
245f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
246f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul */
247e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paulstatic GLuint translate_tex_src_bit( GLbitfield bit )
248ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
249b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul   ASSERT(bit);
250b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul   return _mesa_ffs(bit) - 1;
251ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
252ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
253f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
2541680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
2551680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
2561680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
257239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
258239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Identify all possible varying inputs.  The fragment program will
2591680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * never reference non-varying inputs, but will track them via state
2601680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * constants instead.
2611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell *
2621680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * This function figures out all the inputs that the fragment program
2631680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * has access to.  The bitmask is later reduced to just those which
2641680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * are actually referenced.
2651680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell */
266239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paulstatic GLbitfield get_fp_input_mask( GLcontext *ctx )
2671680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
268e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_PROGRAM */
269f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   const GLboolean vertexShader = (ctx->Shader.CurrentProgram &&
27040990d9dfb20b69585859b2a45596aa46c20140aEric Anholt				   ctx->Shader.CurrentProgram->LinkStatus &&
271f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul                                   ctx->Shader.CurrentProgram->VertexProgram);
272f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
273239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield fp_inputs = 0x0;
2741680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
2756d4d51d647c27288aa625560bc080231099c0b01Brian Paul   if (ctx->VertexProgram._Overriden) {
2766d4d51d647c27288aa625560bc080231099c0b01Brian Paul      /* Somebody's messing with the vertex program and we don't have
2776d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * a clue what's happening.  Assume that it could be producing
2786d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * all possible outputs.
2796d4d51d647c27288aa625560bc080231099c0b01Brian Paul       */
2806d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = ~0;
2816d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
2826d4d51d647c27288aa625560bc080231099c0b01Brian Paul   else if (ctx->RenderMode == GL_FEEDBACK) {
283e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_RENDERMODE */
2846d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
2856d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
286f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   else if (!(vertexProgram || vertexShader) ||
287d7296a1a8e846bc4d41ded1c2406b6f5c658188aBrian Paul            !ctx->VertexProgram._Current) {
288f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul      /* Fixed function vertex logic */
289e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_ARRAY */
290239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul      GLbitfield varying_inputs = ctx->varying_vp_inputs;
2911680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
29297e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
29397e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
29497e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
295e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_POINT */
29697e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
29797e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         varying_inputs |= FRAG_BITS_TEX_ANY;
29897e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
2991680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* First look at what values may be computed by the generated
3001680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * vertex program:
3011680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
302e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_LIGHT */
3031680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (ctx->Light.Enabled) {
3041680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         fp_inputs |= FRAG_BIT_COL0;
3051680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3069cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt         if (texenv_doing_secondary_color(ctx))
3071680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell            fp_inputs |= FRAG_BIT_COL1;
3081680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      }
3091680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
310e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_TEXTURE */
3111680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (ctx->Texture._TexGenEnabled |
3121680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
3131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3141680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* Then look at what might be varying as a result of enabled
3151680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * arrays, etc:
3161680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
3176807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (varying_inputs & VERT_BIT_COLOR0)
3186807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL0;
3196807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (varying_inputs & VERT_BIT_COLOR1)
3206807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL1;
3211680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3221680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
3231680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    << FRAG_ATTRIB_TEX0);
3241680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3251680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
3261680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
3271680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* calculate from vp->outputs */
3282389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      struct gl_vertex_program *vprog;
3292389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      GLbitfield vp_outputs;
3302389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
3312389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      /* Choose GLSL vertex shader over ARB vertex program.  Need this
3322389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * since vertex shader state validation comes after fragment state
3332389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * validation (see additional comments in state.c).
3342389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       */
3352389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      if (vertexShader)
3362389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul         vprog = ctx->Shader.CurrentProgram->VertexProgram;
3372389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      else
338a9ba1bfeb3a2852c6eda718e73c46c972a286648Eric Anholt         vprog = ctx->VertexProgram.Current;
3392389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
3402389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      vp_outputs = vprog->Base.OutputsWritten;
3411680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
34297e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
34397e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
34497e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
345e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_POINT */
34697e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
34797e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         vp_outputs |= FRAG_BITS_TEX_ANY;
34897e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
3496807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (vp_outputs & (1 << VERT_RESULT_COL0))
3506807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL0;
3516807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (vp_outputs & (1 << VERT_RESULT_COL1))
3526807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL1;
3531680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3540370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell      fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
3550370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell                    << FRAG_ATTRIB_TEX0);
3561680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
3571680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3581680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   return fp_inputs;
3591680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
3601680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
36222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
36322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Examine current texture environment state and generate a unique
36422db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * key to identify it.
36522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
3668065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwellstatic void make_state_key( GLcontext *ctx,  struct state_key *key )
367ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
368ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint i, j;
369239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_referenced = FRAG_BIT_COL0;
370f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul   const GLbitfield inputs_available = get_fp_input_mask( ctx );
3711680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3728065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memset(key, 0, sizeof(*key));
3738065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
374e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_TEXTURE */
375e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
376d9736db6676948e06712d4bcba46b7040452f870Brian Paul      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
377f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      const struct gl_texture_object *texObj = texUnit->_Current;
378f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      const struct gl_tex_env_combine_state *comb = texUnit->_CurrentCombine;
379b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao      GLenum format;
380bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger
381bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger      if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
382ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         continue;
383ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
384f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
385b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao
386ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].enabled = 1;
387ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->enabled_units |= (1<<i);
3881680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      key->nr_enabled_units = i+1;
3891680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_TEX(i);
390ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
391f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].source_index =
392f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         translate_tex_src_bit(texUnit->_ReallyEnabled);
393f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
394f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].shadow = ((texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
395b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                             ((format == GL_DEPTH_COMPONENT) ||
396b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                              (format == GL_DEPTH_STENCIL_EXT)));
397ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
398f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].NumArgsRGB = comb->_NumArgsRGB;
399f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].NumArgsA = comb->_NumArgsA;
400ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
401ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeRGB =
402f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul	 translate_mode(texUnit->EnvMode, comb->ModeRGB);
403ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeA =
404f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul	 translate_mode(texUnit->EnvMode, comb->ModeA);
405114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
406f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
407f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].ScaleShiftA = comb->ScaleShiftA;
408ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
409bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul      for (j = 0; j < MAX_COMBINER_TERMS; j++) {
410f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptRGB[j].Operand = translate_operand(comb->OperandRGB[j]);
411f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptA[j].Operand = translate_operand(comb->OperandA[j]);
412f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptRGB[j].Source = translate_source(comb->SourceRGB[j]);
413f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptA[j].Source = translate_source(comb->SourceA[j]);
414ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      }
415114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
416114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
417114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         /* requires some special translation */
418114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].NumArgsRGB = 2;
419114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].ScaleShiftRGB = 0;
420114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
421114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
422114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
423114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
424114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger       }
425ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
426114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
4279cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   /* _NEW_LIGHT | _NEW_FOG */
4289cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (texenv_doing_secondary_color(ctx)) {
429ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->separate_specular = 1;
4301680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_COL1;
4311680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
432ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
433e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_FOG */
434ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->Fog.Enabled) {
435ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_enabled = 1;
436ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
4371680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
438ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
4391680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
4401680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   key->inputs_available = (inputs_available & inputs_referenced);
441ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
442ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
443239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
444239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Use uregs to represent registers internally, translate to Mesa's
44515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * expected formats on emit.
44615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
44715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * NOTE: These are passed by value extensively in this file rather
44815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * than as usual by pointer reference.  If this disturbs you, try
44915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * remembering they are just 32bits in size.
45015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
45115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * GCC is smart enough to deal with these dword-sized structures in
45215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * much the same way as if I had defined them as dwords and was using
45315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * macros to access and set the fields.  This is much nicer and easier
45415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * to evolve.
45515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
45615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct ureg {
45715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint file:4;
45815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint idx:8;
45915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negatebase:1;
46015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint swz:12;
4611480bcacfec8f215c5827278a5f984c6bf68ba69Brian Paul   GLuint pad:7;
46215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
46315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
46413abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paulstatic const struct ureg undef = {
4658d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   PROGRAM_UNDEFINED,
46615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   ~0,
46715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
46815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
46915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0
47015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
47115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
47215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
473239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/** State used to build the fragment program:
47415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
47515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct texenv_fragment_program {
476122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_fragment_program *program;
477ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *state;
47815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
479239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield alu_temps;	/**< Track texture indirections, see spec. */
480239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temps_output;	/**< Track texture indirections, see spec. */
481239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temp_in_use;	/**< Tracks temporary regs which are in use. */
48215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLboolean error;
48315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
484e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul   struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
485ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   /* Reg containing each texture unit's sampled texture color,
486ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    * else undef.
487ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
48815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
489114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
490114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   /* Reg containing texcoord for a texture unit,
491114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger    * needed for bump mapping, else undef.
492114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger    */
493114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
494239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   struct ureg src_previous;	/**< Reg containing color from previous
49515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 * stage.  May need to be decl'd.
49615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 */
49715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
498239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLuint last_tex_stage;	/**< Number of last enabled texture unit */
4992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
5002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg half;
5012dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg one;
5022dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg zero;
50315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
50415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
50515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
50615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
50715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
50815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
50915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg reg;
51015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.file = file;
51115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.idx = idx;
51215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negatebase = 0;
51315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = SWIZZLE_NOOP;
51415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.pad = 0;
51515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
51615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
51715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
51815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
51915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
52015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
52115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, y),
52215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, z),
52315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, w));
52415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
52515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
52615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
52715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
52815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
52915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
53015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return swizzle(reg, x, x, x, x);
53115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
53215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5336fe176a64859798db17fbaed6858cccc646aae38Keith Whitwellstatic struct ureg negate( struct ureg reg )
5346fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell{
5356fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   reg.negatebase ^= 1;
5366fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   return reg;
5376fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell}
5386fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell
53915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic GLboolean is_undef( struct ureg reg )
54015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
5418d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   return reg.file == PROGRAM_UNDEFINED;
54215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
54315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
544ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
54515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_temp( struct texenv_fragment_program *p )
54615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
54713abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   GLint bit;
548ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
549cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try and reuse temps which have been used already:
550ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
551b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
552ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
553ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
554ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
555ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit)
556b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
557ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
558ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit) {
559bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
560b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
561ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   }
562ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
56313abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
564b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
565b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
56693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
567ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
568ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell}
569ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
570ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwellstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
571ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell{
572ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   int bit;
573ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
574d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   /* First try to find available temp not previously used (to avoid
575cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * starting a new texture indirection).  According to the spec, the
576cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * ~p->temps_output isn't necessary, but will keep it there for
577cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * now:
578ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
579b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
580ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
581ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
582ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
583cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!bit)
584b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
585ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
58615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (!bit) {
587bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
588b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      _mesa_exit(1);
58915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
59015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
59113abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
592b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
593b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
59493cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
59515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
59615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
59715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
59815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5995620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul/** Mark a temp reg as being no longer allocatable. */
6005620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paulstatic void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
6015620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul{
6025620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   if (r.file == PROGRAM_TEMPORARY)
6035620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul      p->temps_output |= (1 << r.idx);
6045620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul}
6055620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
6065620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
60793fef22d05d0fb6f011d48d2fde533555c1695a2Brianstatic void release_temps(GLcontext *ctx, struct texenv_fragment_program *p )
60815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
60993fef22d05d0fb6f011d48d2fde533555c1695a2Brian   GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
61093cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell
6112dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   /* KW: To support tex_env_crossbar, don't release the registers in
6122dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    * temps_output.
6132dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    */
61493cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   if (max_temp >= sizeof(int) * 8)
6152dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = p->temps_output;
61693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   else
6172dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
61815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
61915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
62015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6219fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brianstatic struct ureg register_param5( struct texenv_fragment_program *p,
622ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s0,
623ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s1,
624ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s2,
625ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s3,
6269fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian				    GLint s4)
62715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
6289fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian   gl_state_index tokens[STATE_LENGTH];
62947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint idx;
63047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[0] = s0;
63147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[1] = s1;
63247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[2] = s2;
63347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[3] = s3;
63447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[4] = s4;
635de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
63647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
63747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell}
63815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
63915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6409fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
6419fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
6429fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
6439fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
64447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
6451680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwellstatic GLuint frag_to_vert_attrib( GLuint attrib )
6461680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
6471680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   switch (attrib) {
6481680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
6491680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
6501680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   default:
6511680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib >= FRAG_ATTRIB_TEX0);
6521680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib <= FRAG_ATTRIB_TEX7);
6531680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
6541680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
6551680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
6561680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
65747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
65847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
65947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell{
6601680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (p->state->inputs_available & (1<<input)) {
6611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      p->program->Base.InputsRead |= (1 << input);
6621680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return make_ureg(PROGRAM_INPUT, input);
6631680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
6641680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
6651680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      GLuint idx = frag_to_vert_attrib( input );
6661680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
6671680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
66815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
66915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
67047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
6717e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *reg,
67215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg )
67315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
67415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->File = ureg.file;
67515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Index = ureg.idx;
67615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Swizzle = ureg.swz;
6777db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul   reg->Negate = ureg.negatebase ? NEGATE_XYZW : NEGATE_NONE;
6781480bcacfec8f215c5827278a5f984c6bf68ba69Brian Paul   reg->Abs = GL_FALSE;
67915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
68015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6817e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
68215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg, GLuint mask )
68315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
68415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->File = ureg.file;
68515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->Index = ureg.idx;
68615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->WriteMask = mask;
687c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondMask = COND_TR;  /* always pass cond test */
688c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondSwizzle = SWIZZLE_NOOP;
68915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
69015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6917e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic struct prog_instruction *
69215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellemit_op(struct texenv_fragment_program *p,
6935d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul	enum prog_opcode op,
69415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg dest,
69515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	GLuint mask,
69622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	GLboolean saturate,
69715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src0,
69815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src1,
69915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src2 )
70015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
7019ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   const GLuint nr = p->program->Base.NumInstructions++;
702de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
7032a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
7042a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian   assert(nr < MAX_INSTRUCTIONS);
7052a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
706d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul   _mesa_init_instructions(inst, 1);
70715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->Opcode = op;
70815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
70947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
71047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
71147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
71215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
713e31ac052236ea615b4995f9ec301d8af4b864531Brian Paul   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
71415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
71515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_dst( &inst->DstReg, dest, mask );
71615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7175620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#if 0
718cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
719cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
720cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
721cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->temps_output |= 1 << dest.idx;
7225620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#endif
723cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
72415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return inst;
72515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
72615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
72815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_arith( struct texenv_fragment_program *p,
7295d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
73047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg dest,
73147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       GLuint mask,
73222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			       GLboolean saturate,
73347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src0,
73447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src1,
73547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src2 )
73615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
73715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
73815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
739cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
740cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
741cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (src0.file == PROGRAM_TEMPORARY)
742cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src0.idx;
743cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
744cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
745cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src1.idx;
746cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
747cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
748cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src2.idx;
749cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
750cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
751cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << dest.idx;
752cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
75321f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumAluInstructions++;
75415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
75515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
75615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
75715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_texld( struct texenv_fragment_program *p,
7585d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
759ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg dest,
760ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint destmask,
761ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_unit,
762ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_idx,
76344e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul                               GLuint tex_shadow,
764ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg coord )
76515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
7667e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   struct prog_instruction *inst = emit_op( p, op,
76715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  dest, destmask,
76822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul					  GL_FALSE,	/* don't saturate? */
76915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  coord, 	/* arg 0? */
77015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef,
77115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef);
77215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7737e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   inst->TexSrcTarget = tex_idx;
77415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->TexSrcUnit = tex_unit;
77544e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul   inst->TexShadow = tex_shadow;
77615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
77721f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumTexInstructions++;
77815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7795620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   /* Accounting for indirection tracking:
7805620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul    */
7815620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   reserve_temp(p, dest);
7825620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
783114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#if 0
784cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Is this a texture indirection?
785cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
786cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if ((coord.file == PROGRAM_TEMPORARY &&
787cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->temps_output & (1<<coord.idx))) ||
788cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       (dest.file == PROGRAM_TEMPORARY &&
789cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->alu_temps & (1<<dest.idx)))) {
79021f99792a916a62fcfae7c208f50f192d4ce5926Brian      p->program->Base.NumTexIndirections++;
7912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temps_output = 1<<coord.idx;
792cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps = 0;
7932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(0);		/* KW: texture env crossbar */
79415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
795114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#endif
79615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
79715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
79815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
79915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
80015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
80147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_const4f( struct texenv_fragment_program *p,
802ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s0,
803ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s1,
804ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s2,
805ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s3)
80615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
80747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLfloat values[4];
808a90046f1097ad95de2aa95ca65741dff5cddced9Brian   GLuint idx, swizzle;
809d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   struct ureg r;
81047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[0] = s0;
81147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[1] = s1;
81247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[2] = s2;
81347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[3] = s3;
814a90046f1097ad95de2aa95ca65741dff5cddced9Brian   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
815a90046f1097ad95de2aa95ca65741dff5cddced9Brian                                     &swizzle );
816d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r = make_ureg(PROGRAM_CONSTANT, idx);
817d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r.swz = swizzle;
818d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   return r;
81915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
82015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
821e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
82247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
82347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
82447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
82515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
8272dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_one( struct texenv_fragment_program *p )
8282dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
8292dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->one))
8302dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->one = register_scalar_const(p, 1.0);
8312dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->one;
8322dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
8332dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
8342dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_half( struct texenv_fragment_program *p )
8352dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
8362dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->half))
8374dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->half = register_scalar_const(p, 0.5);
8382dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->half;
8392dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
8402dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
8412dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_zero( struct texenv_fragment_program *p )
8422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
8432dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->zero))
8444dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->zero = register_scalar_const(p, 0.0);
8452dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->zero;
8462dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
8472dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
84815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
84915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void program_error( struct texenv_fragment_program *p, const char *msg )
85015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
851bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul   _mesa_problem(NULL, msg);
85215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p->error = 1;
85315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
85415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
85515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_source( struct texenv_fragment_program *p,
856ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint src, GLuint unit )
85715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
85815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (src) {
859ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE:
8602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(!is_undef(p->src_texture[unit]));
8612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return p->src_texture[unit];
86215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
863ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
864ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
865ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
866ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
867ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
868ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
869ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
870ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
871ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
872ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return p->src_texture[src - SRC_TEXTURE0];
873ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
874ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_CONSTANT:
87547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_param2(p, STATE_TEXENV_COLOR, unit);
8762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
877ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PRIMARY_COLOR:
87847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_input(p, FRAG_ATTRIB_COL0);
8792dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
8806947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case SRC_ZERO:
8816947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return get_zero(p);
8826947f85cb5fbc433ba7763530285e470745b009bBrian Paul
883ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PREVIOUS:
88447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (is_undef(p->src_previous))
88547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return register_input(p, FRAG_ATTRIB_COL0);
88647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      else
88747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return p->src_previous;
8886947f85cb5fbc433ba7763530285e470745b009bBrian Paul
8896947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
8906947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
891c6af9b29476e4e445623e7a2f737ba95003bbe13José Fonseca      return undef;
89215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
89315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
8942dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
89515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine_source( struct texenv_fragment_program *p,
896ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint mask,
897ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint unit,
898ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint source,
899ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint operand )
90015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
90115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg arg, src, one;
90215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
90315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   src = get_source(p, source, unit);
90415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
90515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (operand) {
906ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_COLOR:
90715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
90815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.xyzw
90915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
91015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      arg = get_temp( p );
9112dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one( p );
9127e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
91315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
914ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_ALPHA:
91515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_W)
91615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src;
91715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
91822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	 return swizzle1( src, SWIZZLE_W );
919ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_ALPHA:
92015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
92115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.wwww
92215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
9232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      arg = get_temp(p);
9242dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one(p);
9257e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
92622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			one, swizzle1(src, SWIZZLE_W), undef);
927ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ZERO:
9282dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_zero(p);
929ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE:
9302dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_one(p);
931ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_COLOR:
9326947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return src;
93315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
9346947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
93515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src;
93615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
93715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
93815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
939f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul/**
940f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * Check if the RGB and Alpha sources and operands match for the given
941f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * texture unit's combinder state.  When the RGB and A sources and
942f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * operands match, we can emit fewer instructions.
943f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul */
944a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paulstatic GLboolean args_match( const struct state_key *key, GLuint unit )
94515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
9469ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   GLuint i, numArgs = key->unit[unit].NumArgsRGB;
94715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
948457e427e32324884acb064b756e327dc131ff135Brian Paul   for (i = 0; i < numArgs; i++) {
949ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
95015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;
95115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
9529ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      switch (key->unit[unit].OptA[i].Operand) {
953ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_SRC_ALPHA:
9549ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul	 switch (key->unit[unit].OptRGB[i].Operand) {
955ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_COLOR:
956ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_ALPHA:
95715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
95815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
95915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
96015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
96115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
962ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_ONE_MINUS_SRC_ALPHA:
9639ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul	 switch (key->unit[unit].OptRGB[i].Operand) {
964ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_COLOR:
965ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_ALPHA:
96615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
96715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
96815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
96915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
97015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
97115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      default:
97215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;	/* impossible */
97315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
97415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
97515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
97615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return GL_TRUE;
97715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
97815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
97915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine( struct texenv_fragment_program *p,
980ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 struct ureg dest,
981ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mask,
98222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul				 GLboolean saturate,
983ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint unit,
984ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint nr,
985ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mode,
986d9736db6676948e06712d4bcba46b7040452f870Brian Paul				 const struct mode_opt *opt)
987ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
988bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul   struct ureg src[MAX_COMBINER_TERMS];
989cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg tmp, half;
99022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i;
99115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
992bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul   assert(nr <= MAX_COMBINER_TERMS);
9936947f85cb5fbc433ba7763530285e470745b009bBrian Paul
9940063084804d62402d80821a86978660663955442Brian Paul   tmp = undef; /* silence warning (bug 5318) */
9950063084804d62402d80821a86978660663955442Brian Paul
99615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0; i < nr; i++)
997ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
99815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
99915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (mode) {
1000ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_REPLACE:
100115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_XYZW && !saturate)
100215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src[0];
100315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
10047e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
1005ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE:
10067e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
10076fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
1008ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD:
10097e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
10106fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
1011ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD_SIGNED:
101215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp = arg0 + arg1
1013cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       * result = tmp - .5
101415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10152dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
101699da2d30eb08e50edf4b0067518af3acdf2dabc0Jerome Glisse      tmp = get_temp( p );
10177e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
10187e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
101915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
1020ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_INTERPOLATE:
102115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
102215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
102415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1025ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_SUBTRACT:
10267e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
102715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1028ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA:
1029ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
1030ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
1031ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB: {
103215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp0 = get_temp( p );
103315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp1 = get_temp( p );
1034e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg neg1 = register_scalar_const(p, -1);
1035e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg two  = register_scalar_const(p, 2);
103615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
103715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp0 = 2*src0 - 1
103815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * tmp1 = 2*src1 - 1
103915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       *
104015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * dst = tmp0 dot3 tmp1
104115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10427e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
10436fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		  two, src[0], neg1);
104415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1045aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
104615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 tmp1 = tmp0;
104715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
10487e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
10496fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		     two, src[1], neg1);
10507e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
105115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
105215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1053ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_ADD_ATI:
10546fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 */
10557e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
10566fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[2], src[1] );
1057ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SIGNED_ADD_ATI: {
10586fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 - 0.5 */
10596fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      struct ureg tmp0 = get_temp(p);
10602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
10617e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
10627e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
10636fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
10646fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   }
1065ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SUBTRACT_ATI:
10666fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 - Arg1 */
10677e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
10686fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
10696947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case MODE_ADD_PRODUCTS:
10706947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* Arg0 * Arg1 + Arg2 * Arg3 */
10716947f85cb5fbc433ba7763530285e470745b009bBrian Paul      {
10726947f85cb5fbc433ba7763530285e470745b009bBrian Paul         struct ureg tmp0 = get_temp(p);
10736947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
10746947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 );
10756947f85cb5fbc433ba7763530285e470745b009bBrian Paul      }
10766947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return dest;
10776947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case MODE_ADD_PRODUCTS_SIGNED:
10786947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */
10796947f85cb5fbc433ba7763530285e470745b009bBrian Paul      {
10806947f85cb5fbc433ba7763530285e470745b009bBrian Paul         struct ureg tmp0 = get_temp(p);
10816947f85cb5fbc433ba7763530285e470745b009bBrian Paul         half = get_half(p);
10826947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
10836947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 );
10846947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
10856947f85cb5fbc433ba7763530285e470745b009bBrian Paul      }
10866947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return dest;
1087114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   case MODE_BUMP_ENVMAP_ATI:
1088114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* special - not handled here */
1089114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      assert(0);
1090114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      return src[0];
109115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
10926947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
109315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src[0];
109415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
109515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
109615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
109715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
109822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
109922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for one texture unit's env/combiner mode.
110022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
110122db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic struct ureg
110222db53577603afef8fdf62c324ff5977de76b9d8Brian Paulemit_texenv(struct texenv_fragment_program *p, GLuint unit)
110315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1104a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1105956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul   GLboolean saturate;
110615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint rgb_shift, alpha_shift;
1107a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   struct ureg out, dest;
110815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1109ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (!key->unit[unit].enabled) {
1110ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return get_source(p, SRC_PREVIOUS, 0);
111115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1112114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1113114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* this isn't really a env stage delivering a color and handled elsewhere */
1114114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      return get_source(p, SRC_PREVIOUS, 0);
1115114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   }
1116ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1117ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (key->unit[unit].ModeRGB) {
1118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
1119ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
112015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
112115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
1122ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
112315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      alpha_shift = 0;
112415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
112515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
112615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
1127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      rgb_shift = key->unit[unit].ScaleShiftRGB;
1128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
112915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
113015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1132956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul   /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
1133956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul    * We don't want to clamp twice.
1134956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul    */
1135956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul   saturate = !(rgb_shift || alpha_shift);
1136956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul
1137cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* If this is the very last calculation, emit direct to output reg:
1138cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
1139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular ||
1140cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       unit != p->last_tex_stage ||
1141cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       alpha_shift ||
1142cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       rgb_shift)
1143cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      dest = get_temp( p );
1144cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   else
11458d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
114615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
114715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Emit the RGB and A combine ops
114815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
1149ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
1150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       args_match(key, unit)) {
115115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
115215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
115615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
11589a45176dd85a1cd523498efeebd0481950a1bf58Roland Scheidegger	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
115915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
116015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
116415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
116515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else {
116615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Need to do something to stop from re-emitting identical
116715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * argument calculations here:
116815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
116915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
117015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
117415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      out = emit_combine( p, dest, WRITEMASK_W, saturate,
117515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1176ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsA,
1177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeA,
1178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptA);
117915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
118015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
118115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Deal with the final shift:
118215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
118315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (alpha_shift || rgb_shift) {
1184a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul      struct ureg shift;
1185a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul
1186956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul      saturate = GL_TRUE;  /* always saturate at this point */
1187a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul
118815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (rgb_shift == alpha_shift) {
1189452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
119015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
119115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else {
11922dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell	 shift = register_const4f(p,
1193452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1194452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1195452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1196452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<alpha_shift));
119715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
11987e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
119915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			 saturate, out, shift, undef );
120015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
120115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else
120215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return out;
120315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
120415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
120622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
120722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instruction for getting a texture source term.
120822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
12092dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic void load_texture( struct texenv_fragment_program *p, GLuint unit )
12102dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
12112dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->src_texture[unit])) {
1212b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul      const GLuint texTarget = p->state->unit[unit].source_index;
1213114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      struct ureg texcoord;
12142dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg tmp = get_tex_temp( p );
12152dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1216114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (is_undef(p->texcoord_tex[unit])) {
1217114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
1218114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      }
1219114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      else {
1220114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         /* might want to reuse this reg for tex output actually */
1221114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         texcoord = p->texcoord_tex[unit];
1222114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      }
1223114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
12242dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* TODO: Use D0_MASK_XY where possible.
12252dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
122683ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      if (p->state->unit[unit].enabled) {
122744e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul         GLboolean shadow = GL_FALSE;
12280397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell
122944e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul	 if (p->state->unit[unit].shadow) {
123083ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle	    p->program->Base.ShadowSamplers |= 1 << unit;
123144e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul            shadow = GL_TRUE;
123244e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul         }
123344e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul
123444e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
123544e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul					    tmp, WRITEMASK_XYZW,
123644e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul					    unit, texTarget, shadow,
123744e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul                                            texcoord );
12389b7e5a51f49e842f4114545f5eb171a597c83a66Brian
12399b7e5a51f49e842f4114545f5eb171a597c83a66Brian         p->program->Base.SamplersUsed |= (1 << unit);
12401fe385fdc96688a5249d52184f457910a0c25488Brian         /* This identity mapping should already be in place
12411fe385fdc96688a5249d52184f457910a0c25488Brian          * (see _mesa_init_program_struct()) but let's be safe.
12421fe385fdc96688a5249d52184f457910a0c25488Brian          */
12431fe385fdc96688a5249d52184f457910a0c25488Brian         p->program->Base.SamplerUnits[unit] = unit;
12449b7e5a51f49e842f4114545f5eb171a597c83a66Brian      }
12459b7e5a51f49e842f4114545f5eb171a597c83a66Brian      else
1246b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = get_zero(p);
12472dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
12482dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
12492dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1250241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwellstatic GLboolean load_texenv_source( struct texenv_fragment_program *p,
1251ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLuint src, GLuint unit )
12522dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
12532dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   switch (src) {
12544dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola   case SRC_TEXTURE:
12552dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      load_texture(p, unit);
12562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
12572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1258ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
1259ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
1260ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
1261ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
1262ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
1263ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
1264ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
1265ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
1266ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      load_texture(p, src - SRC_TEXTURE0);
12672dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
12682dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
12692dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   default:
12706947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* not a texture src - do nothing */
12712dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
12722dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1273241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell
1274241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
12752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
12762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
127722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
127822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
127922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for loading all texture source terms.
128022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
128122db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic GLboolean
1282457e427e32324884acb064b756e327dc131ff135Brian Paulload_texunit_sources( struct texenv_fragment_program *p, GLuint unit )
12832dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
1284a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1285b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   GLuint i;
1286b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1287b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
1288114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
1289b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   }
1290b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1291b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
1292b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
12932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1294b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1295241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
12962dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
12972dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1298114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger/**
1299114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger * Generate instructions for loading bump map textures.
1300114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger */
1301114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheideggerstatic GLboolean
1302457e427e32324884acb064b756e327dc131ff135Brian Paulload_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit )
1303114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger{
1304a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1305114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
1306114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcDst, bumpMapRes;
1307114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
1308114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
1309114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
1310114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
1311114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1312114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   load_texenv_source( p, unit + SRC_TEXTURE0, unit );
1313114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1314114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
1315114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   texcDst = get_tex_temp( p );
1316114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   p->texcoord_tex[bumpedUnitNr] = texcDst;
1317114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1318457e427e32324884acb064b756e327dc131ff135Brian Paul   /* Apply rot matrix and add coords to be available in next phase.
1319457e427e32324884acb064b756e327dc131ff135Brian Paul    * dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1)
1320457e427e32324884acb064b756e327dc131ff135Brian Paul    * note only 2 coords are affected the rest are left unchanged (mul by 0)
1321457e427e32324884acb064b756e327dc131ff135Brian Paul    */
1322114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1323114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger               swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
1324114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1325114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger               swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
1326114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1327457e427e32324884acb064b756e327dc131ff135Brian Paul   /* Move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
1328457e427e32324884acb064b756e327dc131ff135Brian Paul    * enough to access this later, should optimize away.
1329457e427e32324884acb064b756e327dc131ff135Brian Paul    */
1330457e427e32324884acb064b756e327dc131ff135Brian Paul   emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0,
1331457e427e32324884acb064b756e327dc131ff135Brian Paul               constdudvcolor, undef, undef );
1332114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1333114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   return GL_TRUE;
1334114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger}
133522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
133622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
133722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate a new fragment program which implements the context's
133822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * current texture env/combine mode.
133922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
134022db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic void
1341e998c346471142db91a1bcb6c61551b8247b87e7Brian Paulcreate_new_program(GLcontext *ctx, struct state_key *key,
1342122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                   struct gl_fragment_program *program)
134315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1344e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
134515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct texenv_fragment_program p;
134615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint unit;
134715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg cf, out;
1348276330b2412910777f7016f427909085f02acbb8Keith Whitwell
1349e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell   _mesa_memset(&p, 0, sizeof(p));
1350ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.state = key;
1351ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.program = program;
135215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1353e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* During code generation, use locally-allocated instruction buffer,
1354e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    * then alloc dynamic storage below.
1355e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    */
1356e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.Instructions = instBuffer;
1357276330b2412910777f7016f427909085f02acbb8Keith Whitwell   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
1358457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.String = NULL;
1359457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumTexIndirections = 1; /* is this right? */
136021f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexInstructions = 0;
136121f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumAluInstructions = 0;
1362457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumInstructions = 0;
1363457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumTemporaries = 0;
1364457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumParameters = 0;
1365457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumAttributes = 0;
1366457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumAddressRegs = 0;
1367de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1368457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.InputsRead = 0x0;
13698d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
137015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1371114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
13722dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p.src_texture[unit] = undef;
1373114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      p.texcoord_tex[unit] = undef;
1374114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   }
13752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
137647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   p.src_previous = undef;
13775ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.half = undef;
13785ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.zero = undef;
13795ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.one = undef;
13805ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
138115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.last_tex_stage = 0;
138293fef22d05d0fb6f011d48d2fde533555c1695a2Brian   release_temps(ctx, &p);
138315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1384ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->enabled_units) {
1385457e427e32324884acb064b756e327dc131ff135Brian Paul      GLboolean needbumpstage = GL_FALSE;
1386457e427e32324884acb064b756e327dc131ff135Brian Paul
1387114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* Zeroth pass - bump map textures first */
1388457e427e32324884acb064b756e327dc131ff135Brian Paul      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
1389457e427e32324884acb064b756e327dc131ff135Brian Paul	 if (key->unit[unit].enabled &&
1390457e427e32324884acb064b756e327dc131ff135Brian Paul             key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1391114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	    needbumpstage = GL_TRUE;
1392114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	    load_texunit_bumpmap( &p, unit );
1393114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	 }
1394114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (needbumpstage)
1395114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	 p.program->Base.NumTexIndirections++;
1396114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
13972dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* First pass - to support texture_env_crossbar, first identify
13982dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * all referenced texture sources and emit texld instructions
13992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * for each:
14002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
1401457e427e32324884acb064b756e327dc131ff135Brian Paul      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
1402ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->unit[unit].enabled) {
1403b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    load_texunit_sources( &p, unit );
1404b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    p.last_tex_stage = unit;
140515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
140615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
14072dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* Second pass - emit combine instructions to build final color:
14082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
1409457e427e32324884acb064b756e327dc131ff135Brian Paul      for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++)
141084d6bed4d6844110af23a995e2fad0280a92d46cBrian Paul	 if (key->unit[unit].enabled) {
141115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    p.src_previous = emit_texenv( &p, unit );
14125620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul            reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
141393fef22d05d0fb6f011d48d2fde533555c1695a2Brian	    release_temps(ctx, &p);	/* release all temps */
141415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
141515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
141615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1417ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   cf = get_source( &p, SRC_PREVIOUS, 0 );
14188d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLOR );
141915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1420ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular) {
142115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Emit specular add.
142215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
142347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
14247e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
14257e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
142615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1427aa2069586d434dd0487b0daa2b583efe801a0d51Brian Paul   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
142815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Will wind up in here if no texture enabled or a couple of
142915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * other scenarios (GL_REPLACE for instance).
143015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
14317e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
143215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
143315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
143447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   /* Finish up:
143547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell    */
14367e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
143747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1438ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->fog_enabled) {
1439ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      /* Pull fog mode from GLcontext, the value in the state key is
1440ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       * a reduced value and not what is expected in FogOption
1441ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       */
1442276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = ctx->Fog.Mode;
1443457e427e32324884acb064b756e327dc131ff135Brian Paul      p.program->Base.InputsRead |= FRAG_BIT_FOGC;
1444457e427e32324884acb064b756e327dc131ff135Brian Paul   }
1445457e427e32324884acb064b756e327dc131ff135Brian Paul   else {
1446276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = GL_NONE;
1447457e427e32324884acb064b756e327dc131ff135Brian Paul   }
144847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
144921f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
145015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max nr indirect texture lookups");
145115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
145221f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
145315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max TEX instructions");
145415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
145521f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
145615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max ALU instructions");
145715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
14585d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
14598b88f62fbd62153500fc3483003f438561366a00Keith Whitwell
1460e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* Allocate final instruction array */
1461c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   p.program->Base.Instructions
1462c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      = _mesa_alloc_instructions(p.program->Base.NumInstructions);
1463c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   if (!p.program->Base.Instructions) {
1464e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1465e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                  "generating tex env program");
1466e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      return;
1467e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1468c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
1469c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian                           p.program->Base.NumInstructions);
1470c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian
1471c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   if (p.program->FogOption) {
1472c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      _mesa_append_fog_code(ctx, p.program);
1473c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      p.program->FogOption = GL_NONE;
1474c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   }
1475c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian
1476e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1477dbeea25bb834479a29712100888c862348112018Keith Whitwell   /* Notify driver the fragment program has (actually) changed.
14788b88f62fbd62153500fc3483003f438561366a00Keith Whitwell    */
1479e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (ctx->Driver.ProgramStringNotify) {
1480e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1481e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                                       &p.program->Base );
1482e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1483e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1484e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (DISASSEM) {
1485e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_print_program(&p.program->Base);
1486e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_printf("\n");
1487dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
148815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
148915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
14905d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul
149132ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell/**
149232ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell * Return a fragment program which implements the current
149332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell * fixed-function texture, fog and color-sum operations.
149432ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell */
149532ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwellstruct gl_fragment_program *
149632ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
1497ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
149832ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   struct gl_fragment_program *prog;
149932ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   struct state_key key;
150032ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell
1501a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson   printf("SIZE OF KEY %d\n", sizeof(key));
150232ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   make_state_key(ctx, &key);
150332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell
150432ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   prog = (struct gl_fragment_program *)
150532ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
150632ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell                                 &key, sizeof(key));
1507ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
150832ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   if (!prog) {
150932ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      prog = (struct gl_fragment_program *)
151032ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
15115ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
151232ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      create_new_program(ctx, &key, prog);
15135ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
151432ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
151532ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell                                 &key, sizeof(key), &prog->Base);
15168065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
15178065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
151832ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   return prog;
15198065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell}
1520