1 /*
2 * Copyright (c) 2008-2024 Broadcom. All Rights Reserved.
3 * The term “Broadcom” refers to Broadcom Inc.
4 * and/or its subsidiaries.
5 * SPDX-License-Identifier: MIT
6 */
7
8 #include "pipe/p_defines.h"
9 #include "draw/draw_context.h"
10 #include "util/u_bitmask.h"
11 #include "util/u_inlines.h"
12 #include "util/u_math.h"
13 #include "util/u_memory.h"
14
15 #include "svga_cmd.h"
16 #include "svga_context.h"
17 #include "svga_hw_reg.h"
18 #include "svga_screen.h"
19
20
21 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
22 */
23 static SVGA3dFace
svga_translate_cullmode(unsigned mode,unsigned front_ccw)24 svga_translate_cullmode(unsigned mode, unsigned front_ccw)
25 {
26 const int hw_front_ccw = 0; /* hardware is always CW */
27 switch (mode) {
28 case PIPE_FACE_NONE:
29 return SVGA3D_FACE_NONE;
30 case PIPE_FACE_FRONT:
31 return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK;
32 case PIPE_FACE_BACK:
33 return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT;
34 case PIPE_FACE_FRONT_AND_BACK:
35 return SVGA3D_FACE_FRONT_BACK;
36 default:
37 assert(0);
38 return SVGA3D_FACE_NONE;
39 }
40 }
41
42 static SVGA3dShadeMode
svga_translate_flatshade(unsigned mode)43 svga_translate_flatshade(unsigned mode)
44 {
45 return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
46 }
47
48
49 static unsigned
translate_fill_mode(unsigned fill)50 translate_fill_mode(unsigned fill)
51 {
52 switch (fill) {
53 case PIPE_POLYGON_MODE_POINT:
54 return SVGA3D_FILLMODE_POINT;
55 case PIPE_POLYGON_MODE_LINE:
56 return SVGA3D_FILLMODE_LINE;
57 case PIPE_POLYGON_MODE_FILL:
58 return SVGA3D_FILLMODE_FILL;
59 default:
60 assert(!"Bad fill mode");
61 return SVGA3D_FILLMODE_FILL;
62 }
63 }
64
65
66 static unsigned
translate_cull_mode(unsigned cull)67 translate_cull_mode(unsigned cull)
68 {
69 switch (cull) {
70 case PIPE_FACE_NONE:
71 return SVGA3D_CULL_NONE;
72 case PIPE_FACE_FRONT:
73 return SVGA3D_CULL_FRONT;
74 case PIPE_FACE_BACK:
75 return SVGA3D_CULL_BACK;
76 case PIPE_FACE_FRONT_AND_BACK:
77 /* NOTE: we simply no-op polygon drawing in svga_draw_vbo() */
78 return SVGA3D_CULL_NONE;
79 default:
80 assert(!"Bad cull mode");
81 return SVGA3D_CULL_NONE;
82 }
83 }
84
85
86 int
svga_define_rasterizer_object(struct svga_context * svga,struct svga_rasterizer_state * rast,unsigned samples)87 svga_define_rasterizer_object(struct svga_context *svga,
88 struct svga_rasterizer_state *rast,
89 unsigned samples)
90 {
91 struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
92 unsigned fill_mode = translate_fill_mode(rast->templ.fill_front);
93 const unsigned cull_mode = translate_cull_mode(rast->templ.cull_face);
94 const int depth_bias = rast->templ.offset_units;
95 const float slope_scaled_depth_bias = rast->templ.offset_scale;
96 /* PIPE_CAP_POLYGON_OFFSET_CLAMP not supported: */
97 const float depth_bias_clamp = 0.0;
98 const float line_width = rast->templ.line_width > 0.0f ?
99 rast->templ.line_width : 1.0f;
100 const uint8 line_factor = rast->templ.line_stipple_enable ?
101 rast->templ.line_stipple_factor : 0;
102 const uint16 line_pattern = rast->templ.line_stipple_enable ?
103 rast->templ.line_stipple_pattern : 0;
104 const uint8 pv_last = !rast->templ.flatshade_first &&
105 svgascreen->haveProvokingVertex;
106 int rastId;
107 enum pipe_error ret;
108
109 rastId = util_bitmask_add(svga->rast_object_id_bm);
110
111 if (rast->templ.fill_front != rast->templ.fill_back) {
112 /* The VGPU10 device can't handle different front/back fill modes.
113 * We'll handle that with a swtnl/draw fallback. But we need to
114 * make sure we always fill triangles in that case.
115 */
116 fill_mode = SVGA3D_FILLMODE_FILL;
117 }
118
119 if (samples > 1 && svga_have_gl43(svga) &&
120 svgascreen->sws->have_rasterizer_state_v2_cmd) {
121
122 ret = SVGA3D_sm5_DefineRasterizerState_v2(svga->swc,
123 rastId,
124 fill_mode,
125 cull_mode,
126 rast->templ.front_ccw,
127 depth_bias,
128 depth_bias_clamp,
129 slope_scaled_depth_bias,
130 rast->templ.depth_clip_near,
131 rast->templ.scissor,
132 rast->templ.multisample,
133 rast->templ.line_smooth,
134 line_width,
135 rast->templ.line_stipple_enable,
136 line_factor,
137 line_pattern,
138 pv_last,
139 samples);
140 } else {
141 ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc,
142 rastId,
143 fill_mode,
144 cull_mode,
145 rast->templ.front_ccw,
146 depth_bias,
147 depth_bias_clamp,
148 slope_scaled_depth_bias,
149 rast->templ.depth_clip_near,
150 rast->templ.scissor,
151 rast->templ.multisample,
152 rast->templ.line_smooth,
153 line_width,
154 rast->templ.line_stipple_enable,
155 line_factor,
156 line_pattern,
157 pv_last);
158 }
159
160 if (ret != PIPE_OK) {
161 util_bitmask_clear(svga->rast_object_id_bm, rastId);
162 return SVGA3D_INVALID_ID;
163 }
164
165 return rastId;
166 }
167
168
169 static void *
svga_create_rasterizer_state(struct pipe_context * pipe,const struct pipe_rasterizer_state * templ)170 svga_create_rasterizer_state(struct pipe_context *pipe,
171 const struct pipe_rasterizer_state *templ)
172 {
173 struct svga_context *svga = svga_context(pipe);
174 struct svga_rasterizer_state *rast = CALLOC_STRUCT(svga_rasterizer_state);
175 struct svga_screen *screen = svga_screen(pipe->screen);
176
177 if (!rast)
178 return NULL;
179
180 /* need this for draw module. */
181 rast->templ = *templ;
182
183 rast->shademode = svga_translate_flatshade(templ->flatshade);
184 rast->cullmode = svga_translate_cullmode(templ->cull_face, templ->front_ccw);
185 rast->scissortestenable = templ->scissor;
186 rast->multisampleantialias = templ->multisample;
187 rast->antialiasedlineenable = templ->line_smooth;
188 rast->lastpixel = templ->line_last_pixel;
189 rast->pointsprite = templ->point_quad_rasterization;
190
191 if (rast->templ.multisample) {
192 /* The OpenGL 3.0 spec says points are always drawn as circles when
193 * MSAA is enabled. Note that our implementation isn't 100% correct,
194 * though. Our smooth point implementation involves drawing a square,
195 * computing fragment distance from point center, then attenuating
196 * the fragment alpha value. We should not attenuate alpha if msaa
197 * is enabled. We should discard fragments entirely outside the circle
198 * and let the GPU compute per-fragment coverage.
199 * But as-is, our implementation gives acceptable results and passes
200 * Piglit's MSAA point smooth test.
201 */
202 rast->templ.point_smooth = true;
203 }
204
205 if (rast->templ.point_smooth &&
206 rast->templ.point_size_per_vertex == 0 &&
207 rast->templ.point_size <= screen->pointSmoothThreshold) {
208 /* If the point size is less than the threshold, deactivate smoothing.
209 * Note that this only effects point rendering when we use the
210 * pipe_rasterizer_state::point_size value, not when the point size
211 * is set in the VS.
212 */
213 rast->templ.point_smooth = false;
214 }
215
216 if (rast->templ.point_smooth) {
217 /* For smooth points we need to generate fragments for at least
218 * a 2x2 region. Otherwise the quad we draw may be too small and
219 * we may generate no fragments at all.
220 */
221 rast->pointsize = MAX2(2.0f, templ->point_size);
222 }
223 else {
224 rast->pointsize = templ->point_size;
225 }
226
227 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
228
229 /* Use swtnl + decomposition implement these:
230 */
231
232 if (templ->line_width <= screen->maxLineWidth) {
233 /* pass line width to device */
234 rast->linewidth = MAX2(1.0F, templ->line_width);
235 }
236 else if (svga->debug.no_line_width) {
237 /* nothing */
238 }
239 else {
240 /* use 'draw' pipeline for wide line */
241 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
242 rast->need_pipeline_lines_str = "line width";
243 }
244
245 if (templ->line_stipple_enable) {
246 if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) {
247 SVGA3dLinePattern lp;
248 lp.repeat = templ->line_stipple_factor + 1;
249 lp.pattern = templ->line_stipple_pattern;
250 rast->linepattern = lp.uintValue;
251 }
252 else {
253 /* use 'draw' module to decompose into short line segments */
254 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
255 rast->need_pipeline_lines_str = "line stipple";
256 }
257 }
258
259 if (!svga_have_vgpu10(svga) && rast->templ.point_smooth) {
260 rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
261 rast->need_pipeline_points_str = "smooth points";
262 }
263
264 if (templ->line_smooth && !screen->haveLineSmooth) {
265 /*
266 * XXX: Enabling the pipeline slows down performance immensely, so ignore
267 * line smooth state, where there is very little visual improvement.
268 * Smooth lines will still be drawn for wide lines.
269 */
270 #if 0
271 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
272 rast->need_pipeline_lines_str = "smooth lines";
273 #endif
274 }
275
276 {
277 int fill_front = templ->fill_front;
278 int fill_back = templ->fill_back;
279 int fill = PIPE_POLYGON_MODE_FILL;
280 bool offset_front = util_get_offset(templ, fill_front);
281 bool offset_back = util_get_offset(templ, fill_back);
282 bool offset = false;
283
284 switch (templ->cull_face) {
285 case PIPE_FACE_FRONT_AND_BACK:
286 offset = false;
287 fill = PIPE_POLYGON_MODE_FILL;
288 break;
289
290 case PIPE_FACE_FRONT:
291 offset = offset_back;
292 fill = fill_back;
293 break;
294
295 case PIPE_FACE_BACK:
296 offset = offset_front;
297 fill = fill_front;
298 break;
299
300 case PIPE_FACE_NONE:
301 if (fill_front != fill_back || offset_front != offset_back) {
302 /* Always need the draw module to work out different
303 * front/back fill modes:
304 */
305 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
306 rast->need_pipeline_tris_str = "different front/back fillmodes";
307 fill = PIPE_POLYGON_MODE_FILL;
308 }
309 else {
310 offset = offset_front;
311 fill = fill_front;
312 }
313 break;
314
315 default:
316 assert(0);
317 break;
318 }
319
320 /* Unfilled primitive modes aren't implemented on all virtual
321 * hardware. We can do some unfilled processing with index
322 * translation, but otherwise need the draw module:
323 */
324 if (fill != PIPE_POLYGON_MODE_FILL &&
325 (templ->flatshade ||
326 templ->light_twoside ||
327 offset)) {
328 fill = PIPE_POLYGON_MODE_FILL;
329 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
330 rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation";
331 }
332
333 /* If we are decomposing to lines, and lines need the pipeline,
334 * then we also need the pipeline for tris.
335 */
336 if (fill == PIPE_POLYGON_MODE_LINE &&
337 (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) {
338 fill = PIPE_POLYGON_MODE_FILL;
339 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
340 rast->need_pipeline_tris_str = "decomposing lines";
341 }
342
343 /* Similarly for points:
344 */
345 if (fill == PIPE_POLYGON_MODE_POINT &&
346 (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) {
347 fill = PIPE_POLYGON_MODE_FILL;
348 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
349 rast->need_pipeline_tris_str = "decomposing points";
350 }
351
352 if (offset) {
353 rast->slopescaledepthbias = templ->offset_scale;
354 rast->depthbias = templ->offset_units;
355 }
356
357 rast->hw_fillmode = fill;
358 }
359
360 if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
361 /* Turn off stuff which will get done in the draw module:
362 */
363 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL;
364 rast->slopescaledepthbias = 0;
365 rast->depthbias = 0;
366 }
367
368 if (0 && rast->need_pipeline) {
369 debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline);
370 debug_printf(" pnts: %s \n", rast->need_pipeline_points_str);
371 debug_printf(" lins: %s \n", rast->need_pipeline_lines_str);
372 debug_printf(" tris: %s \n", rast->need_pipeline_tris_str);
373 }
374
375 if (svga_have_vgpu10(svga)) {
376 rast->id = svga_define_rasterizer_object(svga, rast, 0);
377 if (rast->id == SVGA3D_INVALID_ID) {
378 svga_context_flush(svga, NULL);
379 rast->id = svga_define_rasterizer_object(svga, rast, 0);
380 assert(rast->id != SVGA3D_INVALID_ID);
381 }
382 }
383
384 if (svga_have_gl43(svga)) {
385 /* initialize the alternate rasterizer state ids.
386 * For 0 and 1 sample count, we can use the same rasterizer object.
387 */
388 rast->altRastIds[0] = rast->altRastIds[1] = rast->id;
389
390 for (unsigned i = 2; i < ARRAY_SIZE(rast->altRastIds); i++) {
391 rast->altRastIds[i] = SVGA3D_INVALID_ID;
392 }
393 }
394
395 if (templ->poly_smooth) {
396 util_debug_message(&svga->debug.callback, CONFORMANCE,
397 "GL_POLYGON_SMOOTH not supported");
398 }
399
400 svga->hud.num_rasterizer_objects++;
401 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
402 SVGA_STATS_COUNT_RASTERIZERSTATE);
403
404 return rast;
405 }
406
407
408 static void
svga_bind_rasterizer_state(struct pipe_context * pipe,void * state)409 svga_bind_rasterizer_state(struct pipe_context *pipe, void *state)
410 {
411 struct svga_context *svga = svga_context(pipe);
412 struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
413
414 if (!raster || !svga->curr.rast) {
415 svga->dirty |= SVGA_NEW_STIPPLE | SVGA_NEW_DEPTH_STENCIL_ALPHA;
416 }
417 else {
418 if (raster->templ.poly_stipple_enable !=
419 svga->curr.rast->templ.poly_stipple_enable) {
420 svga->dirty |= SVGA_NEW_STIPPLE;
421 }
422 if (raster->templ.rasterizer_discard !=
423 svga->curr.rast->templ.rasterizer_discard) {
424 svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;
425 }
426 }
427
428 svga->curr.rast = raster;
429
430 svga->dirty |= SVGA_NEW_RAST;
431 }
432
433
434 static void
svga_delete_rasterizer_state(struct pipe_context * pipe,void * state)435 svga_delete_rasterizer_state(struct pipe_context *pipe, void *state)
436 {
437 struct svga_context *svga = svga_context(pipe);
438 struct svga_rasterizer_state *raster =
439 (struct svga_rasterizer_state *) state;
440
441 /* free any alternate rasterizer state used for point sprite */
442 if (raster->no_cull_rasterizer)
443 svga_delete_rasterizer_state(pipe, (void *)(raster->no_cull_rasterizer));
444
445 if (svga_have_vgpu10(svga)) {
446 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRasterizerState(svga->swc,
447 raster->id));
448
449 if (raster->id == svga->state.hw_draw.rasterizer_id)
450 svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID;
451
452 util_bitmask_clear(svga->rast_object_id_bm, raster->id);
453 }
454
455 FREE(state);
456 svga->hud.num_rasterizer_objects--;
457 }
458
459
460 void
svga_init_rasterizer_functions(struct svga_context * svga)461 svga_init_rasterizer_functions(struct svga_context *svga)
462 {
463 svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
464 svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
465 svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
466 }
467