From: Brian Date: Thu, 14 Dec 2006 22:01:06 +0000 (-0700) Subject: Split the program.[ch] files into several new files. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00cdc0a472c55330cbc58317f01b07f8f90be5a5;p=mesa.git Split the program.[ch] files into several new files. --- diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c new file mode 100644 index 00000000000..f4dae76de0d --- /dev/null +++ b/src/mesa/shader/prog_instruction.c @@ -0,0 +1,99 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "imports.h" +#include "mtypes.h" +#include "prog_instruction.h" + + +/** + * Initialize program instruction fields to defaults. + * \param inst first instruction to initialize + * \param count number of instructions to initialize + */ +void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count) +{ + GLuint i; + + _mesa_bzero(inst, count * sizeof(struct prog_instruction)); + + for (i = 0; i < count; i++) { + inst[i].SrcReg[0].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[1].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; + inst[i].SrcReg[2].File = PROGRAM_UNDEFINED; + inst[i].SrcReg[2].Swizzle = SWIZZLE_NOOP; + + inst[i].DstReg.File = PROGRAM_UNDEFINED; + inst[i].DstReg.WriteMask = WRITEMASK_XYZW; + inst[i].DstReg.CondMask = COND_TR; + inst[i].DstReg.CondSwizzle = SWIZZLE_NOOP; + + inst[i].SaturateMode = SATURATE_OFF; + inst[i].Precision = FLOAT32; + } +} + + +/** + * Allocate an array of program instructions. + * \param numInst number of instructions + * \return pointer to instruction memory + */ +struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst) +{ + return (struct prog_instruction *) + _mesa_calloc(numInst * sizeof(struct prog_instruction)); +} + + +/** + * Reallocate memory storing an array of program instructions. + * This is used when we need to append additional instructions onto an + * program. + * \param oldInst pointer to first of old/src instructions + * \param numOldInst number of instructions at + * \param numNewInst desired size of new instruction array. + * \return pointer to start of new instruction array. + */ +struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst) +{ + struct prog_instruction *newInst; + + newInst = (struct prog_instruction *) + _mesa_realloc(oldInst, + numOldInst * sizeof(struct prog_instruction), + numNewInst * sizeof(struct prog_instruction)); + + return newInst; +} + + diff --git a/src/mesa/shader/prog_instruction.h b/src/mesa/shader/prog_instruction.h new file mode 100644 index 00000000000..bda6a2c3226 --- /dev/null +++ b/src/mesa/shader/prog_instruction.h @@ -0,0 +1,403 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5 + * + * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/** + * \file prog_instruction.h + * + * Private vertex program types and constants only used by files + * related to vertex programs. + * + * \author Brian Paul + * \author Keith Whitwell + * \author Ian Romanick + */ + + +#ifndef PROG_INSTRUCTION_H +#define PROG_INSTRUCTION_H + + +/* for GL_ARB_v_p and GL_ARB_f_p SWZ instruction */ +#define SWIZZLE_X 0 +#define SWIZZLE_Y 1 +#define SWIZZLE_Z 2 +#define SWIZZLE_W 3 +#define SWIZZLE_ZERO 4 /* keep these values together: KW */ +#define SWIZZLE_ONE 5 /* keep these values together: KW */ + +#define MAKE_SWIZZLE4(a,b,c,d) (((a)<<0) | ((b)<<3) | ((c)<<6) | ((d)<<9)) +#define SWIZZLE_NOOP MAKE_SWIZZLE4(0,1,2,3) +#define GET_SWZ(swz, idx) (((swz) >> ((idx)*3)) & 0x7) +#define GET_BIT(msk, idx) (((msk) >> (idx)) & 0x1) + + +#define WRITEMASK_X 0x1 +#define WRITEMASK_Y 0x2 +#define WRITEMASK_XY 0x3 +#define WRITEMASK_Z 0x4 +#define WRITEMASK_XZ 0x5 +#define WRITEMASK_YZ 0x6 +#define WRITEMASK_XYZ 0x7 +#define WRITEMASK_W 0x8 +#define WRITEMASK_XW 0x9 +#define WRITEMASK_YW 0xa +#define WRITEMASK_XYW 0xb +#define WRITEMASK_ZW 0xc +#define WRITEMASK_XZW 0xd +#define WRITEMASK_YZW 0xe +#define WRITEMASK_XYZW 0xf + + +/** + * Condition codes for GL_NV_fragment_program + */ +/*@{*/ +#define COND_GT 1 /* greater than zero */ +#define COND_EQ 2 /* equal to zero */ +#define COND_LT 3 /* less than zero */ +#define COND_UN 4 /* unordered (NaN) */ +#define COND_GE 5 /* greater then or equal to zero */ +#define COND_LE 6 /* less then or equal to zero */ +#define COND_NE 7 /* not equal to zero */ +#define COND_TR 8 /* always true */ +#define COND_FL 9 /* always false */ +/*@}*/ + + +/** + * Instruction precision for GL_NV_fragment_program + */ +/*@{*/ +#define FLOAT32 0x1 +#define FLOAT16 0x2 +#define FIXED12 0x4 +/*@}*/ + + +/** + * Saturation modes when storing values. + */ +/*@{*/ +#define SATURATE_OFF 0 +#define SATURATE_ZERO_ONE 1 +#define SATURATE_PLUS_MINUS_ONE 2 +/*@}*/ + + +/** + * Per-component negation masks + */ +/*@{*/ +#define NEGATE_X 0x1 +#define NEGATE_Y 0x2 +#define NEGATE_Z 0x4 +#define NEGATE_W 0x8 +#define NEGATE_XYZW 0xf +#define NEGATE_NONE 0x0 +/*@}*/ + + +/** + * Program instruction opcodes, for both vertex and fragment programs. + * \note changes to this opcode list must be reflected in t_vb_arbprogram.c + */ +typedef enum prog_opcode { + /* ARB_vp ARB_fp NV_vp NV_fp */ + /*---------------------------------*/ + OPCODE_NOP = 0, + OPCODE_ABS, /* X X 1.1 */ + OPCODE_ADD, /* X X X X */ + OPCODE_ARA, /* 2 */ + OPCODE_ARL, /* X X */ + OPCODE_ARL_NV, /* 2 */ + OPCODE_ARR, /* 2 */ + OPCODE_BRA, /* 2 */ + OPCODE_CAL, /* 2 2 */ + OPCODE_CMP, /* X */ + OPCODE_COS, /* X 2 X */ + OPCODE_DDX, /* X */ + OPCODE_DDY, /* X */ + OPCODE_DP3, /* X X X X */ + OPCODE_DP4, /* X X X X */ + OPCODE_DPH, /* X X 1.1 */ + OPCODE_DST, /* X X X X */ + OPCODE_END, /* X X X X */ + OPCODE_EX2, /* X X 2 X */ + OPCODE_EXP, /* X X */ + OPCODE_FLR, /* X X 2 X */ + OPCODE_FRC, /* X X 2 X */ + OPCODE_KIL, /* X */ + OPCODE_KIL_NV, /* X */ + OPCODE_LG2, /* X X 2 X */ + OPCODE_LIT, /* X X X X */ + OPCODE_LOG, /* X X */ + OPCODE_LRP, /* X X */ + OPCODE_MAD, /* X X X X */ + OPCODE_MAX, /* X X X X */ + OPCODE_MIN, /* X X X X */ + OPCODE_MOV, /* X X X X */ + OPCODE_MUL, /* X X X X */ + OPCODE_PK2H, /* X */ + OPCODE_PK2US, /* X */ + OPCODE_PK4B, /* X */ + OPCODE_PK4UB, /* X */ + OPCODE_POW, /* X X X */ + OPCODE_POPA, /* 3 */ + OPCODE_PRINT, /* X X */ + OPCODE_PUSHA, /* 3 */ + OPCODE_RCC, /* 1.1 */ + OPCODE_RCP, /* X X X X */ + OPCODE_RET, /* 2 2 */ + OPCODE_RFL, /* X X */ + OPCODE_RSQ, /* X X X X */ + OPCODE_SCS, /* X */ + OPCODE_SEQ, /* 2 X */ + OPCODE_SFL, /* 2 X */ + OPCODE_SGE, /* X X X X */ + OPCODE_SGT, /* 2 X */ + OPCODE_SIN, /* X 2 X */ + OPCODE_SLE, /* 2 X */ + OPCODE_SLT, /* X X X X */ + OPCODE_SNE, /* 2 X */ + OPCODE_SSG, /* 2 */ + OPCODE_STR, /* 2 X */ + OPCODE_SUB, /* X X 1.1 X */ + OPCODE_SWZ, /* X X */ + OPCODE_TEX, /* X 3 X */ + OPCODE_TXB, /* X 3 */ + OPCODE_TXD, /* X */ + OPCODE_TXL, /* 3 2 */ + OPCODE_TXP, /* X */ + OPCODE_TXP_NV, /* 3 X */ + OPCODE_UP2H, /* X */ + OPCODE_UP2US, /* X */ + OPCODE_UP4B, /* X */ + OPCODE_UP4UB, /* X */ + OPCODE_X2D, /* X */ + OPCODE_XPD, /* X X */ + MAX_OPCODE +} gl_inst_opcode; + + +/** + * Instruction source register. + */ +struct prog_src_register +{ + GLuint File:4; /**< One of the PROGRAM_* register file values. */ + GLint Index:9; /**< May be negative for relative addressing. */ + GLuint Swizzle:12; + GLuint RelAddr:1; + + /** + * \name Source register "sign" control. + * + * The ARB and NV extensions allow varrying degrees of control over the + * sign of the source vector components. These values allow enough control + * for all flavors of the extensions. + */ + /*@{*/ + /** + * Per-component negation for the SWZ instruction. For non-SWZ + * instructions the only possible values are NEGATE_XYZW and NEGATE_NONE. + * + * \since + * ARB_vertex_program, ARB_fragment_program + */ + GLuint NegateBase:4; + + /** + * Take the component-wise absolute value. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint Abs:1; + + /** + * Post-absolute value negation (all components). + */ + GLuint NegateAbs:1; + /*@}*/ +}; + + +/** + * Instruction destination register. + */ +struct prog_dst_register +{ + /** + * One of the PROGRAM_* register file values. + */ + GLuint File:4; + + GLuint Index:8; + GLuint WriteMask:4; + + /** + * \name Conditional destination update control. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + /*@{*/ + /** + * Takes one of the 9 possible condition values (EQ, FL, GT, GE, LE, LT, + * NE, TR, or UN). Destination update is enabled if the matching + * (swizzled) condition code value passes. When a conditional update mask + * is not specified, this will be \c COND_TR. + */ + GLuint CondMask:4; + + /** + * Condition code swizzle value. + */ + GLuint CondSwizzle:12; + + /** + * Selects the condition code register to use for conditional destination + * update masking. In NV_fragmnet_program or NV_vertex_program2 mode, only + * condition code register 0 is available. In NV_vertex_program3 mode, + * condition code registers 0 and 1 are available. + */ + GLuint CondSrc:1; + /*@}*/ + + GLuint pad:31; +}; + + +/** + * Vertex/fragment program instruction. + */ +struct prog_instruction +{ + gl_inst_opcode Opcode; +#if FEATURE_MESA_program_debug + GLshort StringPos; +#endif + /** + * Arbitrary data. Used for the PRINT, CAL, and BRA instructions. + */ + void *Data; + + struct prog_src_register SrcReg[3]; + struct prog_dst_register DstReg; + + /** + * Indicates that the instruction should update the condition code + * register. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondUpdate:1; + + /** + * If prog_instruction::CondUpdate is \c GL_TRUE, this value selects the + * condition code register that is to be updated. + * + * In GL_NV_fragment_program or GL_NV_vertex_program2 mode, only condition + * code register 0 is available. In GL_NV_vertex_program3 mode, condition + * code registers 0 and 1 are available. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program2, + * NV_vertex_program2_option. + */ + GLuint CondDst:1; + + /** + * Saturate each value of the vectored result to the range [0,1] or the + * range [-1,1]. \c SSAT mode (i.e., saturation to the range [-1,1]) is + * only available in NV_fragment_program2 mode. + * Value is one of the SATURATE_* tokens. + * + * \since + * NV_fragment_program, NV_fragment_program_option, NV_vertex_program3. + */ + GLuint SaturateMode:2; + + /** + * Per-instruction selectable precision. + * + * \since + * NV_fragment_program, NV_fragment_program_option. + */ + GLuint Precision:3; + + /** + * \name Texture source controls. + * + * The texture source controls are only used with the \c TEX, \c TXD, + * \c TXL, and \c TXP instructions. + * + * \since + * ARB_fragment_program, NV_fragment_program, NV_vertex_program3. + */ + /*@{*/ + /** + * Source texture unit. OpenGL supports a maximum of 32 texture + * units. + */ + GLuint TexSrcUnit:5; + + /** + * Source texture target, one of TEXTURE_{1D,2D,3D,CUBE,RECT}_INDEX. + */ + GLuint TexSrcTarget:3; + /*@}*/ + + /** + * For BRA and CAL instructions, the location to jump to. + */ + GLuint BranchTarget; + + const char *Comment; +}; + + +extern void +_mesa_init_instructions(struct prog_instruction *inst, GLuint count); + +extern struct prog_instruction * +_mesa_alloc_instructions(GLuint numInst); + +extern struct prog_instruction * +_mesa_realloc_instructions(struct prog_instruction *oldInst, + GLuint numOldInst, GLuint numNewInst); + +extern GLuint +_mesa_num_inst_src_regs(gl_inst_opcode opcode); + +extern const char * +_mesa_opcode_string(gl_inst_opcode opcode); + + +#endif /* PROG_INSTRUCTION_H */ diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c new file mode 100644 index 00000000000..f634e38800b --- /dev/null +++ b/src/mesa/shader/prog_parameter.c @@ -0,0 +1,448 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_parameter.c + * Program parameter lists and functions. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "program.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_statevars.h" + + +struct gl_program_parameter_list * +_mesa_new_parameter_list(void) +{ + return (struct gl_program_parameter_list *) + _mesa_calloc(sizeof(struct gl_program_parameter_list)); +} + + +/** + * Free a parameter list and all its parameters + */ +void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList) +{ + GLuint i; + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name) + _mesa_free((void *) paramList->Parameters[i].Name); + } + _mesa_free(paramList->Parameters); + if (paramList->ParameterValues) + _mesa_align_free(paramList->ParameterValues); + _mesa_free(paramList); +} + + + +/** + * Add a new parameter to a parameter list. + * \param paramList the list to add the parameter to + * \param name the parameter name, will be duplicated/copied! + * \param values initial parameter value, up to 4 GLfloats + * \param size number of elements in 'values' vector (1..4) + * \param type type of parameter, such as + * \return index of new parameter in the list, or -1 if error (out of mem) + */ +GLint +_mesa_add_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], GLuint size, + enum register_file type) +{ + const GLuint n = paramList->NumParameters; + + if (n == paramList->Size) { + /* Need to grow the parameter list array */ + if (paramList->Size == 0) + paramList->Size = 8; + else + paramList->Size *= 2; + + /* realloc arrays */ + paramList->Parameters = (struct gl_program_parameter *) + _mesa_realloc(paramList->Parameters, + n * sizeof(struct gl_program_parameter), + paramList->Size * sizeof(struct gl_program_parameter)); + + paramList->ParameterValues = (GLfloat (*)[4]) + _mesa_align_realloc(paramList->ParameterValues, /* old buf */ + n * 4 * sizeof(GLfloat), /* old size */ + paramList->Size * 4 *sizeof(GLfloat), /* new sz */ + 16); + } + + if (!paramList->Parameters || + !paramList->ParameterValues) { + /* out of memory */ + paramList->NumParameters = 0; + paramList->Size = 0; + return -1; + } + else { + paramList->NumParameters = n + 1; + + _mesa_memset(¶mList->Parameters[n], 0, + sizeof(struct gl_program_parameter)); + + paramList->Parameters[n].Name = name ? _mesa_strdup(name) : NULL; + paramList->Parameters[n].Type = type; + paramList->Parameters[n].Size = size; + if (values) + COPY_4V(paramList->ParameterValues[n], values); + return (GLint) n; + } +} + + +/** + * Add a new named program parameter (Ex: NV_fragment_program DEFINE statement) + * \return index of the new entry in the parameter list + */ +GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]) +{ + return _mesa_add_parameter(paramList, name, values, 4, PROGRAM_NAMED_PARAM); +} + + +/** + * Add a new named constant to the parameter list. + * This will be used when the program contains something like this: + * PARAM myVals = { 0, 1, 2, 3 }; + * + * \param paramList the parameter list + * \param name the name for the constant + * \param values four float values + * \return index/position of the new parameter in the parameter list + */ +GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size) +{ +#if 0 /* disable this for now -- we need to save the name! */ + GLint pos; + GLuint swizzle; + ASSERT(size == 4); /* XXX future feature */ + /* check if we already have this constant */ + if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { + return pos; + } +#endif + size = 4; /** XXX fix */ + return _mesa_add_parameter(paramList, name, values, size, PROGRAM_CONSTANT); +} + + +/** + * Add a new unnamed constant to the parameter list. + * This will be used when the program contains something like this: + * MOV r, { 0, 1, 2, 3 }; + * + * \param paramList the parameter list + * \param values four float values + * \param swizzleOut returns swizzle mask for accessing the constant + * \return index/position of the new parameter in the parameter list. + */ +GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size, + GLuint *swizzleOut) +{ + GLint pos; + GLuint swizzle; + ASSERT(size >= 1); + ASSERT(size <= 4); + size = 4; /* XXX temporary */ + /* check if we already have this constant */ + if (_mesa_lookup_parameter_constant(paramList, values, + size, &pos, &swizzle)) { + return pos; + } + return _mesa_add_parameter(paramList, NULL, values, size, PROGRAM_CONSTANT); +} + + +GLint +_mesa_add_uniform(struct gl_program_parameter_list *paramList, + const char *name, GLuint size) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) { + /* already in list */ + return i; + } + else { + assert(size == 4); + i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_UNIFORM); + return i; + } +} + + +GLint +_mesa_add_varying(struct gl_program_parameter_list *paramList, + const char *name, GLuint size) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) { + /* already in list */ + return i; + } + else { + assert(size == 4); + i = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_VARYING); + return i; + } +} + + + + +#if 0 /* not used yet */ +/** + * Returns the number of 4-component registers needed to store a piece + * of GL state. For matrices this may be as many as 4 registers, + * everything else needs + * just 1 register. + */ +static GLuint +sizeof_state_reference(const GLint *stateTokens) +{ + if (stateTokens[0] == STATE_MATRIX) { + GLuint rows = stateTokens[4] - stateTokens[3] + 1; + assert(rows >= 1); + assert(rows <= 4); + return rows; + } + else { + return 1; + } +} +#endif + + +/** + * Add a new state reference to the parameter list. + * This will be used when the program contains something like this: + * PARAM ambient = state.material.front.ambient; + * + * \param paramList the parameter list + * \param state an array of 6 state tokens + * \return index of the new parameter. + */ +GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const GLint *stateTokens) +{ + const GLuint size = 4; /* XXX fix */ + const char *name; + GLint index; + + /* Check if the state reference is already in the list */ + for (index = 0; index < paramList->NumParameters; index++) { + GLuint i, match = 0; + for (i = 0; i < 6; i++) { + if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) { + match++; + } + else { + break; + } + } + if (match == 6) { + /* this state reference is already in the parameter list */ + return index; + } + } + + name = _mesa_program_state_string(stateTokens); + index = _mesa_add_parameter(paramList, name, NULL, size, PROGRAM_STATE_VAR); + if (index >= 0) { + GLuint i; + for (i = 0; i < 6; i++) { + paramList->Parameters[index].StateIndexes[i] + = (gl_state_index) stateTokens[i]; + } + paramList->StateFlags |= _mesa_program_state_flags(stateTokens); + } + + /* free name string here since we duplicated it in add_parameter() */ + _mesa_free((void *) name); + + return index; +} + + +/** + * Lookup a parameter value by name in the given parameter list. + * \return pointer to the float[4] values. + */ +GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name); + if (i < 0) + return NULL; + else + return paramList->ParameterValues[i]; +} + + +/** + * Given a program parameter name, find its position in the list of parameters. + * \param paramList the parameter list to search + * \param nameLen length of name (in chars). + * If length is negative, assume that name is null-terminated. + * \param name the name to search for + * \return index of parameter in the list. + */ +GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name) +{ + GLint i; + + if (!paramList) + return -1; + + if (nameLen == -1) { + /* name is null-terminated */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strcmp(paramList->Parameters[i].Name, name) == 0) + return i; + } + } + else { + /* name is not null-terminated, use nameLen */ + for (i = 0; i < (GLint) paramList->NumParameters; i++) { + if (paramList->Parameters[i].Name && + _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 + && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) + return i; + } + } + return -1; +} + + +/** + * Look for a float vector in the given parameter list. The float vector + * may be of length 1, 2, 3 or 4. + * \param paramList the parameter list to search + * \param v the float vector to search for + * \param size number of element in v + * \param posOut returns the position of the constant, if found + * \param swizzleOut returns a swizzle mask describing location of the + * vector elements if found + * \return GL_TRUE if found, GL_FALSE if not found + */ +GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList, + const GLfloat v[], GLsizei vSize, + GLint *posOut, GLuint *swizzleOut) +{ + GLuint i; + + assert(vSize >= 1); + assert(vSize <= 4); + + if (!paramList) + return -1; + + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Type == PROGRAM_CONSTANT) { + const GLint maxShift = 4 - vSize; + GLint shift, j; + for (shift = 0; shift <= maxShift; shift++) { + GLint matched = 0; + GLuint swizzle[4]; + swizzle[0] = swizzle[1] = swizzle[2] = swizzle[3] = 0; + /* XXX we could do out-of-order swizzle matches too, someday */ + for (j = 0; j < vSize; j++) { + assert(shift + j < 4); + if (paramList->ParameterValues[i][shift + j] == v[j]) { + matched++; + swizzle[j] = shift + j; + ASSERT(swizzle[j] >= SWIZZLE_X); + ASSERT(swizzle[j] <= SWIZZLE_W); + } + } + if (matched == vSize) { + /* found! */ + *posOut = i; + *swizzleOut = MAKE_SWIZZLE4(swizzle[0], swizzle[1], + swizzle[2], swizzle[3]); + return GL_TRUE; + } + } + } + } + + *posOut = -1; + return GL_FALSE; +} + + +struct gl_program_parameter_list * +_mesa_clone_parameter_list(const struct gl_program_parameter_list *list) +{ + struct gl_program_parameter_list *clone; + GLuint i; + + clone = _mesa_new_parameter_list(); + if (!clone) + return NULL; + + /** Not too efficient, but correct */ + for (i = 0; i < list->NumParameters; i++) { + struct gl_program_parameter *p = list->Parameters + i; + GLint j = _mesa_add_parameter(clone, p->Name, list->ParameterValues[i], + p->Size, p->Type); + ASSERT(j >= 0); + /* copy state indexes */ + if (p->Type == PROGRAM_STATE_VAR) { + GLint k; + struct gl_program_parameter *q = clone->Parameters + j; + for (k = 0; k < 6; k++) { + q->StateIndexes[k] = p->StateIndexes[k]; + } + } + } + + return clone; +} diff --git a/src/mesa/shader/prog_parameter.h b/src/mesa/shader/prog_parameter.h new file mode 100644 index 00000000000..c60ef543b75 --- /dev/null +++ b/src/mesa/shader/prog_parameter.h @@ -0,0 +1,123 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_parameter.c + * Program parameter lists and functions. + * \author Brian Paul + */ + +#ifndef PROG_PARAMETER_H +#define PROG_PARAMETER_H + +#include "mtypes.h" + + +/** + * Named program parameters + * Used for NV_fragment_program "DEFINE"d constants and "DECLARE"d parameters, + * and ARB_fragment_program global state references. For the later, Name + * might be "state.light[0].diffuse", for example. + */ +struct gl_program_parameter +{ + const char *Name; /**< Null-terminated string */ + enum register_file Type; /**< PROGRAM_NAMED_PARAM, CONSTANT or STATE_VAR */ + GLuint Size; /**< Number of components (1..4) */ + /** + * A sequence of STATE_* tokens and integers to identify GL state. + */ + GLuint StateIndexes[6]; +}; + + +/** + * A list of the above program_parameter instances. + */ +struct gl_program_parameter_list +{ + GLuint Size; /**< allocated size of Parameters, ParameterValues */ + GLuint NumParameters; /**< number of parameters in arrays */ + struct gl_program_parameter *Parameters; /**< Array [Size] */ + GLfloat (*ParameterValues)[4]; /**< Array [Size] of GLfloat[4] */ + GLbitfield StateFlags; /**< _NEW_* flags indicating which state changes + might invalidate ParameterValues[] */ +}; + + +extern struct gl_program_parameter_list * +_mesa_new_parameter_list(void); + +extern void +_mesa_free_parameter_list(struct gl_program_parameter_list *paramList); + +extern struct gl_program_parameter_list * +_mesa_clone_parameter_list(const struct gl_program_parameter_list *list); + +extern GLint +_mesa_add_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], GLuint size, + enum register_file type); + +extern GLint +_mesa_add_named_parameter(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4]); + +extern GLint +_mesa_add_named_constant(struct gl_program_parameter_list *paramList, + const char *name, const GLfloat values[4], + GLuint size); + +extern GLint +_mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, + const GLfloat values[4], GLuint size, + GLuint *swizzleOut); + +extern GLint +_mesa_add_uniform(struct gl_program_parameter_list *paramList, + const char *name, GLuint size); + +extern GLint +_mesa_add_varying(struct gl_program_parameter_list *paramList, + const char *name, GLuint size); + +extern GLint +_mesa_add_state_reference(struct gl_program_parameter_list *paramList, + const GLint *stateTokens); + +extern GLfloat * +_mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLint +_mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, + GLsizei nameLen, const char *name); + +extern GLboolean +_mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList, + const GLfloat v[], GLsizei vSize, + GLint *posOut, GLuint *swizzleOut); + + +#endif /* PROG_PARAMETER_H */ diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c new file mode 100644 index 00000000000..eded71bbae1 --- /dev/null +++ b/src/mesa/shader/prog_print.c @@ -0,0 +1,464 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_print.c + * Print vertex/fragment programs - for debugging. + * \author Brian Paul + */ + +#include "glheader.h" +#include "context.h" +#include "imports.h" +#include "macros.h" +#include "program.h" +#include "prog_instruction.h" +#include "prog_parameter.h" +#include "prog_print.h" +#include "prog_statevars.h" + + + +/** + * Basic info about each instruction + */ +struct instruction_info +{ + gl_inst_opcode Opcode; + const char *Name; + GLuint NumSrcRegs; +}; + +/** + * Instruction info + * \note Opcode should equal array index! + */ +static const struct instruction_info InstInfo[MAX_OPCODE] = { + { OPCODE_NOP, "NOP", 0 }, + { OPCODE_ABS, "ABS", 1 }, + { OPCODE_ADD, "ADD", 2 }, + { OPCODE_ARA, "ARA", 1 }, + { OPCODE_ARL, "ARL", 1 }, + { OPCODE_ARL_NV, "ARL", 1 }, + { OPCODE_ARR, "ARL", 1 }, + { OPCODE_BRA, "BRA", 0 }, + { OPCODE_CAL, "CAL", 0 }, + { OPCODE_CMP, "CMP", 3 }, + { OPCODE_COS, "COS", 1 }, + { OPCODE_DDX, "DDX", 1 }, + { OPCODE_DDY, "DDY", 1 }, + { OPCODE_DP3, "DP3", 2 }, + { OPCODE_DP4, "DP4", 2 }, + { OPCODE_DPH, "DPH", 2 }, + { OPCODE_DST, "DST", 2 }, + { OPCODE_END, "END", 0 }, + { OPCODE_EX2, "EX2", 1 }, + { OPCODE_EXP, "EXP", 1 }, + { OPCODE_FLR, "FLR", 1 }, + { OPCODE_FRC, "FRC", 1 }, + { OPCODE_KIL, "KIL", 1 }, + { OPCODE_KIL_NV, "KIL", 0 }, + { OPCODE_LG2, "LG2", 1 }, + { OPCODE_LIT, "LIT", 1 }, + { OPCODE_LOG, "LOG", 1 }, + { OPCODE_LRP, "LRP", 3 }, + { OPCODE_MAD, "MAD", 3 }, + { OPCODE_MAX, "MAX", 2 }, + { OPCODE_MIN, "MIN", 2 }, + { OPCODE_MOV, "MOV", 1 }, + { OPCODE_MUL, "MUL", 2 }, + { OPCODE_PK2H, "PK2H", 1 }, + { OPCODE_PK2US, "PK2US", 1 }, + { OPCODE_PK4B, "PK4B", 1 }, + { OPCODE_PK4UB, "PK4UB", 1 }, + { OPCODE_POW, "POW", 2 }, + { OPCODE_POPA, "POPA", 0 }, + { OPCODE_PRINT, "PRINT", 1 }, + { OPCODE_PUSHA, "PUSHA", 0 }, + { OPCODE_RCC, "RCC", 1 }, + { OPCODE_RCP, "RCP", 1 }, + { OPCODE_RET, "RET", 0 }, + { OPCODE_RFL, "RFL", 1 }, + { OPCODE_RSQ, "RSQ", 1 }, + { OPCODE_SCS, "SCS", 1 }, + { OPCODE_SEQ, "SEQ", 2 }, + { OPCODE_SFL, "SFL", 0 }, + { OPCODE_SGE, "SGE", 2 }, + { OPCODE_SGT, "SGT", 2 }, + { OPCODE_SIN, "SIN", 1 }, + { OPCODE_SLE, "SLE", 2 }, + { OPCODE_SLT, "SLT", 2 }, + { OPCODE_SNE, "SNE", 2 }, + { OPCODE_SSG, "SSG", 1 }, + { OPCODE_STR, "STR", 0 }, + { OPCODE_SUB, "SUB", 2 }, + { OPCODE_SWZ, "SWZ", 1 }, + { OPCODE_TEX, "TEX", 1 }, + { OPCODE_TXB, "TXB", 1 }, + { OPCODE_TXD, "TXD", 3 }, + { OPCODE_TXL, "TXL", 1 }, + { OPCODE_TXP, "TXP", 1 }, + { OPCODE_TXP_NV, "TXP", 1 }, + { OPCODE_UP2H, "UP2H", 1 }, + { OPCODE_UP2US, "UP2US", 1 }, + { OPCODE_UP4B, "UP4B", 1 }, + { OPCODE_UP4UB, "UP4UB", 1 }, + { OPCODE_X2D, "X2D", 3 }, + { OPCODE_XPD, "XPD", 2 } +}; + + +/** + * Return the number of src registers for the given instruction/opcode. + */ +GLuint +_mesa_num_inst_src_regs(gl_inst_opcode opcode) +{ + ASSERT(opcode == InstInfo[opcode].Opcode); + ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); + return InstInfo[opcode].NumSrcRegs; +} + + +/** + * Return string name for given program opcode. + */ +const char * +_mesa_opcode_string(gl_inst_opcode opcode) +{ + ASSERT(opcode < MAX_OPCODE); + return InstInfo[opcode].Name; +} + +/** + * Return string name for given program/register file. + */ +static const char * +program_file_string(enum register_file f) +{ + switch (f) { + case PROGRAM_TEMPORARY: + return "TEMP"; + case PROGRAM_LOCAL_PARAM: + return "LOCAL"; + case PROGRAM_ENV_PARAM: + return "ENV"; + case PROGRAM_STATE_VAR: + return "STATE"; + case PROGRAM_INPUT: + return "INPUT"; + case PROGRAM_OUTPUT: + return "OUTPUT"; + case PROGRAM_NAMED_PARAM: + return "NAMED"; + case PROGRAM_CONSTANT: + return "CONST"; + case PROGRAM_UNIFORM: + return "UNIFORM"; + case PROGRAM_VARYING: + return "VARYING"; + case PROGRAM_WRITE_ONLY: + return "WRITE_ONLY"; + case PROGRAM_ADDRESS: + return "ADDR"; + default: + return "Unknown program file!"; + } +} + + +/** + * Return a string representation of the given swizzle word. + * If extended is true, use extended (comma-separated) format. + */ +static const char * +swizzle_string(GLuint swizzle, GLuint negateBase, GLboolean extended) +{ + static const char swz[] = "xyzw01"; + static char s[20]; + GLuint i = 0; + + if (!extended && swizzle == SWIZZLE_NOOP && negateBase == 0) + return ""; /* no swizzle/negation */ + + if (!extended) + s[i++] = '.'; + + if (negateBase & 0x1) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 0)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x2) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 1)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x4) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 2)]; + + if (extended) { + s[i++] = ','; + } + + if (negateBase & 0x8) + s[i++] = '-'; + s[i++] = swz[GET_SWZ(swizzle, 3)]; + + s[i] = 0; + return s; +} + + +static const char * +writemask_string(GLuint writeMask) +{ + static char s[10]; + GLuint i = 0; + + if (writeMask == WRITEMASK_XYZW) + return ""; + + s[i++] = '.'; + if (writeMask & WRITEMASK_X) + s[i++] = 'x'; + if (writeMask & WRITEMASK_Y) + s[i++] = 'y'; + if (writeMask & WRITEMASK_Z) + s[i++] = 'z'; + if (writeMask & WRITEMASK_W) + s[i++] = 'w'; + + s[i] = 0; + return s; +} + +static void +print_dst_reg(const struct prog_dst_register *dstReg) +{ + _mesa_printf(" %s[%d]%s", + program_file_string((enum register_file) dstReg->File), + dstReg->Index, + writemask_string(dstReg->WriteMask)); +} + +static void +print_src_reg(const struct prog_src_register *srcReg) +{ + _mesa_printf("%s[%d]%s", + program_file_string((enum register_file) srcReg->File), + srcReg->Index, + swizzle_string(srcReg->Swizzle, + srcReg->NegateBase, GL_FALSE)); +} + +static void +print_comment(const struct prog_instruction *inst) +{ + if (inst->Comment) + _mesa_printf("; # %s\n", inst->Comment); + else + _mesa_printf(";\n"); +} + + +void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, + GLuint numRegs) +{ + GLuint j; + + _mesa_printf("%s", opcode_string); + + /* frag prog only */ + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + + if (inst->DstReg.File != PROGRAM_UNDEFINED) { + _mesa_printf(" %s[%d]%s", + program_file_string((enum register_file) inst->DstReg.File), + inst->DstReg.Index, + writemask_string(inst->DstReg.WriteMask)); + } + else { + _mesa_printf(" ???"); + } + + if (numRegs > 0) + _mesa_printf(", "); + + for (j = 0; j < numRegs; j++) { + print_src_reg(inst->SrcReg + j); + if (j + 1 < numRegs) + _mesa_printf(", "); + } + + if (inst->Comment) + _mesa_printf(" # %s", inst->Comment); + + print_comment(inst); +} + + +/** + * Print a single vertex/fragment program instruction. + */ +void +_mesa_print_instruction(const struct prog_instruction *inst) +{ + switch (inst->Opcode) { + case OPCODE_PRINT: + _mesa_printf("PRINT '%s'", inst->Data); + if (inst->SrcReg[0].File != PROGRAM_UNDEFINED) { + _mesa_printf(", "); + _mesa_printf("%s[%d]%s", + program_file_string((enum register_file) inst->SrcReg[0].File), + inst->SrcReg[0].Index, + swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_FALSE)); + } + if (inst->Comment) + _mesa_printf(" # %s", inst->Comment); + print_comment(inst); + break; + case OPCODE_SWZ: + _mesa_printf("SWZ"); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + print_dst_reg(&inst->DstReg); + _mesa_printf("%s[%d], %s", + program_file_string((enum register_file) inst->SrcReg[0].File), + inst->SrcReg[0].Index, + swizzle_string(inst->SrcReg[0].Swizzle, + inst->SrcReg[0].NegateBase, GL_TRUE)); + print_comment(inst); + break; + case OPCODE_TEX: + case OPCODE_TXP: + case OPCODE_TXB: + _mesa_printf("%s", _mesa_opcode_string(inst->Opcode)); + if (inst->SaturateMode == SATURATE_ZERO_ONE) + _mesa_printf("_SAT"); + _mesa_printf(" "); + print_dst_reg(&inst->DstReg); + _mesa_printf(", "); + print_src_reg(&inst->SrcReg[0]); + _mesa_printf(", texture[%d], ", inst->TexSrcUnit); + switch (inst->TexSrcTarget) { + case TEXTURE_1D_INDEX: _mesa_printf("1D"); break; + case TEXTURE_2D_INDEX: _mesa_printf("2D"); break; + case TEXTURE_3D_INDEX: _mesa_printf("3D"); break; + case TEXTURE_CUBE_INDEX: _mesa_printf("CUBE"); break; + case TEXTURE_RECT_INDEX: _mesa_printf("RECT"); break; + default: + ; + } + print_comment(inst); + break; + case OPCODE_ARL: + _mesa_printf("ARL addr.x, "); + print_src_reg(&inst->SrcReg[0]); + print_comment(inst); + break; + case OPCODE_BRA: + _mesa_printf("BRA %u", inst->BranchTarget); + print_comment(inst); + break; + case OPCODE_CAL: + _mesa_printf("CAL %u", inst->BranchTarget); + print_comment(inst); + break; + case OPCODE_END: + _mesa_printf("END"); + print_comment(inst); + break; + /* XXX may need other special-case instructions */ + default: + /* typical alu instruction */ + _mesa_print_alu_instruction(inst, + _mesa_opcode_string(inst->Opcode), + _mesa_num_inst_src_regs(inst->Opcode)); + break; + } +} + + +/** + * Print a vertx/fragment program to stdout. + * XXX this function could be greatly improved. + */ +void +_mesa_print_program(const struct gl_program *prog) +{ + GLuint i; + for (i = 0; i < prog->NumInstructions; i++) { + _mesa_printf("%3d: ", i); + _mesa_print_instruction(prog->Instructions + i); + } +} + + +/** + * Print all of a program's parameters. + */ +void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) +{ + GLint i; + + _mesa_printf("InputsRead: 0x%x\n", prog->InputsRead); + _mesa_printf("OutputsWritten: 0x%x\n", prog->OutputsWritten); + _mesa_printf("NumInstructions=%d\n", prog->NumInstructions); + _mesa_printf("NumTemporaries=%d\n", prog->NumTemporaries); + _mesa_printf("NumParameters=%d\n", prog->NumParameters); + _mesa_printf("NumAttributes=%d\n", prog->NumAttributes); + _mesa_printf("NumAddressRegs=%d\n", prog->NumAddressRegs); + + _mesa_load_state_parameters(ctx, prog->Parameters); + +#if 0 + _mesa_printf("Local Params:\n"); + for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ + const GLfloat *p = prog->LocalParams[i]; + _mesa_printf("%2d: %f, %f, %f, %f\n", i, p[0], p[1], p[2], p[3]); + } +#endif + + for (i = 0; i < prog->Parameters->NumParameters; i++){ + struct gl_program_parameter *param = prog->Parameters->Parameters + i; + const GLfloat *v = prog->Parameters->ParameterValues[i]; + _mesa_printf("param[%d] %s %s = {%.3f, %.3f, %.3f, %.3f};\n", + i, + program_file_string(prog->Parameters->Parameters[i].Type), + param->Name, v[0], v[1], v[2], v[3]); + } +} diff --git a/src/mesa/shader/prog_print.h b/src/mesa/shader/prog_print.h new file mode 100644 index 00000000000..595a0dcf372 --- /dev/null +++ b/src/mesa/shader/prog_print.h @@ -0,0 +1,45 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef PROG_PRINT_H +#define PROG_PRINT_H + + +extern void +_mesa_print_instruction(const struct prog_instruction *inst); + +extern void +_mesa_print_alu_instruction(const struct prog_instruction *inst, + const char *opcode_string, + GLuint numRegs); + +extern void +_mesa_print_program(const struct gl_program *prog); + +extern void +_mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog); + + +#endif /* PROG_PRINT_H */ diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c new file mode 100644 index 00000000000..7377c7d8210 --- /dev/null +++ b/src/mesa/shader/prog_statevars.c @@ -0,0 +1,783 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.3 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file prog_statevars.c + * Program state variable management. + * \author Brian Paul + */ + + +#include "glheader.h" +#include "context.h" +#include "hash.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "prog_statevars.h" +#include "prog_parameter.h" +#include "nvvertparse.h" + + +/** + * Use the list of tokens in the state[] array to find global GL state + * and return it in . Usually, four values are returned in + * but matrix queries may return as many as 16 values. + * This function is used for ARB vertex/fragment programs. + * The program parser will produce the state[] values. + */ +static void +_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], + GLfloat *value) +{ + switch (state[0]) { + case STATE_MATERIAL: + { + /* state[1] is either 0=front or 1=back side */ + const GLuint face = (GLuint) state[1]; + const struct gl_material *mat = &ctx->Light.Material; + ASSERT(face == 0 || face == 1); + /* we rely on tokens numbered so that _BACK_ == _FRONT_+ 1 */ + ASSERT(MAT_ATTRIB_FRONT_AMBIENT + 1 == MAT_ATTRIB_BACK_AMBIENT); + /* XXX we could get rid of this switch entirely with a little + * work in arbprogparse.c's parse_state_single_item(). + */ + /* state[2] is the material attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_AMBIENT + face]); + return; + case STATE_DIFFUSE: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_DIFFUSE + face]); + return; + case STATE_SPECULAR: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_SPECULAR + face]); + return; + case STATE_EMISSION: + COPY_4V(value, mat->Attrib[MAT_ATTRIB_FRONT_EMISSION + face]); + return; + case STATE_SHININESS: + value[0] = mat->Attrib[MAT_ATTRIB_FRONT_SHININESS + face][0]; + value[1] = 0.0F; + value[2] = 0.0F; + value[3] = 1.0F; + return; + default: + _mesa_problem(ctx, "Invalid material state in fetch_state"); + return; + } + } + case STATE_LIGHT: + { + /* state[1] is the light number */ + const GLuint ln = (GLuint) state[1]; + /* state[2] is the light attribute */ + switch (state[2]) { + case STATE_AMBIENT: + COPY_4V(value, ctx->Light.Light[ln].Ambient); + return; + case STATE_DIFFUSE: + COPY_4V(value, ctx->Light.Light[ln].Diffuse); + return; + case STATE_SPECULAR: + COPY_4V(value, ctx->Light.Light[ln].Specular); + return; + case STATE_POSITION: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + return; + case STATE_ATTENUATION: + value[0] = ctx->Light.Light[ln].ConstantAttenuation; + value[1] = ctx->Light.Light[ln].LinearAttenuation; + value[2] = ctx->Light.Light[ln].QuadraticAttenuation; + value[3] = ctx->Light.Light[ln].SpotExponent; + return; + case STATE_SPOT_DIRECTION: + COPY_3V(value, ctx->Light.Light[ln].EyeDirection); + value[3] = ctx->Light.Light[ln]._CosCutoff; + return; + case STATE_HALF: + { + GLfloat eye_z[] = {0, 0, 1}; + + /* Compute infinite half angle vector: + * half-vector = light_position + (0, 0, 1) + * and then normalize. w = 0 + * + * light.EyePosition.w should be 0 for infinite lights. + */ + ADD_3V(value, eye_z, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV(value); + value[3] = 0; + } + return; + case STATE_POSITION_NORMALIZED: + COPY_4V(value, ctx->Light.Light[ln].EyePosition); + NORMALIZE_3FV( value ); + return; + default: + _mesa_problem(ctx, "Invalid light state in fetch_state"); + return; + } + } + case STATE_LIGHTMODEL_AMBIENT: + COPY_4V(value, ctx->Light.Model.Ambient); + return; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + /* front */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; + } + else { + /* back */ + GLint i; + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Model.Ambient[i] + * ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_AMBIENT][i] + + ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_EMISSION][i]; + } + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; + } + return; + case STATE_LIGHTPROD: + { + const GLuint ln = (GLuint) state[1]; + const GLuint face = (GLuint) state[2]; + GLint i; + ASSERT(face == 0 || face == 1); + switch (state[3]) { + case STATE_AMBIENT: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Ambient[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_DIFFUSE: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Diffuse[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + case STATE_SPECULAR: + for (i = 0; i < 3; i++) { + value[i] = ctx->Light.Light[ln].Specular[i] * + ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SPECULAR+face][i]; + } + /* [3] = material alpha */ + value[3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE+face][3]; + return; + default: + _mesa_problem(ctx, "Invalid lightprod state in fetch_state"); + return; + } + } + case STATE_TEXGEN: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + /* state[2] is the texgen attribute */ + switch (state[2]) { + case STATE_TEXGEN_EYE_S: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneS); + return; + case STATE_TEXGEN_EYE_T: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneT); + return; + case STATE_TEXGEN_EYE_R: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneR); + return; + case STATE_TEXGEN_EYE_Q: + COPY_4V(value, ctx->Texture.Unit[unit].EyePlaneQ); + return; + case STATE_TEXGEN_OBJECT_S: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneS); + return; + case STATE_TEXGEN_OBJECT_T: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneT); + return; + case STATE_TEXGEN_OBJECT_R: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneR); + return; + case STATE_TEXGEN_OBJECT_Q: + COPY_4V(value, ctx->Texture.Unit[unit].ObjectPlaneQ); + return; + default: + _mesa_problem(ctx, "Invalid texgen state in fetch_state"); + return; + } + } + case STATE_TEXENV_COLOR: + { + /* state[1] is the texture unit */ + const GLuint unit = (GLuint) state[1]; + COPY_4V(value, ctx->Texture.Unit[unit].EnvColor); + } + return; + case STATE_FOG_COLOR: + COPY_4V(value, ctx->Fog.Color); + return; + case STATE_FOG_PARAMS: + value[0] = ctx->Fog.Density; + value[1] = ctx->Fog.Start; + value[2] = ctx->Fog.End; + value[3] = 1.0F / (ctx->Fog.End - ctx->Fog.Start); + return; + case STATE_CLIPPLANE: + { + const GLuint plane = (GLuint) state[1]; + COPY_4V(value, ctx->Transform.EyeUserPlane[plane]); + } + return; + case STATE_POINT_SIZE: + value[0] = ctx->Point.Size; + value[1] = ctx->Point.MinSize; + value[2] = ctx->Point.MaxSize; + value[3] = ctx->Point.Threshold; + return; + case STATE_POINT_ATTENUATION: + value[0] = ctx->Point.Params[0]; + value[1] = ctx->Point.Params[1]; + value[2] = ctx->Point.Params[2]; + value[3] = 1.0F; + return; + case STATE_MATRIX: + { + /* state[1] = modelview, projection, texture, etc. */ + /* state[2] = which texture matrix or program matrix */ + /* state[3] = first row to fetch */ + /* state[4] = last row to fetch */ + /* state[5] = transpose, inverse or invtrans */ + + const GLmatrix *matrix; + const gl_state_index mat = state[1]; + const GLuint index = (GLuint) state[2]; + const GLuint firstRow = (GLuint) state[3]; + const GLuint lastRow = (GLuint) state[4]; + const gl_state_index modifier = state[5]; + const GLfloat *m; + GLuint row, i; + if (mat == STATE_MODELVIEW) { + matrix = ctx->ModelviewMatrixStack.Top; + } + else if (mat == STATE_PROJECTION) { + matrix = ctx->ProjectionMatrixStack.Top; + } + else if (mat == STATE_MVP) { + matrix = &ctx->_ModelProjectMatrix; + } + else if (mat == STATE_TEXTURE) { + matrix = ctx->TextureMatrixStack[index].Top; + } + else if (mat == STATE_PROGRAM) { + matrix = ctx->ProgramMatrixStack[index].Top; + } + else { + _mesa_problem(ctx, "Bad matrix name in _mesa_fetch_state()"); + return; + } + if (modifier == STATE_MATRIX_INVERSE || + modifier == STATE_MATRIX_INVTRANS) { + /* Be sure inverse is up to date: + */ + _math_matrix_alloc_inv( (GLmatrix *) matrix ); + _math_matrix_analyse( (GLmatrix*) matrix ); + m = matrix->inv; + } + else { + m = matrix->m; + } + if (modifier == STATE_MATRIX_TRANSPOSE || + modifier == STATE_MATRIX_INVTRANS) { + for (i = 0, row = firstRow; row <= lastRow; row++) { + value[i++] = m[row * 4 + 0]; + value[i++] = m[row * 4 + 1]; + value[i++] = m[row * 4 + 2]; + value[i++] = m[row * 4 + 3]; + } + } + else { + for (i = 0, row = firstRow; row <= lastRow; row++) { + value[i++] = m[row + 0]; + value[i++] = m[row + 4]; + value[i++] = m[row + 8]; + value[i++] = m[row + 12]; + } + } + } + return; + case STATE_DEPTH_RANGE: + value[0] = ctx->Viewport.Near; /* near */ + value[1] = ctx->Viewport.Far; /* far */ + value[2] = ctx->Viewport.Far - ctx->Viewport.Near; /* far - near */ + value[3] = 0; + return; + case STATE_FRAGMENT_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_VERTEX_PROGRAM: + { + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + const int idx = (int) state[2]; + switch (state[1]) { + case STATE_ENV: + COPY_4V(value, ctx->VertexProgram.Parameters[idx]); + break; + case STATE_LOCAL: + COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); + break; + default: + _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); + return; + } + } + return; + + case STATE_INTERNAL: + { + switch (state[1]) { + case STATE_NORMAL_SCALE: + ASSIGN_4V(value, ctx->_ModelViewInvScale, 0, 0, 1); + break; + case STATE_TEXRECT_SCALE: { + const int unit = (int) state[2]; + const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; + if (texObj) { + struct gl_texture_image *texImage = texObj->Image[0][0]; + ASSIGN_4V(value, 1.0 / texImage->Width, 1.0 / texImage->Height, 0, 1); + } + break; + } + default: + /* unknown state indexes are silently ignored + * should be handled by the driver. + */ + return; + } + } + return; + + default: + _mesa_problem(ctx, "Invalid state in _mesa_fetch_state"); + return; + } +} + + +/** + * Return a bitmask of the Mesa state flags (_NEW_* values) which would + * indicate that the given context state may have changed. + * The bitmask is used during validation to determine if we need to update + * vertex/fragment program parameters (like "state.material.color") when + * some GL state has changed. + */ +GLbitfield +_mesa_program_state_flags(const GLint state[]) +{ + switch (state[0]) { + case STATE_MATERIAL: + case STATE_LIGHT: + case STATE_LIGHTMODEL_AMBIENT: + case STATE_LIGHTMODEL_SCENECOLOR: + case STATE_LIGHTPROD: + return _NEW_LIGHT; + + case STATE_TEXGEN: + case STATE_TEXENV_COLOR: + return _NEW_TEXTURE; + + case STATE_FOG_COLOR: + case STATE_FOG_PARAMS: + return _NEW_FOG; + + case STATE_CLIPPLANE: + return _NEW_TRANSFORM; + + case STATE_POINT_SIZE: + case STATE_POINT_ATTENUATION: + return _NEW_POINT; + + case STATE_MATRIX: + switch (state[1]) { + case STATE_MODELVIEW: + return _NEW_MODELVIEW; + case STATE_PROJECTION: + return _NEW_PROJECTION; + case STATE_MVP: + return _NEW_MODELVIEW | _NEW_PROJECTION; + case STATE_TEXTURE: + return _NEW_TEXTURE_MATRIX; + case STATE_PROGRAM: + return _NEW_TRACK_MATRIX; + default: + _mesa_problem(NULL, + "unexpected matrix in _mesa_program_state_flags()"); + return 0; + } + + case STATE_DEPTH_RANGE: + return _NEW_VIEWPORT; + + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + return _NEW_PROGRAM; + + case STATE_INTERNAL: + switch (state[1]) { + case STATE_NORMAL_SCALE: + return _NEW_MODELVIEW; + case STATE_TEXRECT_SCALE: + return _NEW_TEXTURE; + default: + /* unknown state indexes are silently ignored and + * no flag set, since it is handled by the driver. + */ + return 0; + } + + default: + _mesa_problem(NULL, "unexpected state[0] in make_state_flags()"); + return 0; + } +} + + +static void +append(char *dst, const char *src) +{ + while (*dst) + dst++; + while (*src) + *dst++ = *src++; + *dst = 0; +} + + +static void +append_token(char *dst, gl_state_index k) +{ + switch (k) { + case STATE_MATERIAL: + append(dst, "material."); + break; + case STATE_LIGHT: + append(dst, "light"); + break; + case STATE_LIGHTMODEL_AMBIENT: + append(dst, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + break; + case STATE_LIGHTPROD: + append(dst, "lightprod"); + break; + case STATE_TEXGEN: + append(dst, "texgen"); + break; + case STATE_FOG_COLOR: + append(dst, "fog.color"); + break; + case STATE_FOG_PARAMS: + append(dst, "fog.params"); + break; + case STATE_CLIPPLANE: + append(dst, "clip"); + break; + case STATE_POINT_SIZE: + append(dst, "point.size"); + break; + case STATE_POINT_ATTENUATION: + append(dst, "point.attenuation"); + break; + case STATE_MATRIX: + append(dst, "matrix."); + break; + case STATE_MODELVIEW: + append(dst, "modelview"); + break; + case STATE_PROJECTION: + append(dst, "projection"); + break; + case STATE_MVP: + append(dst, "mvp"); + break; + case STATE_TEXTURE: + append(dst, "texture"); + break; + case STATE_PROGRAM: + append(dst, "program"); + break; + case STATE_MATRIX_INVERSE: + append(dst, ".inverse"); + break; + case STATE_MATRIX_TRANSPOSE: + append(dst, ".transpose"); + break; + case STATE_MATRIX_INVTRANS: + append(dst, ".invtrans"); + break; + case STATE_AMBIENT: + append(dst, "ambient"); + break; + case STATE_DIFFUSE: + append(dst, "diffuse"); + break; + case STATE_SPECULAR: + append(dst, "specular"); + break; + case STATE_EMISSION: + append(dst, "emission"); + break; + case STATE_SHININESS: + append(dst, "shininess"); + break; + case STATE_HALF: + append(dst, "half"); + break; + case STATE_POSITION: + append(dst, ".position"); + break; + case STATE_ATTENUATION: + append(dst, ".attenuation"); + break; + case STATE_SPOT_DIRECTION: + append(dst, ".spot.direction"); + break; + case STATE_TEXGEN_EYE_S: + append(dst, "eye.s"); + break; + case STATE_TEXGEN_EYE_T: + append(dst, "eye.t"); + break; + case STATE_TEXGEN_EYE_R: + append(dst, "eye.r"); + break; + case STATE_TEXGEN_EYE_Q: + append(dst, "eye.q"); + break; + case STATE_TEXGEN_OBJECT_S: + append(dst, "object.s"); + break; + case STATE_TEXGEN_OBJECT_T: + append(dst, "object.t"); + break; + case STATE_TEXGEN_OBJECT_R: + append(dst, "object.r"); + break; + case STATE_TEXGEN_OBJECT_Q: + append(dst, "object.q"); + break; + case STATE_TEXENV_COLOR: + append(dst, "texenv"); + break; + case STATE_DEPTH_RANGE: + append(dst, "depth.range"); + break; + case STATE_VERTEX_PROGRAM: + case STATE_FRAGMENT_PROGRAM: + break; + case STATE_ENV: + append(dst, "env"); + break; + case STATE_LOCAL: + append(dst, "local"); + break; + case STATE_INTERNAL: + case STATE_NORMAL_SCALE: + case STATE_POSITION_NORMALIZED: + append(dst, "(internal)"); + break; + default: + ; + } +} + +static void +append_face(char *dst, GLint face) +{ + if (face == 0) + append(dst, "front."); + else + append(dst, "back."); +} + +static void +append_index(char *dst, GLint index) +{ + char s[20]; + _mesa_sprintf(s, "[%d].", index); + append(dst, s); +} + +/** + * Make a string from the given state vector. + * For example, return "state.matrix.texture[2].inverse". + * Use _mesa_free() to deallocate the string. + */ +const char * +_mesa_program_state_string(const GLint state[6]) +{ + char str[1000] = ""; + char tmp[30]; + + append(str, "state."); + append_token(str, (gl_state_index) state[0]); + + switch (state[0]) { + case STATE_MATERIAL: + append_face(str, state[1]); + append_token(str, (gl_state_index) state[2]); + break; + case STATE_LIGHT: + append(str, "light"); + append_index(str, state[1]); /* light number [i]. */ + append_token(str, (gl_state_index) state[2]); /* coefficients */ + break; + case STATE_LIGHTMODEL_AMBIENT: + append(str, "lightmodel.ambient"); + break; + case STATE_LIGHTMODEL_SCENECOLOR: + if (state[1] == 0) { + append(str, "lightmodel.front.scenecolor"); + } + else { + append(str, "lightmodel.back.scenecolor"); + } + break; + case STATE_LIGHTPROD: + append_index(str, state[1]); /* light number [i]. */ + append_face(str, state[2]); + append_token(str, (gl_state_index) state[3]); + break; + case STATE_TEXGEN: + append_index(str, state[1]); /* tex unit [i] */ + append_token(str, (gl_state_index) state[2]); /* plane coef */ + break; + case STATE_TEXENV_COLOR: + append_index(str, state[1]); /* tex unit [i] */ + append(str, "color"); + break; + case STATE_FOG_COLOR: + case STATE_FOG_PARAMS: + break; + case STATE_CLIPPLANE: + append_index(str, state[1]); /* plane [i] */ + append(str, "plane"); + break; + case STATE_POINT_SIZE: + case STATE_POINT_ATTENUATION: + break; + case STATE_MATRIX: + { + /* state[1] = modelview, projection, texture, etc. */ + /* state[2] = which texture matrix or program matrix */ + /* state[3] = first row to fetch */ + /* state[4] = last row to fetch */ + /* state[5] = transpose, inverse or invtrans */ + const gl_state_index mat = (gl_state_index) state[1]; + const GLuint index = (GLuint) state[2]; + const GLuint firstRow = (GLuint) state[3]; + const GLuint lastRow = (GLuint) state[4]; + const gl_state_index modifier = (gl_state_index) state[5]; + append_token(str, mat); + if (index) + append_index(str, index); + if (modifier) + append_token(str, modifier); + if (firstRow == lastRow) + _mesa_sprintf(tmp, ".row[%d]", firstRow); + else + _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); + append(str, tmp); + } + break; + case STATE_DEPTH_RANGE: + break; + case STATE_FRAGMENT_PROGRAM: + case STATE_VERTEX_PROGRAM: + /* state[1] = {STATE_ENV, STATE_LOCAL} */ + /* state[2] = parameter index */ + append_token(str, (gl_state_index) state[1]); + append_index(str, state[2]); + break; + case STATE_INTERNAL: + break; + default: + _mesa_problem(NULL, "Invalid state in _mesa_program_state_string"); + break; + } + + return _mesa_strdup(str); +} + + +/** + * Loop over all the parameters in a parameter list. If the parameter + * is a GL state reference, look up the current value of that state + * variable and put it into the parameter's Value[4] array. + * This would be called at glBegin time when using a fragment program. + */ +void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList) +{ + GLuint i; + + if (!paramList) + return; + + for (i = 0; i < paramList->NumParameters; i++) { + if (paramList->Parameters[i].Type == PROGRAM_STATE_VAR) { + _mesa_fetch_state(ctx, + paramList->Parameters[i].StateIndexes, + paramList->ParameterValues[i]); + } + } +} + diff --git a/src/mesa/shader/prog_statevars.h b/src/mesa/shader/prog_statevars.h new file mode 100644 index 00000000000..17e38054bb3 --- /dev/null +++ b/src/mesa/shader/prog_statevars.h @@ -0,0 +1,117 @@ +/* + * Mesa 3-D graphics library + * Version: 6.5.2 + * + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef PROG_STATEVARS_H +#define PROG_STATEVARS_H + +#include "mtypes.h" + + +/** + * Used for describing GL state referenced from inside ARB vertex and + * fragment programs. + * A string such as "state.light[0].ambient" gets translated into a + * sequence of tokens such as [ STATE_LIGHT, 0, STATE_AMBIENT ]. + */ +typedef enum gl_state_index_ { + STATE_MATERIAL = 100, /* start at 100 so small ints are seen as ints */ + + STATE_LIGHT, + STATE_LIGHTMODEL_AMBIENT, + STATE_LIGHTMODEL_SCENECOLOR, + STATE_LIGHTPROD, + + STATE_TEXGEN, + + STATE_FOG_COLOR, + STATE_FOG_PARAMS, + + STATE_CLIPPLANE, + + STATE_POINT_SIZE, + STATE_POINT_ATTENUATION, + + STATE_MATRIX, + STATE_MODELVIEW, + STATE_PROJECTION, + STATE_MVP, + STATE_TEXTURE, + STATE_PROGRAM, + STATE_MATRIX_INVERSE, + STATE_MATRIX_TRANSPOSE, + STATE_MATRIX_INVTRANS, + + STATE_AMBIENT, + STATE_DIFFUSE, + STATE_SPECULAR, + STATE_EMISSION, + STATE_SHININESS, + STATE_HALF, + + STATE_POSITION, + STATE_ATTENUATION, + STATE_SPOT_DIRECTION, + + STATE_TEXGEN_EYE_S, + STATE_TEXGEN_EYE_T, + STATE_TEXGEN_EYE_R, + STATE_TEXGEN_EYE_Q, + STATE_TEXGEN_OBJECT_S, + STATE_TEXGEN_OBJECT_T, + STATE_TEXGEN_OBJECT_R, + STATE_TEXGEN_OBJECT_Q, + + STATE_TEXENV_COLOR, + + STATE_DEPTH_RANGE, + + STATE_VERTEX_PROGRAM, + STATE_FRAGMENT_PROGRAM, + + STATE_ENV, + STATE_LOCAL, + + STATE_INTERNAL, /* Mesa additions */ + STATE_NORMAL_SCALE, + STATE_TEXRECT_SCALE, + STATE_POSITION_NORMALIZED, /* normalized light position */ + STATE_INTERNAL_DRIVER /* first available state index for drivers (must be last) */ +} gl_state_index; + + + +extern void +_mesa_load_state_parameters(GLcontext *ctx, + struct gl_program_parameter_list *paramList); + + +extern GLbitfield +_mesa_program_state_flags(const GLint state[]); + + +extern const char * +_mesa_program_state_string(const GLint state[6]); + + +#endif /* PROG_STATEVARS_H */