ff_fragment_shader.cpp revision cdacca4868bbfe2e39f72d524556e7b2c7200ba5
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
29cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholtextern "C" {
3015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "glheader.h"
3125e5a6f279cec0863dcc341805aa7ca71189b626Brian Paul#include "imports.h"
320117da40cd7edd3d165bb28569c289b37eca12b9Vinson Lee#include "mtypes.h"
33ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/program.h"
34ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_parameter.h"
35ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_cache.h"
36ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_instruction.h"
37ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_print.h"
38ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/prog_statevars.h"
39ec2b92f98c2e7f161521b447cc1d9a36bce3707cBrian Paul#include "program/programopt.h"
4015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell#include "texenvprogram.h"
41cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt}
425b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
43e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul/*
44e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * Note on texture units:
45e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
46e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * The number of texture units supported by fixed-function fragment
47e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
48e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * That's because there's a one-to-one correspondence between texture
49e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * coordinates and samplers in fixed-function processing.
50e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
51e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
52e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * sets of texcoords, so is fixed-function fragment processing.
53e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul *
54e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
55e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul */
56e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul
57e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul
585b5c9315275752add1215dba0f86d5f5068d856bBrian Paulstruct texenvprog_cache_item
595b5c9315275752add1215dba0f86d5f5068d856bBrian Paul{
605b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   GLuint hash;
615b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   void *key;
625b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct gl_fragment_program *data;
635b5c9315275752add1215dba0f86d5f5068d856bBrian Paul   struct texenvprog_cache_item *next;
645b5c9315275752add1215dba0f86d5f5068d856bBrian Paul};
655b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
669cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholtstatic GLboolean
67f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergtexenv_doing_secondary_color(struct gl_context *ctx)
689cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt{
699cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (ctx->Light.Enabled &&
709cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt       (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
719cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt      return GL_TRUE;
729cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt
739cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (ctx->Fog.ColorSumEnabled)
749cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt      return GL_TRUE;
759cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt
769cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   return GL_FALSE;
779cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt}
785b5c9315275752add1215dba0f86d5f5068d856bBrian Paul
79e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul/**
80b5e1a93036b22bd30738abccbb8a2645a515667fBrian Paul * Up to nine instructions per tex unit, plus fog, specular color.
81e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul */
820815ebccfc0a12d8f3e831928f1c4210b7f75ad8Brian Paul#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
8315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
84269e3895d9837ac7303b91948f003ca5c12c0fe4Keith Whitwell#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
8515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct mode_opt {
8783e4470d9a3367883b3fe699629f1d8648459a89Brian Paul#ifdef __GNUC__
88d98b9f4edbbee1654b66c8df7b1deeb401b3dc5fGary Wong   __extension__ GLubyte Source:4;  /**< SRC_x */
89d98b9f4edbbee1654b66c8df7b1deeb401b3dc5fGary Wong   __extension__ GLubyte Operand:3; /**< OPR_x */
9083e4470d9a3367883b3fe699629f1d8648459a89Brian Paul#else
915e809216a8d2e7ad093a1d25f3f6495f29e57572Brian Paul   GLubyte Source;  /**< SRC_x */
925e809216a8d2e7ad093a1d25f3f6495f29e57572Brian Paul   GLubyte Operand; /**< OPR_x */
9383e4470d9a3367883b3fe699629f1d8648459a89Brian Paul#endif
94ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
95ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
96ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstruct state_key {
976280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint nr_enabled_units:8;
986280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint enabled_units:8;
995d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint separate_specular:1;
1005d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   GLuint fog_enabled:1;
1019ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   GLuint fog_mode:2;          /**< FOG_x */
1026280e335706f95ed0ebb089d8f72aeede9b5a1adKeith Whitwell   GLuint inputs_available:12;
103b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul   GLuint num_draw_buffers:4;
104ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1057a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   /* NOTE: This array of structs must be last! (see "keySize" below) */
106ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct {
1075d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint enabled:1;
1089ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint source_index:3;   /**< TEXTURE_x_INDEX */
10983ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      GLuint shadow:1;
1105d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftRGB:2;
1115d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul      GLuint ScaleShiftA:2;
112ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1139ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint NumArgsRGB:3;  /**< up to MAX_COMBINER_TERMS */
114f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      GLuint ModeRGB:5;     /**< MODE_x */
115ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1169ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      GLuint NumArgsA:3;  /**< up to MAX_COMBINER_TERMS */
117f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      GLuint ModeA:5;     /**< MODE_x */
118a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson
1194a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul      GLuint texture_cyl_wrap:1; /**< For gallium test/debug only */
1204a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul
121a46e32787d98192d35bf2834011cfa5537e0e703Chris Wilson      struct mode_opt OptRGB[MAX_COMBINER_TERMS];
122bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul      struct mode_opt OptA[MAX_COMBINER_TERMS];
123d55a28e3dc712342e4a2f25aa9b661add7461e82Brian Paul   } unit[MAX_TEXTURE_UNITS];
124ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell};
125ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_LINEAR  0
127ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP     1
128ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_EXP2    2
129ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define FOG_UNKNOWN 3
130ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
131ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_fog_mode( GLenum mode )
132ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
133ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
134ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_LINEAR: return FOG_LINEAR;
135ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP: return FOG_EXP;
136ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_EXP2: return FOG_EXP2;
137ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   default: return FOG_UNKNOWN;
138ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
139ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
140ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
141ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_COLOR           0
142ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_COLOR 1
143ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_SRC_ALPHA           2
144ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE_MINUS_SRC_ALPHA	3
145ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ZERO                4
146ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_ONE                 5
147ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define OPR_UNKNOWN             7
148ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
149ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_operand( GLenum operand )
150ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
151ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (operand) {
152ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_COLOR: return OPR_SRC_COLOR;
153ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
154ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
155ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
156ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ZERO: return OPR_ZERO;
157ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_ONE: return OPR_ONE;
1586947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
1596947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
1606947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return OPR_UNKNOWN;
161ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
162ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
163ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
164ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE  0
165ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE0 1
166ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE1 2
167ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE2 3
168ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE3 4
169ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE4 5
170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE5 6
171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE6 7
172ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_TEXTURE7 8
173ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_CONSTANT 9
174ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PRIMARY_COLOR 10
175ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_PREVIOUS 11
1766947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define SRC_ZERO     12
177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell#define SRC_UNKNOWN  15
178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwellstatic GLuint translate_source( GLenum src )
180ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
181ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (src) {
182ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE: return SRC_TEXTURE;
183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE0:
184ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE1:
185ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE2:
186ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE3:
187ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE4:
188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE5:
189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE6:
190ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
191ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_CONSTANT: return SRC_CONSTANT;
192ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
193ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_PREVIOUS: return SRC_PREVIOUS;
1946947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ZERO:
1956947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return SRC_ZERO;
1966947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
1976947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
1986947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return SRC_UNKNOWN;
199ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
200ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
201ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
2026947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_REPLACE                     0  /* r = a0 */
2036947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE                    1  /* r = a0 * a1 */
2046947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD                         2  /* r = a0 + a1 */
2056947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_SIGNED                  3  /* r = a0 + a1 - 0.5 */
2066947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_INTERPOLATE                 4  /* r = a0 * a2 + a1 * (1 - a2) */
2076947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_SUBTRACT                    5  /* r = a0 - a1 */
2086947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGB                    6  /* r = a0 . a1 */
2096947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGB_EXT                7  /* r = a0 . a1 */
2106947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGBA                   8  /* r = a0 . a1 */
2116947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_DOT3_RGBA_EXT               9  /* r = a0 . a1 */
2126947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_ADD_ATI           10  /* r = a0 * a2 + a1 */
2136947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_SIGNED_ADD_ATI    11  /* r = a0 * a2 + a1 - 0.5 */
2146947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_MODULATE_SUBTRACT_ATI      12  /* r = a0 * a2 - a1 */
2156947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_PRODUCTS               13  /* r = a0 * a1 + a2 * a3 */
2166947f85cb5fbc433ba7763530285e470745b009bBrian Paul#define MODE_ADD_PRODUCTS_SIGNED        14  /* r = a0 * a1 + a2 * a3 - 0.5 */
217114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#define MODE_BUMP_ENVMAP_ATI            15  /* special */
218114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#define MODE_UNKNOWN                    16
2196947f85cb5fbc433ba7763530285e470745b009bBrian Paul
2206947f85cb5fbc433ba7763530285e470745b009bBrian Paul/**
2216947f85cb5fbc433ba7763530285e470745b009bBrian Paul * Translate GL combiner state into a MODE_x value
2226947f85cb5fbc433ba7763530285e470745b009bBrian Paul */
2236947f85cb5fbc433ba7763530285e470745b009bBrian Paulstatic GLuint translate_mode( GLenum envMode, GLenum mode )
224ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
225ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (mode) {
226ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_REPLACE: return MODE_REPLACE;
227ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE: return MODE_MODULATE;
2286947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ADD:
2296947f85cb5fbc433ba7763530285e470745b009bBrian Paul      if (envMode == GL_COMBINE4_NV)
2306947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_PRODUCTS;
2316947f85cb5fbc433ba7763530285e470745b009bBrian Paul      else
2326947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD;
2336947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case GL_ADD_SIGNED:
2346947f85cb5fbc433ba7763530285e470745b009bBrian Paul      if (envMode == GL_COMBINE4_NV)
2356947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_PRODUCTS_SIGNED;
2366947f85cb5fbc433ba7763530285e470745b009bBrian Paul      else
2376947f85cb5fbc433ba7763530285e470745b009bBrian Paul         return MODE_ADD_SIGNED;
238ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_INTERPOLATE: return MODE_INTERPOLATE;
239ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_SUBTRACT: return MODE_SUBTRACT;
240ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB: return MODE_DOT3_RGB;
241ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
242ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
243ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
244ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
245ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
246ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
247114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
2486947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
2496947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
2506947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return MODE_UNKNOWN;
251ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
252ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
253ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
254f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
255f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul/**
256e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul * Do we need to clamp the results of the given texture env/combine mode?
257e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul * If the inputs to the mode are in [0,1] we don't always have to clamp
258e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul * the results.
259e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul */
260e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paulstatic GLboolean
261e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paulneed_saturate( GLuint mode )
262e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul{
263e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   switch (mode) {
264e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_REPLACE:
265e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_MODULATE:
266e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_INTERPOLATE:
267e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      return GL_FALSE;
268e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_ADD:
269e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_ADD_SIGNED:
270e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_SUBTRACT:
271e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_DOT3_RGB:
272e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_DOT3_RGB_EXT:
273e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_DOT3_RGBA:
274e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_DOT3_RGBA_EXT:
275e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_MODULATE_ADD_ATI:
276e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_MODULATE_SIGNED_ADD_ATI:
277e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_MODULATE_SUBTRACT_ATI:
278e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_ADD_PRODUCTS:
279e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_ADD_PRODUCTS_SIGNED:
280e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   case MODE_BUMP_ENVMAP_ATI:
281e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      return GL_TRUE;
282e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   default:
283e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      assert(0);
284a491e25b1fa8683f538ed0d67a6389f2cdf7e4bcBrian Paul      return GL_FALSE;
285e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   }
286e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul}
287e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul
288e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul
289e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul
290e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul/**
291f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
292f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul */
293e00ac11d4dd05c56584622dc2707bbdcfe4b2707Brian Paulstatic GLuint translate_tex_src_bit( GLbitfield bit )
294ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
295b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul   ASSERT(bit);
296b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul   return _mesa_ffs(bit) - 1;
297ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
298ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
299f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
3001680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
3011680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
3021680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
303239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
304239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Identify all possible varying inputs.  The fragment program will
3051680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * never reference non-varying inputs, but will track them via state
3061680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * constants instead.
3071680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell *
3081680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * This function figures out all the inputs that the fragment program
3091680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * has access to.  The bitmask is later reduced to just those which
3101680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell * are actually referenced.
3111680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell */
312f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergstatic GLbitfield get_fp_input_mask( struct gl_context *ctx )
3131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
314e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_PROGRAM */
31584eba3ef71dfa822e5ff0463032cdd2e3515b888Ian Romanick   const GLboolean vertexShader =
31684eba3ef71dfa822e5ff0463032cdd2e3515b888Ian Romanick      (ctx->Shader.CurrentVertexProgram &&
31784eba3ef71dfa822e5ff0463032cdd2e3515b888Ian Romanick       ctx->Shader.CurrentVertexProgram->LinkStatus &&
31884eba3ef71dfa822e5ff0463032cdd2e3515b888Ian Romanick       ctx->Shader.CurrentVertexProgram->VertexProgram);
319f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
320239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield fp_inputs = 0x0;
3211680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3226d4d51d647c27288aa625560bc080231099c0b01Brian Paul   if (ctx->VertexProgram._Overriden) {
3236d4d51d647c27288aa625560bc080231099c0b01Brian Paul      /* Somebody's messing with the vertex program and we don't have
3246d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * a clue what's happening.  Assume that it could be producing
3256d4d51d647c27288aa625560bc080231099c0b01Brian Paul       * all possible outputs.
3266d4d51d647c27288aa625560bc080231099c0b01Brian Paul       */
3276d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = ~0;
3286d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
3296d4d51d647c27288aa625560bc080231099c0b01Brian Paul   else if (ctx->RenderMode == GL_FEEDBACK) {
330e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_RENDERMODE */
3316d4d51d647c27288aa625560bc080231099c0b01Brian Paul      fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
3326d4d51d647c27288aa625560bc080231099c0b01Brian Paul   }
333f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul   else if (!(vertexProgram || vertexShader) ||
334d7296a1a8e846bc4d41ded1c2406b6f5c658188aBrian Paul            !ctx->VertexProgram._Current) {
335f0b0794b3885a2fdfb168ec4521c7b5e942d3228Brian Paul      /* Fixed function vertex logic */
336e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_ARRAY */
337239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul      GLbitfield varying_inputs = ctx->varying_vp_inputs;
3381680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
33997e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
34097e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
34197e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
342e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_POINT */
34397e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
34497e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         varying_inputs |= FRAG_BITS_TEX_ANY;
34597e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
3461680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* First look at what values may be computed by the generated
3471680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * vertex program:
3481680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
349e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_LIGHT */
3501680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      if (ctx->Light.Enabled) {
3511680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell         fp_inputs |= FRAG_BIT_COL0;
3521680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3539cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt         if (texenv_doing_secondary_color(ctx))
3541680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell            fp_inputs |= FRAG_BIT_COL1;
3551680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      }
3561680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
357e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_TEXTURE */
3581680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (ctx->Texture._TexGenEnabled |
3591680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
3601680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3611680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* Then look at what might be varying as a result of enabled
3621680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       * arrays, etc:
3631680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell       */
3646807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (varying_inputs & VERT_BIT_COLOR0)
3656807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL0;
3666807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (varying_inputs & VERT_BIT_COLOR1)
3676807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL1;
3681680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3691680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
3701680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell                    << FRAG_ATTRIB_TEX0);
3711680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
3721680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
3731680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
3741680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      /* calculate from vp->outputs */
3752389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      struct gl_vertex_program *vprog;
3765606dfb572bf4b89b4882265924705bacc8c182bIan Romanick      GLbitfield64 vp_outputs;
3772389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
3782389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      /* Choose GLSL vertex shader over ARB vertex program.  Need this
3792389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * since vertex shader state validation comes after fragment state
3802389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       * validation (see additional comments in state.c).
3812389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul       */
3822389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      if (vertexShader)
38384eba3ef71dfa822e5ff0463032cdd2e3515b888Ian Romanick         vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
3842389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      else
385a9ba1bfeb3a2852c6eda718e73c46c972a286648Eric Anholt         vprog = ctx->VertexProgram.Current;
3862389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul
3872389c055ed4c26ba5f3979c4a7871a333725dd88Brian Paul      vp_outputs = vprog->Base.OutputsWritten;
3881680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
38997e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      /* These get generated in the setup routine regardless of the
39097e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       * vertex program:
39197e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell       */
392e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt      /* _NEW_POINT */
39397e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell      if (ctx->Point.PointSprite)
39497e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell         vp_outputs |= FRAG_BITS_TEX_ANY;
39597e63437dc216c7fdb25220655ecbf26042cfec8Keith Whitwell
3966807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (vp_outputs & (1 << VERT_RESULT_COL0))
3976807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL0;
3986807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul      if (vp_outputs & (1 << VERT_RESULT_COL1))
3996807d96f8efeecd9d71e1e1bff856e7e04f5f364Brian Paul         fp_inputs |= FRAG_BIT_COL1;
4001680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
4010370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell      fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
4020370d6b359016790c6b879c2a4b6661adac20deaKeith Whitwell                    << FRAG_ATTRIB_TEX0);
4031680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
4041680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
4051680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   return fp_inputs;
4061680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
4071680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
4081680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
40922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
41022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Examine current texture environment state and generate a unique
41122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * key to identify it.
41222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
413f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergstatic GLuint make_state_key( struct gl_context *ctx,  struct state_key *key )
414ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
415ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   GLuint i, j;
416239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield inputs_referenced = FRAG_BIT_COL0;
417f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul   const GLbitfield inputs_available = get_fp_input_mask( ctx );
4187a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   GLuint keySize;
4191680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
4208065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   memset(key, 0, sizeof(*key));
4218065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
422e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_TEXTURE */
423e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
424d9736db6676948e06712d4bcba46b7040452f870Brian Paul      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
425f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      const struct gl_texture_object *texObj = texUnit->_Current;
426f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      const struct gl_tex_env_combine_state *comb = texUnit->_CurrentCombine;
427b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao      GLenum format;
428bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger
429bf4a0fafc86bba8dc868cf30244a237e33645164Roland Scheidegger      if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
430ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell         continue;
431ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
432f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
433b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao
434ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].enabled = 1;
435ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->enabled_units |= (1<<i);
4367a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul      key->nr_enabled_units = i + 1;
4371680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_TEX(i);
438ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
439f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].source_index =
440f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         translate_tex_src_bit(texUnit->_ReallyEnabled);
441f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul
442f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].shadow = ((texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
443b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                             ((format == GL_DEPTH_COMPONENT) ||
444b6bb5e09e0ad1f61f96c65bbc870bd493df12f1aXiang, Haihao                              (format == GL_DEPTH_STENCIL_EXT)));
445ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
446f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].NumArgsRGB = comb->_NumArgsRGB;
447f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].NumArgsA = comb->_NumArgsA;
448ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
449ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeRGB =
450f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul	 translate_mode(texUnit->EnvMode, comb->ModeRGB);
451ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->unit[i].ModeA =
452f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul	 translate_mode(texUnit->EnvMode, comb->ModeA);
453114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
454f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
455f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul      key->unit[i].ScaleShiftA = comb->ScaleShiftA;
456ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
457bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul      for (j = 0; j < MAX_COMBINER_TERMS; j++) {
458f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptRGB[j].Operand = translate_operand(comb->OperandRGB[j]);
459f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptA[j].Operand = translate_operand(comb->OperandA[j]);
460f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptRGB[j].Source = translate_source(comb->SourceRGB[j]);
461f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul         key->unit[i].OptA[j].Source = translate_source(comb->SourceA[j]);
462ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      }
463114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
464114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
465114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         /* requires some special translation */
466114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].NumArgsRGB = 2;
467114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].ScaleShiftRGB = 0;
468114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
469114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
470114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
471114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
472114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger       }
4734a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul
4744a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul      /* this is a back-door for enabling cylindrical texture wrap mode */
4754a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul      if (texObj->Priority == 0.125)
4764a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul         key->unit[i].texture_cyl_wrap = 1;
477ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
478114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
4799cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   /* _NEW_LIGHT | _NEW_FOG */
4809cea84b6b5f96bf3bb42546e49b76024d7126e30Eric Anholt   if (texenv_doing_secondary_color(ctx)) {
481ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->separate_specular = 1;
4821680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_COL1;
4831680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
484ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
485e5f63c403b767f9974e8eb5d412c012b8a69287fEric Anholt   /* _NEW_FOG */
486ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (ctx->Fog.Enabled) {
487ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_enabled = 1;
488ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
4891680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
490ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   }
4911680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
492b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul   /* _NEW_BUFFERS */
493b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul   key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
494b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul
4951680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   key->inputs_available = (inputs_available & inputs_referenced);
4967a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul
4977a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   /* compute size of state key, ignoring unused texture units */
4987a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   keySize = sizeof(*key) - sizeof(key->unit)
4997a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul      + key->nr_enabled_units * sizeof(key->unit[0]);
5007a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul
5017a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   return keySize;
502ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell}
503ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
5047a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul
505239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/**
506239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul * Use uregs to represent registers internally, translate to Mesa's
50715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * expected formats on emit.
50815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
50915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * NOTE: These are passed by value extensively in this file rather
51015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * than as usual by pointer reference.  If this disturbs you, try
51115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * remembering they are just 32bits in size.
51215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell *
51315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * GCC is smart enough to deal with these dword-sized structures in
51415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * much the same way as if I had defined them as dwords and was using
51515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * macros to access and set the fields.  This is much nicer and easier
51615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell * to evolve.
51715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
51815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct ureg {
51915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint file:4;
52015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint idx:8;
52115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint negatebase:1;
52215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint swz:12;
5231480bcacfec8f215c5827278a5f984c6bf68ba69Brian Paul   GLuint pad:7;
52415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
52515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
52613abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paulstatic const struct ureg undef = {
5278d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   PROGRAM_UNDEFINED,
528cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt   255,
52915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
53015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0,
53115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   0
53215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
53315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
53415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
535239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul/** State used to build the fragment program:
53615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell */
53715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstruct texenv_fragment_program {
538122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul   struct gl_fragment_program *program;
539ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   struct state_key *state;
54015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
541239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield alu_temps;	/**< Track texture indirections, see spec. */
542239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temps_output;	/**< Track texture indirections, see spec. */
543239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLbitfield temp_in_use;	/**< Tracks temporary regs which are in use. */
54415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLboolean error;
54515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
546e9b34885b8ff2ccb67a801cd1ce07e0df1b0e397Brian Paul   struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
547ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   /* Reg containing each texture unit's sampled texture color,
548ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    * else undef.
549ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell    */
55015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
551114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
552114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   /* Reg containing texcoord for a texture unit,
553114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger    * needed for bump mapping, else undef.
554114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger    */
555114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
556239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   struct ureg src_previous;	/**< Reg containing color from previous
55715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 * stage.  May need to be decl'd.
55815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell				 */
55915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
560239617fbe22d4dd7b2794510a6665f09602b5adfBrian Paul   GLuint last_tex_stage;	/**< Number of last enabled texture unit */
5612dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
5622dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg half;
5632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg one;
5642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   struct ureg zero;
56515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell};
56615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
56915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg make_ureg(GLuint file, GLuint idx)
57015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
57115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg reg;
57215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.file = file;
57315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.idx = idx;
57415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.negatebase = 0;
57515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = SWIZZLE_NOOP;
57615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.pad = 0;
57715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
57815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
57915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
58015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
58115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
58215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
58315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, y),
58415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, z),
58515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			   GET_SWZ(reg.swz, w));
58615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
58715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return reg;
58815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
58915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
59015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg swizzle1( struct ureg reg, int x )
59115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
59215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return swizzle(reg, x, x, x, x);
59315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
59415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
5956fe176a64859798db17fbaed6858cccc646aae38Keith Whitwellstatic struct ureg negate( struct ureg reg )
5966fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell{
5976fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   reg.negatebase ^= 1;
5986fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   return reg;
5996fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell}
6006fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell
60115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic GLboolean is_undef( struct ureg reg )
60215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
6038d97265711b172da4f387748f0e72da9267492b0Alan Hourihane   return reg.file == PROGRAM_UNDEFINED;
60415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
60515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
606ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
60715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_temp( struct texenv_fragment_program *p )
60815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
60913abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   GLint bit;
610ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
611cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* First try and reuse temps which have been used already:
612ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
613b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
614ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
615ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
616ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
617ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit)
618b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
619ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
620ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   if (!bit) {
621bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
6221a80fe461e162d5b6e25bd270a54e6662f72e5b3Eric Anholt      exit(1);
623ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   }
624ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
62513abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
626b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
627b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
62893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
629ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
630ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell}
631ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
632ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwellstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
633ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell{
634ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   int bit;
635ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
636d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   /* First try to find available temp not previously used (to avoid
637cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * starting a new texture indirection).  According to the spec, the
638cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * ~p->temps_output isn't necessary, but will keep it there for
639cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    * now:
640ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
641b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
642ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
643ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell   /* Then any unused temporary:
644ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell    */
645cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!bit)
646b3aefd1cfb6aacd1695c52911dd39da50d893eceBrian Paul      bit = _mesa_ffs( ~p->temp_in_use );
647ecb6bfc0ce33b1daa84093dceeb58a4b741283e9Keith Whitwell
64815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (!bit) {
649bfb5ea307ec48b9b8d0d2eca0c03f6d02273d454Brian Paul      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
6501a80fe461e162d5b6e25bd270a54e6662f72e5b3Eric Anholt      exit(1);
65115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
65215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
65313abf91b42b00c7eb64c373aff3a4c1bb3d8fb7fBrian Paul   if ((GLuint) bit > p->program->Base.NumTemporaries)
654b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell      p->program->Base.NumTemporaries = bit;
655b5cbaf945dd5213d5faf7bb7e4d68d0d25a25b55Keith Whitwell
65693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   p->temp_in_use |= 1<<(bit-1);
65715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
65815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
65915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
66015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6615620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul/** Mark a temp reg as being no longer allocatable. */
6625620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paulstatic void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
6635620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul{
6645620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   if (r.file == PROGRAM_TEMPORARY)
6655620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul      p->temps_output |= (1 << r.idx);
6665620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul}
6675620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
6685620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
669f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergstatic void release_temps(struct gl_context *ctx, struct texenv_fragment_program *p )
67015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
67193fef22d05d0fb6f011d48d2fde533555c1695a2Brian   GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
67293cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell
6732dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   /* KW: To support tex_env_crossbar, don't release the registers in
6742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    * temps_output.
6752dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell    */
67693cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   if (max_temp >= sizeof(int) * 8)
6772dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = p->temps_output;
67893cd9237d793e38ba4479d1367be7548853f67f4Keith Whitwell   else
6792dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
68015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
68115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
68215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
6839fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brianstatic struct ureg register_param5( struct texenv_fragment_program *p,
684ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s0,
685ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s1,
686ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s2,
687ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				    GLint s3,
6889fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian				    GLint s4)
68915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
690cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt   int tokens[STATE_LENGTH];
69147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLuint idx;
69247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[0] = s0;
69347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[1] = s1;
69447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[2] = s2;
69547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[3] = s3;
69647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   tokens[4] = s4;
697cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt   idx = _mesa_add_state_reference(p->program->Base.Parameters,
698cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt				   (gl_state_index *)tokens);
69947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   return make_ureg(PROGRAM_STATE_VAR, idx);
70047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell}
70115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
70215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7039fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
7049fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
7059fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
7069fe3e2efc3a76b2a2fb82031041f6a6170c5b1d9Brian#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
70747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
7081680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwellstatic GLuint frag_to_vert_attrib( GLuint attrib )
7091680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell{
7101680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   switch (attrib) {
7111680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
7121680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
7131680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   default:
7141680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib >= FRAG_ATTRIB_TEX0);
7151680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      assert(attrib <= FRAG_ATTRIB_TEX7);
7161680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
7171680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
7181680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell}
7191680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell
72047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
72147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
72247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell{
7231680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   if (p->state->inputs_available & (1<<input)) {
7241680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      p->program->Base.InputsRead |= (1 << input);
7251680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return make_ureg(PROGRAM_INPUT, input);
7261680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
7271680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   else {
7281680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      GLuint idx = frag_to_vert_attrib( input );
7291680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
7301680ef869625dc1fe9cf481b180382a34e0738e7Keith Whitwell   }
73115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
73215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
73347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
7347e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_arg( struct prog_src_register *reg,
73515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg )
73615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
73715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->File = ureg.file;
73815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Index = ureg.idx;
73915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   reg->Swizzle = ureg.swz;
7407db7ff878d3e5a6b345228e6eaee4797bb68b360Brian Paul   reg->Negate = ureg.negatebase ? NEGATE_XYZW : NEGATE_NONE;
7411480bcacfec8f215c5827278a5f984c6bf68ba69Brian Paul   reg->Abs = GL_FALSE;
74215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
74315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7447e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic void emit_dst( struct prog_dst_register *dst,
74515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell		      struct ureg ureg, GLuint mask )
74615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
74715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->File = ureg.file;
74815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->Index = ureg.idx;
74915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   dst->WriteMask = mask;
750c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondMask = COND_TR;  /* always pass cond test */
751c9d495c6f064aacd1e072033b9c17a83b8c37fa1Brian   dst->CondSwizzle = SWIZZLE_NOOP;
75215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
75315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7547e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paulstatic struct prog_instruction *
75515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellemit_op(struct texenv_fragment_program *p,
7565d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul	enum prog_opcode op,
75715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg dest,
75815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	GLuint mask,
75922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	GLboolean saturate,
76015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src0,
76115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src1,
76215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	struct ureg src2 )
76315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
7649ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   const GLuint nr = p->program->Base.NumInstructions++;
765de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
7662a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
7672a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian   assert(nr < MAX_INSTRUCTIONS);
7682a8e9bb00f8cf830783cbc20a2a57f31b19491eaBrian
769d6272e06172f7ac7a0d6e8062e8ffba33e1ab3baBrian Paul   _mesa_init_instructions(inst, 1);
77015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->Opcode = op;
77115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
77247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[0], src0 );
77347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[1], src1 );
77447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   emit_arg( &inst->SrcReg[2], src2 );
77515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
776e31ac052236ea615b4995f9ec301d8af4b864531Brian Paul   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
77715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
77815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_dst( &inst->DstReg, dest, mask );
77915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
7805620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#if 0
781cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
782cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
783cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
784cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->temps_output |= 1 << dest.idx;
7855620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul#endif
786cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
78715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return inst;
78815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
78915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
79015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
79115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_arith( struct texenv_fragment_program *p,
7925d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
79347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg dest,
79447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       GLuint mask,
79522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			       GLboolean saturate,
79647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src0,
79747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src1,
79847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell			       struct ureg src2 )
79915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
80015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
80115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
802cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Accounting for indirection tracking:
803cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
804cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (src0.file == PROGRAM_TEMPORARY)
805cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src0.idx;
806cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
807cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
808cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src1.idx;
809cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
810cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
811cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << src2.idx;
812cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
813cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if (dest.file == PROGRAM_TEMPORARY)
814cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps |= 1 << dest.idx;
815cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell
81621f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumAluInstructions++;
81715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
81815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
81915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
82015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_texld( struct texenv_fragment_program *p,
8215d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul			       enum prog_opcode op,
822ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg dest,
823ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint destmask,
824ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_unit,
825ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint tex_idx,
82644e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul                               GLuint tex_shadow,
827ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       struct ureg coord )
82815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
8297e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   struct prog_instruction *inst = emit_op( p, op,
83015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  dest, destmask,
83122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul					  GL_FALSE,	/* don't saturate? */
83215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  coord, 	/* arg 0? */
83315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef,
83415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell					  undef);
83515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
8367e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   inst->TexSrcTarget = tex_idx;
83715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   inst->TexSrcUnit = tex_unit;
83844e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul   inst->TexShadow = tex_shadow;
83915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
84021f99792a916a62fcfae7c208f50f192d4ce5926Brian   p->program->Base.NumTexInstructions++;
84115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
8425620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   /* Accounting for indirection tracking:
8435620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul    */
8445620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul   reserve_temp(p, dest);
8455620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul
846114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#if 0
847cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   /* Is this a texture indirection?
848cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
849cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   if ((coord.file == PROGRAM_TEMPORARY &&
850cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->temps_output & (1<<coord.idx))) ||
851cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       (dest.file == PROGRAM_TEMPORARY &&
852cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell	(p->alu_temps & (1<<dest.idx)))) {
85321f99792a916a62fcfae7c208f50f192d4ce5926Brian      p->program->Base.NumTexIndirections++;
8542dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->temps_output = 1<<coord.idx;
855cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      p->alu_temps = 0;
8562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(0);		/* KW: texture env crossbar */
85715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
858114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger#endif
85915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return dest;
86115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
86215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
86447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwellstatic struct ureg register_const4f( struct texenv_fragment_program *p,
865ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s0,
866ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s1,
867ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s2,
868ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLfloat s3)
86915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
87047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   GLfloat values[4];
871a90046f1097ad95de2aa95ca65741dff5cddced9Brian   GLuint idx, swizzle;
872d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   struct ureg r;
87347b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[0] = s0;
87447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[1] = s1;
87547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[2] = s2;
87647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   values[3] = s3;
877a90046f1097ad95de2aa95ca65741dff5cddced9Brian   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
878a90046f1097ad95de2aa95ca65741dff5cddced9Brian                                     &swizzle );
879d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r = make_ureg(PROGRAM_CONSTANT, idx);
880d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   r.swz = swizzle;
881d01269a57f4cfdb859352c933bc546296545dd80Brian Paul   return r;
88215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
88315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
884e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
88547b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
88647b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
88747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
88815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
88915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
8902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_one( struct texenv_fragment_program *p )
8912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
8922dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->one))
8932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p->one = register_scalar_const(p, 1.0);
8942dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->one;
8952dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
8962dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
8972dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_half( struct texenv_fragment_program *p )
8982dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
8992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->half))
9004dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->half = register_scalar_const(p, 0.5);
9012dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->half;
9022dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
9032dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
9042dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic struct ureg get_zero( struct texenv_fragment_program *p )
9052dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
9062dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->zero))
9074dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola      p->zero = register_scalar_const(p, 0.0);
9082dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   return p->zero;
9092dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
9102dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
91115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
91215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic void program_error( struct texenv_fragment_program *p, const char *msg )
91315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
914c5dde53f4e42612518cd927bb58f08c0e22db17aVinson Lee   _mesa_problem(NULL, "%s", msg);
91515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p->error = 1;
91615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
91715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
91815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg get_source( struct texenv_fragment_program *p,
919ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			       GLuint src, GLuint unit )
92015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
92115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (src) {
922ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE:
9232dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      assert(!is_undef(p->src_texture[unit]));
9242dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return p->src_texture[unit];
92515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
926ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
927ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
928ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
929ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
930ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
931ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
932ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
933ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
934ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
935ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return p->src_texture[src - SRC_TEXTURE0];
936ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
937ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_CONSTANT:
93847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_param2(p, STATE_TEXENV_COLOR, unit);
9392dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
940ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PRIMARY_COLOR:
94147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      return register_input(p, FRAG_ATTRIB_COL0);
9422dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
9436947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case SRC_ZERO:
9446947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return get_zero(p);
9456947f85cb5fbc433ba7763530285e470745b009bBrian Paul
946ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_PREVIOUS:
94747b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      if (is_undef(p->src_previous))
94847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return register_input(p, FRAG_ATTRIB_COL0);
94947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell      else
95047b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell	 return p->src_previous;
9516947f85cb5fbc433ba7763530285e470745b009bBrian Paul
9526947f85cb5fbc433ba7763530285e470745b009bBrian Paul   default:
9536947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
954c6af9b29476e4e445623e7a2f737ba95003bbe13José Fonseca      return undef;
95515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
95615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
9572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
95815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine_source( struct texenv_fragment_program *p,
959ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint mask,
960ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint unit,
961ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint source,
962ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell					GLuint operand )
96315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
96415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg arg, src, one;
96515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
96615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   src = get_source(p, source, unit);
96715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
96815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (operand) {
969ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_COLOR:
97015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
97115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.xyzw
97215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
97315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      arg = get_temp( p );
9742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one( p );
9757e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
97615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
977ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_ALPHA:
97815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_W)
97915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src;
98015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
98122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul	 return swizzle1( src, SWIZZLE_W );
982ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE_MINUS_SRC_ALPHA:
98315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Get unused tmp,
98415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * Emit tmp = 1.0 - arg.wwww
98515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
9862dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      arg = get_temp(p);
9872dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      one = get_one(p);
9887e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
98922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul			one, swizzle1(src, SWIZZLE_W), undef);
990ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ZERO:
9912dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_zero(p);
992ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_ONE:
9932dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      return get_one(p);
994ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case OPR_SRC_COLOR:
9956947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return src;
99615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
9976947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
99815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src;
99915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
100015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
100115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1002f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul/**
1003f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * Check if the RGB and Alpha sources and operands match for the given
1004f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * texture unit's combinder state.  When the RGB and A sources and
1005f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul * operands match, we can emit fewer instructions.
1006f337e2c4954b4779dcf2c2b4e0e068cb3ed7b841Brian Paul */
1007a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paulstatic GLboolean args_match( const struct state_key *key, GLuint unit )
100815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
10099ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul   GLuint i, numArgs = key->unit[unit].NumArgsRGB;
101015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1011457e427e32324884acb064b756e327dc131ff135Brian Paul   for (i = 0; i < numArgs; i++) {
1012ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
101315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;
101415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
10159ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul      switch (key->unit[unit].OptA[i].Operand) {
1016ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_SRC_ALPHA:
10179ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul	 switch (key->unit[unit].OptRGB[i].Operand) {
1018ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_COLOR:
1019ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_SRC_ALPHA:
102015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
102115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
102215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
102315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
102415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
1025ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      case OPR_ONE_MINUS_SRC_ALPHA:
10269ed0315271c38f5fe9cdd65020a54cbb7f61ed2bBrian Paul	 switch (key->unit[unit].OptRGB[i].Operand) {
1027ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_COLOR:
1028ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 case OPR_ONE_MINUS_SRC_ALPHA:
102915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    break;
103015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 default:
103115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    return GL_FALSE;
103215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
103315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 break;
103415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      default:
103515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return GL_FALSE;	/* impossible */
103615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
103715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
103815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
103915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   return GL_TRUE;
104015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
104115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
104215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwellstatic struct ureg emit_combine( struct texenv_fragment_program *p,
1043ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 struct ureg dest,
1044ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mask,
104522db53577603afef8fdf62c324ff5977de76b9d8Brian Paul				 GLboolean saturate,
1046ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint unit,
1047ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint nr,
1048ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				 GLuint mode,
1049d9736db6676948e06712d4bcba46b7040452f870Brian Paul				 const struct mode_opt *opt)
1050ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
1051bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul   struct ureg src[MAX_COMBINER_TERMS];
1052cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   struct ureg tmp, half;
105322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul   GLuint i;
105415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1055bd9b2be8284fda3f8aac235908ded118b5648a38Brian Paul   assert(nr <= MAX_COMBINER_TERMS);
10566947f85cb5fbc433ba7763530285e470745b009bBrian Paul
105715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   for (i = 0; i < nr; i++)
1058ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
105915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
106015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   switch (mode) {
1061ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_REPLACE:
106215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (mask == WRITEMASK_XYZW && !saturate)
106315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 return src[0];
106415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
10657e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
1066ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE:
10677e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
10686fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
1069ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD:
10707e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
10716fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[1], undef );
1072ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_ADD_SIGNED:
107315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp = arg0 + arg1
1074cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       * result = tmp - .5
107515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10762dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
107799da2d30eb08e50edf4b0067518af3acdf2dabc0Jerome Glisse      tmp = get_temp( p );
10787e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
10797e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
108015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
1081ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_INTERPOLATE:
108215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
108315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
10847e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
108515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1086ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_SUBTRACT:
10877e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
108815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1089ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA:
1090ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
1091ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
1092ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB: {
109315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp0 = get_temp( p );
109415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      struct ureg tmp1 = get_temp( p );
1095e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg neg1 = register_scalar_const(p, -1);
1096e490242b9aeb50bd96fed7a9afbf529295a8ac0eKeith Whitwell      struct ureg two  = register_scalar_const(p, 2);
109715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
109815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* tmp0 = 2*src0 - 1
109915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * tmp1 = 2*src1 - 1
110015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       *
110115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * dst = tmp0 dot3 tmp1
110215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
11037e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
11046fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		  two, src[0], neg1);
110515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
11062efa86ea3040c37965987160733b22e2a0541a3eKenneth Graunke      if (memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
110715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 tmp1 = tmp0;
110815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else
11097e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
11106fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell		     two, src[1], neg1);
11117e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
111215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return dest;
111315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1114ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_ADD_ATI:
11156fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 */
11167e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
11176fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell			 src[0], src[2], src[1] );
1118ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SIGNED_ADD_ATI: {
11196fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 + Arg1 - 0.5 */
11206fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      struct ureg tmp0 = get_temp(p);
11212dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      half = get_half(p);
11227e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
11237e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
11246fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
11256fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell   }
1126ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_MODULATE_SUBTRACT_ATI:
11276fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      /* Arg0 * Arg2 - Arg1 */
11287e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
11296fe176a64859798db17fbaed6858cccc646aae38Keith Whitwell      return dest;
11306947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case MODE_ADD_PRODUCTS:
11316947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* Arg0 * Arg1 + Arg2 * Arg3 */
11326947f85cb5fbc433ba7763530285e470745b009bBrian Paul      {
11336947f85cb5fbc433ba7763530285e470745b009bBrian Paul         struct ureg tmp0 = get_temp(p);
11346947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
11356947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 );
11366947f85cb5fbc433ba7763530285e470745b009bBrian Paul      }
11376947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return dest;
11386947f85cb5fbc433ba7763530285e470745b009bBrian Paul   case MODE_ADD_PRODUCTS_SIGNED:
11396947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */
11406947f85cb5fbc433ba7763530285e470745b009bBrian Paul      {
11416947f85cb5fbc433ba7763530285e470745b009bBrian Paul         struct ureg tmp0 = get_temp(p);
11426947f85cb5fbc433ba7763530285e470745b009bBrian Paul         half = get_half(p);
11436947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
11446947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 );
11456947f85cb5fbc433ba7763530285e470745b009bBrian Paul         emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
11466947f85cb5fbc433ba7763530285e470745b009bBrian Paul      }
11476947f85cb5fbc433ba7763530285e470745b009bBrian Paul      return dest;
1148114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   case MODE_BUMP_ENVMAP_ATI:
1149114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* special - not handled here */
1150114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      assert(0);
1151114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      return src[0];
115215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
11536947f85cb5fbc433ba7763530285e470745b009bBrian Paul      assert(0);
115415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return src[0];
115515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
115615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
115715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
115815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
115922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
116022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for one texture unit's env/combiner mode.
116122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
116222db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic struct ureg
116322db53577603afef8fdf62c324ff5977de76b9d8Brian Paulemit_texenv(struct texenv_fragment_program *p, GLuint unit)
116415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1165a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1166e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   GLboolean rgb_saturate, alpha_saturate;
116715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint rgb_shift, alpha_shift;
1168a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   struct ureg out, dest;
116915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1170ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (!key->unit[unit].enabled) {
1171ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      return get_source(p, SRC_PREVIOUS, 0);
117215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1173114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1174114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* this isn't really a env stage delivering a color and handled elsewhere */
1175114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      return get_source(p, SRC_PREVIOUS, 0);
1176114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   }
1177ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1178ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   switch (key->unit[unit].ModeRGB) {
1179ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGB_EXT:
1180ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
118115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
118215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
1183ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case MODE_DOT3_RGBA_EXT:
118415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      alpha_shift = 0;
118515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      rgb_shift = 0;
118615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
118715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   default:
1188ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      rgb_shift = key->unit[unit].ScaleShiftRGB;
1189ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      alpha_shift = key->unit[unit].ScaleShiftA;
119015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      break;
119115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1192ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
1193956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul   /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
1194956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul    * We don't want to clamp twice.
1195956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul    */
1196e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   if (rgb_shift)
1197e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      rgb_saturate = GL_FALSE;  /* saturate after rgb shift */
1198e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   else if (need_saturate(key->unit[unit].ModeRGB))
1199e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      rgb_saturate = GL_TRUE;
1200e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   else
1201e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      rgb_saturate = GL_FALSE;
1202e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul
1203e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   if (alpha_shift)
1204e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      alpha_saturate = GL_FALSE;  /* saturate after alpha shift */
1205e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   else if (need_saturate(key->unit[unit].ModeA))
1206e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      alpha_saturate = GL_TRUE;
1207e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul   else
1208e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      alpha_saturate = GL_FALSE;
1209956e6c3978abe918348377cf05e5c92971e50d3fBrian Paul
12106e83420ee0ccb2228fab0f86a6e8bf8a6aefe57aBrian Paul   /* If this is the very last calculation (and various other conditions
12116e83420ee0ccb2228fab0f86a6e8bf8a6aefe57aBrian Paul    * are met), emit directly to the color output register.  Otherwise,
12126e83420ee0ccb2228fab0f86a6e8bf8a6aefe57aBrian Paul    * emit to a temporary register.
1213cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell    */
1214ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->separate_specular ||
1215cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       unit != p->last_tex_stage ||
1216cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       alpha_shift ||
12176e83420ee0ccb2228fab0f86a6e8bf8a6aefe57aBrian Paul       key->num_draw_buffers != 1 ||
1218cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell       rgb_shift)
1219cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell      dest = get_temp( p );
1220cf4f3c5061423ab7241ea2a59d4949dbfb9a3278Keith Whitwell   else
12218d475822e6e19fa79719c856a2db5b6a205db1b9Brian Paul      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
122215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
122315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Emit the RGB and A combine ops
122415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
1225ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
1226ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       args_match(key, unit)) {
1227e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
122815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1229ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1230ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1231ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
123215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
1233ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
12349a45176dd85a1cd523498efeebd0481950a1bf58Roland Scheidegger	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
1235e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
123615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1237ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1238ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1239ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
124015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
124115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else {
124215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      /* Need to do something to stop from re-emitting identical
124315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       * argument calculations here:
124415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell       */
1245e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      out = emit_combine( p, dest, WRITEMASK_XYZ, rgb_saturate,
124615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1247ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsRGB,
1248ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeRGB,
1249ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptRGB);
1250e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      out = emit_combine( p, dest, WRITEMASK_W, alpha_saturate,
125115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			  unit,
1252ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].NumArgsA,
1253ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].ModeA,
1254ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell			  key->unit[unit].OptA);
125515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
125615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
125715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   /* Deal with the final shift:
125815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell    */
125915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   if (alpha_shift || rgb_shift) {
1260a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul      struct ureg shift;
1261e9ba9ffc9aa5dcc2de02dc3e58279ffda2318c79Brian Paul      GLboolean saturate = GL_TRUE;  /* always saturate at this point */
1262a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul
126315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      if (rgb_shift == alpha_shift) {
1264452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
126515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
126615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      else {
12672dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell	 shift = register_const4f(p,
1268452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1269452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1270452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<rgb_shift),
1271452a592ca4b1bac78eee53fb9f2f1deac7832840José Fonseca				  (GLfloat)(1<<alpha_shift));
127215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      }
12737e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
127415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell			 saturate, out, shift, undef );
127515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
127615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   else
127715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      return out;
127815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
127915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
12802dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
128122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
128222db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instruction for getting a texture source term.
128322db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
12842dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwellstatic void load_texture( struct texenv_fragment_program *p, GLuint unit )
12852dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
12862dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   if (is_undef(p->src_texture[unit])) {
1287b5ec0a68589c5d8f0d4be2556ea6d6b01fd4e37dBrian Paul      const GLuint texTarget = p->state->unit[unit].source_index;
1288114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      struct ureg texcoord;
12892dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      struct ureg tmp = get_tex_temp( p );
12902dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1291114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (is_undef(p->texcoord_tex[unit])) {
1292114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
1293114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      }
1294114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      else {
1295114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         /* might want to reuse this reg for tex output actually */
1296114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger         texcoord = p->texcoord_tex[unit];
1297114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      }
1298114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
12992dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* TODO: Use D0_MASK_XY where possible.
13002dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
130183ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle      if (p->state->unit[unit].enabled) {
130244e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul         GLboolean shadow = GL_FALSE;
13030397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1Keith Whitwell
130444e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul	 if (p->state->unit[unit].shadow) {
130583ad2a756ea8dd1b0ca9746e355ce3de0f29356eNicolai Haehnle	    p->program->Base.ShadowSamplers |= 1 << unit;
130644e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul            shadow = GL_TRUE;
130744e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul         }
130844e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul
130944e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
131044e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul					    tmp, WRITEMASK_XYZW,
131144e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul					    unit, texTarget, shadow,
131244e018c09e7aeba9fd9f4c380da224bd6622c470Brian Paul                                            texcoord );
13139b7e5a51f49e842f4114545f5eb171a597c83a66Brian
13149b7e5a51f49e842f4114545f5eb171a597c83a66Brian         p->program->Base.SamplersUsed |= (1 << unit);
13151fe385fdc96688a5249d52184f457910a0c25488Brian         /* This identity mapping should already be in place
13161fe385fdc96688a5249d52184f457910a0c25488Brian          * (see _mesa_init_program_struct()) but let's be safe.
13171fe385fdc96688a5249d52184f457910a0c25488Brian          */
13181fe385fdc96688a5249d52184f457910a0c25488Brian         p->program->Base.SamplerUnits[unit] = unit;
13199b7e5a51f49e842f4114545f5eb171a597c83a66Brian      }
13209b7e5a51f49e842f4114545f5eb171a597c83a66Brian      else
1321b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	 p->src_texture[unit] = get_zero(p);
13224a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul
13234a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul      if (p->state->unit[unit].texture_cyl_wrap) {
13244a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul         /* set flag which is checked by Mesa->Gallium program translation */
13254a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul         p->program->Base.InputFlags[0] |= PROG_PARAM_BIT_CYL_WRAP;
13264a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul      }
13274a9f1eed2ba02f2ae2bf92d16f89d10f09b2a21eBrian Paul
13282dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
13292dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
13302dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1331241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwellstatic GLboolean load_texenv_source( struct texenv_fragment_program *p,
1332ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell				     GLuint src, GLuint unit )
13332dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
13342dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   switch (src) {
13354dd8a8907e40126e42131a400b59e7d5da5e302aAapo Tahkola   case SRC_TEXTURE:
13362dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      load_texture(p, unit);
13372dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
13382dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1339ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE0:
1340ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE1:
1341ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE2:
1342ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE3:
1343ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE4:
1344ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE5:
1345ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE6:
1346ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   case SRC_TEXTURE7:
1347ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell      load_texture(p, src - SRC_TEXTURE0);
13482dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
13492dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
13502dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   default:
13516947f85cb5fbc433ba7763530285e470745b009bBrian Paul      /* not a texture src - do nothing */
13522dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      break;
13532dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1354241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell
1355241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
13562dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
13572dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
135822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
135922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
136022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate instructions for loading all texture source terms.
136122db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
136222db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic GLboolean
1363457e427e32324884acb064b756e327dc131ff135Brian Paulload_texunit_sources( struct texenv_fragment_program *p, GLuint unit )
13642dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell{
1365a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1366b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   GLuint i;
1367b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1368b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
1369114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
1370b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   }
1371b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1372b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
1373b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
13742dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell   }
1375b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola
1376241b6b7ab1a1a11c7fc516d1b6ff2c1bc8aba238Keith Whitwell   return GL_TRUE;
13772dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell}
13782dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
1379114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger/**
1380114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger * Generate instructions for loading bump map textures.
1381114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger */
1382114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheideggerstatic GLboolean
1383457e427e32324884acb064b756e327dc131ff135Brian Paulload_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit )
1384114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger{
1385a5e7003565a021ceb82a8b16f4a0ecc7cc6c02e0Brian Paul   const struct state_key *key = p->state;
1386114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
1387114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcDst, bumpMapRes;
1388114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
1389114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
1390114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
1391114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
1392114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1393114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   load_texenv_source( p, unit + SRC_TEXTURE0, unit );
1394114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1395114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
1396114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   texcDst = get_tex_temp( p );
1397114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   p->texcoord_tex[bumpedUnitNr] = texcDst;
1398114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1399457e427e32324884acb064b756e327dc131ff135Brian Paul   /* Apply rot matrix and add coords to be available in next phase.
1400457e427e32324884acb064b756e327dc131ff135Brian Paul    * dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1)
1401457e427e32324884acb064b756e327dc131ff135Brian Paul    * note only 2 coords are affected the rest are left unchanged (mul by 0)
1402457e427e32324884acb064b756e327dc131ff135Brian Paul    */
1403114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1404114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger               swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
1405114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
1406114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger               swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
1407114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1408457e427e32324884acb064b756e327dc131ff135Brian Paul   /* Move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
1409457e427e32324884acb064b756e327dc131ff135Brian Paul    * enough to access this later, should optimize away.
1410457e427e32324884acb064b756e327dc131ff135Brian Paul    */
1411457e427e32324884acb064b756e327dc131ff135Brian Paul   emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0,
1412457e427e32324884acb064b756e327dc131ff135Brian Paul               constdudvcolor, undef, undef );
1413114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
1414114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   return GL_TRUE;
1415114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger}
141622db53577603afef8fdf62c324ff5977de76b9d8Brian Paul
141722db53577603afef8fdf62c324ff5977de76b9d8Brian Paul/**
141822db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * Generate a new fragment program which implements the context's
141922db53577603afef8fdf62c324ff5977de76b9d8Brian Paul * current texture env/combine mode.
142022db53577603afef8fdf62c324ff5977de76b9d8Brian Paul */
142122db53577603afef8fdf62c324ff5977de76b9d8Brian Paulstatic void
1422f9995b30756140724f41daf963fa06167912be7fKristian Høgsbergcreate_new_program(struct gl_context *ctx, struct state_key *key,
1423122629f27925a9dc50029bebc5079f87f416a7e1Brian Paul                   struct gl_fragment_program *program)
142415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell{
1425e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
142615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct texenv_fragment_program p;
142715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   GLuint unit;
142815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   struct ureg cf, out;
14294b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie   int i;
1430276330b2412910777f7016f427909085f02acbb8Keith Whitwell
143126f8fad1456fdc2b352cea9d3b4c32cb5f6ae947Kenneth Graunke   memset(&p, 0, sizeof(p));
1432ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.state = key;
1433ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   p.program = program;
143415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1435e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* During code generation, use locally-allocated instruction buffer,
1436e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    * then alloc dynamic storage below.
1437e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul    */
1438e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   p.program->Base.Instructions = instBuffer;
1439276330b2412910777f7016f427909085f02acbb8Keith Whitwell   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
1440457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.String = NULL;
1441457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumTexIndirections = 1; /* is this right? */
144221f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumTexInstructions = 0;
144321f99792a916a62fcfae7c208f50f192d4ce5926Brian   p.program->Base.NumAluInstructions = 0;
1444457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumInstructions = 0;
1445457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumTemporaries = 0;
1446457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumParameters = 0;
1447457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumAttributes = 0;
1448457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.NumAddressRegs = 0;
1449de99760bf3511d05185799c4fb4347f9e5f420f4Brian Paul   p.program->Base.Parameters = _mesa_new_parameter_list();
1450457e427e32324884acb064b756e327dc131ff135Brian Paul   p.program->Base.InputsRead = 0x0;
14514b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie
1452b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul   if (key->num_draw_buffers == 1)
14534b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
14544b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie   else {
1455b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul      for (i = 0; i < key->num_draw_buffers; i++)
14564b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 p.program->Base.OutputsWritten |= (1 << (FRAG_RESULT_DATA0 + i));
14574b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie   }
145815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1459114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
14602dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      p.src_texture[unit] = undef;
1461114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      p.texcoord_tex[unit] = undef;
1462114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger   }
14632dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell
146447b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   p.src_previous = undef;
14655ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.half = undef;
14665ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.zero = undef;
14675ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell   p.one = undef;
14685ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
146915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   p.last_tex_stage = 0;
147093fef22d05d0fb6f011d48d2fde533555c1695a2Brian   release_temps(ctx, &p);
147115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
14722fa6012f6a0b02de6093cbccba3bf4432f072e57Brian Paul   if (key->enabled_units && key->num_draw_buffers) {
1473457e427e32324884acb064b756e327dc131ff135Brian Paul      GLboolean needbumpstage = GL_FALSE;
1474457e427e32324884acb064b756e327dc131ff135Brian Paul
1475114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      /* Zeroth pass - bump map textures first */
14767a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul      for (unit = 0; unit < key->nr_enabled_units; unit++)
1477457e427e32324884acb064b756e327dc131ff135Brian Paul	 if (key->unit[unit].enabled &&
1478457e427e32324884acb064b756e327dc131ff135Brian Paul             key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
1479114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	    needbumpstage = GL_TRUE;
1480114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	    load_texunit_bumpmap( &p, unit );
1481114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	 }
1482114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger      if (needbumpstage)
1483114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger	 p.program->Base.NumTexIndirections++;
1484114152e068ec919feb0a57a1259c2ada970b9f02Roland Scheidegger
14852dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* First pass - to support texture_env_crossbar, first identify
14862dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * all referenced texture sources and emit texld instructions
14872dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       * for each:
14882dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
14897a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul      for (unit = 0; unit < key->nr_enabled_units; unit++)
1490ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell	 if (key->unit[unit].enabled) {
1491b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    load_texunit_sources( &p, unit );
1492b8915340eab706776244e04547f64444f0ff2f8bAapo Tahkola	    p.last_tex_stage = unit;
149315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
149415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
14952dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell      /* Second pass - emit combine instructions to build final color:
14962dea6df80b51ad8c5e2e88c2eb214b55889821c6Keith Whitwell       */
14977a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul      for (unit = 0; unit < key->nr_enabled_units; unit++)
149884d6bed4d6844110af23a995e2fad0280a92d46cBrian Paul	 if (key->unit[unit].enabled) {
149915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	    p.src_previous = emit_texenv( &p, unit );
15005620c20b24dc4f780a2246eb5270c4476b487e0aBrian Paul            reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
150193fef22d05d0fb6f011d48d2fde533555c1695a2Brian	    release_temps(ctx, &p);	/* release all temps */
150215e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell	 }
150315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell   }
150415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1505ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   cf = get_source( &p, SRC_PREVIOUS, 0 );
150615e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1507b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul   for (i = 0; i < key->num_draw_buffers; i++) {
1508b6b9b17d27c570cc99ae339e595cf2f63ca5e8d7Brian Paul      if (key->num_draw_buffers == 1)
15094b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLOR );
15104b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      else {
15114b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i );
15124b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      }
151315e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
15144b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      if (key->separate_specular) {
15154b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 /* Emit specular add.
15164b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	  */
15174b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
15184b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
15194b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
15204b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      }
15214b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      else if (memcmp(&cf, &out, sizeof(cf)) != 0) {
15224b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 /* Will wind up in here if no texture enabled or a couple of
15234b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	  * other scenarios (GL_REPLACE for instance).
15244b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	  */
15254b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
15264b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie      }
15274b39a0da89f5b07d4a24bc9ce52693e6c2acfe99Dave Airlie   }
152847b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell   /* Finish up:
152947b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell    */
15307e807510d8c3e88ee7ae6c697393201cf08f992fBrian Paul   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
153147b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
1532ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell   if (key->fog_enabled) {
1533f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg      /* Pull fog mode from struct gl_context, the value in the state key is
1534ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       * a reduced value and not what is expected in FogOption
1535ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell       */
1536276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = ctx->Fog.Mode;
1537457e427e32324884acb064b756e327dc131ff135Brian Paul      p.program->Base.InputsRead |= FRAG_BIT_FOGC;
1538457e427e32324884acb064b756e327dc131ff135Brian Paul   }
1539457e427e32324884acb064b756e327dc131ff135Brian Paul   else {
1540276330b2412910777f7016f427909085f02acbb8Keith Whitwell      p.program->FogOption = GL_NONE;
1541457e427e32324884acb064b756e327dc131ff135Brian Paul   }
154247b29f511a8e917c65536fde90397d54d2ad23d3Keith Whitwell
154321f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
154415e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max nr indirect texture lookups");
154515e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
154621f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
154715e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max TEX instructions");
154815e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
154921f99792a916a62fcfae7c208f50f192d4ce5926Brian   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
155015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell      program_error(&p, "Exceeded max ALU instructions");
155115e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
15525d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
15538b88f62fbd62153500fc3483003f438561366a00Keith Whitwell
1554e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   /* Allocate final instruction array */
1555c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   p.program->Base.Instructions
1556c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      = _mesa_alloc_instructions(p.program->Base.NumInstructions);
1557c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   if (!p.program->Base.Instructions) {
1558e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1559e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul                  "generating tex env program");
1560e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      return;
1561e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1562c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
1563c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian                           p.program->Base.NumInstructions);
1564c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian
15652fa6012f6a0b02de6093cbccba3bf4432f072e57Brian Paul   if (key->num_draw_buffers && p.program->FogOption) {
1566c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      _mesa_append_fog_code(ctx, p.program);
1567c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian      p.program->FogOption = GL_NONE;
1568c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian   }
1569c81cce78313a62e0d36a5c80bd9d35b770d0814aBrian
1570e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1571dbeea25bb834479a29712100888c862348112018Keith Whitwell   /* Notify driver the fragment program has (actually) changed.
15728b88f62fbd62153500fc3483003f438561366a00Keith Whitwell    */
1573e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (ctx->Driver.ProgramStringNotify) {
15744ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul      GLboolean ok = ctx->Driver.ProgramStringNotify(ctx,
15754ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul                                                     GL_FRAGMENT_PROGRAM_ARB,
15764ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul                                                     &p.program->Base);
15774ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul      /* Driver should be able to handle any texenv programs as long as
15784ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul       * the driver correctly reported max number of texture units correctly,
15794ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul       * etc.
15804ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul       */
15814ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul      ASSERT(ok);
15824ac9c80e5beea26e13ccf12ce6bd9ee051c229f5Brian Paul      (void) ok; /* silence unused var warning */
1583e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   }
1584e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul
1585e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul   if (DISASSEM) {
1586e998c346471142db91a1bcb6c61551b8247b87e7Brian Paul      _mesa_print_program(&p.program->Base);
1587298be2b028263b2c343a707662c6fbfa18293cb2Kristian Høgsberg      printf("\n");
1588dbeea25bb834479a29712100888c862348112018Keith Whitwell   }
158915e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell}
159015e75e00c7dc79c28aeac84891bcf18ffc77cff9Keith Whitwell
1591cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholtextern "C" {
15925d7b49f7e77f9e3303e0910834b6c014e7267289Brian Paul
159332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell/**
159432ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell * Return a fragment program which implements the current
159532ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell * fixed-function texture, fog and color-sum operations.
159632ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell */
159732ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwellstruct gl_fragment_program *
1598f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_get_fixed_func_fragment_program(struct gl_context *ctx)
1599ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell{
160032ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   struct gl_fragment_program *prog;
160132ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   struct state_key key;
16027a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   GLuint keySize;
160332ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell
16047a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul   keySize = make_state_key(ctx, &key);
160532ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell
160632ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   prog = (struct gl_fragment_program *)
160732ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
16087a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul                                 &key, keySize);
1609ce721143b4d44d239baefe965e499606149b15cbKeith Whitwell
161032ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   if (!prog) {
161132ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      prog = (struct gl_fragment_program *)
161232ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
16135ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
161432ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      create_new_program(ctx, &key, prog);
16155ddc53f899598396003ec6c723f8132c76aafe79Keith Whitwell
161632ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
16177a7d5879e28607c151132a8b6a07cf4be36b5b3eBrian Paul                                 &key, keySize, &prog->Base);
16188065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell   }
16198065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell
162032ef6e75839d6be283e034436e5dd34eabb67958Keith Whitwell   return prog;
16218065c120c45e89e49ca9f707408fd7bd14db6b23Keith Whitwell}
1622cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt
1623cdacca4868bbfe2e39f72d524556e7b2c7200ba5Eric Anholt}
1624