xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_pipe_depthstencil.c (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 #include "pipe/p_defines.h"
9 #include "util/u_bitmask.h"
10 #include "util/u_inlines.h"
11 #include "util/u_math.h"
12 #include "util/u_memory.h"
13 
14 #include "svga_context.h"
15 #include "svga_hw_reg.h"
16 #include "svga_cmd.h"
17 
18 
19 static inline unsigned
svga_translate_compare_func(unsigned func)20 svga_translate_compare_func(unsigned func)
21 {
22    switch (func) {
23    case PIPE_FUNC_NEVER:     return SVGA3D_CMP_NEVER;
24    case PIPE_FUNC_LESS:      return SVGA3D_CMP_LESS;
25    case PIPE_FUNC_LEQUAL:    return SVGA3D_CMP_LESSEQUAL;
26    case PIPE_FUNC_GREATER:   return SVGA3D_CMP_GREATER;
27    case PIPE_FUNC_GEQUAL:    return SVGA3D_CMP_GREATEREQUAL;
28    case PIPE_FUNC_NOTEQUAL:  return SVGA3D_CMP_NOTEQUAL;
29    case PIPE_FUNC_EQUAL:     return SVGA3D_CMP_EQUAL;
30    case PIPE_FUNC_ALWAYS:    return SVGA3D_CMP_ALWAYS;
31    default:
32       assert(0);
33       return SVGA3D_CMP_ALWAYS;
34    }
35 }
36 
37 static inline unsigned
svga_translate_stencil_op(unsigned op)38 svga_translate_stencil_op(unsigned op)
39 {
40    switch (op) {
41    case PIPE_STENCIL_OP_KEEP:      return SVGA3D_STENCILOP_KEEP;
42    case PIPE_STENCIL_OP_ZERO:      return SVGA3D_STENCILOP_ZERO;
43    case PIPE_STENCIL_OP_REPLACE:   return SVGA3D_STENCILOP_REPLACE;
44    case PIPE_STENCIL_OP_INCR:      return SVGA3D_STENCILOP_INCRSAT;
45    case PIPE_STENCIL_OP_DECR:      return SVGA3D_STENCILOP_DECRSAT;
46    case PIPE_STENCIL_OP_INCR_WRAP: return SVGA3D_STENCILOP_INCR;
47    case PIPE_STENCIL_OP_DECR_WRAP: return SVGA3D_STENCILOP_DECR;
48    case PIPE_STENCIL_OP_INVERT:    return SVGA3D_STENCILOP_INVERT;
49    default:
50       assert(0);
51       return SVGA3D_STENCILOP_KEEP;
52    }
53 }
54 
55 
56 /**
57  * Define a vgpu10 depth/stencil state object for the given
58  * svga depth/stencil state.
59  */
60 static void
define_depth_stencil_state_object(struct svga_context * svga,struct svga_depth_stencil_state * ds)61 define_depth_stencil_state_object(struct svga_context *svga,
62                                   struct svga_depth_stencil_state *ds)
63 {
64    assert(svga_have_vgpu10(svga));
65 
66    ds->id = util_bitmask_add(svga->ds_object_id_bm);
67 
68    /* spot check that these comparision tokens are the same */
69    STATIC_ASSERT(SVGA3D_COMPARISON_NEVER == SVGA3D_CMP_NEVER);
70    STATIC_ASSERT(SVGA3D_COMPARISON_LESS == SVGA3D_CMP_LESS);
71    STATIC_ASSERT(SVGA3D_COMPARISON_NOT_EQUAL == SVGA3D_CMP_NOTEQUAL);
72 
73    /* Note: we use the ds->stencil[0].enabled value for both the front
74     * and back-face enables.  If single-side stencil is used, we'll have
75     * set the back state the same as the front state.
76     */
77    SVGA_RETRY(svga, SVGA3D_vgpu10_DefineDepthStencilState
78               (svga->swc,
79                ds->id,
80                /* depth/Z */
81                ds->zenable,
82                ds->zwriteenable,
83                ds->zfunc,
84                /* Stencil */
85                ds->stencil[0].enabled, /*f|b*/
86                ds->stencil[0].enabled, /*f*/
87                ds->stencil[0].enabled, /*b*/
88                ds->stencil_mask,
89                ds->stencil_writemask,
90                /* front stencil */
91                ds->stencil[0].fail,
92                ds->stencil[0].zfail,
93                ds->stencil[0].pass,
94                ds->stencil[0].func,
95                /* back stencil */
96                ds->stencil[1].fail,
97                ds->stencil[1].zfail,
98                ds->stencil[1].pass,
99                ds->stencil[1].func));
100 }
101 
102 
103 static void *
svga_create_depth_stencil_state(struct pipe_context * pipe,const struct pipe_depth_stencil_alpha_state * templ)104 svga_create_depth_stencil_state(struct pipe_context *pipe,
105 				const struct pipe_depth_stencil_alpha_state *templ)
106 {
107    struct svga_context *svga = svga_context(pipe);
108    struct svga_depth_stencil_state *ds = CALLOC_STRUCT(svga_depth_stencil_state);
109 
110    if (!ds)
111       return NULL;
112 
113    /* Don't try to figure out CW/CCW correspondence with
114     * stencil[0]/[1] at this point.  Presumably this can change as
115     * back/front face are modified.
116     */
117    ds->stencil[0].enabled = templ->stencil[0].enabled;
118    if (ds->stencil[0].enabled) {
119       ds->stencil[0].func  = svga_translate_compare_func(templ->stencil[0].func);
120       ds->stencil[0].fail  = svga_translate_stencil_op(templ->stencil[0].fail_op);
121       ds->stencil[0].zfail = svga_translate_stencil_op(templ->stencil[0].zfail_op);
122       ds->stencil[0].pass  = svga_translate_stencil_op(templ->stencil[0].zpass_op);
123 
124       /* SVGA3D has one ref/mask/writemask triple shared between front &
125        * back face stencil.  We really need two:
126        */
127       ds->stencil_mask      = templ->stencil[0].valuemask & 0xff;
128       ds->stencil_writemask = templ->stencil[0].writemask & 0xff;
129    }
130    else {
131       ds->stencil[0].func = SVGA3D_CMP_ALWAYS;
132       ds->stencil[0].fail = SVGA3D_STENCILOP_KEEP;
133       ds->stencil[0].zfail = SVGA3D_STENCILOP_KEEP;
134       ds->stencil[0].pass = SVGA3D_STENCILOP_KEEP;
135    }
136 
137    ds->stencil[1].enabled = templ->stencil[1].enabled;
138    if (templ->stencil[1].enabled) {
139       assert(templ->stencil[0].enabled);
140       /* two-sided stencil */
141       ds->stencil[1].func   = svga_translate_compare_func(templ->stencil[1].func);
142       ds->stencil[1].fail   = svga_translate_stencil_op(templ->stencil[1].fail_op);
143       ds->stencil[1].zfail  = svga_translate_stencil_op(templ->stencil[1].zfail_op);
144       ds->stencil[1].pass   = svga_translate_stencil_op(templ->stencil[1].zpass_op);
145 
146       ds->stencil_mask      = templ->stencil[1].valuemask & 0xff;
147       ds->stencil_writemask = templ->stencil[1].writemask & 0xff;
148 
149       if (templ->stencil[1].valuemask != templ->stencil[0].valuemask) {
150          util_debug_message(&svga->debug.callback, CONFORMANCE,
151                             "two-sided stencil mask not supported "
152                             "(front=0x%x, back=0x%x)",
153                             templ->stencil[0].valuemask,
154                             templ->stencil[1].valuemask);
155       }
156       if (templ->stencil[1].writemask != templ->stencil[0].writemask) {
157          util_debug_message(&svga->debug.callback, CONFORMANCE,
158                             "two-sided stencil writemask not supported "
159                             "(front=0x%x, back=0x%x)",
160                             templ->stencil[0].writemask,
161                             templ->stencil[1].writemask);
162       }
163    }
164    else {
165       /* back face state is same as front-face state */
166       ds->stencil[1].func = ds->stencil[0].func;
167       ds->stencil[1].fail = ds->stencil[0].fail;
168       ds->stencil[1].zfail = ds->stencil[0].zfail;
169       ds->stencil[1].pass = ds->stencil[0].pass;
170    }
171 
172 
173    ds->zenable = templ->depth_enabled;
174    if (ds->zenable) {
175       ds->zfunc = svga_translate_compare_func(templ->depth_func);
176       ds->zwriteenable = templ->depth_writemask;
177    }
178    else {
179       ds->zfunc = SVGA3D_CMP_ALWAYS;
180    }
181 
182    ds->alphatestenable = templ->alpha_enabled;
183    if (ds->alphatestenable) {
184       ds->alphafunc = svga_translate_compare_func(templ->alpha_func);
185       ds->alpharef = templ->alpha_ref_value;
186    }
187    else {
188       ds->alphafunc = SVGA3D_CMP_ALWAYS;
189    }
190 
191    if (svga_have_vgpu10(svga)) {
192       define_depth_stencil_state_object(svga, ds);
193    }
194 
195    svga->hud.num_depthstencil_objects++;
196 
197    SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws,
198                         SVGA_STATS_COUNT_DEPTHSTENCILSTATE);
199 
200    return ds;
201 }
202 
203 
204 static void
svga_bind_depth_stencil_state(struct pipe_context * pipe,void * depth_stencil)205 svga_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
206 {
207    struct svga_context *svga = svga_context(pipe);
208 
209    if (svga_have_vgpu10(svga)) {
210       /* flush any previously queued drawing before changing state */
211       svga_hwtnl_flush_retry(svga);
212    }
213 
214    svga->curr.depth = (const struct svga_depth_stencil_state *)depth_stencil;
215    svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA;
216 }
217 
218 
219 static void
svga_delete_depth_stencil_state(struct pipe_context * pipe,void * depth_stencil)220 svga_delete_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil)
221 {
222    struct svga_context *svga = svga_context(pipe);
223    struct svga_depth_stencil_state *ds =
224       (struct svga_depth_stencil_state *) depth_stencil;
225 
226    if (svga_have_vgpu10(svga)) {
227       svga_hwtnl_flush_retry(svga);
228 
229       assert(ds->id != SVGA3D_INVALID_ID);
230 
231       SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilState(svga->swc,
232                                                               ds->id));
233 
234       if (ds->id == svga->state.hw_draw.depth_stencil_id)
235          svga->state.hw_draw.depth_stencil_id = SVGA3D_INVALID_ID;
236 
237       util_bitmask_clear(svga->ds_object_id_bm, ds->id);
238       ds->id = SVGA3D_INVALID_ID;
239    }
240 
241    FREE(depth_stencil);
242    svga->hud.num_depthstencil_objects--;
243 }
244 
245 
246 static void
svga_set_stencil_ref(struct pipe_context * pipe,const struct pipe_stencil_ref stencil_ref)247 svga_set_stencil_ref(struct pipe_context *pipe,
248                      const struct pipe_stencil_ref stencil_ref)
249 {
250    struct svga_context *svga = svga_context(pipe);
251 
252    if (svga_have_vgpu10(svga)) {
253       /* flush any previously queued drawing before changing state */
254       svga_hwtnl_flush_retry(svga);
255    }
256 
257    svga->curr.stencil_ref = stencil_ref;
258 
259    svga->dirty |= SVGA_NEW_STENCIL_REF;
260 }
261 
262 
263 static void
svga_set_sample_mask(struct pipe_context * pipe,unsigned sample_mask)264 svga_set_sample_mask(struct pipe_context *pipe,
265                      unsigned sample_mask)
266 {
267    struct svga_context *svga = svga_context(pipe);
268 
269    svga->curr.sample_mask = sample_mask;
270 
271    svga->dirty |= SVGA_NEW_BLEND; /* See emit_rss_vgpu10() */
272 }
273 
274 
275 static void
svga_set_min_samples(struct pipe_context * pipe,unsigned min_samples)276 svga_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
277 {
278    /* This specifies the minimum number of times the fragment shader
279     * must run when doing per-sample shading for a MSAA render target.
280     * For our SVGA3D device, the FS is automatically run in per-sample
281     * mode if it uses the sample ID or sample position registers.
282     */
283 }
284 
285 
286 void
svga_init_depth_stencil_functions(struct svga_context * svga)287 svga_init_depth_stencil_functions(struct svga_context *svga)
288 {
289    svga->pipe.create_depth_stencil_alpha_state = svga_create_depth_stencil_state;
290    svga->pipe.bind_depth_stencil_alpha_state = svga_bind_depth_stencil_state;
291    svga->pipe.delete_depth_stencil_alpha_state = svga_delete_depth_stencil_state;
292 
293    svga->pipe.set_stencil_ref = svga_set_stencil_ref;
294    svga->pipe.set_sample_mask = svga_set_sample_mask;
295    svga->pipe.set_min_samples = svga_set_min_samples;
296 }
297