gallium: free bitmap fragment shaders, misc clean-up
[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
43 #include "pipe/p_context.h"
44 #include "pipe/p_shader_tokens.h"
45
46 #include "cso_cache/cso_context.h"
47
48 #include "st_context.h"
49 #include "st_atom.h"
50 #include "st_program.h"
51 #include "st_atom_shader.h"
52 #include "st_mesa_to_tgsi.h"
53
54
55 /**
56 * This represents a vertex program, especially translated to match
57 * the inputs of a particular fragment shader.
58 */
59 struct translated_vertex_program
60 {
61 struct st_vertex_program *master;
62
63 /** The fragment shader "signature" this vertex shader is meant for: */
64 GLbitfield frag_inputs;
65
66 /** Compared against master vertex program's serialNo: */
67 GLuint serialNo;
68
69 /** Maps VERT_RESULT_x to slot */
70 GLuint output_to_slot[VERT_RESULT_MAX];
71
72 /** Pointer to the translated vertex program */
73 struct st_vertex_program *vp;
74
75 struct translated_vertex_program *next; /**< next in linked list */
76 };
77
78
79
80 /**
81 * Given a vertex program output attribute, return the corresponding
82 * fragment program input attribute.
83 * \return -1 for vertex outputs that have no corresponding fragment input
84 */
85 static GLint
86 vp_out_to_fp_in(GLuint vertResult)
87 {
88 if (vertResult >= VERT_RESULT_TEX0 &&
89 vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
90 return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
91
92 if (vertResult >= VERT_RESULT_VAR0 &&
93 vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
94 return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
95
96 switch (vertResult) {
97 case VERT_RESULT_HPOS:
98 return FRAG_ATTRIB_WPOS;
99 case VERT_RESULT_COL0:
100 return FRAG_ATTRIB_COL0;
101 case VERT_RESULT_COL1:
102 return FRAG_ATTRIB_COL1;
103 case VERT_RESULT_FOGC:
104 return FRAG_ATTRIB_FOGC;
105 default:
106 /* Back-face colors, edge flags, etc */
107 return -1;
108 }
109 }
110
111
112 /**
113 * Find a translated vertex program that corresponds to stvp and
114 * has outputs matched to stfp's inputs.
115 * This performs vertex and fragment translation (to TGSI) when needed.
116 */
117 static struct translated_vertex_program *
118 find_translated_vp(struct st_context *st,
119 struct st_vertex_program *stvp,
120 struct st_fragment_program *stfp)
121 {
122 static const GLuint UNUSED = ~0;
123 struct translated_vertex_program *xvp;
124 const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
125
126 /*
127 * Translate fragment program if needed.
128 */
129 if (!stfp->state.tokens) {
130 GLuint inAttr, numIn = 0;
131
132 for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
133 if (fragInputsRead & (1 << inAttr)) {
134 stfp->input_to_slot[inAttr] = numIn;
135 numIn++;
136 }
137 else {
138 stfp->input_to_slot[inAttr] = UNUSED;
139 }
140 }
141
142 stfp->num_input_slots = numIn;
143
144 assert(stfp->Base.Base.NumInstructions > 1);
145
146 st_translate_fragment_program(st, stfp, stfp->input_to_slot);
147 }
148
149
150 /* See if we've got a translated vertex program whose outputs match
151 * the fragment program's inputs.
152 * XXX This could be a hash lookup, using InputsRead as the key.
153 */
154 for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
155 if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
156 break;
157 }
158 }
159
160 /* No? Allocate translated vp object now */
161 if (!xvp) {
162 xvp = CALLOC_STRUCT(translated_vertex_program);
163 xvp->frag_inputs = fragInputsRead;
164 xvp->master = stvp;
165
166 xvp->next = stfp->vertex_programs;
167 stfp->vertex_programs = xvp;
168 }
169
170 /* See if we need to translate vertex program to TGSI form */
171 if (xvp->serialNo != stvp->serialNo) {
172 GLuint outAttr, dummySlot;
173 const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
174 GLuint numVpOuts = 0;
175
176 /* Compute mapping of vertex program outputs to slots, which depends
177 * on the fragment program's input->slot mapping.
178 */
179 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
180 /* set default: */
181 xvp->output_to_slot[outAttr] = UNUSED;
182
183 if (outAttr == VERT_RESULT_HPOS) {
184 /* always put xformed position into slot zero */
185 xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
186 numVpOuts++;
187 }
188 else if (outputsWritten & (1 << outAttr)) {
189 /* see if the frag prog wants this vert output */
190 GLint fpInAttrib = vp_out_to_fp_in(outAttr);
191 if (fpInAttrib >= 0) {
192 GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
193 if (fpInSlot != ~0) {
194 GLuint vpOutSlot = stfp->input_map[fpInSlot];
195 xvp->output_to_slot[outAttr] = vpOutSlot;
196 numVpOuts++;
197 }
198 }
199 else if (outAttr == VERT_RESULT_PSIZ ||
200 outAttr == VERT_RESULT_BFC0 ||
201 outAttr == VERT_RESULT_BFC1) {
202 /* backface colors go into last slots */
203 xvp->output_to_slot[outAttr] = numVpOuts++;
204 }
205 }
206 /*
207 printf("output_to_slot[%d] = %d\n", outAttr,
208 xvp->output_to_slot[outAttr]);
209 */
210 }
211
212 /* Unneeded vertex program outputs will go to this slot.
213 * We could use this info to do dead code elimination in the
214 * vertex program.
215 */
216 dummySlot = numVpOuts;
217
218 /* Map vert program outputs that aren't used to the dummy slot */
219 for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
220 if (outputsWritten & (1 << outAttr)) {
221 if (xvp->output_to_slot[outAttr] == UNUSED)
222 xvp->output_to_slot[outAttr] = dummySlot;
223 }
224 }
225
226 assert(stvp->Base.Base.NumInstructions > 1);
227
228 st_translate_vertex_program(st, stvp, xvp->output_to_slot);
229
230 xvp->vp = stvp;
231
232 /* translated VP is up to date now */
233 xvp->serialNo = stvp->serialNo;
234 }
235
236 return xvp;
237 }
238
239
240 void
241 st_free_translated_vertex_programs(struct st_context *st,
242 struct translated_vertex_program *xvp)
243 {
244 struct translated_vertex_program *next;
245
246 while (xvp) {
247 next = xvp->next;
248 free(xvp);
249 xvp = next;
250 }
251 }
252
253
254
255 static void
256 update_linkage( struct st_context *st )
257 {
258 struct st_vertex_program *stvp;
259 struct st_fragment_program *stfp;
260 struct translated_vertex_program *xvp;
261
262 /* find active shader and params -- Should be covered by
263 * ST_NEW_VERTEX_PROGRAM
264 */
265 assert(st->ctx->VertexProgram._Current);
266 stvp = st_vertex_program(st->ctx->VertexProgram._Current);
267
268 assert(st->ctx->FragmentProgram._Current);
269 stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
270
271 xvp = find_translated_vp(st, stvp, stfp);
272
273 st->vp = stvp;
274 st->fp = stfp;
275
276 st->pipe->bind_vs_state(st->pipe, stvp->driver_shader);
277 st->pipe->bind_fs_state(st->pipe, stfp->driver_shader);
278
279 st->vertex_result_to_slot = xvp->output_to_slot;
280 }
281
282
283 const struct st_tracked_state st_update_shader = {
284 .name = "st_update_shader",
285 .dirty = {
286 .mesa = 0,
287 .st = ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM
288 },
289 .update = update_linkage
290 };