1 /************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 #include "util/u_memory.h" 30 #include "pipe/p_shader_tokens.h" 31 #include "draw/draw_context.h" 32 #include "draw/draw_vertex.h" 33 #include "i915_context.h" 34 #include "i915_state.h" 35 #include "i915_debug.h" 36 #include "i915_fpc.h" 37 #include "i915_reg.h" 38 39 static uint find_mapping(const struct i915_fragment_shader* fs, int unit) 40 { 41 int i; 42 for (i = 0; i < I915_TEX_UNITS ; i++) 43 { 44 if (fs->generic_mapping[i] == unit) 45 return i; 46 } 47 debug_printf("Mapping not found\n"); 48 return 0; 49 } 50 51 52 53 /*********************************************************************** 54 * Determine the hardware vertex layout. 55 * Depends on vertex/fragment shader state. 56 */ 57 static void calculate_vertex_layout(struct i915_context *i915) 58 { 59 const struct i915_fragment_shader *fs = i915->fs; 60 const enum interp_mode colorInterp = i915->rasterizer->color_interp; 61 struct vertex_info vinfo; 62 boolean texCoords[I915_TEX_UNITS], colors[2], fog, needW, face; 63 uint i; 64 int src; 65 66 memset(texCoords, 0, sizeof(texCoords)); 67 colors[0] = colors[1] = fog = needW = face = FALSE; 68 memset(&vinfo, 0, sizeof(vinfo)); 69 70 /* Determine which fragment program inputs are needed. Setup HW vertex 71 * layout below, in the HW-specific attribute order. 72 */ 73 for (i = 0; i < fs->info.num_inputs; i++) { 74 switch (fs->info.input_semantic_name[i]) { 75 case TGSI_SEMANTIC_POSITION: 76 { 77 uint unit = I915_SEMANTIC_POS; 78 texCoords[find_mapping(fs, unit)] = TRUE; 79 } 80 break; 81 case TGSI_SEMANTIC_COLOR: 82 assert(fs->info.input_semantic_index[i] < 2); 83 colors[fs->info.input_semantic_index[i]] = TRUE; 84 break; 85 case TGSI_SEMANTIC_GENERIC: 86 { 87 /* texcoords/varyings/other generic */ 88 uint unit = fs->info.input_semantic_index[i]; 89 90 texCoords[find_mapping(fs, unit)] = TRUE; 91 needW = TRUE; 92 } 93 break; 94 case TGSI_SEMANTIC_FOG: 95 fog = TRUE; 96 break; 97 case TGSI_SEMANTIC_FACE: 98 face = TRUE; 99 break; 100 default: 101 debug_printf("Unknown input type %d\n", fs->info.input_semantic_name[i]); 102 assert(0); 103 } 104 } 105 106 107 /* pos */ 108 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_POSITION, 0); 109 if (needW) { 110 draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_LINEAR, src); 111 vinfo.hwfmt[0] |= S4_VFMT_XYZW; 112 vinfo.attrib[0].emit = EMIT_4F; 113 } 114 else { 115 draw_emit_vertex_attr(&vinfo, EMIT_3F, INTERP_LINEAR, src); 116 vinfo.hwfmt[0] |= S4_VFMT_XYZ; 117 vinfo.attrib[0].emit = EMIT_3F; 118 } 119 120 /* hardware point size */ 121 /* XXX todo */ 122 123 /* primary color */ 124 if (colors[0]) { 125 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 0); 126 draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src); 127 vinfo.hwfmt[0] |= S4_VFMT_COLOR; 128 } 129 130 /* secondary color */ 131 if (colors[1]) { 132 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_COLOR, 1); 133 draw_emit_vertex_attr(&vinfo, EMIT_4UB_BGRA, colorInterp, src); 134 vinfo.hwfmt[0] |= S4_VFMT_SPEC_FOG; 135 } 136 137 /* fog coord, not fog blend factor */ 138 if (fog) { 139 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FOG, 0); 140 draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_PERSPECTIVE, src); 141 vinfo.hwfmt[0] |= S4_VFMT_FOG_PARAM; 142 } 143 144 /* texcoords/varyings */ 145 for (i = 0; i < I915_TEX_UNITS; i++) { 146 uint hwtc; 147 if (texCoords[i]) { 148 hwtc = TEXCOORDFMT_4D; 149 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_GENERIC, fs->generic_mapping[i]); 150 draw_emit_vertex_attr(&vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); 151 } 152 else { 153 hwtc = TEXCOORDFMT_NOT_PRESENT; 154 } 155 vinfo.hwfmt[1] |= hwtc << (i * 4); 156 } 157 158 /* front/back face */ 159 if (face) { 160 uint slot = find_mapping(fs, I915_SEMANTIC_FACE); 161 debug_printf("Front/back face is broken\n"); 162 /* XXX Because of limitations in the draw module, currently src will be 0 163 * for SEMANTIC_FACE, so this aliases to POS. We need to fix in the draw 164 * module by adding an extra shader output. 165 */ 166 src = draw_find_shader_output(i915->draw, TGSI_SEMANTIC_FACE, 0); 167 draw_emit_vertex_attr(&vinfo, EMIT_1F, INTERP_CONSTANT, src); 168 vinfo.hwfmt[1] &= ~(TEXCOORDFMT_NOT_PRESENT << (slot * 4)); 169 vinfo.hwfmt[1] |= TEXCOORDFMT_1D << (slot * 4); 170 } 171 172 draw_compute_vertex_size(&vinfo); 173 174 if (memcmp(&i915->current.vertex_info, &vinfo, sizeof(vinfo))) { 175 /* Need to set this flag so that the LIS2/4 registers get set. 176 * It also means the i915_update_immediate() function must be called 177 * after this one, in i915_update_derived(). 178 */ 179 i915->dirty |= I915_NEW_VERTEX_FORMAT; 180 181 memcpy(&i915->current.vertex_info, &vinfo, sizeof(vinfo)); 182 } 183 } 184 185 struct i915_tracked_state i915_update_vertex_layout = { 186 "vertex_layout", 187 calculate_vertex_layout, 188 I915_NEW_RASTERIZER | I915_NEW_FS | I915_NEW_VS 189 }; 190 191 192 193 /*********************************************************************** 194 */ 195 static struct i915_tracked_state *atoms[] = { 196 &i915_update_vertex_layout, 197 &i915_hw_samplers, 198 &i915_hw_sampler_views, 199 &i915_hw_immediate, 200 &i915_hw_dynamic, 201 &i915_hw_fs, 202 &i915_hw_framebuffer, 203 &i915_hw_dst_buf_vars, 204 &i915_hw_constants, 205 NULL, 206 }; 207 208 void i915_update_derived(struct i915_context *i915) 209 { 210 int i; 211 212 if (I915_DBG_ON(DBG_ATOMS)) 213 i915_dump_dirty(i915, __FUNCTION__); 214 215 for (i = 0; atoms[i]; i++) 216 if (atoms[i]->dirty & i915->dirty) 217 atoms[i]->update(i915); 218 219 i915->dirty = 0; 220 } 221