ff_fragment_shader.cpp revision 0117da40cd7edd3d165bb28569c289b37eca12b9
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**************************************************************************
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All Rights Reserved.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2009 VMware, Inc.  All Rights Reserved.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * copy of this software and associated documentation files (the
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * "Software"), to deal in the Software without restriction, including
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the following conditions:
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The above copyright notice and this permission notice (including the
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of the Software.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) **************************************************************************/
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "glheader.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "imports.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "mtypes.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/program.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/prog_parameter.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/prog_cache.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/prog_instruction.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/prog_print.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/prog_statevars.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "program/programopt.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "texenvprogram.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note on texture units:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The number of texture units supported by fixed-function fragment
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * processing is MAX_TEXTURE_COORD_UNITS, not MAX_TEXTURE_IMAGE_UNITS.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * That's because there's a one-to-one correspondence between texture
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * coordinates and samplers in fixed-function processing.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Since fixed-function vertex processing is limited to MAX_TEXTURE_COORD_UNITS
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sets of texcoords, so is fixed-function fragment processing.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We can safely use ctx->Const.MaxTextureUnits for loop bounds.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct texenvprog_cache_item
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint hash;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   void *key;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct gl_fragment_program *data;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct texenvprog_cache_item *next;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)texenv_doing_secondary_color(struct gl_context *ctx)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (ctx->Light.Enabled &&
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR))
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_TRUE;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (ctx->Fog.ColorSumEnabled)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_TRUE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_FALSE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Up to nine instructions per tex unit, plus fog, specular color.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_INSTRUCTIONS ((MAX_TEXTURE_COORD_UNITS * 9) + 12)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DISASSEM (MESA_VERBOSE & VERBOSE_DISASSEM)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct mode_opt {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __GNUC__
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   __extension__ GLubyte Source:4;  /**< SRC_x */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   __extension__ GLubyte Operand:3; /**< OPR_x */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLubyte Source;  /**< SRC_x */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLubyte Operand; /**< OPR_x */
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct state_key {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint nr_enabled_units:8;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint enabled_units:8;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint separate_specular:1;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint fog_enabled:1;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint fog_mode:2;          /**< FOG_x */
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint inputs_available:12;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint num_draw_buffers:4;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* NOTE: This array of structs must be last! (see "keySize" below) */
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint enabled:1;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint source_index:3;   /**< TEXTURE_x_INDEX */
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint shadow:1;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint ScaleShiftRGB:2;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint ScaleShiftA:2;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint NumArgsRGB:3;  /**< up to MAX_COMBINER_TERMS */
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint ModeRGB:5;     /**< MODE_x */
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint NumArgsA:3;  /**< up to MAX_COMBINER_TERMS */
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint ModeA:5;     /**< MODE_x */
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint texture_cyl_wrap:1; /**< For gallium test/debug only */
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct mode_opt OptRGB[MAX_COMBINER_TERMS];
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct mode_opt OptA[MAX_COMBINER_TERMS];
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   } unit[MAX_TEXTURE_UNITS];
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FOG_LINEAR  0
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FOG_EXP     1
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FOG_EXP2    2
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define FOG_UNKNOWN 3
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint translate_fog_mode( GLenum mode )
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (mode) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_LINEAR: return FOG_LINEAR;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_EXP: return FOG_EXP;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_EXP2: return FOG_EXP2;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default: return FOG_UNKNOWN;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_SRC_COLOR           0
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_ONE_MINUS_SRC_COLOR 1
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_SRC_ALPHA           2
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_ONE_MINUS_SRC_ALPHA	3
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_ZERO                4
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_ONE                 5
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define OPR_UNKNOWN             7
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint translate_operand( GLenum operand )
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (operand) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_SRC_COLOR: return OPR_SRC_COLOR;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ONE_MINUS_SRC_COLOR: return OPR_ONE_MINUS_SRC_COLOR;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_SRC_ALPHA: return OPR_SRC_ALPHA;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ONE_MINUS_SRC_ALPHA: return OPR_ONE_MINUS_SRC_ALPHA;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ZERO: return OPR_ZERO;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ONE: return OPR_ONE;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OPR_UNKNOWN;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE  0
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE0 1
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE1 2
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE2 3
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE3 4
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE4 5
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE5 6
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE6 7
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_TEXTURE7 8
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_CONSTANT 9
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_PRIMARY_COLOR 10
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_PREVIOUS 11
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_ZERO     12
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SRC_UNKNOWN  15
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint translate_source( GLenum src )
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (src) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE: return SRC_TEXTURE;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE0:
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE1:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE2:
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE3:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE4:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE5:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE6:
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_TEXTURE7: return SRC_TEXTURE0 + (src - GL_TEXTURE0);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_CONSTANT: return SRC_CONSTANT;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_PRIMARY_COLOR: return SRC_PRIMARY_COLOR;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_PREVIOUS: return SRC_PREVIOUS;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ZERO:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SRC_ZERO;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return SRC_UNKNOWN;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_REPLACE                     0  /* r = a0 */
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_MODULATE                    1  /* r = a0 * a1 */
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_ADD                         2  /* r = a0 + a1 */
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_ADD_SIGNED                  3  /* r = a0 + a1 - 0.5 */
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_INTERPOLATE                 4  /* r = a0 * a2 + a1 * (1 - a2) */
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_SUBTRACT                    5  /* r = a0 - a1 */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_DOT3_RGB                    6  /* r = a0 . a1 */
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_DOT3_RGB_EXT                7  /* r = a0 . a1 */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_DOT3_RGBA                   8  /* r = a0 . a1 */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_DOT3_RGBA_EXT               9  /* r = a0 . a1 */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_MODULATE_ADD_ATI           10  /* r = a0 * a2 + a1 */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_MODULATE_SIGNED_ADD_ATI    11  /* r = a0 * a2 + a1 - 0.5 */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_MODULATE_SUBTRACT_ATI      12  /* r = a0 * a2 - a1 */
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_ADD_PRODUCTS               13  /* r = a0 * a1 + a2 * a3 */
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_ADD_PRODUCTS_SIGNED        14  /* r = a0 * a1 + a2 * a3 - 0.5 */
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_BUMP_ENVMAP_ATI            15  /* special */
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MODE_UNKNOWN                    16
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Translate GL combiner state into a MODE_x value
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint translate_mode( GLenum envMode, GLenum mode )
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (mode) {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_REPLACE: return MODE_REPLACE;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_MODULATE: return MODE_MODULATE;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ADD:
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (envMode == GL_COMBINE4_NV)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return MODE_ADD_PRODUCTS;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return MODE_ADD;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_ADD_SIGNED:
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (envMode == GL_COMBINE4_NV)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return MODE_ADD_PRODUCTS_SIGNED;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         return MODE_ADD_SIGNED;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_INTERPOLATE: return MODE_INTERPOLATE;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_SUBTRACT: return MODE_SUBTRACT;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_DOT3_RGB: return MODE_DOT3_RGB;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_DOT3_RGB_EXT: return MODE_DOT3_RGB_EXT;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_DOT3_RGBA: return MODE_DOT3_RGBA;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_DOT3_RGBA_EXT: return MODE_DOT3_RGBA_EXT;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_MODULATE_ADD_ATI: return MODE_MODULATE_ADD_ATI;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_MODULATE_SIGNED_ADD_ATI: return MODE_MODULATE_SIGNED_ADD_ATI;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_MODULATE_SUBTRACT_ATI: return MODE_MODULATE_SUBTRACT_ATI;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case GL_BUMP_ENVMAP_ATI: return MODE_BUMP_ENVMAP_ATI;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MODE_UNKNOWN;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Do we need to clamp the results of the given texture env/combine mode?
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If the inputs to the mode are in [0,1] we don't always have to clamp
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the results.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)need_saturate( GLuint mode )
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (mode) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_REPLACE:
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_INTERPOLATE:
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_SIGNED:
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_SUBTRACT:
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGB:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGB_EXT:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGBA:
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGBA_EXT:
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_ADD_ATI:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_SIGNED_ADD_ATI:
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_SUBTRACT_ATI:
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_PRODUCTS:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_PRODUCTS_SIGNED:
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_BUMP_ENVMAP_ATI:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_TRUE;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return GL_FALSE;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Translate TEXTURE_x_BIT to TEXTURE_x_INDEX.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint translate_tex_src_bit( GLbitfield bit )
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ASSERT(bit);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return _mesa_ffs(bit) - 1;
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VERT_BIT_TEX_ANY    (0xff << VERT_ATTRIB_TEX0)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VERT_RESULT_TEX_ANY (0xff << VERT_RESULT_TEX0)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Identify all possible varying inputs.  The fragment program will
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * never reference non-varying inputs, but will track them via state
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * constants instead.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This function figures out all the inputs that the fragment program
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * has access to.  The bitmask is later reduced to just those which
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * are actually referenced.
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLbitfield get_fp_input_mask( struct gl_context *ctx )
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* _NEW_PROGRAM */
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const GLboolean vertexShader =
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (ctx->Shader.CurrentVertexProgram &&
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ctx->Shader.CurrentVertexProgram->LinkStatus &&
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ctx->Shader.CurrentVertexProgram->VertexProgram);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const GLboolean vertexProgram = ctx->VertexProgram._Enabled;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLbitfield fp_inputs = 0x0;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (ctx->VertexProgram._Overriden) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Somebody's messing with the vertex program and we don't have
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * a clue what's happening.  Assume that it could be producing
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * all possible outputs.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fp_inputs = ~0;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (ctx->RenderMode == GL_FEEDBACK) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_RENDERMODE */
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fp_inputs = (FRAG_BIT_COL0 | FRAG_BIT_TEX0);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (!(vertexProgram || vertexShader) ||
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !ctx->VertexProgram._Current) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Fixed function vertex logic */
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_ARRAY */
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLbitfield varying_inputs = ctx->varying_vp_inputs;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* These get generated in the setup routine regardless of the
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * vertex program:
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_POINT */
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ctx->Point.PointSprite)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         varying_inputs |= FRAG_BITS_TEX_ANY;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* First look at what values may be computed by the generated
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * vertex program:
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_LIGHT */
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ctx->Light.Enabled) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         fp_inputs |= FRAG_BIT_COL0;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         if (texenv_doing_secondary_color(ctx))
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            fp_inputs |= FRAG_BIT_COL1;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_TEXTURE */
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fp_inputs |= (ctx->Texture._TexGenEnabled |
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ctx->Texture._TexMatEnabled) << FRAG_ATTRIB_TEX0;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Then look at what might be varying as a result of enabled
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * arrays, etc:
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (varying_inputs & VERT_BIT_COLOR0)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         fp_inputs |= FRAG_BIT_COL0;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (varying_inputs & VERT_BIT_COLOR1)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         fp_inputs |= FRAG_BIT_COL1;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fp_inputs |= (((varying_inputs & VERT_BIT_TEX_ANY) >> VERT_ATTRIB_TEX0)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << FRAG_ATTRIB_TEX0);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* calculate from vp->outputs */
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct gl_vertex_program *vprog;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLbitfield64 vp_outputs;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Choose GLSL vertex shader over ARB vertex program.  Need this
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * since vertex shader state validation comes after fragment state
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * validation (see additional comments in state.c).
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (vertexShader)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         vprog = ctx->Shader.CurrentVertexProgram->VertexProgram;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         vprog = ctx->VertexProgram.Current;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vp_outputs = vprog->Base.OutputsWritten;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* These get generated in the setup routine regardless of the
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * vertex program:
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* _NEW_POINT */
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (ctx->Point.PointSprite)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         vp_outputs |= FRAG_BITS_TEX_ANY;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (vp_outputs & (1 << VERT_RESULT_COL0))
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         fp_inputs |= FRAG_BIT_COL0;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (vp_outputs & (1 << VERT_RESULT_COL1))
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         fp_inputs |= FRAG_BIT_COL1;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fp_inputs |= (((vp_outputs & VERT_RESULT_TEX_ANY) >> VERT_RESULT_TEX0)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    << FRAG_ATTRIB_TEX0);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return fp_inputs;
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Examine current texture environment state and generate a unique
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * key to identify it.
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint make_state_key( struct gl_context *ctx,  struct state_key *key )
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint i, j;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLbitfield inputs_referenced = FRAG_BIT_COL0;
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const GLbitfield inputs_available = get_fp_input_mask( ctx );
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint keySize;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   memset(key, 0, sizeof(*key));
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* _NEW_TEXTURE */
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct gl_texture_object *texObj = texUnit->_Current;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct gl_tex_env_combine_state *comb = texUnit->_CurrentCombine;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLenum format;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!texUnit->_ReallyEnabled || !texUnit->Enabled)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         continue;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      format = texObj->Image[0][texObj->BaseLevel]->_BaseFormat;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].enabled = 1;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->enabled_units |= (1<<i);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->nr_enabled_units = i + 1;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inputs_referenced |= FRAG_BIT_TEX(i);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].source_index =
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         translate_tex_src_bit(texUnit->_ReallyEnabled);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].shadow = ((texObj->CompareMode == GL_COMPARE_R_TO_TEXTURE) &&
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             ((format == GL_DEPTH_COMPONENT) ||
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              (format == GL_DEPTH_STENCIL_EXT)));
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].NumArgsRGB = comb->_NumArgsRGB;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].NumArgsA = comb->_NumArgsA;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].ModeRGB =
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 translate_mode(texUnit->EnvMode, comb->ModeRGB);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].ModeA =
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 translate_mode(texUnit->EnvMode, comb->ModeA);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].ScaleShiftRGB = comb->ScaleShiftRGB;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->unit[i].ScaleShiftA = comb->ScaleShiftA;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (j = 0; j < MAX_COMBINER_TERMS; j++) {
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[j].Operand = translate_operand(comb->OperandRGB[j]);
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptA[j].Operand = translate_operand(comb->OperandA[j]);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[j].Source = translate_source(comb->SourceRGB[j]);
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptA[j].Source = translate_source(comb->SourceA[j]);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (key->unit[i].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* requires some special translation */
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].NumArgsRGB = 2;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].ScaleShiftRGB = 0;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[0].Operand = OPR_SRC_COLOR;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[0].Source = SRC_TEXTURE;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[1].Operand = OPR_SRC_COLOR;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].OptRGB[1].Source = texUnit->BumpTarget - GL_TEXTURE0 + SRC_TEXTURE0;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* this is a back-door for enabling cylindrical texture wrap mode */
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (texObj->Priority == 0.125)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         key->unit[i].texture_cyl_wrap = 1;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* _NEW_LIGHT | _NEW_FOG */
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (texenv_doing_secondary_color(ctx)) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->separate_specular = 1;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inputs_referenced |= FRAG_BIT_COL1;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* _NEW_FOG */
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (ctx->Fog.Enabled) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->fog_enabled = 1;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key->fog_mode = translate_fog_mode(ctx->Fog.Mode);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      inputs_referenced |= FRAG_BIT_FOGC; /* maybe */
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* _NEW_BUFFERS */
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   key->num_draw_buffers = ctx->DrawBuffer->_NumColorDrawBuffers;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   key->inputs_available = (inputs_available & inputs_referenced);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* compute size of state key, ignoring unused texture units */
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   keySize = sizeof(*key) - sizeof(key->unit)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      + key->nr_enabled_units * sizeof(key->unit[0]);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return keySize;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use uregs to represent registers internally, translate to Mesa's
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * expected formats on emit.
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * NOTE: These are passed by value extensively in this file rather
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * than as usual by pointer reference.  If this disturbs you, try
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * remembering they are just 32bits in size.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GCC is smart enough to deal with these dword-sized structures in
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * much the same way as if I had defined them as dwords and was using
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * macros to access and set the fields.  This is much nicer and easier
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * to evolve.
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ureg {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint file:4;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint idx:8;
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint negatebase:1;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint swz:12;
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint pad:7;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const struct ureg undef = {
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   PROGRAM_UNDEFINED,
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ~0,
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   0,
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   0,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   0
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** State used to build the fragment program:
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct texenv_fragment_program {
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct gl_fragment_program *program;
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct state_key *state;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLbitfield alu_temps;	/**< Track texture indirections, see spec. */
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLbitfield temps_output;	/**< Track texture indirections, see spec. */
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLbitfield temp_in_use;	/**< Tracks temporary regs which are in use. */
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLboolean error;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg src_texture[MAX_TEXTURE_COORD_UNITS];
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Reg containing each texture unit's sampled texture color,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * else undef.
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg texcoord_tex[MAX_TEXTURE_COORD_UNITS];
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Reg containing texcoord for a texture unit,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * needed for bump mapping, else undef.
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg src_previous;	/**< Reg containing color from previous
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * stage.  May need to be decl'd.
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 */
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint last_tex_stage;	/**< Number of last enabled texture unit */
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg half;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg one;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg zero;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg make_ureg(GLuint file, GLuint idx)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg reg;
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.file = file;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.idx = idx;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.negatebase = 0;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.swz = SWIZZLE_NOOP;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.pad = 0;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reg;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg swizzle( struct ureg reg, int x, int y, int z, int w )
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.swz = MAKE_SWIZZLE4(GET_SWZ(reg.swz, x),
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   GET_SWZ(reg.swz, y),
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   GET_SWZ(reg.swz, z),
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			   GET_SWZ(reg.swz, w));
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reg;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg swizzle1( struct ureg reg, int x )
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return swizzle(reg, x, x, x, x);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg negate( struct ureg reg )
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg.negatebase ^= 1;
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reg;
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean is_undef( struct ureg reg )
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reg.file == PROGRAM_UNDEFINED;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_temp( struct texenv_fragment_program *p )
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLint bit;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* First try and reuse temps which have been used already:
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   bit = _mesa_ffs( ~p->temp_in_use & p->alu_temps );
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Then any unused temporary:
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!bit)
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bit = _mesa_ffs( ~p->temp_in_use );
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!bit) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit(1);
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((GLuint) bit > p->program->Base.NumTemporaries)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->program->Base.NumTemporaries = bit;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->temp_in_use |= 1<<(bit-1);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_tex_temp( struct texenv_fragment_program *p )
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int bit;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* First try to find available temp not previously used (to avoid
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * starting a new texture indirection).  According to the spec, the
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * ~p->temps_output isn't necessary, but will keep it there for
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * now:
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   bit = _mesa_ffs( ~p->temp_in_use & ~p->alu_temps & ~p->temps_output );
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Then any unused temporary:
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!bit)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bit = _mesa_ffs( ~p->temp_in_use );
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!bit) {
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_problem(NULL, "%s: out of temporaries\n", __FILE__);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      exit(1);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((GLuint) bit > p->program->Base.NumTemporaries)
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->program->Base.NumTemporaries = bit;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->temp_in_use |= 1<<(bit-1);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return make_ureg(PROGRAM_TEMPORARY, (bit-1));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** Mark a temp reg as being no longer allocatable. */
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void reserve_temp( struct texenv_fragment_program *p, struct ureg r )
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (r.file == PROGRAM_TEMPORARY)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->temps_output |= (1 << r.idx);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void release_temps(struct gl_context *ctx, struct texenv_fragment_program *p )
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint max_temp = ctx->Const.FragmentProgram.MaxTemps;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* KW: To support tex_env_crossbar, don't release the registers in
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * temps_output.
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (max_temp >= sizeof(int) * 8)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->temp_in_use = p->temps_output;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->temp_in_use = ~((1<<max_temp)-1) | p->temps_output;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg register_param5( struct texenv_fragment_program *p,
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    GLint s0,
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    GLint s1,
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    GLint s2,
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    GLint s3,
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				    GLint s4)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   gl_state_index tokens[STATE_LENGTH];
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint idx;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   tokens[0] = s0;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   tokens[1] = s1;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   tokens[2] = s2;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   tokens[3] = s3;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   tokens[4] = s4;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   idx = _mesa_add_state_reference( p->program->Base.Parameters, tokens );
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return make_ureg(PROGRAM_STATE_VAR, idx);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_param1(p,s0)          register_param5(p,s0,0,0,0,0)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_param2(p,s0,s1)       register_param5(p,s0,s1,0,0,0)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_param3(p,s0,s1,s2)    register_param5(p,s0,s1,s2,0,0)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_param4(p,s0,s1,s2,s3) register_param5(p,s0,s1,s2,s3,0)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLuint frag_to_vert_attrib( GLuint attrib )
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (attrib) {
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case FRAG_ATTRIB_COL0: return VERT_ATTRIB_COLOR0;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case FRAG_ATTRIB_COL1: return VERT_ATTRIB_COLOR1;
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(attrib >= FRAG_ATTRIB_TEX0);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(attrib <= FRAG_ATTRIB_TEX7);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return attrib - FRAG_ATTRIB_TEX0 + VERT_ATTRIB_TEX0;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg register_input( struct texenv_fragment_program *p, GLuint input )
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (p->state->inputs_available & (1<<input)) {
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->program->Base.InputsRead |= (1 << input);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return make_ureg(PROGRAM_INPUT, input);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLuint idx = frag_to_vert_attrib( input );
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return register_param3( p, STATE_INTERNAL, STATE_CURRENT_ATTRIB, idx );
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void emit_arg( struct prog_src_register *reg,
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      struct ureg ureg )
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg->File = ureg.file;
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg->Index = ureg.idx;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg->Swizzle = ureg.swz;
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg->Negate = ureg.negatebase ? NEGATE_XYZW : NEGATE_NONE;
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reg->Abs = GL_FALSE;
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void emit_dst( struct prog_dst_register *dst,
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		      struct ureg ureg, GLuint mask )
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->File = ureg.file;
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->Index = ureg.idx;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->WriteMask = mask;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->CondMask = COND_TR;  /* always pass cond test */
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   dst->CondSwizzle = SWIZZLE_NOOP;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct prog_instruction *
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)emit_op(struct texenv_fragment_program *p,
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	enum prog_opcode op,
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ureg dest,
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	GLuint mask,
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	GLboolean saturate,
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ureg src0,
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ureg src1,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	struct ureg src2 )
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const GLuint nr = p->program->Base.NumInstructions++;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct prog_instruction *inst = &p->program->Base.Instructions[nr];
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   assert(nr < MAX_INSTRUCTIONS);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _mesa_init_instructions(inst, 1);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   inst->Opcode = op;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arg( &inst->SrcReg[0], src0 );
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arg( &inst->SrcReg[1], src1 );
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arg( &inst->SrcReg[2], src2 );
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   inst->SaturateMode = saturate ? SATURATE_ZERO_ONE : SATURATE_OFF;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_dst( &inst->DstReg, dest, mask );
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Accounting for indirection tracking:
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (dest.file == PROGRAM_TEMPORARY)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->temps_output |= 1 << dest.idx;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return inst;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg emit_arith( struct texenv_fragment_program *p,
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       enum prog_opcode op,
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg dest,
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLuint mask,
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLboolean saturate,
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg src0,
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg src1,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg src2 )
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_op(p, op, dest, mask, saturate, src0, src1, src2);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Accounting for indirection tracking:
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (src0.file == PROGRAM_TEMPORARY)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->alu_temps |= 1 << src0.idx;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!is_undef(src1) && src1.file == PROGRAM_TEMPORARY)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->alu_temps |= 1 << src1.idx;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!is_undef(src2) && src2.file == PROGRAM_TEMPORARY)
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->alu_temps |= 1 << src2.idx;
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (dest.file == PROGRAM_TEMPORARY)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->alu_temps |= 1 << dest.idx;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->program->Base.NumAluInstructions++;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return dest;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg emit_texld( struct texenv_fragment_program *p,
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       enum prog_opcode op,
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg dest,
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLuint destmask,
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLuint tex_unit,
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLuint tex_idx,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               GLuint tex_shadow,
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       struct ureg coord )
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct prog_instruction *inst = emit_op( p, op,
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  dest, destmask,
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  GL_FALSE,	/* don't saturate? */
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  coord, 	/* arg 0? */
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  undef,
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  undef);
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   inst->TexSrcTarget = tex_idx;
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   inst->TexSrcUnit = tex_unit;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   inst->TexShadow = tex_shadow;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->program->Base.NumTexInstructions++;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Accounting for indirection tracking:
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   reserve_temp(p, dest);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Is this a texture indirection?
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if ((coord.file == PROGRAM_TEMPORARY &&
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(p->temps_output & (1<<coord.idx))) ||
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       (dest.file == PROGRAM_TEMPORARY &&
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	(p->alu_temps & (1<<dest.idx)))) {
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->program->Base.NumTexIndirections++;
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->temps_output = 1<<coord.idx;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->alu_temps = 0;
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);		/* KW: texture env crossbar */
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return dest;
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg register_const4f( struct texenv_fragment_program *p,
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     GLfloat s0,
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     GLfloat s1,
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     GLfloat s2,
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     GLfloat s3)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLfloat values[4];
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint idx, swizzle;
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg r;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   values[0] = s0;
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   values[1] = s1;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   values[2] = s2;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   values[3] = s3;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   idx = _mesa_add_unnamed_constant( p->program->Base.Parameters, values, 4,
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &swizzle );
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   r = make_ureg(PROGRAM_CONSTANT, idx);
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   r.swz = swizzle;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return r;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_scalar_const(p, s0)    register_const4f(p, s0, s0, s0, s0)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_const1f(p, s0)         register_const4f(p, s0, 0, 0, 1)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_const2f(p, s0, s1)     register_const4f(p, s0, s1, 0, 1)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define register_const3f(p, s0, s1, s2) register_const4f(p, s0, s1, s2, 1)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_one( struct texenv_fragment_program *p )
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (is_undef(p->one))
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->one = register_scalar_const(p, 1.0);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return p->one;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_half( struct texenv_fragment_program *p )
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (is_undef(p->half))
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->half = register_scalar_const(p, 0.5);
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return p->half;
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_zero( struct texenv_fragment_program *p )
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (is_undef(p->zero))
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p->zero = register_scalar_const(p, 0.0);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return p->zero;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void program_error( struct texenv_fragment_program *p, const char *msg )
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _mesa_problem(NULL, "%s", msg);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->error = 1;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg get_source( struct texenv_fragment_program *p,
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			       GLuint src, GLuint unit )
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (src) {
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE:
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(!is_undef(p->src_texture[unit]));
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return p->src_texture[unit];
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE0:
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE1:
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE2:
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE3:
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE4:
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE5:
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE6:
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE7:
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(!is_undef(p->src_texture[src - SRC_TEXTURE0]));
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return p->src_texture[src - SRC_TEXTURE0];
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_CONSTANT:
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return register_param2(p, STATE_TEXENV_COLOR, unit);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_PRIMARY_COLOR:
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return register_input(p, FRAG_ATTRIB_COL0);
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_ZERO:
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return get_zero(p);
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_PREVIOUS:
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (is_undef(p->src_previous))
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return register_input(p, FRAG_ATTRIB_COL0);
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return p->src_previous;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return undef;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg emit_combine_source( struct texenv_fragment_program *p,
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					GLuint mask,
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					GLuint unit,
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					GLuint source,
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					GLuint operand )
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg arg, src, one;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   src = get_source(p, source, unit);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (operand) {
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_ONE_MINUS_SRC_COLOR:
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Get unused tmp,
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * Emit tmp = 1.0 - arg.xyzw
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      arg = get_temp( p );
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      one = get_one( p );
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_SUB, arg, mask, 0, one, src, undef);
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_SRC_ALPHA:
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mask == WRITEMASK_W)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return src;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return swizzle1( src, SWIZZLE_W );
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_ONE_MINUS_SRC_ALPHA:
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Get unused tmp,
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * Emit tmp = 1.0 - arg.wwww
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      arg = get_temp(p);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      one = get_one(p);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith(p, OPCODE_SUB, arg, mask, 0,
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			one, swizzle1(src, SWIZZLE_W), undef);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_ZERO:
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return get_zero(p);
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_ONE:
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return get_one(p);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case OPR_SRC_COLOR:
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return src;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return src;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Check if the RGB and Alpha sources and operands match for the given
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * texture unit's combinder state.  When the RGB and A sources and
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * operands match, we can emit fewer instructions.
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean args_match( const struct state_key *key, GLuint unit )
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint i, numArgs = key->unit[unit].NumArgsRGB;
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < numArgs; i++) {
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (key->unit[unit].OptA[i].Source != key->unit[unit].OptRGB[i].Source)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return GL_FALSE;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (key->unit[unit].OptA[i].Operand) {
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case OPR_SRC_ALPHA:
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 switch (key->unit[unit].OptRGB[i].Operand) {
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 case OPR_SRC_COLOR:
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 case OPR_SRC_ALPHA:
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    break;
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 default:
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return GL_FALSE;
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case OPR_ONE_MINUS_SRC_ALPHA:
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 switch (key->unit[unit].OptRGB[i].Operand) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 case OPR_ONE_MINUS_SRC_COLOR:
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 case OPR_ONE_MINUS_SRC_ALPHA:
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    break;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 default:
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    return GL_FALSE;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 break;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return GL_FALSE;	/* impossible */
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg emit_combine( struct texenv_fragment_program *p,
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 struct ureg dest,
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 GLuint mask,
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 GLboolean saturate,
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 GLuint unit,
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 GLuint nr,
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 GLuint mode,
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 const struct mode_opt *opt)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg src[MAX_COMBINER_TERMS];
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg tmp, half;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint i;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   assert(nr <= MAX_COMBINER_TERMS);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < nr; i++)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      src[i] = emit_combine_source( p, mask, unit, opt[i].Source, opt[i].Operand );
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (mode) {
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_REPLACE:
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (mask == WRITEMASK_XYZW && !saturate)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return src[0];
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 return emit_arith( p, OPCODE_MOV, dest, mask, saturate, src[0], undef, undef );
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE:
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_MUL, dest, mask, saturate,
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 src[0], src[1], undef );
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD:
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_ADD, dest, mask, saturate,
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 src[0], src[1], undef );
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_SIGNED:
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* tmp = arg0 + arg1
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * result = tmp - .5
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      half = get_half(p);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tmp = get_temp( p );
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_ADD, tmp, mask, 0, src[0], src[1], undef );
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp, half, undef );
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_INTERPOLATE:
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * (Arg2) + Arg1 * (1-Arg2) -- note arguments are reordered:
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_LRP, dest, mask, saturate, src[2], src[0], src[1] );
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_SUBTRACT:
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_SUB, dest, mask, saturate, src[0], src[1], undef );
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGBA:
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGBA_EXT:
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGB_EXT:
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGB: {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg tmp0 = get_temp( p );
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg tmp1 = get_temp( p );
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg neg1 = register_scalar_const(p, -1);
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg two  = register_scalar_const(p, 2);
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* tmp0 = 2*src0 - 1
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * tmp1 = 2*src1 - 1
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * dst = tmp0 dot3 tmp1
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_MAD, tmp0, WRITEMASK_XYZW, 0,
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		  two, src[0], neg1);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (memcmp(&src[0], &src[1], sizeof(struct ureg)) == 0)
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 tmp1 = tmp0;
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 emit_arith( p, OPCODE_MAD, tmp1, WRITEMASK_XYZW, 0,
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		     two, src[1], neg1);
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_DP3, dest, mask, saturate, tmp0, tmp1, undef);
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_ADD_ATI:
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * Arg2 + Arg1 */
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_MAD, dest, mask, saturate,
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 src[0], src[2], src[1] );
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_SIGNED_ADD_ATI: {
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * Arg2 + Arg1 - 0.5 */
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg tmp0 = get_temp(p);
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      half = get_half(p);
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[0], src[2], src[1] );
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_MODULATE_SUBTRACT_ATI:
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * Arg2 - Arg1 */
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      emit_arith( p, OPCODE_MAD, dest, mask, 0, src[0], src[2], negate(src[1]) );
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_PRODUCTS:
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * Arg1 + Arg2 * Arg3 */
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         struct ureg tmp0 = get_temp(p);
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         emit_arith( p, OPCODE_MAD, dest, mask, saturate, src[2], src[3], tmp0 );
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_ADD_PRODUCTS_SIGNED:
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Arg0 * Arg1 + Arg2 * Arg3 - 0.5 */
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      {
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         struct ureg tmp0 = get_temp(p);
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         half = get_half(p);
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         emit_arith( p, OPCODE_MUL, tmp0, mask, 0, src[0], src[1], undef );
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         emit_arith( p, OPCODE_MAD, tmp0, mask, 0, src[2], src[3], tmp0 );
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         emit_arith( p, OPCODE_SUB, dest, mask, saturate, tmp0, half, undef );
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return dest;
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_BUMP_ENVMAP_ATI:
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* special - not handled here */
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return src[0];
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      assert(0);
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return src[0];
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate instructions for one texture unit's env/combiner mode.
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct ureg
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)emit_texenv(struct texenv_fragment_program *p, GLuint unit)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const struct state_key *key = p->state;
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLboolean rgb_saturate, alpha_saturate;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint rgb_shift, alpha_shift;
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg out, dest;
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!key->unit[unit].enabled) {
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return get_source(p, SRC_PREVIOUS, 0);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* this isn't really a env stage delivering a color and handled elsewhere */
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return get_source(p, SRC_PREVIOUS, 0);
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (key->unit[unit].ModeRGB) {
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGB_EXT:
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_shift = key->unit[unit].ScaleShiftA;
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_shift = 0;
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case MODE_DOT3_RGBA_EXT:
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_shift = 0;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_shift = 0;
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_shift = key->unit[unit].ScaleShiftRGB;
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_shift = key->unit[unit].ScaleShiftA;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* If we'll do rgb/alpha shifting don't saturate in emit_combine().
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * We don't want to clamp twice.
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (rgb_shift)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_saturate = GL_FALSE;  /* saturate after rgb shift */
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (need_saturate(key->unit[unit].ModeRGB))
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_saturate = GL_TRUE;
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_saturate = GL_FALSE;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (alpha_shift)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_saturate = GL_FALSE;  /* saturate after alpha shift */
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (need_saturate(key->unit[unit].ModeA))
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_saturate = GL_TRUE;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alpha_saturate = GL_FALSE;
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* If this is the very last calculation (and various other conditions
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * are met), emit directly to the color output register.  Otherwise,
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * emit to a temporary register.
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->separate_specular ||
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       unit != p->last_tex_stage ||
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       alpha_shift ||
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       key->num_draw_buffers != 1 ||
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       rgb_shift)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dest = get_temp( p );
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dest = make_ureg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR);
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Emit the RGB and A combine ops
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->unit[unit].ModeRGB == key->unit[unit].ModeA &&
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       args_match(key, unit)) {
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  unit,
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].NumArgsRGB,
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].ModeRGB,
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].OptRGB);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else if (key->unit[unit].ModeRGB == MODE_DOT3_RGBA_EXT ||
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    key->unit[unit].ModeRGB == MODE_DOT3_RGBA) {
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = emit_combine( p, dest, WRITEMASK_XYZW, rgb_saturate,
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  unit,
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].NumArgsRGB,
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].ModeRGB,
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].OptRGB);
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Need to do something to stop from re-emitting identical
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * argument calculations here:
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = emit_combine( p, dest, WRITEMASK_XYZ, rgb_saturate,
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  unit,
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].NumArgsRGB,
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].ModeRGB,
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].OptRGB);
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      out = emit_combine( p, dest, WRITEMASK_W, alpha_saturate,
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  unit,
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].NumArgsA,
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].ModeA,
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			  key->unit[unit].OptA);
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Deal with the final shift:
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (alpha_shift || rgb_shift) {
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg shift;
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLboolean saturate = GL_TRUE;  /* always saturate at this point */
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rgb_shift == alpha_shift) {
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 shift = register_scalar_const(p, (GLfloat)(1<<rgb_shift));
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 shift = register_const4f(p,
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  (GLfloat)(1<<rgb_shift),
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  (GLfloat)(1<<rgb_shift),
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  (GLfloat)(1<<rgb_shift),
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				  (GLfloat)(1<<alpha_shift));
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return emit_arith( p, OPCODE_MUL, dest, WRITEMASK_XYZW,
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 saturate, out, shift, undef );
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return out;
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate instruction for getting a texture source term.
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void load_texture( struct texenv_fragment_program *p, GLuint unit )
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (is_undef(p->src_texture[unit])) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GLuint texTarget = p->state->unit[unit].source_index;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg texcoord;
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      struct ureg tmp = get_tex_temp( p );
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (is_undef(p->texcoord_tex[unit])) {
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         texcoord = register_input(p, FRAG_ATTRIB_TEX0+unit);
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* might want to reuse this reg for tex output actually */
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         texcoord = p->texcoord_tex[unit];
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* TODO: Use D0_MASK_XY where possible.
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (p->state->unit[unit].enabled) {
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         GLboolean shadow = GL_FALSE;
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (p->state->unit[unit].shadow) {
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    p->program->Base.ShadowSamplers |= 1 << unit;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            shadow = GL_TRUE;
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         }
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 p->src_texture[unit] = emit_texld( p, OPCODE_TXP,
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    tmp, WRITEMASK_XYZW,
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					    unit, texTarget, shadow,
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            texcoord );
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         p->program->Base.SamplersUsed |= (1 << unit);
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* This identity mapping should already be in place
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          * (see _mesa_init_program_struct()) but let's be safe.
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          */
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         p->program->Base.SamplerUnits[unit] = unit;
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 p->src_texture[unit] = get_zero(p);
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (p->state->unit[unit].texture_cyl_wrap) {
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         /* set flag which is checked by Mesa->Gallium program translation */
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         p->program->Base.InputFlags[0] |= PROG_PARAM_BIT_CYL_WRAP;
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean load_texenv_source( struct texenv_fragment_program *p,
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				     GLuint src, GLuint unit )
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   switch (src) {
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE:
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_texture(p, unit);
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE0:
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE1:
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE2:
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE3:
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE4:
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE5:
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE6:
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   case SRC_TEXTURE7:
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_texture(p, src - SRC_TEXTURE0);
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   default:
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* not a texture src - do nothing */
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate instructions for loading all texture source terms.
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_texunit_sources( struct texenv_fragment_program *p, GLuint unit )
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const struct state_key *key = p->state;
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint i;
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < key->unit[unit].NumArgsRGB; i++) {
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_texenv_source( p, key->unit[unit].OptRGB[i].Source, unit );
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < key->unit[unit].NumArgsA; i++) {
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_texenv_source( p, key->unit[unit].OptA[i].Source, unit );
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate instructions for loading bump map textures.
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLboolean
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)load_texunit_bumpmap( struct texenv_fragment_program *p, GLuint unit )
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   const struct state_key *key = p->state;
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint bumpedUnitNr = key->unit[unit].OptRGB[1].Source - SRC_TEXTURE0;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg texcDst, bumpMapRes;
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg constdudvcolor = register_const4f(p, 0.0, 0.0, 0.0, 1.0);
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg texcSrc = register_input(p, FRAG_ATTRIB_TEX0 + bumpedUnitNr);
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg rotMat0 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_0, unit );
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg rotMat1 = register_param3( p, STATE_INTERNAL, STATE_ROT_MATRIX_1, unit );
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   load_texenv_source( p, unit + SRC_TEXTURE0, unit );
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   bumpMapRes = get_source(p, key->unit[unit].OptRGB[0].Source, unit);
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   texcDst = get_tex_temp( p );
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p->texcoord_tex[bumpedUnitNr] = texcDst;
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Apply rot matrix and add coords to be available in next phase.
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * dest = (Arg0.xxxx * rotMat0 + Arg1) + (Arg0.yyyy * rotMat1)
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * note only 2 coords are affected the rest are left unchanged (mul by 0)
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               swizzle1(bumpMapRes, SWIZZLE_X), rotMat0, texcSrc );
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arith( p, OPCODE_MAD, texcDst, WRITEMASK_XYZW, 0,
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               swizzle1(bumpMapRes, SWIZZLE_Y), rotMat1, texcDst );
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Move 0,0,0,1 into bumpmap src if someone (crossbar) is foolish
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * enough to access this later, should optimize away.
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arith( p, OPCODE_MOV, bumpMapRes, WRITEMASK_XYZW, 0,
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               constdudvcolor, undef, undef );
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return GL_TRUE;
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Generate a new fragment program which implements the context's
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * current texture env/combine mode.
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)create_new_program(struct gl_context *ctx, struct state_key *key,
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   struct gl_fragment_program *program)
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct prog_instruction instBuffer[MAX_INSTRUCTIONS];
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct texenv_fragment_program p;
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint unit;
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct ureg cf, out;
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   int i;
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   memset(&p, 0, sizeof(p));
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.state = key;
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program = program;
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* During code generation, use locally-allocated instruction buffer,
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    * then alloc dynamic storage below.
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.Instructions = instBuffer;
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.Target = GL_FRAGMENT_PROGRAM_ARB;
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.String = NULL;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumTexIndirections = 1; /* is this right? */
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumTexInstructions = 0;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumAluInstructions = 0;
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumInstructions = 0;
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumTemporaries = 0;
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumParameters = 0;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumAttributes = 0;
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.NumAddressRegs = 0;
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.Parameters = _mesa_new_parameter_list();
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.InputsRead = 0x0;
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->num_draw_buffers == 1)
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.program->Base.OutputsWritten = 1 << FRAG_RESULT_COLOR;
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (i = 0; i < key->num_draw_buffers; i++)
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 p.program->Base.OutputsWritten |= (1 << (FRAG_RESULT_DATA0 + i));
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.src_texture[unit] = undef;
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.texcoord_tex[unit] = undef;
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.src_previous = undef;
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.half = undef;
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.zero = undef;
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.one = undef;
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.last_tex_stage = 0;
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   release_temps(ctx, &p);
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->enabled_units) {
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLboolean needbumpstage = GL_FALSE;
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Zeroth pass - bump map textures first */
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unit = 0; unit < key->nr_enabled_units; unit++)
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (key->unit[unit].enabled &&
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             key->unit[unit].ModeRGB == MODE_BUMP_ENVMAP_ATI) {
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    needbumpstage = GL_TRUE;
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    load_texunit_bumpmap( &p, unit );
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (needbumpstage)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 p.program->Base.NumTexIndirections++;
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* First pass - to support texture_env_crossbar, first identify
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * all referenced texture sources and emit texld instructions
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * for each:
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unit = 0; unit < key->nr_enabled_units; unit++)
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (key->unit[unit].enabled) {
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    load_texunit_sources( &p, unit );
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    p.last_tex_stage = unit;
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Second pass - emit combine instructions to build final color:
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unit = 0; unit < key->nr_enabled_units; unit++)
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 if (key->unit[unit].enabled) {
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    p.src_previous = emit_texenv( &p, unit );
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            reserve_temp(&p, p.src_previous); /* don't re-use this temp reg */
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	    release_temps(ctx, &p);	/* release all temps */
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 }
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   cf = get_source( &p, SRC_PREVIOUS, 0 );
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   for (i = 0; i < key->num_draw_buffers; i++) {
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (key->num_draw_buffers == 1)
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_COLOR );
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else {
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 out = make_ureg( PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i );
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (key->separate_specular) {
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 /* Emit specular add.
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  */
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 struct ureg s = register_input(&p, FRAG_ATTRIB_COL1);
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 emit_arith( &p, OPCODE_ADD, out, WRITEMASK_XYZ, 0, cf, s, undef );
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_W, 0, cf, undef, undef );
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (memcmp(&cf, &out, sizeof(cf)) != 0) {
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 /* Will wind up in here if no texture enabled or a couple of
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  * other scenarios (GL_REPLACE for instance).
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  */
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	 emit_arith( &p, OPCODE_MOV, out, WRITEMASK_XYZW, 0, cf, undef, undef );
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Finish up:
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   emit_arith( &p, OPCODE_END, undef, WRITEMASK_XYZW, 0, undef, undef, undef);
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (key->fog_enabled) {
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Pull fog mode from struct gl_context, the value in the state key is
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * a reduced value and not what is expected in FogOption
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.program->FogOption = ctx->Fog.Mode;
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.program->Base.InputsRead |= FRAG_BIT_FOGC;
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   else {
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.program->FogOption = GL_NONE;
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (p.program->Base.NumTexIndirections > ctx->Const.FragmentProgram.MaxTexIndirections)
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      program_error(&p, "Exceeded max nr indirect texture lookups");
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (p.program->Base.NumTexInstructions > ctx->Const.FragmentProgram.MaxTexInstructions)
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      program_error(&p, "Exceeded max TEX instructions");
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (p.program->Base.NumAluInstructions > ctx->Const.FragmentProgram.MaxAluInstructions)
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      program_error(&p, "Exceeded max ALU instructions");
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   ASSERT(p.program->Base.NumInstructions <= MAX_INSTRUCTIONS);
15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Allocate final instruction array */
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   p.program->Base.Instructions
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      = _mesa_alloc_instructions(p.program->Base.NumInstructions);
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!p.program->Base.Instructions) {
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_error(ctx, GL_OUT_OF_MEMORY,
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  "generating tex env program");
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   _mesa_copy_instructions(p.program->Base.Instructions, instBuffer,
15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           p.program->Base.NumInstructions);
15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (p.program->FogOption) {
15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_append_fog_code(ctx, p.program);
15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p.program->FogOption = GL_NONE;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   /* Notify driver the fragment program has (actually) changed.
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (ctx->Driver.ProgramStringNotify) {
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GLboolean ok = ctx->Driver.ProgramStringNotify(ctx,
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     GL_FRAGMENT_PROGRAM_ARB,
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     &p.program->Base);
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      /* Driver should be able to handle any texenv programs as long as
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * the driver correctly reported max number of texture units correctly,
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       * etc.
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       */
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT(ok);
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (void) ok; /* silence unused var warning */
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (DISASSEM) {
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_print_program(&p.program->Base);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      printf("\n");
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Return a fragment program which implements the current
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * fixed-function texture, fog and color-sum operations.
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct gl_fragment_program *
15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_mesa_get_fixed_func_fragment_program(struct gl_context *ctx)
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct gl_fragment_program *prog;
15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   struct state_key key;
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   GLuint keySize;
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   keySize = make_state_key(ctx, &key);
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   prog = (struct gl_fragment_program *)
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_search_program_cache(ctx->FragmentProgram.Cache,
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 &key, keySize);
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   if (!prog) {
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prog = (struct gl_fragment_program *)
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      create_new_program(ctx, &key, prog);
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      _mesa_program_cache_insert(ctx, ctx->FragmentProgram.Cache,
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 &key, keySize, &prog->Base);
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   }
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return prog;
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)