xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_draw_private.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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