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 interp
= indexed_interp
[semantic_index
];
177 /* Otherwise, search in the FS inputs, with a decent default
178 * if we don't find it.
181 interp
= TGSI_INTERPOLATE_PERSPECTIVE
;
183 for (j
= 0; j
< fs
->info
.num_inputs
; j
++) {
184 if (semantic_name
== fs
->info
.input_semantic_name
[j
] &&
185 semantic_index
== fs
->info
.input_semantic_index
[j
]) {
186 interp
= fs
->info
.input_interpolate
[j
];
196 static void flatshade_init_state( struct draw_stage
*stage
)
198 struct flat_stage
*flat
= flat_stage(stage
);
199 const struct draw_context
*draw
= stage
->draw
;
200 const struct draw_fragment_shader
*fs
= draw
->fs
.fragment_shader
;
201 const struct tgsi_shader_info
*info
= draw_get_shader_info(draw
);
204 /* Find which vertex shader outputs need constant interpolation, make a list */
206 /* XXX: this code is a near exact copy of the one in clip_init_state.
207 * The latter also cares about perspective though.
210 /* First pick up the interpolation mode for
211 * gl_Color/gl_SecondaryColor, with the correct default.
213 int indexed_interp
[2];
214 indexed_interp
[0] = indexed_interp
[1] = draw
->rasterizer
->flatshade
?
215 TGSI_INTERPOLATE_CONSTANT
: TGSI_INTERPOLATE_PERSPECTIVE
;
218 for (i
= 0; i
< fs
->info
.num_inputs
; i
++) {
219 if (fs
->info
.input_semantic_name
[i
] == TGSI_SEMANTIC_COLOR
) {
220 if (fs
->info
.input_interpolate
[i
] != TGSI_INTERPOLATE_COLOR
)
221 indexed_interp
[fs
->info
.input_semantic_index
[i
]] = fs
->info
.input_interpolate
[i
];
226 /* Then resolve the interpolation mode for every output attribute.
228 * Given how the rest of the code, the most efficient way is to
229 * have a vector of flat-mode attributes.
231 flat
->num_flat_attribs
= 0;
232 for (i
= 0; i
< info
->num_outputs
; i
++) {
233 /* Find the interpolation mode for a specific attribute */
234 int interp
= find_interp(fs
, indexed_interp
,
235 info
->output_semantic_name
[i
],
236 info
->output_semantic_index
[i
]);
237 /* If it's flat, add it to the flat vector. */
239 if (interp
== TGSI_INTERPOLATE_CONSTANT
) {
240 flat
->flat_attribs
[flat
->num_flat_attribs
] = i
;
241 flat
->num_flat_attribs
++;
244 /* Search the extra vertex attributes */
245 for (j
= 0; j
< draw
->extra_shader_outputs
.num
; j
++) {
246 /* Find the interpolation mode for a specific attribute */
247 int interp
= find_interp(fs
, indexed_interp
,
248 draw
->extra_shader_outputs
.semantic_name
[j
],
249 draw
->extra_shader_outputs
.semantic_index
[j
]);
250 /* If it's flat, add it to the flat vector. */
251 if (interp
== TGSI_INTERPOLATE_CONSTANT
) {
252 flat
->flat_attribs
[flat
->num_flat_attribs
] = i
+ j
;
253 flat
->num_flat_attribs
++;
257 /* Choose flatshade routine according to provoking vertex:
259 if (draw
->rasterizer
->flatshade_first
) {
260 stage
->line
= flatshade_line_0
;
261 stage
->tri
= flatshade_tri_0
;
264 stage
->line
= flatshade_line_1
;
265 stage
->tri
= flatshade_tri_2
;
269 static void flatshade_first_tri( struct draw_stage
*stage
,
270 struct prim_header
*header
)
272 flatshade_init_state( stage
);
273 stage
->tri( stage
, header
);
276 static void flatshade_first_line( struct draw_stage
*stage
,
277 struct prim_header
*header
)
279 flatshade_init_state( stage
);
280 stage
->line( stage
, header
);
284 static void flatshade_flush( struct draw_stage
*stage
,
287 stage
->tri
= flatshade_first_tri
;
288 stage
->line
= flatshade_first_line
;
289 stage
->next
->flush( stage
->next
, flags
);
293 static void flatshade_reset_stipple_counter( struct draw_stage
*stage
)
295 stage
->next
->reset_stipple_counter( stage
->next
);
299 static void flatshade_destroy( struct draw_stage
*stage
)
301 draw_free_temp_verts( stage
);
307 * Create flatshading drawing stage.
309 struct draw_stage
*draw_flatshade_stage( struct draw_context
*draw
)
311 struct flat_stage
*flatshade
= CALLOC_STRUCT(flat_stage
);
315 flatshade
->stage
.draw
= draw
;
316 flatshade
->stage
.name
= "flatshade";
317 flatshade
->stage
.next
= NULL
;
318 flatshade
->stage
.point
= draw_pipe_passthrough_point
;
319 flatshade
->stage
.line
= flatshade_first_line
;
320 flatshade
->stage
.tri
= flatshade_first_tri
;
321 flatshade
->stage
.flush
= flatshade_flush
;
322 flatshade
->stage
.reset_stipple_counter
= flatshade_reset_stipple_counter
;
323 flatshade
->stage
.destroy
= flatshade_destroy
;
325 if (!draw_alloc_temp_verts( &flatshade
->stage
, 2 ))
328 return &flatshade
->stage
;
332 flatshade
->stage
.destroy( &flatshade
->stage
);