1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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 VMWARE 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.
26 **************************************************************************/
28 /* Authors: Keith Whitwell <keithw@vmware.com>
31 #include "util/u_math.h"
32 #include "util/u_memory.h"
34 #include "pipe/p_shader_tokens.h"
37 #include "draw_pipe.h"
40 /** subclass of draw_stage */
43 struct draw_stage stage
;
45 uint num_flat_attribs
;
46 uint flat_attribs
[PIPE_MAX_SHADER_OUTPUTS
]; /* flatshaded attribs */
50 static inline struct flat_stage
*
51 flat_stage(struct draw_stage
*stage
)
53 return (struct flat_stage
*) stage
;
57 /** Copy all the constant attributes from 'src' vertex to 'dst' vertex */
58 static inline void copy_flats( struct draw_stage
*stage
,
59 struct vertex_header
*dst
,
60 const struct vertex_header
*src
)
62 const struct flat_stage
*flat
= flat_stage(stage
);
65 for (i
= 0; i
< flat
->num_flat_attribs
; i
++) {
66 const uint attr
= flat
->flat_attribs
[i
];
67 COPY_4FV(dst
->data
[attr
], src
->data
[attr
]);
72 /** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
73 static inline void copy_flats2( struct draw_stage
*stage
,
74 struct vertex_header
*dst0
,
75 struct vertex_header
*dst1
,
76 const struct vertex_header
*src
)
78 const struct flat_stage
*flat
= flat_stage(stage
);
80 for (i
= 0; i
< flat
->num_flat_attribs
; i
++) {
81 const uint attr
= flat
->flat_attribs
[i
];
82 COPY_4FV(dst0
->data
[attr
], src
->data
[attr
]);
83 COPY_4FV(dst1
->data
[attr
], src
->data
[attr
]);
89 * Flatshade tri. Not required for clipping which handles this on its own,
90 * but required for unfilled tris and other primitive-changing stages
91 * (like widelines). If no such stages are active, handled by hardware.
93 static void flatshade_tri_0( struct draw_stage
*stage
,
94 struct prim_header
*header
)
96 struct prim_header tmp
;
98 tmp
.det
= header
->det
;
99 tmp
.flags
= header
->flags
;
100 tmp
.pad
= header
->pad
;
101 tmp
.v
[0] = header
->v
[0];
102 tmp
.v
[1] = dup_vert(stage
, header
->v
[1], 0);
103 tmp
.v
[2] = dup_vert(stage
, header
->v
[2], 1);
105 copy_flats2(stage
, tmp
.v
[1], tmp
.v
[2], tmp
.v
[0]);
107 stage
->next
->tri( stage
->next
, &tmp
);
111 static void flatshade_tri_2( struct draw_stage
*stage
,
112 struct prim_header
*header
)
114 struct prim_header tmp
;
116 tmp
.det
= header
->det
;
117 tmp
.flags
= header
->flags
;
118 tmp
.pad
= header
->pad
;
119 tmp
.v
[0] = dup_vert(stage
, header
->v
[0], 0);
120 tmp
.v
[1] = dup_vert(stage
, header
->v
[1], 1);
121 tmp
.v
[2] = header
->v
[2];
123 copy_flats2(stage
, tmp
.v
[0], tmp
.v
[1], tmp
.v
[2]);
125 stage
->next
->tri( stage
->next
, &tmp
);
132 static void flatshade_line_0( struct draw_stage
*stage
,
133 struct prim_header
*header
)
135 struct prim_header tmp
;
137 tmp
.det
= header
->det
;
138 tmp
.flags
= header
->flags
;
139 tmp
.pad
= header
->pad
;
140 tmp
.v
[0] = header
->v
[0];
141 tmp
.v
[1] = dup_vert(stage
, header
->v
[1], 0);
143 copy_flats(stage
, tmp
.v
[1], tmp
.v
[0]);
145 stage
->next
->line( stage
->next
, &tmp
);
149 static void flatshade_line_1( struct draw_stage
*stage
,
150 struct prim_header
*header
)
152 struct prim_header tmp
;
154 tmp
.det
= header
->det
;
155 tmp
.flags
= header
->flags
;
156 tmp
.pad
= header
->pad
;
157 tmp
.v
[0] = dup_vert(stage
, header
->v
[0], 0);
158 tmp
.v
[1] = header
->v
[1];
160 copy_flats(stage
, tmp
.v
[0], tmp
.v
[1]);
162 stage
->next
->line( stage
->next
, &tmp
);
167 find_interp(const struct draw_fragment_shader
*fs
, int *indexed_interp
,
168 uint semantic_name
, uint semantic_index
)
171 /* If it's gl_{Front,Back}{,Secondary}Color, pick up the mode
172 * from the array we've filled before. */
173 if ((semantic_name
== TGSI_SEMANTIC_COLOR
||
174 semantic_name
== TGSI_SEMANTIC_BCOLOR
) &&
175 semantic_index
< 2) {
176 interp
= indexed_interp
[semantic_index
];
178 /* Otherwise, search in the FS inputs, with a decent default
179 * if we don't find it.
182 interp
= TGSI_INTERPOLATE_PERSPECTIVE
;
184 for (j
= 0; j
< fs
->info
.num_inputs
; j
++) {
185 if (semantic_name
== fs
->info
.input_semantic_name
[j
] &&
186 semantic_index
== fs
->info
.input_semantic_index
[j
]) {
187 interp
= fs
->info
.input_interpolate
[j
];
197 static void flatshade_init_state( struct draw_stage
*stage
)
199 struct flat_stage
*flat
= flat_stage(stage
);
200 const struct draw_context
*draw
= stage
->draw
;
201 const struct draw_fragment_shader
*fs
= draw
->fs
.fragment_shader
;
202 const struct tgsi_shader_info
*info
= draw_get_shader_info(draw
);
205 /* Find which vertex shader outputs need constant interpolation, make a list */
207 /* XXX: this code is a near exact copy of the one in clip_init_state.
208 * The latter also cares about perspective though.
211 /* First pick up the interpolation mode for
212 * gl_Color/gl_SecondaryColor, with the correct default.
214 int indexed_interp
[2];
215 indexed_interp
[0] = indexed_interp
[1] = draw
->rasterizer
->flatshade
?
216 TGSI_INTERPOLATE_CONSTANT
: TGSI_INTERPOLATE_PERSPECTIVE
;
219 for (i
= 0; i
< fs
->info
.num_inputs
; i
++) {
220 if (fs
->info
.input_semantic_name
[i
] == TGSI_SEMANTIC_COLOR
&&
221 fs
->info
.input_semantic_index
[i
] < 2) {
222 if (fs
->info
.input_interpolate
[i
] != TGSI_INTERPOLATE_COLOR
)
223 indexed_interp
[fs
->info
.input_semantic_index
[i
]] = fs
->info
.input_interpolate
[i
];
228 /* Then resolve the interpolation mode for every output attribute.
230 * Given how the rest of the code, the most efficient way is to
231 * have a vector of flat-mode attributes.
233 flat
->num_flat_attribs
= 0;
234 for (i
= 0; i
< info
->num_outputs
; i
++) {
235 /* Find the interpolation mode for a specific attribute */
236 int interp
= find_interp(fs
, indexed_interp
,
237 info
->output_semantic_name
[i
],
238 info
->output_semantic_index
[i
]);
239 /* If it's flat, add it to the flat vector. */
241 if (interp
== TGSI_INTERPOLATE_CONSTANT
||
242 (interp
== TGSI_INTERPOLATE_COLOR
&& draw
->rasterizer
->flatshade
)) {
243 flat
->flat_attribs
[flat
->num_flat_attribs
] = i
;
244 flat
->num_flat_attribs
++;
247 /* Search the extra vertex attributes */
248 for (j
= 0; j
< draw
->extra_shader_outputs
.num
; j
++) {
249 /* Find the interpolation mode for a specific attribute */
250 int interp
= find_interp(fs
, indexed_interp
,
251 draw
->extra_shader_outputs
.semantic_name
[j
],
252 draw
->extra_shader_outputs
.semantic_index
[j
]);
253 /* If it's flat, add it to the flat vector. */
254 if (interp
== TGSI_INTERPOLATE_CONSTANT
) {
255 flat
->flat_attribs
[flat
->num_flat_attribs
] = i
+ j
;
256 flat
->num_flat_attribs
++;
260 /* Choose flatshade routine according to provoking vertex:
262 if (draw
->rasterizer
->flatshade_first
) {
263 stage
->line
= flatshade_line_0
;
264 stage
->tri
= flatshade_tri_0
;
267 stage
->line
= flatshade_line_1
;
268 stage
->tri
= flatshade_tri_2
;
272 static void flatshade_first_tri( struct draw_stage
*stage
,
273 struct prim_header
*header
)
275 flatshade_init_state( stage
);
276 stage
->tri( stage
, header
);
279 static void flatshade_first_line( struct draw_stage
*stage
,
280 struct prim_header
*header
)
282 flatshade_init_state( stage
);
283 stage
->line( stage
, header
);
287 static void flatshade_flush( struct draw_stage
*stage
,
290 stage
->tri
= flatshade_first_tri
;
291 stage
->line
= flatshade_first_line
;
292 stage
->next
->flush( stage
->next
, flags
);
296 static void flatshade_reset_stipple_counter( struct draw_stage
*stage
)
298 stage
->next
->reset_stipple_counter( stage
->next
);
302 static void flatshade_destroy( struct draw_stage
*stage
)
304 draw_free_temp_verts( stage
);
310 * Create flatshading drawing stage.
312 struct draw_stage
*draw_flatshade_stage( struct draw_context
*draw
)
314 struct flat_stage
*flatshade
= CALLOC_STRUCT(flat_stage
);
318 flatshade
->stage
.draw
= draw
;
319 flatshade
->stage
.name
= "flatshade";
320 flatshade
->stage
.next
= NULL
;
321 flatshade
->stage
.point
= draw_pipe_passthrough_point
;
322 flatshade
->stage
.line
= flatshade_first_line
;
323 flatshade
->stage
.tri
= flatshade_first_tri
;
324 flatshade
->stage
.flush
= flatshade_flush
;
325 flatshade
->stage
.reset_stipple_counter
= flatshade_reset_stipple_counter
;
326 flatshade
->stage
.destroy
= flatshade_destroy
;
328 if (!draw_alloc_temp_verts( &flatshade
->stage
, 2 ))
331 return &flatshade
->stage
;
335 flatshade
->stage
.destroy( &flatshade
->stage
);