Merge branch 'mesa_7_5_branch'
[mesa.git] / src / mesa / state_tracker / st_atom_shader.c
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 * State validation for vertex/fragment shaders.
30 * Note that we have to delay most vertex/fragment shader translation
31 * until rendering time since the linkage between the vertex outputs and
32 * fragment inputs can vary depending on the pairing of shaders.
33 *
34 * Authors:
35 * Brian Paul
36 */
37
38
39
40 #include "main/imports.h"
41 #include "main/mtypes.h"
42 #include "main/macros.h"
43 #include "shader/program.h"
44
45 #include "pipe/p_context.h"
46 #include "pipe/p_shader_tokens.h"
47
48 #include "util/u_simple_shaders.h"
49
50 #include "cso_cache/cso_context.h"
51
52 #include "st_context.h"
53 #include "st_atom.h"
54 #include "st_program.h"
55 #include "st_atom_shader.h"
56 #include "st_mesa_to_tgsi.h"
57
58
59 /**
60 * This represents a vertex program, especially translated to match
61 * the inputs of a particular fragment shader.
62 */
63 struct translated_vertex_program
64 {
65 struct st_vertex_program *master;
66
67 /** The fragment shader "signature" this vertex shader is meant for: */
68 GLbitfield frag_inputs;
69
70 /** Compared against master vertex program's serialNo: */
71 GLuint serialNo;
72
73 /** Maps VERT_RESULT_x to slot */
74 GLuint output_to_slot[VERT_RESULT_MAX];
75 ubyte output_to_semantic_name[VERT_RESULT_MAX];
76 ubyte output_to_semantic_index[VERT_RESULT_MAX];
77
78 /** Pointer to the translated vertex program */
79 struct st_vertex_program *vp;
80
81 struct translated_vertex_program *next; /**< next in linked list */
82 };
83
84
85
86 /**
87 * Given a vertex program output attribute, return the corresponding
88 * fragment program input attribute.
89 * \return -1 for vertex outputs that have no corresponding fragment input
90 */
91 static GLint
92 vp_out_to_fp_in(GLuint vertResult)
93 {
94 if (vertResult >= VERT_RESULT_TEX0 &&
95 vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
96 return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
97
98 if (vertResult >= VERT_RESULT_VAR0 &&
99 vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
100 return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
101
102 switch (vertResult) {
103 case VERT_RESULT_HPOS:
104 return FRAG_ATTRIB_WPOS;
105 case VERT_RESULT_COL0:
106 return FRAG_ATTRIB_COL0;
107 case VERT_RESULT_COL1:
108 return FRAG_ATTRIB_COL1;
109 case VERT_RESULT_FOGC:
110 return FRAG_ATTRIB_FOGC;
111 default:
112 /* Back-face colors, edge flags, etc */
113 return -1;
114 }
115 }
116
117
118 /**
119 * Find a translated vertex program that corresponds to stvp and
120 * has outputs matched to stfp's inputs.
121 * This performs vertex and fragment translation (to TGSI) when needed.
122 */
123 static struct translated_vertex_program *
124 find_translated_vp(struct st_context *st,
125 struct st_vertex_program *stvp,
126 struct st_fragment_program *stfp)
127 {
128 static const GLuint UNUSED = ~0;
129 struct translated_vertex_program *xvp;
130 const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
131
132 /*
133 * Translate fragment program if needed.
134 */
135 if (!stfp->state.tokens) {
136 GLuint inAttr, numIn = 0;
137
138 for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
139 if (fragInputsRead & (1 << inAttr)) {
140 stfp->input_to_slot[inAttr] = numIn;
141 numIn++;
142 if ((fragInputsRead & FRAG_BIT_FOGC)) {
143 /* leave placeholders for the
144 * extra registers we extract from fog */
145 if (stfp->Base.UsesFrontFacing) {
146 if (!stfp->Base.UsesFogFragCoord)
147 --stfp->input_to_slot[inAttr];
148 else
149 ++numIn;
150 }
151 if (stfp->Base.UsesPointCoord) {
152 if (!stfp->Base.UsesFrontFacing &&
153 !stfp->Base.UsesFogFragCoord)
154 stfp->input_to_slot[inAttr] -= 2;
155 else
156 ++numIn;
157 }
158 }
159 }
160 else {
161 stfp->input_to_slot[inAttr] = UNUSED;
162 }
163 }
164
165 stfp->num_input_slots = numIn;
166
167 assert(stfp->Base.Base.NumInstructions > 1);
168
169 st_translate_fragment_program(st, stfp, stfp->input_to_slot);
170 }
171
172
173 /* See if we've got a translated vertex program whose outputs match
174 * the fragment program's inputs.
175 * XXX This could be a hash lookup, using InputsRead as the key.
176 */
177 for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
178 if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
179 break;
180 }
181 }
182
183 /* No? Allocate translated vp object now */
184 if (!xvp) {
185 xvp = ST_CALLOC_STRUCT(translated_vertex_program);
186 xvp->frag_inputs = fragInputsRead;
187 xvp->master = stvp;
188
189 xvp->next = stfp->vertex_programs;
190 stfp->vertex_programs = xvp;
191 }
192
193 /* See if we need to translate vertex program to TGSI form */
194 if (xvp->serialNo != stvp->serialNo) {
195 GLuint outAttr;
196 const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
197 GLuint numVpOuts = 0;
198 GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
199 GLbitfield usedGenerics = 0x0;
200 GLbitfield usedOutputSlots = 0x0;
201
202 /* Compute mapping of vertex program outputs to slots, which depends
203 * on the fragment program's input->slot mapping.
204 */
205 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
206 /* set defaults: */
207 xvp->output_to_slot[outAttr] = UNUSED;
208 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
209 xvp->output_to_semantic_index[outAttr] = 99;
210
211 if (outAttr == VERT_RESULT_HPOS) {
212 /* always put xformed position into slot zero */
213 GLuint slot = 0;
214 xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
215 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
216 xvp->output_to_semantic_index[outAttr] = 0;
217 numVpOuts++;
218 usedOutputSlots |= (1 << slot);
219 }
220 else if (outputsWritten & (1 << outAttr)) {
221 /* see if the frag prog wants this vert output */
222 GLint fpInAttrib = vp_out_to_fp_in(outAttr);
223 if (fpInAttrib >= 0) {
224 GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
225 if (fpInSlot != ~0) {
226 /* match this vp output to the fp input */
227 GLuint vpOutSlot = stfp->input_map[fpInSlot];
228 xvp->output_to_slot[outAttr] = vpOutSlot;
229 xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
230 xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
231 numVpOuts++;
232 usedOutputSlots |= (1 << vpOutSlot);
233 }
234 else {
235 #if 0 /*debug*/
236 printf("VP output %d not used by FP\n", outAttr);
237 #endif
238 }
239 }
240 else if (outAttr == VERT_RESULT_PSIZ)
241 emitPntSize = GL_TRUE;
242 else if (outAttr == VERT_RESULT_BFC0)
243 emitBFC0 = GL_TRUE;
244 else if (outAttr == VERT_RESULT_BFC1)
245 emitBFC1 = GL_TRUE;
246 }
247 #if 0 /*debug*/
248 printf("assign vp output_to_slot[%d] = %d\n", outAttr,
249 xvp->output_to_slot[outAttr]);
250 #endif
251 }
252
253 /* must do these last */
254 if (emitPntSize) {
255 GLuint slot = numVpOuts++;
256 xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
257 xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
258 xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
259 usedOutputSlots |= (1 << slot);
260 }
261 if (emitBFC0) {
262 GLuint slot = numVpOuts++;
263 xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
264 xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
265 xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
266 usedOutputSlots |= (1 << slot);
267 }
268 if (emitBFC1) {
269 GLuint slot = numVpOuts++;
270 xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
271 xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
272 xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
273 usedOutputSlots |= (1 << slot);
274 }
275
276 /* build usedGenerics mask */
277 usedGenerics = 0x0;
278 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
279 if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
280 usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
281 }
282 }
283
284 /* For each vertex program output that doesn't match up to a fragment
285 * program input, map the vertex program output to a free slot and
286 * free generic attribute.
287 */
288 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
289 if (outputsWritten & (1 << outAttr)) {
290 if (xvp->output_to_slot[outAttr] == UNUSED) {
291 GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
292 GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
293 usedGenerics |= (1 << freeGeneric);
294 usedOutputSlots |= (1 << freeSlot);
295 xvp->output_to_slot[outAttr] = freeSlot;
296 xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
297 xvp->output_to_semantic_index[outAttr] = freeGeneric;
298 }
299 }
300
301 #if 0 /*debug*/
302 printf("vp output_to_slot[%d] = %d\n", outAttr,
303 xvp->output_to_slot[outAttr]);
304 #endif
305 }
306
307 assert(stvp->Base.Base.NumInstructions > 1);
308
309 st_translate_vertex_program(st, stvp, xvp->output_to_slot,
310 xvp->output_to_semantic_name,
311 xvp->output_to_semantic_index);
312
313 xvp->vp = stvp;
314
315 /* translated VP is up to date now */
316 xvp->serialNo = stvp->serialNo;
317 }
318
319 return xvp;
320 }
321
322
323 void
324 st_free_translated_vertex_programs(struct st_context *st,
325 struct translated_vertex_program *xvp)
326 {
327 struct translated_vertex_program *next;
328
329 while (xvp) {
330 next = xvp->next;
331 _mesa_free(xvp);
332 xvp = next;
333 }
334 }
335
336
337 static void *
338 get_passthrough_fs(struct st_context *st)
339 {
340 if (!st->passthrough_fs) {
341 st->passthrough_fs =
342 util_make_fragment_passthrough_shader(st->pipe);
343 }
344
345 return st->passthrough_fs;
346 }
347
348
349 static void
350 update_linkage( struct st_context *st )
351 {
352 struct st_vertex_program *stvp;
353 struct st_fragment_program *stfp;
354 struct translated_vertex_program *xvp;
355
356 /* find active shader and params -- Should be covered by
357 * ST_NEW_VERTEX_PROGRAM
358 */
359 assert(st->ctx->VertexProgram._Current);
360 stvp = st_vertex_program(st->ctx->VertexProgram._Current);
361 assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
362
363 assert(st->ctx->FragmentProgram._Current);
364 stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
365 assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
366
367 xvp = find_translated_vp(st, stvp, stfp);
368
369 st_reference_vertprog(st, &st->vp, stvp);
370 st_reference_fragprog(st, &st->fp, stfp);
371
372 cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
373
374 if (st->missing_textures) {
375 /* use a pass-through frag shader that uses no textures */
376 void *fs = get_passthrough_fs(st);
377 cso_set_fragment_shader_handle(st->cso_context, fs);
378 }
379 else {
380 cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
381 }
382
383 st->vertex_result_to_slot = xvp->output_to_slot;
384 }
385
386
387 const struct st_tracked_state st_update_shader = {
388 "st_update_shader", /* name */
389 { /* dirty */
390 0, /* mesa */
391 ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */
392 },
393 update_linkage /* update */
394 };