1 /*
2 * Copyright © 2016 Rob Clark <[email protected]>
3 * Copyright © 2018 Google, Inc.
4 * SPDX-License-Identifier: MIT
5 *
6 * Authors:
7 * Rob Clark <[email protected]>
8 */
9
10 #define FD_BO_NO_HARDPIN 1
11
12 #include "pipe/p_state.h"
13 #include "util/u_memory.h"
14 #include "util/u_string.h"
15
16 #include "freedreno_state.h"
17
18 #include "fd6_context.h"
19 #include "fd6_pack.h"
20 #include "fd6_rasterizer.h"
21
22 template <chip CHIP>
23 struct fd_ringbuffer *
__fd6_setup_rasterizer_stateobj(struct fd_context * ctx,const struct pipe_rasterizer_state * cso,bool primitive_restart)24 __fd6_setup_rasterizer_stateobj(struct fd_context *ctx,
25 const struct pipe_rasterizer_state *cso,
26 bool primitive_restart)
27 {
28 unsigned ndwords = (CHIP >= A7XX) ? 66 : 26;
29 struct fd_ringbuffer *ring = fd_ringbuffer_new_object(ctx->pipe, ndwords * 4);
30 float psize_min, psize_max;
31
32 if (cso->point_size_per_vertex) {
33 psize_min = util_get_min_point_size(cso);
34 psize_max = 4092;
35 } else {
36 /* Force the point size to be as if the vertex output was disabled. */
37 psize_min = cso->point_size;
38 psize_max = cso->point_size;
39 }
40
41 OUT_REG(ring,
42 A6XX_GRAS_CL_CNTL(
43 .znear_clip_disable = !cso->depth_clip_near,
44 .zfar_clip_disable = !cso->depth_clip_far,
45 .z_clamp_enable = cso->depth_clamp || CHIP >= A7XX,
46 .zero_gb_scale_z = cso->clip_halfz,
47 .vp_clip_code_ignore = 1,
48 ),
49 );
50
51 OUT_REG(ring,
52 A6XX_GRAS_SU_CNTL(
53 .cull_front = cso->cull_face & PIPE_FACE_FRONT,
54 .cull_back = cso->cull_face & PIPE_FACE_BACK,
55 .front_cw = !cso->front_ccw,
56 .linehalfwidth = cso->line_width / 2.0f,
57 .poly_offset = cso->offset_tri,
58 .line_mode = cso->multisample ? RECTANGULAR : BRESENHAM,
59 ),
60 );
61
62 OUT_REG(ring,
63 A6XX_GRAS_SU_POINT_MINMAX(.min = psize_min, .max = psize_max, ),
64 A6XX_GRAS_SU_POINT_SIZE(cso->point_size));
65
66 OUT_REG(ring, A6XX_GRAS_SU_POLY_OFFSET_SCALE(cso->offset_scale),
67 A6XX_GRAS_SU_POLY_OFFSET_OFFSET(cso->offset_units),
68 A6XX_GRAS_SU_POLY_OFFSET_OFFSET_CLAMP(cso->offset_clamp));
69
70 OUT_REG(ring,
71 A6XX_PC_PRIMITIVE_CNTL_0(
72 .primitive_restart = primitive_restart,
73 .provoking_vtx_last = !cso->flatshade_first,
74 ),
75 );
76
77 if (CHIP >= A7XX) {
78 OUT_REG(ring,
79 A7XX_VPC_PRIMITIVE_CNTL_0(
80 .primitive_restart = primitive_restart,
81 .provoking_vtx_last = !cso->flatshade_first,
82 ),
83 );
84 }
85
86 enum a6xx_polygon_mode mode = POLYMODE6_TRIANGLES;
87 switch (cso->fill_front) {
88 case PIPE_POLYGON_MODE_POINT:
89 mode = POLYMODE6_POINTS;
90 break;
91 case PIPE_POLYGON_MODE_LINE:
92 mode = POLYMODE6_LINES;
93 break;
94 default:
95 assert(cso->fill_front == PIPE_POLYGON_MODE_FILL);
96 break;
97 }
98
99 OUT_REG(ring, A6XX_VPC_POLYGON_MODE(mode));
100 OUT_REG(ring, PC_POLYGON_MODE(CHIP, mode));
101
102 if (CHIP == A7XX) {
103 OUT_REG(ring, A7XX_VPC_POLYGON_MODE2(mode));
104 }
105
106 /* With a7xx the hw doesn't do the clamping for us. When depth clamp
107 * is enabled, this gets emitted in fd6_emit_non_ring() due to
108 * dependency on viewport state. But when it is disabled there is
109 * no dependency on external state (other than to know the max
110 * number of viewports, here we just assume the max) so we can emit
111 * this state here:
112 */
113 if (CHIP >= A7XX && !fd_rast_depth_clamp_enabled(cso)) {
114 /* We must assume the max: */
115 const unsigned num_viewports = 16;
116
117 OUT_PKT4(ring, REG_A6XX_GRAS_CL_Z_CLAMP(0), num_viewports * 2);
118 for (unsigned i = 0; i < num_viewports; i++) {
119 OUT_RING(ring, fui(0.0f));
120 OUT_RING(ring, fui(1.0f));
121 }
122
123 OUT_REG(ring,
124 A6XX_RB_Z_CLAMP_MIN(0.0f),
125 A6XX_RB_Z_CLAMP_MAX(1.0),
126 );
127 }
128
129 if (CHIP == A6XX && ctx->screen->info->a6xx.has_shading_rate) {
130 OUT_REG(ring, A6XX_RB_UNKNOWN_8A00());
131 OUT_REG(ring, A6XX_RB_UNKNOWN_8A10());
132 OUT_REG(ring, A6XX_RB_UNKNOWN_8A20());
133 OUT_REG(ring, A6XX_RB_UNKNOWN_8A30());
134 }
135
136 return ring;
137 }
138 FD_GENX(__fd6_setup_rasterizer_stateobj);
139
140 void *
fd6_rasterizer_state_create(struct pipe_context * pctx,const struct pipe_rasterizer_state * cso)141 fd6_rasterizer_state_create(struct pipe_context *pctx,
142 const struct pipe_rasterizer_state *cso)
143 {
144 struct fd6_rasterizer_stateobj *so;
145
146 so = CALLOC_STRUCT(fd6_rasterizer_stateobj);
147 if (!so)
148 return NULL;
149
150 so->base = *cso;
151
152 return so;
153 }
154
155 void
fd6_rasterizer_state_delete(struct pipe_context * pctx,void * hwcso)156 fd6_rasterizer_state_delete(struct pipe_context *pctx, void *hwcso)
157 {
158 struct fd6_rasterizer_stateobj *so = (struct fd6_rasterizer_stateobj *)hwcso;
159
160 for (unsigned i = 0; i < ARRAY_SIZE(so->stateobjs); i++)
161 if (so->stateobjs[i])
162 fd_ringbuffer_del(so->stateobjs[i]);
163
164 FREE(hwcso);
165 }
166