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