2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
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:
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.
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.
26 **********************************************************************/
29 * Keith Whitwell <keith@tungstengraphics.com>
33 #include "brw_defines.h"
34 #include "brw_context.h"
38 #include "brw_state.h"
39 #include "tgsi/tgsi_parse.h"
42 static void compile_sf_prog( struct brw_context
*brw
,
43 struct brw_sf_prog_key
*key
)
45 struct brw_sf_compile c
;
46 const unsigned *program
;
47 unsigned program_size
;
49 memset(&c
, 0, sizeof(c
));
51 /* Begin the compilation:
53 brw_init_compile(&c
.func
);
58 c
.nr_attrs
= c
.key
.vp_output_count
;
59 c
.nr_attr_regs
= (c
.nr_attrs
+1)/2;
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;
64 c
.prog_data
.urb_read_length
= c
.nr_attr_regs
;
65 c
.prog_data
.urb_entry_size
= c
.nr_setup_regs
* 2;
68 /* Which primitive? Or all three?
70 switch (key
->primitive
) {
73 brw_emit_tri_setup( &c
);
77 brw_emit_line_setup( &c
);
81 brw_emit_point_setup( &c
);
84 case SF_UNFILLED_TRIS
:
94 program
= brw_get_program(&c
.func
, &program_size
);
98 brw
->sf
.prog_gs_offset
= brw_upload_cache( &brw
->cache
[BRW_SF_PROG
],
104 &brw
->sf
.prog_data
);
108 static boolean
search_cache( struct brw_context
*brw
,
109 struct brw_sf_prog_key
*key
)
111 return brw_search_cache(&brw
->cache
[BRW_SF_PROG
],
114 &brw
->sf
.prog_gs_offset
);
118 /* Calculate interpolants for triangle and line rasterization.
120 static void upload_sf_prog( struct brw_context
*brw
)
122 const struct brw_fragment_program
*fs
= brw
->attribs
.FragmentProgram
;
123 struct brw_sf_prog_key key
;
124 struct tgsi_parse_context parse
;
128 memset(&key
, 0, sizeof(key
));
130 /* Populate the key, noting state dependencies:
132 /* CACHE_NEW_VS_PROG */
133 key
.vp_output_count
= brw
->vs
.prog_data
->outputs_written
;
136 key
.fp_input_count
= brw
->attribs
.FragmentProgram
->info
.file_max
[TGSI_FILE_INPUT
] + 1;
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;
145 key
.primitive
= SF_TRIANGLES
;
147 case PIPE_PRIM_LINES
:
148 key
.primitive
= SF_LINES
;
150 case PIPE_PRIM_POINTS
:
151 key
.primitive
= SF_POINTS
;
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??)
162 tgsi_parse_init( &parse
, fs
->program
.tokens
);
164 !tgsi_parse_end_of_tokens( &parse
) )
166 tgsi_parse_token( &parse
);
168 switch( parse
.FullToken
.Token
.Type
) {
169 case TGSI_TOKEN_TYPE_DECLARATION
:
170 if (parse
.FullToken
.FullDeclaration
.Declaration
.File
== TGSI_FILE_INPUT
)
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;
178 debug_printf("fs input %d..%d interp mode %d\n", first
, last
, interp_mode
);
180 switch (interp_mode
) {
181 case TGSI_INTERPOLATE_CONSTANT
:
182 for (i
= first
; i
<= last
; i
++)
183 key
.const_mask
|= (1 << i
);
185 case TGSI_INTERPOLATE_LINEAR
:
186 for (i
= first
; i
<= last
; i
++)
187 key
.linear_mask
|= (1 << i
);
189 case TGSI_INTERPOLATE_PERSPECTIVE
:
190 for (i
= first
; i
<= last
; i
++)
191 key
.persp_mask
|= (1 << i
);
197 /* Also need stuff for flat shading, twosided color.
208 /* Hack: Adjust for position. Optimize away when not required (ie
209 * for perspective interpolation).
211 key
.persp_mask
<<= 1;
212 key
.linear_mask
<<= 1;
213 key
.linear_mask
|= 1;
214 key
.const_mask
<<= 1;
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
);
221 // key.do_point_sprite = brw->attribs.Point->PointSprite;
222 // key.SpriteOrigin = brw->attribs.Point->SpriteOrigin;
224 // key.do_flat_shading = (brw->attribs.Raster->flatshade);
225 // key.do_twoside_color = (brw->attribs.Light->Enabled && brw->attribs.Light->Model.TwoSide);
227 // if (key.do_twoside_color)
228 // key.frontface_ccw = (brw->attribs.Polygon->FrontFace == GL_CCW);
231 if (!search_cache(brw
, &key
))
232 compile_sf_prog( brw
, &key
);
236 const struct brw_tracked_state brw_sf_prog
= {
238 .brw
= (BRW_NEW_RASTERIZER
|
239 BRW_NEW_REDUCED_PRIMITIVE
|
244 .update
= upload_sf_prog
250 /* Build a struct like the one we'd like the state tracker to pass to
253 static void update_sf_linkage( struct brw_context
*brw
)
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
;
261 int nr_vp_outputs
= 0;
266 unsigned semantic_index
:16;
267 } fp_semantic
[32], vp_semantic
[32];
269 memset(&state
, 0, sizeof(state
));
271 state
.fp_input_count
= 0;
278 assert(state
.fp_input_count
== fs
->program
.num_inputs
);
281 /* Then scan vp outputs
284 tgsi_parse_init( &parse
, vs
->program
.tokens
);
286 !tgsi_parse_end_of_tokens( &parse
) )
288 tgsi_parse_token( &parse
);
290 switch( parse
.FullToken
.Token
.Type
) {
291 case TGSI_TOKEN_TYPE_DECLARATION
:
292 if (parse
.FullToken
.FullDeclaration
.Declaration
.File
== TGSI_FILE_INPUT
)
294 int first
= parse
.FullToken
.FullDeclaration
.DeclarationRange
.First
;
295 int last
= parse
.FullToken
.FullDeclaration
.DeclarationRange
.Last
;
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
;
304 assert(last
> nr_vp_outputs
);
305 nr_vp_outputs
= last
;
315 /* Now match based on semantic information.
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
;
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
;
334 if (memcmp(&brw
->sf
.linkage
, &state
, sizeof(state
)) != 0) {
335 brw
->sf
.linkage
= state
;
336 brw
->state
.dirty
.brw
|= BRW_NEW_SF_LINKAGE
;
341 const struct brw_tracked_state brw_sf_linkage
= {
347 .update
= update_sf_linkage