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 #ifndef SVGA_DRAW_H_
9 #define SVGA_DRAW_H_
10
11 #include "util/compiler.h"
12 #include "pipe/p_defines.h"
13 #include "indices/u_indices.h"
14 #include "util/u_prim.h"
15 #include "svga_context.h"
16 #include "svga_hw_reg.h"
17 #include "svga3d_shaderdefs.h"
18
19 struct svga_context;
20 struct u_upload_mgr;
21
22 /**
23 * Mask indicating which types of gallium primitives are actually
24 * handled by the svga device. Other types will be converted to
25 * these types by the index/translation code.
26 */
27 static const unsigned svga_hw_prims =
28 ((1 << MESA_PRIM_POINTS) |
29 (1 << MESA_PRIM_LINES) |
30 (1 << MESA_PRIM_LINE_STRIP) |
31 (1 << MESA_PRIM_TRIANGLES) |
32 (1 << MESA_PRIM_TRIANGLE_STRIP) |
33 (1 << MESA_PRIM_TRIANGLE_FAN) |
34 (1 << MESA_PRIM_LINES_ADJACENCY) |
35 (1 << MESA_PRIM_LINE_STRIP_ADJACENCY) |
36 (1 << MESA_PRIM_TRIANGLES_ADJACENCY) |
37 (1 << MESA_PRIM_TRIANGLE_STRIP_ADJACENCY) |
38 (1 << MESA_PRIM_PATCHES));
39
40
41 /**
42 * Translate a gallium MESA_PRIM_x value to an SVGA3D_PRIMITIVE_x value.
43 * Also, compute the number of primitives that'll be drawn given a
44 * vertex count.
45 * Note that this function doesn't have to handle MESA_PRIM_LINE_LOOP,
46 * MESA_PRIM_QUADS, MESA_PRIM_QUAD_STRIP or MESA_PRIM_POLYGON. We convert
47 * those to other types of primitives with index/translation code.
48 */
49 static inline SVGA3dPrimitiveType
svga_translate_prim(unsigned mode,unsigned vcount,unsigned * prim_count,uint8_t vertices_per_patch)50 svga_translate_prim(unsigned mode, unsigned vcount, unsigned *prim_count,
51 uint8_t vertices_per_patch)
52 {
53 switch (mode) {
54 case MESA_PRIM_POINTS:
55 *prim_count = vcount;
56 return SVGA3D_PRIMITIVE_POINTLIST;
57
58 case MESA_PRIM_LINES:
59 *prim_count = vcount / 2;
60 return SVGA3D_PRIMITIVE_LINELIST;
61
62 case MESA_PRIM_LINE_STRIP:
63 *prim_count = vcount - 1;
64 return SVGA3D_PRIMITIVE_LINESTRIP;
65
66 case MESA_PRIM_TRIANGLES:
67 *prim_count = vcount / 3;
68 return SVGA3D_PRIMITIVE_TRIANGLELIST;
69
70 case MESA_PRIM_TRIANGLE_STRIP:
71 *prim_count = vcount - 2;
72 return SVGA3D_PRIMITIVE_TRIANGLESTRIP;
73
74 case MESA_PRIM_TRIANGLE_FAN:
75 *prim_count = vcount - 2;
76 return SVGA3D_PRIMITIVE_TRIANGLEFAN;
77
78 case MESA_PRIM_LINES_ADJACENCY:
79 *prim_count = vcount / 4;
80 return SVGA3D_PRIMITIVE_LINELIST_ADJ;
81
82 case MESA_PRIM_LINE_STRIP_ADJACENCY:
83 *prim_count = vcount - 3;
84 return SVGA3D_PRIMITIVE_LINESTRIP_ADJ;
85
86 case MESA_PRIM_TRIANGLES_ADJACENCY:
87 *prim_count = vcount / 6;
88 return SVGA3D_PRIMITIVE_TRIANGLELIST_ADJ;
89
90 case MESA_PRIM_TRIANGLE_STRIP_ADJACENCY:
91 *prim_count = vcount / 2 - 2 ;
92 return SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ;
93
94 case MESA_PRIM_PATCHES:
95 *prim_count = vcount / vertices_per_patch ;
96 assert(vertices_per_patch >= 1);
97 assert(vertices_per_patch <= 32);
98 return (SVGA3D_PRIMITIVE_1_CONTROL_POINT_PATCH - 1)
99 + vertices_per_patch;
100
101 default:
102 assert(0);
103 *prim_count = 0;
104 return 0;
105 }
106 }
107
108
109 struct index_cache {
110 u_generate_func generate;
111 unsigned gen_nr;
112
113 /* If non-null, this buffer is filled by calling generate(nr, map(buffer))
114 */
115 struct pipe_resource *buffer;
116 };
117
118
119 /** Max number of primitives per draw call */
120 #define QSZ SVGA3D_MAX_DRAW_PRIMITIVE_RANGES
121
122 struct draw_cmd {
123 struct svga_winsys_context *swc;
124
125 /* vertex layout info */
126 SVGA3dVertexDecl vdecl[SVGA3D_INPUTREG_MAX];
127 unsigned vdecl_count;
128 SVGA3dElementLayoutId vdecl_layout_id;
129 unsigned vdecl_buffer_index[SVGA3D_INPUTREG_MAX];
130
131 /* vertex buffer info */
132 struct pipe_vertex_buffer vbufs[SVGA3D_INPUTREG_MAX];
133 unsigned vbuf_count;
134
135 SVGA3dPrimitiveRange prim[QSZ];
136 struct pipe_resource *prim_ib[QSZ];
137 unsigned prim_count; /**< number of primitives for this draw */
138 unsigned min_index[QSZ];
139 unsigned max_index[QSZ];
140 };
141
142 #define IDX_CACHE_MAX 8
143
144 struct svga_hwtnl {
145 struct svga_context *svga;
146 struct u_upload_mgr *upload_ib;
147
148 /* Additional negative index bias due to partial buffer uploads
149 * This is compensated for in the offset associated with all
150 * vertex buffers.
151 */
152 int index_bias;
153
154 /* Provoking vertex information (for flat shading). */
155 unsigned api_pv; /**< app-requested PV mode (PV_FIRST or PV_LAST) */
156 unsigned hw_pv; /**< device-supported PV mode (PV_FIRST or PV_LAST) */
157
158 /* The triangle fillmode for the device (one of PIPE_POLYGON_MODE_{FILL,
159 * LINE,POINT}). If the polygon front mode matches the back mode,
160 * api_fillmode will be that mode. Otherwise, api_fillmode will be
161 * PIPE_POLYGON_MODE_FILL.
162 */
163 unsigned api_fillmode;
164
165 /* Cache the results of running a particular generate func on each
166 * primitive type.
167 */
168 struct index_cache index_cache[MESA_PRIM_COUNT][IDX_CACHE_MAX];
169
170 /* Try to build the maximal draw command packet before emitting:
171 */
172 struct draw_cmd cmd;
173 };
174
175
176
177 /**
178 * Do we need to use the gallium 'indices' helper to render unfilled
179 * triangles?
180 */
181 static inline bool
svga_need_unfilled_fallback(const struct svga_hwtnl * hwtnl,enum mesa_prim prim)182 svga_need_unfilled_fallback(const struct svga_hwtnl *hwtnl,
183 enum mesa_prim prim)
184 {
185 if (u_reduced_prim(prim) != MESA_PRIM_TRIANGLES) {
186 /* if we're drawing points or lines, no fallback needed */
187 return false;
188 }
189
190 if ((prim == MESA_PRIM_QUADS ||
191 prim == MESA_PRIM_QUAD_STRIP ||
192 prim == MESA_PRIM_POLYGON) &&
193 hwtnl->api_fillmode == PIPE_POLYGON_MODE_LINE) {
194 /* We can't directly render quads or polygons. They're
195 * converted to triangles. If we let the device draw the triangle
196 * outlines we'll get an extra, stray lines in the interiors.
197 * So, to draw unfilled quads correctly, we need the fallback.
198 */
199 return true;
200 }
201 return false;
202 }
203
204
205 enum pipe_error
206 svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
207 const SVGA3dPrimitiveRange *range,
208 unsigned vcount,
209 unsigned min_index,
210 unsigned max_index,
211 struct pipe_resource *ib,
212 unsigned start_instance, unsigned instance_count,
213 const struct pipe_draw_indirect_info *indirect,
214 const struct pipe_stream_output_target *so_vertex_count);
215
216 enum pipe_error
217 svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
218 struct pipe_resource *indexBuffer,
219 unsigned index_size,
220 int index_bias,
221 unsigned min_index,
222 unsigned max_index,
223 enum mesa_prim prim,
224 unsigned start,
225 unsigned count,
226 unsigned start_instance,
227 unsigned instance_count,
228 uint8_t vertices_per_patch);
229
230 #endif
231