Go to the source code of this file.
Data Structures | |
struct | translated_vertex_program |
State validation for vertex/fragment shaders. More... | |
Functions | |
static GLint | vp_out_to_fp_in (GLuint vertResult) |
Given a vertex program output attribute, return the corresponding fragment program input attribute. | |
static struct translated_vertex_program * | find_translated_vp (struct st_context *st, struct st_vertex_program *stvp, struct st_fragment_program *stfp) |
Find a translated vertex program that corresponds to stvp and has outputs matched to stfp's inputs. | |
void | st_free_translated_vertex_programs (struct st_context *st, struct translated_vertex_program *xvp) |
static void * | get_passthrough_fs (struct st_context *st) |
static void | update_linkage (struct st_context *st) |
Variables | |
struct st_tracked_state | st_update_shader |
static struct translated_vertex_program* find_translated_vp | ( | struct st_context * | st, | |
struct st_vertex_program * | stvp, | |||
struct st_fragment_program * | stfp | |||
) | [static, read] |
Find a translated vertex program that corresponds to stvp and has outputs matched to stfp's inputs.
This performs vertex and fragment translation (to TGSI) when needed.
Definition at line 124 of file st_atom_shader.c.
References assert, st_vertex_program::Base, st_fragment_program::Base, CALLOC_STRUCT, translated_vertex_program::frag_inputs, st_fragment_program::input_map, st_fragment_program::input_semantic_index, st_fragment_program::input_semantic_name, st_fragment_program::input_to_slot, translated_vertex_program::master, MAX2, translated_vertex_program::next, st_fragment_program::num_input_slots, translated_vertex_program::output_to_semantic_index, translated_vertex_program::output_to_semantic_name, translated_vertex_program::output_to_slot, st_vertex_program::serialNo, translated_vertex_program::serialNo, st_translate_fragment_program(), st_translate_vertex_program(), st_fragment_program::state, TGSI_SEMANTIC_COLOR, TGSI_SEMANTIC_COUNT, TGSI_SEMANTIC_GENERIC, TGSI_SEMANTIC_POSITION, TGSI_SEMANTIC_PSIZE, pipe_shader_state::tokens, st_fragment_program::vertex_programs, translated_vertex_program::vp, and vp_out_to_fp_in().
00127 { 00128 static const GLuint UNUSED = ~0; 00129 struct translated_vertex_program *xvp; 00130 const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; 00131 00132 /* 00133 * Translate fragment program if needed. 00134 */ 00135 if (!stfp->state.tokens) { 00136 GLuint inAttr, numIn = 0; 00137 00138 for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) { 00139 if (fragInputsRead & (1 << inAttr)) { 00140 stfp->input_to_slot[inAttr] = numIn; 00141 numIn++; 00142 } 00143 else { 00144 stfp->input_to_slot[inAttr] = UNUSED; 00145 } 00146 } 00147 00148 stfp->num_input_slots = numIn; 00149 00150 assert(stfp->Base.Base.NumInstructions > 1); 00151 00152 st_translate_fragment_program(st, stfp, stfp->input_to_slot); 00153 } 00154 00155 00156 /* See if we've got a translated vertex program whose outputs match 00157 * the fragment program's inputs. 00158 * XXX This could be a hash lookup, using InputsRead as the key. 00159 */ 00160 for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { 00161 if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { 00162 break; 00163 } 00164 } 00165 00166 /* No? Allocate translated vp object now */ 00167 if (!xvp) { 00168 xvp = CALLOC_STRUCT(translated_vertex_program); 00169 xvp->frag_inputs = fragInputsRead; 00170 xvp->master = stvp; 00171 00172 xvp->next = stfp->vertex_programs; 00173 stfp->vertex_programs = xvp; 00174 } 00175 00176 /* See if we need to translate vertex program to TGSI form */ 00177 if (xvp->serialNo != stvp->serialNo) { 00178 GLuint outAttr, dummySlot; 00179 const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; 00180 GLuint numVpOuts = 0; 00181 GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; 00182 GLint maxGeneric; 00183 00184 /* Compute mapping of vertex program outputs to slots, which depends 00185 * on the fragment program's input->slot mapping. 00186 */ 00187 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { 00188 /* set defaults: */ 00189 xvp->output_to_slot[outAttr] = UNUSED; 00190 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; 00191 xvp->output_to_semantic_index[outAttr] = 99; 00192 00193 if (outAttr == VERT_RESULT_HPOS) { 00194 /* always put xformed position into slot zero */ 00195 xvp->output_to_slot[VERT_RESULT_HPOS] = 0; 00196 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; 00197 xvp->output_to_semantic_index[outAttr] = 0; 00198 numVpOuts++; 00199 } 00200 else if (outputsWritten & (1 << outAttr)) { 00201 /* see if the frag prog wants this vert output */ 00202 GLint fpInAttrib = vp_out_to_fp_in(outAttr); 00203 if (fpInAttrib >= 0) { 00204 GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; 00205 if (fpInSlot != ~0) { 00206 /* match this vp output to the fp input */ 00207 GLuint vpOutSlot = stfp->input_map[fpInSlot]; 00208 xvp->output_to_slot[outAttr] = vpOutSlot; 00209 xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; 00210 xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; 00211 numVpOuts++; 00212 } 00213 } 00214 else if (outAttr == VERT_RESULT_PSIZ) 00215 emitPntSize = GL_TRUE; 00216 else if (outAttr == VERT_RESULT_BFC0) 00217 emitBFC0 = GL_TRUE; 00218 else if (outAttr == VERT_RESULT_BFC1) 00219 emitBFC1 = GL_TRUE; 00220 } 00221 #if 0 /*debug*/ 00222 printf("assign vp output_to_slot[%d] = %d\n", outAttr, 00223 xvp->output_to_slot[outAttr]); 00224 #endif 00225 } 00226 00227 /* must do these last */ 00228 if (emitPntSize) { 00229 xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++; 00230 xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; 00231 xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; 00232 } 00233 if (emitBFC0) { 00234 xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++; 00235 xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; 00236 xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; 00237 } 00238 if (emitBFC1) { 00239 xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++; 00240 xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; 00241 xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1; 00242 } 00243 00244 /* Unneeded vertex program outputs will go to this slot. 00245 * We could use this info to do dead code elimination in the 00246 * vertex program. 00247 */ 00248 dummySlot = numVpOuts; 00249 00250 /* find max GENERIC slot index */ 00251 maxGeneric = -1; 00252 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { 00253 if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { 00254 maxGeneric = MAX2(maxGeneric, 00255 xvp->output_to_semantic_index[outAttr]); 00256 } 00257 } 00258 00259 /* Map vert program outputs that aren't used to the dummy slot 00260 * (and an unused generic attribute slot). 00261 */ 00262 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { 00263 if (outputsWritten & (1 << outAttr)) { 00264 if (xvp->output_to_slot[outAttr] == UNUSED) { 00265 xvp->output_to_slot[outAttr] = dummySlot; 00266 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; 00267 xvp->output_to_semantic_index[outAttr] = maxGeneric + 1; 00268 } 00269 } 00270 00271 #if 0 /*debug*/ 00272 printf("vp output_to_slot[%d] = %d\n", outAttr, 00273 xvp->output_to_slot[outAttr]); 00274 #endif 00275 } 00276 00277 assert(stvp->Base.Base.NumInstructions > 1); 00278 00279 st_translate_vertex_program(st, stvp, xvp->output_to_slot, 00280 xvp->output_to_semantic_name, 00281 xvp->output_to_semantic_index); 00282 00283 xvp->vp = stvp; 00284 00285 /* translated VP is up to date now */ 00286 xvp->serialNo = stvp->serialNo; 00287 } 00288 00289 return xvp; 00290 }
static void* get_passthrough_fs | ( | struct st_context * | st | ) | [static] |
Definition at line 308 of file st_atom_shader.c.
References st_context::passthrough_fs, st_context::pipe, util_free_shader(), and util_make_fragment_passthrough_shader().
00309 { 00310 struct pipe_shader_state shader; 00311 00312 if (!st->passthrough_fs) { 00313 st->passthrough_fs = 00314 util_make_fragment_passthrough_shader(st->pipe, &shader); 00315 #if 0 /* We actually need to keep the tokens around at this time */ 00316 util_free_shader(&shader); 00317 #endif 00318 } 00319 00320 return st->passthrough_fs; 00321 }
void st_free_translated_vertex_programs | ( | struct st_context * | st, | |
struct translated_vertex_program * | xvp | |||
) |
Definition at line 294 of file st_atom_shader.c.
References translated_vertex_program::next.
00296 { 00297 struct translated_vertex_program *next; 00298 00299 while (xvp) { 00300 next = xvp->next; 00301 free(xvp); 00302 xvp = next; 00303 } 00304 }
static void update_linkage | ( | struct st_context * | st | ) | [static] |
Definition at line 325 of file st_atom_shader.c.
References assert, st_fragment_program::Base, st_vertex_program::Base, st_context::cso_context, cso_set_fragment_shader_handle(), cso_set_vertex_shader_handle(), st_context::ctx, st_fragment_program::driver_shader, st_vertex_program::driver_shader, find_translated_vp(), st_context::fp, get_passthrough_fs(), st_context::missing_textures, translated_vertex_program::output_to_slot, st_fragment_program(), st_reference_fragprog(), st_reference_vertprog(), st_vertex_program(), st_context::vertex_result_to_slot, and st_context::vp.
00326 { 00327 struct st_vertex_program *stvp; 00328 struct st_fragment_program *stfp; 00329 struct translated_vertex_program *xvp; 00330 00331 /* find active shader and params -- Should be covered by 00332 * ST_NEW_VERTEX_PROGRAM 00333 */ 00334 assert(st->ctx->VertexProgram._Current); 00335 stvp = st_vertex_program(st->ctx->VertexProgram._Current); 00336 assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); 00337 00338 assert(st->ctx->FragmentProgram._Current); 00339 stfp = st_fragment_program(st->ctx->FragmentProgram._Current); 00340 assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); 00341 00342 xvp = find_translated_vp(st, stvp, stfp); 00343 00344 st_reference_vertprog(st, &st->vp, stvp); 00345 st_reference_fragprog(st, &st->fp, stfp); 00346 00347 cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader); 00348 00349 if (st->missing_textures) { 00350 /* use a pass-through frag shader that uses no textures */ 00351 void *fs = get_passthrough_fs(st); 00352 cso_set_fragment_shader_handle(st->cso_context, fs); 00353 } 00354 else { 00355 cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); 00356 } 00357 00358 st->vertex_result_to_slot = xvp->output_to_slot; 00359 }
static GLint vp_out_to_fp_in | ( | GLuint | vertResult | ) | [static] |
Given a vertex program output attribute, return the corresponding fragment program input attribute.
Definition at line 92 of file st_atom_shader.c.
00093 { 00094 if (vertResult >= VERT_RESULT_TEX0 && 00095 vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) 00096 return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0); 00097 00098 if (vertResult >= VERT_RESULT_VAR0 && 00099 vertResult < VERT_RESULT_VAR0 + MAX_VARYING) 00100 return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0); 00101 00102 switch (vertResult) { 00103 case VERT_RESULT_HPOS: 00104 return FRAG_ATTRIB_WPOS; 00105 case VERT_RESULT_COL0: 00106 return FRAG_ATTRIB_COL0; 00107 case VERT_RESULT_COL1: 00108 return FRAG_ATTRIB_COL1; 00109 case VERT_RESULT_FOGC: 00110 return FRAG_ATTRIB_FOGC; 00111 default: 00112 /* Back-face colors, edge flags, etc */ 00113 return -1; 00114 } 00115 }
struct st_tracked_state st_update_shader |
Initial value:
{ "st_update_shader", { 0, 0x4 | 0x2 }, update_linkage }
Definition at line 362 of file st_atom_shader.c.