1 /* 2 * Copyright 2009 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /** 25 * \file prog_parameter_layout.c 26 * \brief Helper functions to layout storage for program parameters 27 * 28 * \author Ian Romanick <ian.d.romanick (at) intel.com> 29 */ 30 31 #include "main/compiler.h" 32 #include "main/mtypes.h" 33 #include "prog_parameter.h" 34 #include "prog_parameter_layout.h" 35 #include "prog_instruction.h" 36 #include "program_parser.h" 37 38 unsigned 39 _mesa_combine_swizzles(unsigned base, unsigned applied) 40 { 41 unsigned swiz = 0; 42 unsigned i; 43 44 for (i = 0; i < 4; i++) { 45 const unsigned s = GET_SWZ(applied, i); 46 47 swiz |= ((s <= SWIZZLE_W) ? GET_SWZ(base, s) : s) << (i * 3); 48 } 49 50 return swiz; 51 } 52 53 54 /** 55 * Copy indirect access array from one parameter list to another 56 * 57 * \param src Parameter array copied from 58 * \param dst Parameter array copied to 59 * \param first Index of first element in \c src to copy 60 * \param count Number of elements to copy 61 * 62 * \return 63 * The location in \c dst of the first element copied from \c src on 64 * success. -1 on failure. 65 * 66 * \warning 67 * This function assumes that there is already enough space available in 68 * \c dst to hold all of the elements that will be copied over. 69 */ 70 static int 71 copy_indirect_accessed_array(struct gl_program_parameter_list *src, 72 struct gl_program_parameter_list *dst, 73 unsigned first, unsigned count) 74 { 75 const int base = dst->NumParameters; 76 unsigned i, j; 77 78 for (i = first; i < (first + count); i++) { 79 struct gl_program_parameter *curr = & src->Parameters[i]; 80 81 if (curr->Type == PROGRAM_CONSTANT) { 82 j = dst->NumParameters; 83 } else { 84 for (j = 0; j < dst->NumParameters; j++) { 85 if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes, 86 sizeof(curr->StateIndexes)) == 0) { 87 return -1; 88 } 89 } 90 } 91 92 assert(j == dst->NumParameters); 93 94 /* copy src parameter [i] to dest parameter [j] */ 95 memcpy(& dst->Parameters[j], curr, 96 sizeof(dst->Parameters[j])); 97 memcpy(dst->ParameterValues[j], src->ParameterValues[i], 98 sizeof(GLfloat) * 4); 99 100 /* Pointer to the string name was copied. Null-out src param name 101 * to prevent double free later. 102 */ 103 curr->Name = NULL; 104 105 dst->NumParameters++; 106 } 107 108 return base; 109 } 110 111 112 /** 113 * XXX description??? 114 * \return GL_TRUE for success, GL_FALSE for failure 115 */ 116 GLboolean 117 _mesa_layout_parameters(struct asm_parser_state *state) 118 { 119 struct gl_program_parameter_list *layout; 120 struct asm_instruction *inst; 121 unsigned i; 122 123 layout = 124 _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters); 125 126 /* PASS 1: Move any parameters that are accessed indirectly from the 127 * original parameter list to the new parameter list. 128 */ 129 for (inst = state->inst_head; inst != NULL; inst = inst->next) { 130 for (i = 0; i < 3; i++) { 131 if (inst->SrcReg[i].Base.RelAddr) { 132 /* Only attempt to add the to the new parameter list once. 133 */ 134 if (!inst->SrcReg[i].Symbol->pass1_done) { 135 const int new_begin = 136 copy_indirect_accessed_array(state->prog->Parameters, layout, 137 inst->SrcReg[i].Symbol->param_binding_begin, 138 inst->SrcReg[i].Symbol->param_binding_length); 139 140 if (new_begin < 0) { 141 _mesa_free_parameter_list(layout); 142 return GL_FALSE; 143 } 144 145 inst->SrcReg[i].Symbol->param_binding_begin = new_begin; 146 inst->SrcReg[i].Symbol->pass1_done = 1; 147 } 148 149 /* Previously the Index was just the offset from the parameter 150 * array. Now that the base of the parameter array is known, the 151 * index can be updated to its actual value. 152 */ 153 inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 154 inst->Base.SrcReg[i].Index += 155 inst->SrcReg[i].Symbol->param_binding_begin; 156 } 157 } 158 } 159 160 /* PASS 2: Move any parameters that are not accessed indirectly from the 161 * original parameter list to the new parameter list. 162 */ 163 for (inst = state->inst_head; inst != NULL; inst = inst->next) { 164 for (i = 0; i < 3; i++) { 165 const struct gl_program_parameter *p; 166 const int idx = inst->SrcReg[i].Base.Index; 167 unsigned swizzle = SWIZZLE_NOOP; 168 169 /* All relative addressed operands were processed on the first 170 * pass. Just skip them here. 171 */ 172 if (inst->SrcReg[i].Base.RelAddr) { 173 continue; 174 } 175 176 if ((inst->SrcReg[i].Base.File <= PROGRAM_VARYING ) 177 || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) { 178 continue; 179 } 180 181 inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 182 p = & state->prog->Parameters->Parameters[idx]; 183 184 switch (p->Type) { 185 case PROGRAM_CONSTANT: { 186 const gl_constant_value *const v = 187 state->prog->Parameters->ParameterValues[idx]; 188 189 inst->Base.SrcReg[i].Index = 190 _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle); 191 192 inst->Base.SrcReg[i].Swizzle = 193 _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle); 194 break; 195 } 196 197 case PROGRAM_STATE_VAR: 198 inst->Base.SrcReg[i].Index = 199 _mesa_add_state_reference(layout, p->StateIndexes); 200 break; 201 202 default: 203 break; 204 } 205 206 inst->SrcReg[i].Base.File = p->Type; 207 inst->Base.SrcReg[i].File = p->Type; 208 } 209 } 210 211 layout->StateFlags = state->prog->Parameters->StateFlags; 212 _mesa_free_parameter_list(state->prog->Parameters); 213 state->prog->Parameters = layout; 214 215 return GL_TRUE; 216 } 217