ff_fragment_shader.cpp revision 32ef6e75839d6be283e034436e5dd34eabb67958
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**************************************************************************
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * All Rights Reserved.
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * copy of this software and associated documentation files (the
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * "Software"), to deal in the Software without restriction, including
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * without limitation the rights to use, copy, modify, merge, publish,
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * distribute, sub license, and/or sell copies of the Software, and to
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * permit persons to whom the Software is furnished to do so, subject to
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the following conditions:
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The above copyright notice and this permission notice (including the
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * next paragraph) shall be included in all copies or substantial portions
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * of the Software.
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **************************************************************************/
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "glheader.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "macros.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "enums.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/program.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/prog_parameter.h"
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/prog_cache.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/prog_instruction.h"
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/prog_print.h"
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shader/prog_statevars.h"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "texenvprogram.h"
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct texenvprog_cache_item
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint hash;
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   void *key;
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct gl_fragment_program *data;
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct texenvprog_cache_item *next;
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This MAX is probably a bit generous, but that's OK.  There can be
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * up to four instructions per texture unit (TEX + 3 for combine),
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * then there's fog and specular add.
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MAX_INSTRUCTIONS ((MAX_TEXTURE_UNITS * 4) + 12)
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct mode_opt {
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint Source:4;
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint Operand:3;
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct state_key {
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLbitfield enabled_units;
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint separate_specular:1;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint fog_enabled:1;
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint fog_mode:2;
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct {
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint enabled:1;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint source_index:3;   /* one of TEXTURE_1D/2D/3D/CUBE/RECT_INDEX */
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint shadow:1;
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint ScaleShiftRGB:2;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint ScaleShiftA:2;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint NumArgsRGB:2;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint ModeRGB:4;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      struct mode_opt OptRGB[3];
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint NumArgsA:2;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      GLuint ModeA:4;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      struct mode_opt OptA[3];
835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   } unit[8];
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FOG_LINEAR  0
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FOG_EXP     1
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FOG_EXP2    2
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define FOG_UNKNOWN 3
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLuint translate_fog_mode( GLenum mode )
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (mode) {
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_LINEAR: return FOG_LINEAR;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_EXP: return FOG_EXP;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_EXP2: return FOG_EXP2;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   default: return FOG_UNKNOWN;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_SRC_COLOR           0
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_ONE_MINUS_SRC_COLOR 1
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_SRC_ALPHA           2
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_ONE_MINUS_SRC_ALPHA	3
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_ZERO                4
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_ONE                 5
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define OPR_UNKNOWN             7
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLuint translate_operand( GLenum operand )
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (operand) {
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_SRC_COLOR: return OPR_SRC_COLOR;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_ZERO: return OPR_ZERO;
1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   case GL_ONE: return OPR_ONE;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   default:	return OPR_UNKNOWN;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE  0
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE0 1
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE1 2
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE2 3
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE3 4
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE4 5
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE5 6
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE6 7
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_TEXTURE7 8
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_CONSTANT 9
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_PRIMARY_COLOR 10
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_PREVIOUS 11
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define SRC_UNKNOWN  15
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLuint translate_source( GLenum src )
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (src) {
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE: return SRC_TEXTURE;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE0:
1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   case GL_TEXTURE1:
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE2:
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE3:
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE4:
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE5:
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE6:
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_CONSTANT: return SRC_CONSTANT;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_PREVIOUS: return SRC_PREVIOUS;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   default: return SRC_UNKNOWN;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_REPLACE       0
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_MODULATE      1
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_ADD           2
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_ADD_SIGNED    3
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_INTERPOLATE   4
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_SUBTRACT      5
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_DOT3_RGB      6
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_DOT3_RGB_EXT  7
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_DOT3_RGBA     8
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_DOT3_RGBA_EXT 9
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_MODULATE_ADD_ATI           10
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_MODULATE_SIGNED_ADD_ATI    11
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_MODULATE_SUBTRACT_ATI      12
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define MODE_UNKNOWN       15
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLuint translate_mode( GLenum mode )
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (mode) {
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_REPLACE: return MODE_REPLACE;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_MODULATE: return MODE_MODULATE;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_ADD: return MODE_ADD;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_ADD_SIGNED: return MODE_ADD_SIGNED;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_INTERPOLATE: return MODE_INTERPOLATE;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_SUBTRACT: return MODE_SUBTRACT;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_DOT3_RGB: return MODE_DOT3_RGB;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   default: return MODE_UNKNOWN;
187a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   }
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define TEXTURE_UNKNOWN_INDEX 7
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLuint translate_tex_src_bit( GLbitfield bit )
192a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner{
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (bit) {
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case TEXTURE_1D_BIT:   return TEXTURE_1D_INDEX;
1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   case TEXTURE_2D_BIT:   return TEXTURE_2D_INDEX;
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case TEXTURE_RECT_BIT: return TEXTURE_RECT_INDEX;
1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   case TEXTURE_3D_BIT:   return TEXTURE_3D_INDEX;
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   case TEXTURE_CUBE_BIT: return TEXTURE_CUBE_INDEX;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   default: return TEXTURE_UNKNOWN_INDEX;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/**
204a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * Examine current texture environment state and generate a unique
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * key to identify it.
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void make_state_key( GLcontext *ctx,  struct state_key *key )
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint i, j;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   memset(key, 0, sizeof(*key));
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i=0;i<MAX_TEXTURE_UNITS;i++) {
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         continue;
2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].enabled = 1;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->enabled_units |= (1<<i);
2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].source_index =
2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	 translate_tex_src_bit(texUnit->_ReallyEnabled);
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].shadow = texUnit->_Current->CompareMode == GL_COMPARE_R_TO_TEXTURE;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].NumArgsRGB = texUnit->_CurrentCombine->_NumArgsRGB;
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].NumArgsA = texUnit->_CurrentCombine->_NumArgsA;
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].ModeRGB =
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 translate_mode(texUnit->_CurrentCombine->ModeRGB);
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].ModeA =
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	 translate_mode(texUnit->_CurrentCombine->ModeA);
2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].ScaleShiftRGB = texUnit->_CurrentCombine->ScaleShiftRGB;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->unit[i].ScaleShiftA = texUnit->_CurrentCombine->ScaleShiftA;
2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (j=0;j<3;j++) {
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         key->unit[i].OptRGB[j].Operand =
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    translate_operand(texUnit->_CurrentCombine->OperandRGB[j]);
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         key->unit[i].OptA[j].Operand =
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    translate_operand(texUnit->_CurrentCombine->OperandA[j]);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         key->unit[i].OptRGB[j].Source =
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    translate_source(texUnit->_CurrentCombine->SourceRGB[j]);
2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner         key->unit[i].OptA[j].Source =
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	    translate_source(texUnit->_CurrentCombine->SourceA[j]);
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   }
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->separate_specular = 1;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (ctx->Fog.Enabled) {
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->fog_enabled = 1;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Use uregs to represent registers internally, translate to Mesa's
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * expected formats on emit.
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * NOTE: These are passed by value extensively in this file rather
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * than as usual by pointer reference.  If this disturbs you, try
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * remembering they are just 32bits in size.
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * GCC is smart enough to deal with these dword-sized structures in
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * much the same way as if I had defined them as dwords and was using
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * macros to access and set the fields.  This is much nicer and easier
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * to evolve.
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct ureg {
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint file:4;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint idx:8;
273a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   GLuint negatebase:1;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint abs:1;
275a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   GLuint negateabs:1;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint swz:12;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint pad:5;
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct ureg undef = {
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PROGRAM_UNDEFINED,
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   ~0,
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   0,
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   0,
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   0,
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   0,
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   0
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* State used to build the fragment program:
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstruct texenv_fragment_program {
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct gl_fragment_program *program;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLcontext *ctx;
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct state_key *state;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLbitfield alu_temps;	/* Track texture indirections, see spec. */
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLbitfield temps_output;	/* Track texture indirections, see spec. */
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLbitfield temp_in_use;	/* Tracks temporary regs which are in use. */
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLboolean error;
302a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct ureg src_texture[MAX_TEXTURE_UNITS];
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Reg containing each texture unit's sampled texture color,
3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    * else undef.
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct ureg src_previous;	/* Reg containing color from previous
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 * stage.  May need to be decl'd.
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				 */
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint last_tex_stage;	/* Number of last enabled texture unit */
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct ureg half;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct ureg one;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct ureg zero;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg make_ureg(GLuint file, GLuint idx)
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   struct ureg reg;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.file = file;
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.idx = idx;
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.negatebase = 0;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.abs = 0;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.negateabs = 0;
3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   reg.swz = SWIZZLE_NOOP;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.pad = 0;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return reg;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   GET_SWZ(reg.swz, y),
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			   GET_SWZ(reg.swz, z),
3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner			   GET_SWZ(reg.swz, w));
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return reg;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct ureg swizzle1( struct ureg reg, int x )
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return swizzle(reg, x, x, x, x);
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct ureg negate( struct ureg reg )
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg.negatebase ^= 1;
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return reg;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic GLboolean is_undef( struct ureg reg )
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return reg.file == PROGRAM_UNDEFINED;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg get_temp( struct texenv_fragment_program *p )
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLint bit;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   /* First try and reuse temps which have been used already:
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Then any unused temporary:
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!bit)
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      bit = _mesa_ffs( ~p->temp_in_use );
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!bit) {
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      _mesa_exit(1);
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if ((GLuint) bit > p->program->Base.NumTemporaries)
3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      p->program->Base.NumTemporaries = bit;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   p->temp_in_use |= 1<<(bit-1);
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg get_tex_temp( struct texenv_fragment_program *p )
3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int bit;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* First try to find availble temp not previously used (to avoid
3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    * starting a new texture indirection).  According to the spec, the
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * ~p->temps_output isn't necessary, but will keep it there for
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * now:
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Then any unused temporary:
3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    */
3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner   if (!bit)
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      bit = _mesa_ffs( ~p->temp_in_use );
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!bit) {
4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      _mesa_exit(1);
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if ((GLuint) bit > p->program->Base.NumTemporaries)
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->program->Base.NumTemporaries = bit;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   p->temp_in_use |= 1<<(bit-1);
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
412a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner}
4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void release_temps( struct texenv_fragment_program *p )
4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint max_temp = p->ctx->Const.FragmentProgram.MaxTemps;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* KW: To support tex_env_crossbar, don't release the registers in
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * temps_output.
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (max_temp >= sizeof(int) * 8)
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->temp_in_use = p->temps_output;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}
4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg register_param5( struct texenv_fragment_program *p,
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				    GLint s0,
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				    GLint s1,
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				    GLint s2,
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				    GLint s3,
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project				    GLint s4)
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   gl_state_index tokens[STATE_LENGTH];
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint idx;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   tokens[0] = s0;
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   tokens[1] = s1;
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   tokens[2] = s2;
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   tokens[3] = s3;
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   tokens[4] = s4;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return make_ureg(PROGRAM_STATE_VAR, idx);
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   p->program->Base.InputsRead |= (1 << input);
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return make_ureg(PROGRAM_INPUT, input);
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void emit_arg( struct prog_src_register *reg,
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		      struct ureg ureg )
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->File = ureg.file;
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->Index = ureg.idx;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->Swizzle = ureg.swz;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->NegateBase = ureg.negatebase ? 0xf : 0x0;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->Abs = ureg.abs;
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   reg->NegateAbs = ureg.negateabs;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void emit_dst( struct prog_dst_register *dst,
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project		      struct ureg ureg, GLuint mask )
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   dst->File = ureg.file;
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   dst->Index = ureg.idx;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   dst->WriteMask = mask;
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   dst->CondMask = COND_TR;  /* always pass cond test */
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   dst->CondSwizzle = SWIZZLE_NOOP;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct prog_instruction *
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectemit_op(struct texenv_fragment_program *p,
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	enum prog_opcode op,
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct ureg dest,
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	GLuint mask,
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	GLboolean saturate,
4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner	struct ureg src0,
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct ureg src1,
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	struct ureg src2 )
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   GLuint nr = p->program->Base.NumInstructions++;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
495a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   assert(nr < MAX_INSTRUCTIONS);
496a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
497a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   _mesa_init_instructions(inst, 1);
498a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   inst->Opcode = op;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   emit_arg( &inst->SrcReg[0], src0 );
501a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   emit_arg( &inst->SrcReg[1], src1 );
502a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   emit_arg( &inst->SrcReg[2], src2 );
503a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
504a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
505a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   emit_dst( &inst->DstReg, dest, mask );
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
508a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   /* Accounting for indirection tracking:
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
510a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   if (dest.file == PROGRAM_TEMPORARY)
511a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner      p->temps_output |= 1 << dest.idx;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return inst;
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
515a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
516a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner
517a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turnerstatic struct ureg emit_arith( struct texenv_fragment_program *p,
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       enum prog_opcode op,
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg dest,
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       GLuint mask,
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       GLboolean saturate,
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg src0,
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg src1,
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg src2 )
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Accounting for indirection tracking:
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (src0.file == PROGRAM_TEMPORARY)
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->alu_temps |= 1 << src0.idx;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->alu_temps |= 1 << src1.idx;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->alu_temps |= 1 << src2.idx;
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (dest.file == PROGRAM_TEMPORARY)
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      p->alu_temps |= 1 << dest.idx;
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   p->program->Base.NumAluInstructions++;
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return dest;
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic struct ureg emit_texld( struct texenv_fragment_program *p,
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       enum prog_opcode op,
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg dest,
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       GLuint destmask,
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       GLuint tex_unit,
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       GLuint tex_idx,
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			       struct ureg coord )
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   struct prog_instruction *inst = emit_op( p, op,
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					  dest, destmask,
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					  GL_FALSE,	/* don't saturate? */
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					  coord, 	/* arg 0? */
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					  undef,
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project					  undef);
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inst->TexSrcTarget = tex_idx;
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   inst->TexSrcUnit = tex_unit;
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
564a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner   p->program->Base.NumTexInstructions++;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Is this a texture indirection?
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if ((coord.file == PROGRAM_TEMPORARY &&
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	(p->temps_output & (1<<coord.idx))) ||
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       (dest.file == PROGRAM_TEMPORARY &&
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	(p->alu_temps & (1<<dest.idx)))) {
572      p->program->Base.NumTexIndirections++;
573      p->temps_output = 1<<coord.idx;
574      p->alu_temps = 0;
575      assert(0);		/* KW: texture env crossbar */
576   }
577
578   return dest;
579}
580
581
582static struct ureg register_const4f( struct texenv_fragment_program *p,
583				     GLfloat s0,
584				     GLfloat s1,
585				     GLfloat s2,
586				     GLfloat s3)
587{
588   GLfloat values[4];
589   GLuint idx, swizzle;
590   values[0] = s0;
591   values[1] = s1;
592   values[2] = s2;
593   values[3] = s3;
594   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
595                                     &swizzle );
596   ASSERT(swizzle == SWIZZLE_NOOP);
597   return make_ureg(PROGRAM_STATE_VAR, idx);
598}
599
600#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
601#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
602#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
603#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
604
605
606static struct ureg get_one( struct texenv_fragment_program *p )
607{
608   if (is_undef(p->one))
609      p->one = register_scalar_const(p, 1.0);
610   return p->one;
611}
612
613static struct ureg get_half( struct texenv_fragment_program *p )
614{
615   if (is_undef(p->half))
616      p->half = register_scalar_const(p, 0.5);
617   return p->half;
618}
619
620static struct ureg get_zero( struct texenv_fragment_program *p )
621{
622   if (is_undef(p->zero))
623      p->zero = register_scalar_const(p, 0.0);
624   return p->zero;
625}
626
627
628static void program_error( struct texenv_fragment_program *p, const char *msg )
629{
630   _mesa_problem(NULL, msg);
631   p->error = 1;
632}
633
634static struct ureg get_source( struct texenv_fragment_program *p,
635			       GLuint src, GLuint unit )
636{
637   switch (src) {
638   case SRC_TEXTURE:
639      assert(!is_undef(p->src_texture[unit]));
640      return p->src_texture[unit];
641
642   case SRC_TEXTURE0:
643   case SRC_TEXTURE1:
644   case SRC_TEXTURE2:
645   case SRC_TEXTURE3:
646   case SRC_TEXTURE4:
647   case SRC_TEXTURE5:
648   case SRC_TEXTURE6:
649   case SRC_TEXTURE7:
650      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
651      return p->src_texture[src - SRC_TEXTURE0];
652
653   case SRC_CONSTANT:
654      return register_param2(p, STATE_TEXENV_COLOR, unit);
655
656   case SRC_PRIMARY_COLOR:
657      return register_input(p, FRAG_ATTRIB_COL0);
658
659   case SRC_PREVIOUS:
660   default:
661      if (is_undef(p->src_previous))
662	 return register_input(p, FRAG_ATTRIB_COL0);
663      else
664	 return p->src_previous;
665   }
666}
667
668static struct ureg emit_combine_source( struct texenv_fragment_program *p,
669					GLuint mask,
670					GLuint unit,
671					GLuint source,
672					GLuint operand )
673{
674   struct ureg arg, src, one;
675
676   src = get_source(p, source, unit);
677
678   switch (operand) {
679   case OPR_ONE_MINUS_SRC_COLOR:
680      /* Get unused tmp,
681       * Emit tmp = 1.0 - arg.xyzw
682       */
683      arg = get_temp( p );
684      one = get_one( p );
685      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
686
687   case OPR_SRC_ALPHA:
688      if (mask == WRITEMASK_W)
689	 return src;
690      else
691	 return swizzle1( src, SWIZZLE_W );
692   case OPR_ONE_MINUS_SRC_ALPHA:
693      /* Get unused tmp,
694       * Emit tmp = 1.0 - arg.wwww
695       */
696      arg = get_temp(p);
697      one = get_one(p);
698      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
699			one, swizzle1(src, SWIZZLE_W), undef);
700   case OPR_ZERO:
701      return get_zero(p);
702   case OPR_ONE:
703      return get_one(p);
704   case OPR_SRC_COLOR:
705   default:
706      return src;
707   }
708}
709
710static GLboolean args_match( struct state_key *key, GLuint unit )
711{
712   GLuint i, nr = key->unit[unit].NumArgsRGB;
713
714   for (i = 0 ; i < nr ; i++) {
715      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
716	 return GL_FALSE;
717
718      switch(key->unit[unit].OptA[i].Operand) {
719      case OPR_SRC_ALPHA:
720	 switch(key->unit[unit].OptRGB[i].Operand) {
721	 case OPR_SRC_COLOR:
722	 case OPR_SRC_ALPHA:
723	    break;
724	 default:
725	    return GL_FALSE;
726	 }
727	 break;
728      case OPR_ONE_MINUS_SRC_ALPHA:
729	 switch(key->unit[unit].OptRGB[i].Operand) {
730	 case OPR_ONE_MINUS_SRC_COLOR:
731	 case OPR_ONE_MINUS_SRC_ALPHA:
732	    break;
733	 default:
734	    return GL_FALSE;
735	 }
736	 break;
737      default:
738	 return GL_FALSE;	/* impossible */
739      }
740   }
741
742   return GL_TRUE;
743}
744
745static struct ureg emit_combine( struct texenv_fragment_program *p,
746				 struct ureg dest,
747				 GLuint mask,
748				 GLboolean saturate,
749				 GLuint unit,
750				 GLuint nr,
751				 GLuint mode,
752				 const struct mode_opt *opt)
753{
754   struct ureg src[3];
755   struct ureg tmp, half;
756   GLuint i;
757
758   tmp = undef; /* silence warning (bug 5318) */
759
760   for (i = 0; i < nr; i++)
761      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
762
763   switch (mode) {
764   case MODE_REPLACE:
765      if (mask == WRITEMASK_XYZW && !saturate)
766	 return src[0];
767      else
768	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
769   case MODE_MODULATE:
770      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
771			 src[0], src[1], undef );
772   case MODE_ADD:
773      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
774			 src[0], src[1], undef );
775   case MODE_ADD_SIGNED:
776      /* tmp = arg0 + arg1
777       * result = tmp - .5
778       */
779      half = get_half(p);
780      tmp = get_temp( p );
781      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
782      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
783      return dest;
784   case MODE_INTERPOLATE:
785      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
786       */
787      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
788
789   case MODE_SUBTRACT:
790      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
791
792   case MODE_DOT3_RGBA:
793   case MODE_DOT3_RGBA_EXT:
794   case MODE_DOT3_RGB_EXT:
795   case MODE_DOT3_RGB: {
796      struct ureg tmp0 = get_temp( p );
797      struct ureg tmp1 = get_temp( p );
798      struct ureg neg1 = register_scalar_const(p, -1);
799      struct ureg two  = register_scalar_const(p, 2);
800
801      /* tmp0 = 2*src0 - 1
802       * tmp1 = 2*src1 - 1
803       *
804       * dst = tmp0 dot3 tmp1
805       */
806      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
807		  two, src[0], neg1);
808
809      if (_mesa_memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
810	 tmp1 = tmp0;
811      else
812	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
813		     two, src[1], neg1);
814      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
815      return dest;
816   }
817   case MODE_MODULATE_ADD_ATI:
818      /* Arg0 * Arg2 + Arg1 */
819      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
820			 src[0], src[2], src[1] );
821   case MODE_MODULATE_SIGNED_ADD_ATI: {
822      /* Arg0 * Arg2 + Arg1 - 0.5 */
823      struct ureg tmp0 = get_temp(p);
824      half = get_half(p);
825      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
826      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
827      return dest;
828   }
829   case MODE_MODULATE_SUBTRACT_ATI:
830      /* Arg0 * Arg2 - Arg1 */
831      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
832      return dest;
833   default:
834      return src[0];
835   }
836}
837
838
839/**
840 * Generate instructions for one texture unit's env/combiner mode.
841 */
842static struct ureg
843emit_texenv(struct texenv_fragment_program *p, GLuint unit)
844{
845   struct state_key *key = p->state;
846   GLboolean saturate = (unit < p->last_tex_stage);
847   GLuint rgb_shift, alpha_shift;
848   struct ureg out, shift;
849   struct ureg dest;
850
851   if (!key->unit[unit].enabled) {
852      return get_source(p, SRC_PREVIOUS, 0);
853   }
854
855   switch (key->unit[unit].ModeRGB) {
856   case MODE_DOT3_RGB_EXT:
857      alpha_shift = key->unit[unit].ScaleShiftA;
858      rgb_shift = 0;
859      break;
860   case MODE_DOT3_RGBA_EXT:
861      alpha_shift = 0;
862      rgb_shift = 0;
863      break;
864   default:
865      rgb_shift = key->unit[unit].ScaleShiftRGB;
866      alpha_shift = key->unit[unit].ScaleShiftA;
867      break;
868   }
869
870   /* If this is the very last calculation, emit direct to output reg:
871    */
872   if (key->separate_specular ||
873       unit != p->last_tex_stage ||
874       alpha_shift ||
875       rgb_shift)
876      dest = get_temp( p );
877   else
878      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
879
880   /* Emit the RGB and A combine ops
881    */
882   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
883       args_match(key, unit)) {
884      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
885			  unit,
886			  key->unit[unit].NumArgsRGB,
887			  key->unit[unit].ModeRGB,
888			  key->unit[unit].OptRGB);
889   }
890   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
891	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
892
893      out = emit_combine( p, dest, WRITEMASK_XYZW, saturate,
894			  unit,
895			  key->unit[unit].NumArgsRGB,
896			  key->unit[unit].ModeRGB,
897			  key->unit[unit].OptRGB);
898   }
899   else {
900      /* Need to do something to stop from re-emitting identical
901       * argument calculations here:
902       */
903      out = emit_combine( p, dest, WRITEMASK_XYZ, saturate,
904			  unit,
905			  key->unit[unit].NumArgsRGB,
906			  key->unit[unit].ModeRGB,
907			  key->unit[unit].OptRGB);
908      out = emit_combine( p, dest, WRITEMASK_W, saturate,
909			  unit,
910			  key->unit[unit].NumArgsA,
911			  key->unit[unit].ModeA,
912			  key->unit[unit].OptA);
913   }
914
915   /* Deal with the final shift:
916    */
917   if (alpha_shift || rgb_shift) {
918      if (rgb_shift == alpha_shift) {
919	 shift = register_scalar_const(p, 1<<rgb_shift);
920      }
921      else {
922	 shift = register_const4f(p,
923				  1<<rgb_shift,
924				  1<<rgb_shift,
925				  1<<rgb_shift,
926				  1<<alpha_shift);
927      }
928      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
929			 saturate, out, shift, undef );
930   }
931   else
932      return out;
933}
934
935
936/**
937 * Generate instruction for getting a texture source term.
938 */
939static void load_texture( struct texenv_fragment_program *p, GLuint unit )
940{
941   if (is_undef(p->src_texture[unit])) {
942      GLuint dim = p->state->unit[unit].source_index;
943      struct ureg texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
944      struct ureg tmp = get_tex_temp( p );
945
946      if (dim == TEXTURE_UNKNOWN_INDEX)
947         program_error(p, "TexSrcBit");
948
949      /* TODO: Use D0_MASK_XY where possible.
950       */
951      if (p->state->unit[unit].enabled) {
952	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
953					    tmp, WRITEMASK_XYZW,
954					    unit, dim, texcoord );
955	 if (p->state->unit[unit].shadow)
956	    p->program->Base.ShadowSamplers |= 1 << unit;
957      } else
958	 p->src_texture[unit] = get_zero(p);
959   }
960}
961
962static GLboolean load_texenv_source( struct texenv_fragment_program *p,
963				     GLuint src, GLuint unit )
964{
965   switch (src) {
966   case SRC_TEXTURE:
967      load_texture(p, unit);
968      break;
969
970   case SRC_TEXTURE0:
971   case SRC_TEXTURE1:
972   case SRC_TEXTURE2:
973   case SRC_TEXTURE3:
974   case SRC_TEXTURE4:
975   case SRC_TEXTURE5:
976   case SRC_TEXTURE6:
977   case SRC_TEXTURE7:
978      load_texture(p, src - SRC_TEXTURE0);
979      break;
980
981   default:
982      break;
983   }
984
985   return GL_TRUE;
986}
987
988
989/**
990 * Generate instructions for loading all texture source terms.
991 */
992static GLboolean
993load_texunit_sources( struct texenv_fragment_program *p, int unit )
994{
995   struct state_key *key = p->state;
996   GLuint i;
997
998   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
999      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit);
1000   }
1001
1002   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
1003      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
1004   }
1005
1006   return GL_TRUE;
1007}
1008
1009
1010/**
1011 * Generate a new fragment program which implements the context's
1012 * current texture env/combine mode.
1013 */
1014static void
1015create_new_program(GLcontext *ctx, struct state_key *key,
1016                   struct gl_fragment_program *program)
1017{
1018   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
1019   struct texenv_fragment_program p;
1020   GLuint unit;
1021   struct ureg cf, out;
1022
1023   _mesa_memset(&p, 0, sizeof(p));
1024   p.ctx = ctx;
1025   p.state = key;
1026   p.program = program;
1027
1028   /* During code generation, use locally-allocated instruction buffer,
1029    * then alloc dynamic storage below.
1030    */
1031   p.program->Base.Instructions = instBuffer;
1032   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
1033   p.program->Base.NumTexIndirections = 1;	/* correct? */
1034   p.program->Base.NumTexInstructions = 0;
1035   p.program->Base.NumAluInstructions = 0;
1036   p.program->Base.String = NULL;
1037   p.program->Base.NumInstructions =
1038   p.program->Base.NumTemporaries =
1039   p.program->Base.NumParameters =
1040   p.program->Base.NumAttributes = p.program->Base.NumAddressRegs = 0;
1041   p.program->Base.Parameters = _mesa_new_parameter_list();
1042
1043   p.program->Base.InputsRead = 0;
1044   p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLR;
1045
1046   for (unit = 0; unit < MAX_TEXTURE_UNITS; unit++)
1047      p.src_texture[unit] = undef;
1048
1049   p.src_previous = undef;
1050   p.half = undef;
1051   p.zero = undef;
1052   p.one = undef;
1053
1054   p.last_tex_stage = 0;
1055   release_temps(&p);
1056
1057   if (key->enabled_units) {
1058      /* First pass - to support texture_env_crossbar, first identify
1059       * all referenced texture sources and emit texld instructions
1060       * for each:
1061       */
1062      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits ; unit++)
1063	 if (key->unit[unit].enabled) {
1064	    load_texunit_sources( &p, unit );
1065	    p.last_tex_stage = unit;
1066	 }
1067
1068      /* Second pass - emit combine instructions to build final color:
1069       */
1070      for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++)
1071	 if (key->enabled_units & (1<<unit)) {
1072	    p.src_previous = emit_texenv( &p, unit );
1073	    release_temps(&p);	/* release all temps */
1074	 }
1075   }
1076
1077   cf = get_source( &p, SRC_PREVIOUS, 0 );
1078   out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLR );
1079
1080   if (key->separate_specular) {
1081      /* Emit specular add.
1082       */
1083      struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
1084      emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
1085      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
1086   }
1087   else if (_mesa_memcmp(&cf, &out, sizeof(cf)) != 0) {
1088      /* Will wind up in here if no texture enabled or a couple of
1089       * other scenarios (GL_REPLACE for instance).
1090       */
1091      emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
1092   }
1093
1094   /* Finish up:
1095    */
1096   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
1097
1098   if (key->fog_enabled) {
1099      /* Pull fog mode from GLcontext, the value in the state key is
1100       * a reduced value and not what is expected in FogOption
1101       */
1102      p.program->FogOption = ctx->Fog.Mode;
1103   } else
1104      p.program->FogOption = GL_NONE;
1105
1106   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
1107      program_error(&p, "Exceeded max nr indirect texture lookups");
1108
1109   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
1110      program_error(&p, "Exceeded max TEX instructions");
1111
1112   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
1113      program_error(&p, "Exceeded max ALU instructions");
1114
1115   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
1116
1117   /* Allocate final instruction array */
1118   program->Base.Instructions
1119      = _mesa_alloc_instructions(program->Base.NumInstructions);
1120   if (!program->Base.Instructions) {
1121      _mesa_error(ctx, GL_OUT_OF_MEMORY,
1122                  "generating tex env program");
1123      return;
1124   }
1125   _mesa_copy_instructions(program->Base.Instructions, instBuffer,
1126                           program->Base.NumInstructions);
1127
1128   /* Notify driver the fragment program has (actually) changed.
1129    */
1130   if (ctx->Driver.ProgramStringNotify) {
1131      ctx->Driver.ProgramStringNotify( ctx, GL_FRAGMENT_PROGRAM_ARB,
1132                                       &p.program->Base );
1133   }
1134
1135   if (DISASSEM) {
1136      _mesa_print_program(&p.program->Base);
1137      _mesa_printf("\n");
1138   }
1139}
1140
1141
1142/**
1143 * Return a fragment program which implements the current
1144 * fixed-function texture, fog and color-sum operations.
1145 */
1146struct gl_fragment_program *
1147_mesa_get_fixed_func_fragment_program(GLcontext *ctx)
1148{
1149   struct gl_fragment_program *prog;
1150   struct state_key key;
1151
1152   make_state_key(ctx, &key);
1153
1154   prog = (struct gl_fragment_program *)
1155      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
1156                                 &key, sizeof(key));
1157
1158   if (!prog) {
1159      prog = (struct gl_fragment_program *)
1160         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
1161
1162      create_new_program(ctx, &key, prog);
1163
1164      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
1165                                 &key, sizeof(key), &prog->Base);
1166   }
1167
1168   return prog;
1169}
1170
1171
1172
1173/**
1174 * If _MaintainTexEnvProgram is set we'll generate a fragment program that
1175 * implements the current texture env/combine mode.
1176 * This function generates that program and puts it into effect.
1177 */
1178void
1179_mesa_UpdateTexEnvProgram( GLcontext *ctx )
1180{
1181   const struct gl_fragment_program *prev = ctx->FragmentProgram._Current;
1182
1183   ASSERT(ctx->FragmentProgram._MaintainTexEnvProgram);
1184
1185   /* If a conventional fragment program/shader isn't in effect... */
1186   if (!ctx->FragmentProgram._Enabled &&
1187       (!ctx->Shader.CurrentProgram ||
1188        !ctx->Shader.CurrentProgram->FragmentProgram) )
1189   {
1190      struct gl_fragment_program *newProg;
1191
1192      newProg = _mesa_get_fixed_func_fragment_program(ctx);
1193
1194      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, newProg);
1195      _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, newProg);
1196   }
1197
1198   /* Tell the driver about the change.  Could define a new target for
1199    * this?
1200    */
1201   if (ctx->FragmentProgram._Current != prev && ctx->Driver.BindProgram) {
1202      ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB,
1203                         (struct gl_program *) ctx->FragmentProgram._Current);
1204   }
1205}
1206