Merge commit 'origin/gallium-master-merge'
[mesa.git] / src / gallium / drivers / i965simple / brw_sf.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32
33 #include "brw_defines.h"
34 #include "brw_context.h"
35 #include "brw_eu.h"
36 #include "brw_util.h"
37 #include "brw_sf.h"
38 #include "brw_state.h"
39 #include "tgsi/tgsi_parse.h"
40
41
42 static void compile_sf_prog( struct brw_context *brw,
43 struct brw_sf_prog_key *key )
44 {
45 struct brw_sf_compile c;
46 const unsigned *program;
47 unsigned program_size;
48
49 memset(&c, 0, sizeof(c));
50
51 /* Begin the compilation:
52 */
53 brw_init_compile(&c.func);
54
55 c.key = *key;
56
57
58 c.nr_attrs = c.key.vp_output_count;
59 c.nr_attr_regs = (c.nr_attrs+1)/2;
60
61 c.nr_setup_attrs = c.key.fp_input_count + 1; /* +1 for position */
62 c.nr_setup_regs = (c.nr_setup_attrs+1)/2;
63
64 c.prog_data.urb_read_length = c.nr_attr_regs;
65 c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
66
67
68 /* Which primitive? Or all three?
69 */
70 switch (key->primitive) {
71 case SF_TRIANGLES:
72 c.nr_verts = 3;
73 brw_emit_tri_setup( &c );
74 break;
75 case SF_LINES:
76 c.nr_verts = 2;
77 brw_emit_line_setup( &c );
78 break;
79 case SF_POINTS:
80 c.nr_verts = 1;
81 brw_emit_point_setup( &c );
82 break;
83
84 case SF_UNFILLED_TRIS:
85 default:
86 assert(0);
87 return;
88 }
89
90
91
92 /* get the program
93 */
94 program = brw_get_program(&c.func, &program_size);
95
96 /* Upload
97 */
98 brw->sf.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_SF_PROG],
99 &c.key,
100 sizeof(c.key),
101 program,
102 program_size,
103 &c.prog_data,
104 &brw->sf.prog_data );
105 }
106
107
108 static boolean search_cache( struct brw_context *brw,
109 struct brw_sf_prog_key *key )
110 {
111 return brw_search_cache(&brw->cache[BRW_SF_PROG],
112 key, sizeof(*key),
113 &brw->sf.prog_data,
114 &brw->sf.prog_gs_offset);
115 }
116
117
118 /* Calculate interpolants for triangle and line rasterization.
119 */
120 static void upload_sf_prog( struct brw_context *brw )
121 {
122 const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
123 struct brw_sf_prog_key key;
124 struct tgsi_parse_context parse;
125 int i, done = 0;
126
127
128 memset(&key, 0, sizeof(key));
129
130 /* Populate the key, noting state dependencies:
131 */
132 /* CACHE_NEW_VS_PROG */
133 key.vp_output_count = brw->vs.prog_data->outputs_written;
134
135 /* BRW_NEW_FS */
136 key.fp_input_count = brw->attribs.FragmentProgram->info.file_max[TGSI_FILE_INPUT] + 1;
137
138
139 /* BRW_NEW_REDUCED_PRIMITIVE */
140 switch (brw->reduced_primitive) {
141 case PIPE_PRIM_TRIANGLES:
142 // if (key.attrs & (1<<VERT_RESULT_EDGE))
143 // key.primitive = SF_UNFILLED_TRIS;
144 // else
145 key.primitive = SF_TRIANGLES;
146 break;
147 case PIPE_PRIM_LINES:
148 key.primitive = SF_LINES;
149 break;
150 case PIPE_PRIM_POINTS:
151 key.primitive = SF_POINTS;
152 break;
153 }
154
155
156
157 /* Scan fp inputs to figure out what interpolation modes are
158 * required for each incoming vp output. There is an assumption
159 * that the state tracker makes sure there is a 1:1 linkage between
160 * these sets of attributes (XXX: position??)
161 */
162 tgsi_parse_init( &parse, fs->program.tokens );
163 while( !done &&
164 !tgsi_parse_end_of_tokens( &parse ) )
165 {
166 tgsi_parse_token( &parse );
167
168 switch( parse.FullToken.Token.Type ) {
169 case TGSI_TOKEN_TYPE_DECLARATION:
170 if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT)
171 {
172 int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
173 int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;
174 int interp_mode = parse.FullToken.FullDeclaration.Declaration.Interpolate;
175 //int semantic = parse.FullToken.FullDeclaration.Semantic.SemanticName;
176 //int semantic_index = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
177
178 debug_printf("fs input %d..%d interp mode %d\n", first, last, interp_mode);
179
180 switch (interp_mode) {
181 case TGSI_INTERPOLATE_CONSTANT:
182 for (i = first; i <= last; i++)
183 key.const_mask |= (1 << i);
184 break;
185 case TGSI_INTERPOLATE_LINEAR:
186 for (i = first; i <= last; i++)
187 key.linear_mask |= (1 << i);
188 break;
189 case TGSI_INTERPOLATE_PERSPECTIVE:
190 for (i = first; i <= last; i++)
191 key.persp_mask |= (1 << i);
192 break;
193 default:
194 break;
195 }
196
197 /* Also need stuff for flat shading, twosided color.
198 */
199
200 }
201 break;
202 default:
203 done = 1;
204 break;
205 }
206 }
207
208 /* Hack: Adjust for position. Optimize away when not required (ie
209 * for perspective interpolation).
210 */
211 key.persp_mask <<= 1;
212 key.linear_mask <<= 1;
213 key.linear_mask |= 1;
214 key.const_mask <<= 1;
215
216 debug_printf("key.persp_mask: %x\n", key.persp_mask);
217 debug_printf("key.linear_mask: %x\n", key.linear_mask);
218 debug_printf("key.const_mask: %x\n", key.const_mask);
219
220
221 // key.do_point_sprite = brw->attribs.Point->PointSprite;
222 // key.SpriteOrigin = brw->attribs.Point->SpriteOrigin;
223
224 // key.do_flat_shading = (brw->attribs.Raster->flatshade);
225 // key.do_twoside_color = (brw->attribs.Light->Enabled && brw->attribs.Light->Model.TwoSide);
226
227 // if (key.do_twoside_color)
228 // key.frontface_ccw = (brw->attribs.Polygon->FrontFace == GL_CCW);
229
230
231 if (!search_cache(brw, &key))
232 compile_sf_prog( brw, &key );
233 }
234
235
236 const struct brw_tracked_state brw_sf_prog = {
237 .dirty = {
238 .brw = (BRW_NEW_RASTERIZER |
239 BRW_NEW_REDUCED_PRIMITIVE |
240 BRW_NEW_VS |
241 BRW_NEW_FS),
242 .cache = 0,
243 },
244 .update = upload_sf_prog
245 };
246
247
248
249 #if 0
250 /* Build a struct like the one we'd like the state tracker to pass to
251 * us.
252 */
253 static void update_sf_linkage( struct brw_context *brw )
254 {
255 const struct brw_vertex_program *vs = brw->attribs.VertexProgram;
256 const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
257 struct pipe_setup_linkage state;
258 struct tgsi_parse_context parse;
259
260 int i, j;
261 int nr_vp_outputs = 0;
262 int done = 0;
263
264 struct {
265 unsigned semantic:8;
266 unsigned semantic_index:16;
267 } fp_semantic[32], vp_semantic[32];
268
269 memset(&state, 0, sizeof(state));
270
271 state.fp_input_count = 0;
272
273
274
275
276
277
278 assert(state.fp_input_count == fs->program.num_inputs);
279
280
281 /* Then scan vp outputs
282 */
283 done = 0;
284 tgsi_parse_init( &parse, vs->program.tokens );
285 while( !done &&
286 !tgsi_parse_end_of_tokens( &parse ) )
287 {
288 tgsi_parse_token( &parse );
289
290 switch( parse.FullToken.Token.Type ) {
291 case TGSI_TOKEN_TYPE_DECLARATION:
292 if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT)
293 {
294 int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
295 int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;
296
297 for (i = first; i < last; i++) {
298 vp_semantic[i].semantic =
299 parse.FullToken.FullDeclaration.Semantic.SemanticName;
300 vp_semantic[i].semantic_index =
301 parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
302 }
303
304 assert(last > nr_vp_outputs);
305 nr_vp_outputs = last;
306 }
307 break;
308 default:
309 done = 1;
310 break;
311 }
312 }
313
314
315 /* Now match based on semantic information.
316 */
317 for (i = 0; i< state.fp_input_count; i++) {
318 for (j = 0; j < nr_vp_outputs; j++) {
319 if (fp_semantic[i].semantic == vp_semantic[j].semantic &&
320 fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
321 state.fp_input[i].vp_output = j;
322 }
323 }
324 if (fp_semantic[i].semantic == TGSI_SEMANTIC_COLOR) {
325 for (j = 0; j < nr_vp_outputs; j++) {
326 if (TGSI_SEMANTIC_BCOLOR == vp_semantic[j].semantic &&
327 fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
328 state.fp_input[i].bf_vp_output = j;
329 }
330 }
331 }
332 }
333
334 if (memcmp(&brw->sf.linkage, &state, sizeof(state)) != 0) {
335 brw->sf.linkage = state;
336 brw->state.dirty.brw |= BRW_NEW_SF_LINKAGE;
337 }
338 }
339
340
341 const struct brw_tracked_state brw_sf_linkage = {
342 .dirty = {
343 .brw = (BRW_NEW_VS |
344 BRW_NEW_FS),
345 .cache = 0,
346 },
347 .update = update_sf_linkage
348 };
349
350
351 #endif