st/mesa: fix pipe_rasterizer_state::scissor with multiple viewports
[mesa.git] / src / mesa / state_tracker / st_atom_rasterizer.c
1 /**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
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 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.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Keith Whitwell <keithw@vmware.com>
31 */
32
33 #include "main/macros.h"
34 #include "main/framebuffer.h"
35 #include "main/state.h"
36 #include "st_context.h"
37 #include "st_atom.h"
38 #include "st_debug.h"
39 #include "st_program.h"
40 #include "pipe/p_context.h"
41 #include "pipe/p_defines.h"
42 #include "cso_cache/cso_context.h"
43
44
45 static GLuint translate_fill( GLenum mode )
46 {
47 switch (mode) {
48 case GL_POINT:
49 return PIPE_POLYGON_MODE_POINT;
50 case GL_LINE:
51 return PIPE_POLYGON_MODE_LINE;
52 case GL_FILL:
53 return PIPE_POLYGON_MODE_FILL;
54 case GL_FILL_RECTANGLE_NV:
55 return PIPE_POLYGON_MODE_FILL_RECTANGLE;
56 default:
57 assert(0);
58 return 0;
59 }
60 }
61
62
63
64 void st_update_rasterizer( struct st_context *st )
65 {
66 struct gl_context *ctx = st->ctx;
67 struct pipe_rasterizer_state *raster = &st->state.rasterizer;
68 const struct gl_program *vertProg = ctx->VertexProgram._Current;
69 const struct gl_program *fragProg = ctx->FragmentProgram._Current;
70
71 memset(raster, 0, sizeof(*raster));
72
73 /* _NEW_POLYGON, _NEW_BUFFERS
74 */
75 {
76 raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW);
77
78 /* _NEW_TRANSFORM */
79 if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT) {
80 raster->front_ccw ^= 1;
81 }
82
83 /*
84 * Gallium's surfaces are Y=0=TOP orientation. OpenGL is the
85 * opposite. Window system surfaces are Y=0=TOP. Mesa's FBOs
86 * must match OpenGL conventions so FBOs use Y=0=BOTTOM. In that
87 * case, we must invert Y and flip the notion of front vs. back.
88 */
89 if (st->state.fb_orientation == Y_0_BOTTOM) {
90 /* Drawing to an FBO. The viewport will be inverted. */
91 raster->front_ccw ^= 1;
92 }
93 }
94
95 /* _NEW_LIGHT
96 */
97 raster->flatshade = ctx->Light.ShadeModel == GL_FLAT;
98
99 raster->flatshade_first = ctx->Light.ProvokingVertex ==
100 GL_FIRST_VERTEX_CONVENTION_EXT;
101
102 /* _NEW_LIGHT | _NEW_PROGRAM */
103 raster->light_twoside = _mesa_vertex_program_two_side_enabled(ctx);
104
105 /*_NEW_LIGHT | _NEW_BUFFERS */
106 raster->clamp_vertex_color = !st->clamp_vert_color_in_shader &&
107 ctx->Light._ClampVertexColor;
108
109 /* _NEW_POLYGON
110 */
111 if (ctx->Polygon.CullFlag) {
112 switch (ctx->Polygon.CullFaceMode) {
113 case GL_FRONT:
114 raster->cull_face = PIPE_FACE_FRONT;
115 break;
116 case GL_BACK:
117 raster->cull_face = PIPE_FACE_BACK;
118 break;
119 case GL_FRONT_AND_BACK:
120 raster->cull_face = PIPE_FACE_FRONT_AND_BACK;
121 break;
122 }
123 }
124 else {
125 raster->cull_face = PIPE_FACE_NONE;
126 }
127
128 /* _NEW_POLYGON
129 */
130 {
131 if (ST_DEBUG & DEBUG_WIREFRAME) {
132 raster->fill_front = PIPE_POLYGON_MODE_LINE;
133 raster->fill_back = PIPE_POLYGON_MODE_LINE;
134 }
135 else {
136 raster->fill_front = translate_fill( ctx->Polygon.FrontMode );
137 raster->fill_back = translate_fill( ctx->Polygon.BackMode );
138 }
139
140 /* Simplify when culling is active:
141 */
142 if (raster->cull_face & PIPE_FACE_FRONT) {
143 raster->fill_front = raster->fill_back;
144 }
145
146 if (raster->cull_face & PIPE_FACE_BACK) {
147 raster->fill_back = raster->fill_front;
148 }
149 }
150
151 /* _NEW_POLYGON
152 */
153 if (ctx->Polygon.OffsetPoint ||
154 ctx->Polygon.OffsetLine ||
155 ctx->Polygon.OffsetFill) {
156 raster->offset_point = ctx->Polygon.OffsetPoint;
157 raster->offset_line = ctx->Polygon.OffsetLine;
158 raster->offset_tri = ctx->Polygon.OffsetFill;
159 raster->offset_units = ctx->Polygon.OffsetUnits;
160 raster->offset_scale = ctx->Polygon.OffsetFactor;
161 raster->offset_clamp = ctx->Polygon.OffsetClamp;
162 }
163
164 raster->poly_smooth = ctx->Polygon.SmoothFlag;
165 raster->poly_stipple_enable = ctx->Polygon.StippleFlag;
166
167 /* _NEW_POINT
168 */
169 raster->point_size = ctx->Point.Size;
170 raster->point_smooth = !ctx->Point.PointSprite && ctx->Point.SmoothFlag;
171
172 /* _NEW_POINT | _NEW_PROGRAM
173 */
174 if (ctx->Point.PointSprite) {
175 /* origin */
176 if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
177 (st->state.fb_orientation == Y_0_BOTTOM))
178 raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
179 else
180 raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT;
181
182 /* Coord replacement flags. If bit 'k' is set that means
183 * that we need to replace GENERIC[k] attrib with an automatically
184 * computed texture coord.
185 */
186 raster->sprite_coord_enable = ctx->Point.CoordReplace &
187 ((1u << MAX_TEXTURE_COORD_UNITS) - 1);
188 if (!st->needs_texcoord_semantic &&
189 fragProg->info.inputs_read & VARYING_BIT_PNTC) {
190 raster->sprite_coord_enable |=
191 1 << st_get_generic_varying_index(st, VARYING_SLOT_PNTC);
192 }
193
194 raster->point_quad_rasterization = 1;
195 }
196
197 /* ST_NEW_VERTEX_PROGRAM
198 */
199 if (vertProg) {
200 if (vertProg->Id == 0) {
201 if (vertProg->info.outputs_written &
202 BITFIELD64_BIT(VARYING_SLOT_PSIZ)) {
203 /* generated program which emits point size */
204 raster->point_size_per_vertex = TRUE;
205 }
206 }
207 else if (ctx->API != API_OPENGLES2) {
208 /* PointSizeEnabled is always set in ES2 contexts */
209 raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
210 }
211 else {
212 /* ST_NEW_TESSEVAL_PROGRAM | ST_NEW_GEOMETRY_PROGRAM */
213 /* We have to check the last bound stage and see if it writes psize */
214 struct gl_program *last = NULL;
215 if (ctx->GeometryProgram._Current)
216 last = ctx->GeometryProgram._Current;
217 else if (ctx->TessEvalProgram._Current)
218 last = ctx->TessEvalProgram._Current;
219 else if (ctx->VertexProgram._Current)
220 last = ctx->VertexProgram._Current;
221 if (last)
222 raster->point_size_per_vertex =
223 !!(last->info.outputs_written &
224 BITFIELD64_BIT(VARYING_SLOT_PSIZ));
225 }
226 }
227 if (!raster->point_size_per_vertex) {
228 /* clamp size now */
229 raster->point_size = CLAMP(ctx->Point.Size,
230 ctx->Point.MinSize,
231 ctx->Point.MaxSize);
232 }
233
234 /* _NEW_LINE
235 */
236 raster->line_smooth = ctx->Line.SmoothFlag;
237 if (ctx->Line.SmoothFlag) {
238 raster->line_width = CLAMP(ctx->Line.Width,
239 ctx->Const.MinLineWidthAA,
240 ctx->Const.MaxLineWidthAA);
241 }
242 else {
243 raster->line_width = CLAMP(ctx->Line.Width,
244 ctx->Const.MinLineWidth,
245 ctx->Const.MaxLineWidth);
246 }
247
248 raster->line_stipple_enable = ctx->Line.StippleFlag;
249 raster->line_stipple_pattern = ctx->Line.StipplePattern;
250 /* GL stipple factor is in [1,256], remap to [0, 255] here */
251 raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
252
253 /* _NEW_MULTISAMPLE */
254 raster->multisample = _mesa_is_multisample_enabled(ctx);
255
256 /* _NEW_MULTISAMPLE | _NEW_BUFFERS */
257 raster->force_persample_interp =
258 !st->force_persample_in_shader &&
259 raster->multisample &&
260 ctx->Multisample.SampleShading &&
261 ctx->Multisample.MinSampleShadingValue *
262 _mesa_geometric_samples(ctx->DrawBuffer) > 1;
263
264 /* _NEW_SCISSOR */
265 raster->scissor = !!ctx->Scissor.EnableFlags;
266
267 /* _NEW_FRAG_CLAMP */
268 raster->clamp_fragment_color = !st->clamp_frag_color_in_shader &&
269 ctx->Color._ClampFragmentColor;
270
271 raster->half_pixel_center = 1;
272 if (st->state.fb_orientation == Y_0_TOP)
273 raster->bottom_edge_rule = 1;
274 /* _NEW_TRANSFORM */
275 if (ctx->Transform.ClipOrigin == GL_UPPER_LEFT)
276 raster->bottom_edge_rule ^= 1;
277
278 /* ST_NEW_RASTERIZER */
279 raster->rasterizer_discard = ctx->RasterDiscard;
280
281 if (st->edgeflag_culls_prims) {
282 /* All edge flags are FALSE. Cull the affected faces. */
283 if (raster->fill_front != PIPE_POLYGON_MODE_FILL)
284 raster->cull_face |= PIPE_FACE_FRONT;
285 if (raster->fill_back != PIPE_POLYGON_MODE_FILL)
286 raster->cull_face |= PIPE_FACE_BACK;
287 }
288
289 /* _NEW_TRANSFORM */
290 raster->depth_clip = !ctx->Transform.DepthClamp;
291 raster->clip_plane_enable = ctx->Transform.ClipPlanesEnabled;
292 raster->clip_halfz = (ctx->Transform.ClipDepthMode == GL_ZERO_TO_ONE);
293
294 cso_set_rasterizer(st->cso_context, raster);
295 }