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