1 /************************************************************************** 2 * 3 * Copyright 2003 VMware, Inc. 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 VMWARE 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 #include "util/u_math.h" 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 "draw/draw_private.h" 34 #include "lp_context.h" 35 #include "lp_screen.h" 36 #include "lp_setup.h" 37 #include "lp_state.h" 38 39 40 41 /** 42 * The vertex info describes how to convert the post-transformed vertices 43 * (simple float[][4]) used by the 'draw' module into vertices for 44 * rasterization. 45 * 46 * This function validates the vertex layout. 47 */ 48 static void 49 compute_vertex_info(struct llvmpipe_context *llvmpipe) 50 { 51 const struct tgsi_shader_info *fsInfo = &llvmpipe->fs->info.base; 52 struct vertex_info *vinfo = &llvmpipe->vertex_info; 53 int vs_index; 54 uint i; 55 56 draw_prepare_shader_outputs(llvmpipe->draw); 57 58 /* 59 * Those can't actually be 0 (because pos is always at 0). 60 * But use ints anyway to avoid confusion (in vs outputs, they 61 * can very well be at pos 0). 62 */ 63 llvmpipe->color_slot[0] = -1; 64 llvmpipe->color_slot[1] = -1; 65 llvmpipe->bcolor_slot[0] = -1; 66 llvmpipe->bcolor_slot[1] = -1; 67 llvmpipe->viewport_index_slot = -1; 68 llvmpipe->layer_slot = -1; 69 llvmpipe->face_slot = -1; 70 llvmpipe->psize_slot = -1; 71 72 /* 73 * Match FS inputs against VS outputs, emitting the necessary 74 * attributes. Could cache these structs and look them up with a 75 * combination of fragment shader, vertex shader ids. 76 */ 77 78 vinfo->num_attribs = 0; 79 80 vs_index = draw_find_shader_output(llvmpipe->draw, 81 TGSI_SEMANTIC_POSITION, 0); 82 83 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 84 85 for (i = 0; i < fsInfo->num_inputs; i++) { 86 /* 87 * Search for each input in current vs output: 88 */ 89 vs_index = draw_find_shader_output(llvmpipe->draw, 90 fsInfo->input_semantic_name[i], 91 fsInfo->input_semantic_index[i]); 92 93 if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && 94 fsInfo->input_semantic_index[i] < 2) { 95 int idx = fsInfo->input_semantic_index[i]; 96 llvmpipe->color_slot[idx] = (int)vinfo->num_attribs; 97 } 98 99 if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_FACE) { 100 llvmpipe->face_slot = (int)vinfo->num_attribs; 101 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 102 /* 103 * For vp index and layer, if the fs requires them but the vs doesn't 104 * provide them, draw (vbuf) will give us the required 0 (slot -1). 105 * (This means in this case we'll also use those slots in setup, which 106 * isn't necessary but they'll contain the correct (0) value.) 107 */ 108 } else if (fsInfo->input_semantic_name[i] == 109 TGSI_SEMANTIC_VIEWPORT_INDEX) { 110 llvmpipe->viewport_index_slot = (int)vinfo->num_attribs; 111 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 112 } else if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_LAYER) { 113 llvmpipe->layer_slot = (int)vinfo->num_attribs; 114 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 115 } else { 116 /* 117 * Note that we'd actually want to skip position (as we won't use 118 * the attribute in the fs) but can't. The reason is that we don't 119 * actually have an input/output map for setup (even though it looks 120 * like we do...). Could adjust for this though even without a map 121 * (in llvmpipe_create_fs_state()). 122 */ 123 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 124 } 125 } 126 127 /* Figure out if we need bcolor as well. 128 */ 129 for (i = 0; i < 2; i++) { 130 vs_index = draw_find_shader_output(llvmpipe->draw, 131 TGSI_SEMANTIC_BCOLOR, i); 132 133 if (vs_index >= 0) { 134 llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs; 135 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 136 } 137 } 138 139 /* Figure out if we need pointsize as well. 140 */ 141 vs_index = draw_find_shader_output(llvmpipe->draw, 142 TGSI_SEMANTIC_PSIZE, 0); 143 144 if (vs_index >= 0) { 145 llvmpipe->psize_slot = (int)vinfo->num_attribs; 146 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 147 } 148 149 /* Figure out if we need viewport index (if it wasn't already in fs input) */ 150 if (llvmpipe->viewport_index_slot < 0) { 151 vs_index = draw_find_shader_output(llvmpipe->draw, 152 TGSI_SEMANTIC_VIEWPORT_INDEX, 153 0); 154 if (vs_index >= 0) { 155 llvmpipe->viewport_index_slot =(int)vinfo->num_attribs; 156 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 157 } 158 } 159 160 /* Figure out if we need layer (if it wasn't already in fs input) */ 161 if (llvmpipe->layer_slot < 0) { 162 vs_index = draw_find_shader_output(llvmpipe->draw, 163 TGSI_SEMANTIC_LAYER, 164 0); 165 if (vs_index >= 0) { 166 llvmpipe->layer_slot = (int)vinfo->num_attribs; 167 draw_emit_vertex_attr(vinfo, EMIT_4F, vs_index); 168 } 169 } 170 171 draw_compute_vertex_size(vinfo); 172 lp_setup_set_vertex_info(llvmpipe->setup, vinfo); 173 } 174 175 176 /** 177 * Handle state changes. 178 * Called just prior to drawing anything (pipe::draw_arrays(), etc). 179 * 180 * Hopefully this will remain quite simple, otherwise need to pull in 181 * something like the state tracker mechanism. 182 */ 183 void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) 184 { 185 struct llvmpipe_screen *lp_screen = llvmpipe_screen(llvmpipe->pipe.screen); 186 187 /* Check for updated textures. 188 */ 189 if (llvmpipe->tex_timestamp != lp_screen->timestamp) { 190 llvmpipe->tex_timestamp = lp_screen->timestamp; 191 llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; 192 } 193 194 /* This needs LP_NEW_RASTERIZER because of draw_prepare_shader_outputs(). */ 195 if (llvmpipe->dirty & (LP_NEW_RASTERIZER | 196 LP_NEW_FS | 197 LP_NEW_VS)) 198 compute_vertex_info(llvmpipe); 199 200 if (llvmpipe->dirty & (LP_NEW_FS | 201 LP_NEW_FRAMEBUFFER | 202 LP_NEW_BLEND | 203 LP_NEW_SCISSOR | 204 LP_NEW_DEPTH_STENCIL_ALPHA | 205 LP_NEW_RASTERIZER | 206 LP_NEW_SAMPLER | 207 LP_NEW_SAMPLER_VIEW | 208 LP_NEW_OCCLUSION_QUERY)) 209 llvmpipe_update_fs( llvmpipe ); 210 211 if (llvmpipe->dirty & (LP_NEW_RASTERIZER)) { 212 boolean discard = 213 (llvmpipe->sample_mask & 1) == 0 || 214 (llvmpipe->rasterizer ? llvmpipe->rasterizer->rasterizer_discard : FALSE); 215 216 lp_setup_set_rasterizer_discard(llvmpipe->setup, discard); 217 } 218 219 if (llvmpipe->dirty & (LP_NEW_FS | 220 LP_NEW_FRAMEBUFFER | 221 LP_NEW_RASTERIZER)) 222 llvmpipe_update_setup( llvmpipe ); 223 224 if (llvmpipe->dirty & LP_NEW_BLEND_COLOR) 225 lp_setup_set_blend_color(llvmpipe->setup, 226 &llvmpipe->blend_color); 227 228 if (llvmpipe->dirty & LP_NEW_SCISSOR) 229 lp_setup_set_scissors(llvmpipe->setup, llvmpipe->scissors); 230 231 if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) { 232 lp_setup_set_alpha_ref_value(llvmpipe->setup, 233 llvmpipe->depth_stencil->alpha.ref_value); 234 lp_setup_set_stencil_ref_values(llvmpipe->setup, 235 llvmpipe->stencil_ref.ref_value); 236 } 237 238 if (llvmpipe->dirty & LP_NEW_FS_CONSTANTS) 239 lp_setup_set_fs_constants(llvmpipe->setup, 240 ARRAY_SIZE(llvmpipe->constants[PIPE_SHADER_FRAGMENT]), 241 llvmpipe->constants[PIPE_SHADER_FRAGMENT]); 242 243 if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW)) 244 lp_setup_set_fragment_sampler_views(llvmpipe->setup, 245 llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT], 246 llvmpipe->sampler_views[PIPE_SHADER_FRAGMENT]); 247 248 if (llvmpipe->dirty & (LP_NEW_SAMPLER)) 249 lp_setup_set_fragment_sampler_state(llvmpipe->setup, 250 llvmpipe->num_samplers[PIPE_SHADER_FRAGMENT], 251 llvmpipe->samplers[PIPE_SHADER_FRAGMENT]); 252 253 if (llvmpipe->dirty & LP_NEW_VIEWPORT) { 254 /* 255 * Update setup and fragment's view of the active viewport state. 256 * 257 * XXX TODO: It is possible to only loop over the active viewports 258 * instead of all viewports (PIPE_MAX_VIEWPORTS). 259 */ 260 lp_setup_set_viewports(llvmpipe->setup, 261 PIPE_MAX_VIEWPORTS, 262 llvmpipe->viewports); 263 } 264 265 llvmpipe->dirty = 0; 266 } 267 268