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 #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 lp_fragment_shader *lpfs = llvmpipe->fs; 52 struct vertex_info *vinfo = &llvmpipe->vertex_info; 53 unsigned vs_index; 54 uint i; 55 56 llvmpipe->color_slot[0] = -1; 57 llvmpipe->color_slot[1] = -1; 58 llvmpipe->bcolor_slot[0] = -1; 59 llvmpipe->bcolor_slot[1] = -1; 60 61 /* 62 * Match FS inputs against VS outputs, emitting the necessary 63 * attributes. Could cache these structs and look them up with a 64 * combination of fragment shader, vertex shader ids. 65 */ 66 67 vinfo->num_attribs = 0; 68 69 vs_index = draw_find_shader_output(llvmpipe->draw, 70 TGSI_SEMANTIC_POSITION, 71 0); 72 73 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); 74 75 for (i = 0; i < lpfs->info.base.num_inputs; i++) { 76 /* 77 * Search for each input in current vs output: 78 */ 79 80 vs_index = draw_find_shader_output(llvmpipe->draw, 81 lpfs->info.base.input_semantic_name[i], 82 lpfs->info.base.input_semantic_index[i]); 83 84 if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR && 85 lpfs->info.base.input_semantic_index[i] < 2) { 86 int idx = lpfs->info.base.input_semantic_index[i]; 87 llvmpipe->color_slot[idx] = (int)vinfo->num_attribs; 88 } 89 90 /* 91 * Emit the requested fs attribute for all but position. 92 */ 93 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); 94 } 95 96 /* Figure out if we need bcolor as well. 97 */ 98 for (i = 0; i < 2; i++) { 99 vs_index = draw_find_shader_output(llvmpipe->draw, 100 TGSI_SEMANTIC_BCOLOR, i); 101 102 if (vs_index > 0) { 103 llvmpipe->bcolor_slot[i] = (int)vinfo->num_attribs; 104 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index); 105 } 106 } 107 108 109 /* Figure out if we need pointsize as well. 110 */ 111 vs_index = draw_find_shader_output(llvmpipe->draw, 112 TGSI_SEMANTIC_PSIZE, 0); 113 114 if (vs_index > 0) { 115 llvmpipe->psize_slot = vinfo->num_attribs; 116 draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT, vs_index); 117 } 118 119 draw_compute_vertex_size(vinfo); 120 lp_setup_set_vertex_info(llvmpipe->setup, vinfo); 121 } 122 123 124 /** 125 * Handle state changes. 126 * Called just prior to drawing anything (pipe::draw_arrays(), etc). 127 * 128 * Hopefully this will remain quite simple, otherwise need to pull in 129 * something like the state tracker mechanism. 130 */ 131 void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe ) 132 { 133 struct llvmpipe_screen *lp_screen = llvmpipe_screen(llvmpipe->pipe.screen); 134 135 /* Check for updated textures. 136 */ 137 if (llvmpipe->tex_timestamp != lp_screen->timestamp) { 138 llvmpipe->tex_timestamp = lp_screen->timestamp; 139 llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; 140 } 141 142 if (llvmpipe->dirty & (LP_NEW_RASTERIZER | 143 LP_NEW_FS | 144 LP_NEW_VS)) 145 compute_vertex_info( llvmpipe ); 146 147 if (llvmpipe->dirty & (LP_NEW_FS | 148 LP_NEW_BLEND | 149 LP_NEW_SCISSOR | 150 LP_NEW_DEPTH_STENCIL_ALPHA | 151 LP_NEW_RASTERIZER | 152 LP_NEW_SAMPLER | 153 LP_NEW_SAMPLER_VIEW | 154 LP_NEW_QUERY)) 155 llvmpipe_update_fs( llvmpipe ); 156 157 if (llvmpipe->dirty & (LP_NEW_FS | 158 LP_NEW_RASTERIZER)) 159 llvmpipe_update_setup( llvmpipe ); 160 161 if (llvmpipe->dirty & LP_NEW_BLEND_COLOR) 162 lp_setup_set_blend_color(llvmpipe->setup, 163 &llvmpipe->blend_color); 164 165 if (llvmpipe->dirty & LP_NEW_SCISSOR) 166 lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor); 167 168 if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA) { 169 lp_setup_set_alpha_ref_value(llvmpipe->setup, 170 llvmpipe->depth_stencil->alpha.ref_value); 171 lp_setup_set_stencil_ref_values(llvmpipe->setup, 172 llvmpipe->stencil_ref.ref_value); 173 } 174 175 if (llvmpipe->dirty & LP_NEW_CONSTANTS) 176 lp_setup_set_fs_constants(llvmpipe->setup, 177 llvmpipe->constants[PIPE_SHADER_FRAGMENT][0]); 178 179 if (llvmpipe->dirty & (LP_NEW_SAMPLER_VIEW)) 180 lp_setup_set_fragment_sampler_views(llvmpipe->setup, 181 llvmpipe->num_sampler_views[PIPE_SHADER_FRAGMENT], 182 llvmpipe->sampler_views[PIPE_SHADER_FRAGMENT]); 183 184 if (llvmpipe->dirty & (LP_NEW_SAMPLER)) 185 lp_setup_set_fragment_sampler_state(llvmpipe->setup, 186 llvmpipe->num_samplers[PIPE_SHADER_FRAGMENT], 187 llvmpipe->samplers[PIPE_SHADER_FRAGMENT]); 188 189 llvmpipe->dirty = 0; 190 } 191 192