1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2014-2017 Broadcom
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "util/format/u_format.h"
25bf215546Sopenharmony_ci#include "util/half_float.h"
26bf215546Sopenharmony_ci#include "v3d_context.h"
27bf215546Sopenharmony_ci#include "broadcom/common/v3d_macros.h"
28bf215546Sopenharmony_ci#include "broadcom/cle/v3dx_pack.h"
29bf215546Sopenharmony_ci#include "broadcom/common/v3d_util.h"
30bf215546Sopenharmony_ci#include "broadcom/compiler/v3d_compiler.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cistatic uint8_t
33bf215546Sopenharmony_civ3d_factor(enum pipe_blendfactor factor, bool dst_alpha_one)
34bf215546Sopenharmony_ci{
35bf215546Sopenharmony_ci        /* We may get a bad blendfactor when blending is disabled. */
36bf215546Sopenharmony_ci        if (factor == 0)
37bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_ZERO;
38bf215546Sopenharmony_ci
39bf215546Sopenharmony_ci        switch (factor) {
40bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_ZERO:
41bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_ZERO;
42bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_ONE:
43bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_ONE;
44bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_SRC_COLOR:
45bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_SRC_COLOR;
46bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_SRC_COLOR:
47bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_INV_SRC_COLOR;
48bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_DST_COLOR:
49bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_DST_COLOR;
50bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_DST_COLOR:
51bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_INV_DST_COLOR;
52bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_SRC_ALPHA:
53bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_SRC_ALPHA;
54bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
55bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_INV_SRC_ALPHA;
56bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_DST_ALPHA:
57bf215546Sopenharmony_ci                return (dst_alpha_one ?
58bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_ONE :
59bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_DST_ALPHA);
60bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_DST_ALPHA:
61bf215546Sopenharmony_ci                return (dst_alpha_one ?
62bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_ZERO :
63bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_INV_DST_ALPHA);
64bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_CONST_COLOR:
65bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_CONST_COLOR;
66bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_CONST_COLOR:
67bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_INV_CONST_COLOR;
68bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_CONST_ALPHA:
69bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_CONST_ALPHA;
70bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
71bf215546Sopenharmony_ci                return V3D_BLEND_FACTOR_INV_CONST_ALPHA;
72bf215546Sopenharmony_ci        case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
73bf215546Sopenharmony_ci                return (dst_alpha_one ?
74bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_ZERO :
75bf215546Sopenharmony_ci                        V3D_BLEND_FACTOR_SRC_ALPHA_SATURATE);
76bf215546Sopenharmony_ci        default:
77bf215546Sopenharmony_ci                unreachable("Bad blend factor");
78bf215546Sopenharmony_ci        }
79bf215546Sopenharmony_ci}
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci#if V3D_VERSION < 40
82bf215546Sopenharmony_cistatic inline uint16_t
83bf215546Sopenharmony_ciswizzled_border_color(const struct v3d_device_info *devinfo,
84bf215546Sopenharmony_ci                      struct pipe_sampler_state *sampler,
85bf215546Sopenharmony_ci                      struct v3d_sampler_view *sview,
86bf215546Sopenharmony_ci                      int chan)
87bf215546Sopenharmony_ci{
88bf215546Sopenharmony_ci        const struct util_format_description *desc =
89bf215546Sopenharmony_ci                util_format_description(sview->base.format);
90bf215546Sopenharmony_ci        uint8_t swiz = chan;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci        /* If we're doing swizzling in the sampler, then only rearrange the
93bf215546Sopenharmony_ci         * border color for the mismatch between the V3D texture format and
94bf215546Sopenharmony_ci         * the PIPE_FORMAT, since GL_ARB_texture_swizzle will be handled by
95bf215546Sopenharmony_ci         * the sampler's swizzle.
96bf215546Sopenharmony_ci         *
97bf215546Sopenharmony_ci         * For swizzling in the shader, we don't do any pre-swizzling of the
98bf215546Sopenharmony_ci         * border color.
99bf215546Sopenharmony_ci         */
100bf215546Sopenharmony_ci        if (v3d_get_tex_return_size(devinfo, sview->base.format,
101bf215546Sopenharmony_ci                                    sampler->compare_mode) != 32)
102bf215546Sopenharmony_ci                swiz = desc->swizzle[swiz];
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci        switch (swiz) {
105bf215546Sopenharmony_ci        case PIPE_SWIZZLE_0:
106bf215546Sopenharmony_ci                return _mesa_float_to_half(0.0);
107bf215546Sopenharmony_ci        case PIPE_SWIZZLE_1:
108bf215546Sopenharmony_ci                return _mesa_float_to_half(1.0);
109bf215546Sopenharmony_ci        default:
110bf215546Sopenharmony_ci                return _mesa_float_to_half(sampler->border_color.f[swiz]);
111bf215546Sopenharmony_ci        }
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_cistatic void
115bf215546Sopenharmony_ciemit_one_texture(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex,
116bf215546Sopenharmony_ci                 int i)
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci        struct v3d_job *job = v3d->job;
119bf215546Sopenharmony_ci        struct pipe_sampler_state *psampler = stage_tex->samplers[i];
120bf215546Sopenharmony_ci        struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
121bf215546Sopenharmony_ci        struct pipe_sampler_view *psview = stage_tex->textures[i];
122bf215546Sopenharmony_ci        struct v3d_sampler_view *sview = v3d_sampler_view(psview);
123bf215546Sopenharmony_ci        struct pipe_resource *prsc = psview->texture;
124bf215546Sopenharmony_ci        struct v3d_resource *rsc = v3d_resource(prsc);
125bf215546Sopenharmony_ci        const struct v3d_device_info *devinfo = &v3d->screen->devinfo;
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci        stage_tex->texture_state[i].offset =
128bf215546Sopenharmony_ci                v3d_cl_ensure_space(&job->indirect,
129bf215546Sopenharmony_ci                                    cl_packet_length(TEXTURE_SHADER_STATE),
130bf215546Sopenharmony_ci                                    32);
131bf215546Sopenharmony_ci        v3d_bo_set_reference(&stage_tex->texture_state[i].bo,
132bf215546Sopenharmony_ci                             job->indirect.bo);
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci        uint32_t return_size = v3d_get_tex_return_size(devinfo, psview->format,
135bf215546Sopenharmony_ci                                                       psampler->compare_mode);
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci        struct V3D33_TEXTURE_SHADER_STATE unpacked = {
138bf215546Sopenharmony_ci                /* XXX */
139bf215546Sopenharmony_ci                .border_color_red = swizzled_border_color(devinfo, psampler,
140bf215546Sopenharmony_ci                                                          sview, 0),
141bf215546Sopenharmony_ci                .border_color_green = swizzled_border_color(devinfo, psampler,
142bf215546Sopenharmony_ci                                                            sview, 1),
143bf215546Sopenharmony_ci                .border_color_blue = swizzled_border_color(devinfo, psampler,
144bf215546Sopenharmony_ci                                                           sview, 2),
145bf215546Sopenharmony_ci                .border_color_alpha = swizzled_border_color(devinfo, psampler,
146bf215546Sopenharmony_ci                                                            sview, 3),
147bf215546Sopenharmony_ci
148bf215546Sopenharmony_ci                /* In the normal texturing path, the LOD gets clamped between
149bf215546Sopenharmony_ci                 * min/max, and the base_level field (set in the sampler view
150bf215546Sopenharmony_ci                 * from first_level) only decides where the min/mag switch
151bf215546Sopenharmony_ci                 * happens, so we need to use the LOD clamps to keep us
152bf215546Sopenharmony_ci                 * between min and max.
153bf215546Sopenharmony_ci                 *
154bf215546Sopenharmony_ci                 * For txf, the LOD clamp is still used, despite GL not
155bf215546Sopenharmony_ci                 * wanting that.  We will need to have a separate
156bf215546Sopenharmony_ci                 * TEXTURE_SHADER_STATE that ignores psview->min/max_lod to
157bf215546Sopenharmony_ci                 * support txf properly.
158bf215546Sopenharmony_ci                 */
159bf215546Sopenharmony_ci                .min_level_of_detail = MIN2(psview->u.tex.first_level +
160bf215546Sopenharmony_ci                                            MAX2(psampler->min_lod, 0),
161bf215546Sopenharmony_ci                                            psview->u.tex.last_level),
162bf215546Sopenharmony_ci                .max_level_of_detail = MIN2(psview->u.tex.first_level +
163bf215546Sopenharmony_ci                                            MAX2(psampler->max_lod,
164bf215546Sopenharmony_ci                                                 psampler->min_lod),
165bf215546Sopenharmony_ci                                            psview->u.tex.last_level),
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci                .texture_base_pointer = cl_address(rsc->bo,
168bf215546Sopenharmony_ci                                                   rsc->slices[0].offset),
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci                .output_32_bit = return_size == 32,
171bf215546Sopenharmony_ci        };
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci        /* Set up the sampler swizzle if we're doing 16-bit sampling.  For
174bf215546Sopenharmony_ci         * 32-bit, we leave swizzling up to the shader compiler.
175bf215546Sopenharmony_ci         *
176bf215546Sopenharmony_ci         * Note: Contrary to the docs, the swizzle still applies even if the
177bf215546Sopenharmony_ci         * return size is 32.  It's just that you probably want to swizzle in
178bf215546Sopenharmony_ci         * the shader, because you need the Y/Z/W channels to be defined.
179bf215546Sopenharmony_ci         */
180bf215546Sopenharmony_ci        if (return_size == 32) {
181bf215546Sopenharmony_ci                unpacked.swizzle_r = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_X);
182bf215546Sopenharmony_ci                unpacked.swizzle_g = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Y);
183bf215546Sopenharmony_ci                unpacked.swizzle_b = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_Z);
184bf215546Sopenharmony_ci                unpacked.swizzle_a = v3d_translate_pipe_swizzle(PIPE_SWIZZLE_W);
185bf215546Sopenharmony_ci        } else {
186bf215546Sopenharmony_ci                unpacked.swizzle_r = v3d_translate_pipe_swizzle(sview->swizzle[0]);
187bf215546Sopenharmony_ci                unpacked.swizzle_g = v3d_translate_pipe_swizzle(sview->swizzle[1]);
188bf215546Sopenharmony_ci                unpacked.swizzle_b = v3d_translate_pipe_swizzle(sview->swizzle[2]);
189bf215546Sopenharmony_ci                unpacked.swizzle_a = v3d_translate_pipe_swizzle(sview->swizzle[3]);
190bf215546Sopenharmony_ci        }
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci        int min_img_filter = psampler->min_img_filter;
193bf215546Sopenharmony_ci        int min_mip_filter = psampler->min_mip_filter;
194bf215546Sopenharmony_ci        int mag_img_filter = psampler->mag_img_filter;
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci        if (return_size == 32) {
197bf215546Sopenharmony_ci                min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
198bf215546Sopenharmony_ci                min_img_filter = PIPE_TEX_FILTER_NEAREST;
199bf215546Sopenharmony_ci                mag_img_filter = PIPE_TEX_FILTER_NEAREST;
200bf215546Sopenharmony_ci        }
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci        bool min_nearest = min_img_filter == PIPE_TEX_FILTER_NEAREST;
203bf215546Sopenharmony_ci        switch (min_mip_filter) {
204bf215546Sopenharmony_ci        case PIPE_TEX_MIPFILTER_NONE:
205bf215546Sopenharmony_ci                unpacked.filter += min_nearest ? 2 : 0;
206bf215546Sopenharmony_ci                break;
207bf215546Sopenharmony_ci        case PIPE_TEX_MIPFILTER_NEAREST:
208bf215546Sopenharmony_ci                unpacked.filter += min_nearest ? 4 : 8;
209bf215546Sopenharmony_ci                break;
210bf215546Sopenharmony_ci        case PIPE_TEX_MIPFILTER_LINEAR:
211bf215546Sopenharmony_ci                unpacked.filter += min_nearest ? 4 : 8;
212bf215546Sopenharmony_ci                unpacked.filter += 2;
213bf215546Sopenharmony_ci                break;
214bf215546Sopenharmony_ci        }
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci        if (mag_img_filter == PIPE_TEX_FILTER_NEAREST)
217bf215546Sopenharmony_ci                unpacked.filter++;
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci        if (psampler->max_anisotropy > 8)
220bf215546Sopenharmony_ci                unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_16_1;
221bf215546Sopenharmony_ci        else if (psampler->max_anisotropy > 4)
222bf215546Sopenharmony_ci                unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_8_1;
223bf215546Sopenharmony_ci        else if (psampler->max_anisotropy > 2)
224bf215546Sopenharmony_ci                unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_4_1;
225bf215546Sopenharmony_ci        else if (psampler->max_anisotropy)
226bf215546Sopenharmony_ci                unpacked.filter = V3D_TMU_FILTER_ANISOTROPIC_2_1;
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci        uint8_t packed[cl_packet_length(TEXTURE_SHADER_STATE)];
229bf215546Sopenharmony_ci        cl_packet_pack(TEXTURE_SHADER_STATE)(&job->indirect, packed, &unpacked);
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ci        for (int i = 0; i < ARRAY_SIZE(packed); i++)
232bf215546Sopenharmony_ci                packed[i] |= sview->texture_shader_state[i] | sampler->texture_shader_state[i];
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci        /* TMU indirect structs need to be 32b aligned. */
235bf215546Sopenharmony_ci        v3d_cl_ensure_space(&job->indirect, ARRAY_SIZE(packed), 32);
236bf215546Sopenharmony_ci        cl_emit_prepacked(&job->indirect, &packed);
237bf215546Sopenharmony_ci}
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_cistatic void
240bf215546Sopenharmony_ciemit_textures(struct v3d_context *v3d, struct v3d_texture_stateobj *stage_tex)
241bf215546Sopenharmony_ci{
242bf215546Sopenharmony_ci        for (int i = 0; i < stage_tex->num_textures; i++) {
243bf215546Sopenharmony_ci                if (stage_tex->textures[i])
244bf215546Sopenharmony_ci                        emit_one_texture(v3d, stage_tex, i);
245bf215546Sopenharmony_ci        }
246bf215546Sopenharmony_ci}
247bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */
248bf215546Sopenharmony_ci
249bf215546Sopenharmony_cistatic uint32_t
250bf215546Sopenharmony_citranslate_colormask(struct v3d_context *v3d, uint32_t colormask, int rt)
251bf215546Sopenharmony_ci{
252bf215546Sopenharmony_ci        if (v3d->swap_color_rb & (1 << rt)) {
253bf215546Sopenharmony_ci                colormask = ((colormask & (2 | 8)) |
254bf215546Sopenharmony_ci                             ((colormask & 1) << 2) |
255bf215546Sopenharmony_ci                             ((colormask & 4) >> 2));
256bf215546Sopenharmony_ci        }
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci        return (~colormask) & 0xf;
259bf215546Sopenharmony_ci}
260bf215546Sopenharmony_ci
261bf215546Sopenharmony_cistatic void
262bf215546Sopenharmony_ciemit_rt_blend(struct v3d_context *v3d, struct v3d_job *job,
263bf215546Sopenharmony_ci              struct pipe_blend_state *blend, int rt, uint8_t rt_mask,
264bf215546Sopenharmony_ci              bool blend_dst_alpha_one)
265bf215546Sopenharmony_ci{
266bf215546Sopenharmony_ci        struct pipe_rt_blend_state *rtblend = &blend->rt[rt];
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci#if V3D_VERSION >= 40
269bf215546Sopenharmony_ci        /* We don't need to emit blend state for disabled RTs. */
270bf215546Sopenharmony_ci        if (!rtblend->blend_enable)
271bf215546Sopenharmony_ci                return;
272bf215546Sopenharmony_ci#endif
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci        cl_emit(&job->bcl, BLEND_CFG, config) {
275bf215546Sopenharmony_ci#if V3D_VERSION >= 40
276bf215546Sopenharmony_ci                config.render_target_mask = rt_mask;
277bf215546Sopenharmony_ci#else
278bf215546Sopenharmony_ci                assert(rt == 0);
279bf215546Sopenharmony_ci#endif
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci                config.color_blend_mode = rtblend->rgb_func;
282bf215546Sopenharmony_ci                config.color_blend_dst_factor =
283bf215546Sopenharmony_ci                        v3d_factor(rtblend->rgb_dst_factor,
284bf215546Sopenharmony_ci                                   blend_dst_alpha_one);
285bf215546Sopenharmony_ci                config.color_blend_src_factor =
286bf215546Sopenharmony_ci                        v3d_factor(rtblend->rgb_src_factor,
287bf215546Sopenharmony_ci                                   blend_dst_alpha_one);
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci                config.alpha_blend_mode = rtblend->alpha_func;
290bf215546Sopenharmony_ci                config.alpha_blend_dst_factor =
291bf215546Sopenharmony_ci                        v3d_factor(rtblend->alpha_dst_factor,
292bf215546Sopenharmony_ci                                   blend_dst_alpha_one);
293bf215546Sopenharmony_ci                config.alpha_blend_src_factor =
294bf215546Sopenharmony_ci                        v3d_factor(rtblend->alpha_src_factor,
295bf215546Sopenharmony_ci                                   blend_dst_alpha_one);
296bf215546Sopenharmony_ci        }
297bf215546Sopenharmony_ci}
298bf215546Sopenharmony_ci
299bf215546Sopenharmony_cistatic void
300bf215546Sopenharmony_ciemit_flat_shade_flags(struct v3d_job *job,
301bf215546Sopenharmony_ci                      int varying_offset,
302bf215546Sopenharmony_ci                      uint32_t varyings,
303bf215546Sopenharmony_ci                      enum V3DX(Varying_Flags_Action) lower,
304bf215546Sopenharmony_ci                      enum V3DX(Varying_Flags_Action) higher)
305bf215546Sopenharmony_ci{
306bf215546Sopenharmony_ci        cl_emit(&job->bcl, FLAT_SHADE_FLAGS, flags) {
307bf215546Sopenharmony_ci                flags.varying_offset_v0 = varying_offset;
308bf215546Sopenharmony_ci                flags.flat_shade_flags_for_varyings_v024 = varyings;
309bf215546Sopenharmony_ci                flags.action_for_flat_shade_flags_of_lower_numbered_varyings =
310bf215546Sopenharmony_ci                        lower;
311bf215546Sopenharmony_ci                flags.action_for_flat_shade_flags_of_higher_numbered_varyings =
312bf215546Sopenharmony_ci                        higher;
313bf215546Sopenharmony_ci        }
314bf215546Sopenharmony_ci}
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci#if V3D_VERSION >= 40
317bf215546Sopenharmony_cistatic void
318bf215546Sopenharmony_ciemit_noperspective_flags(struct v3d_job *job,
319bf215546Sopenharmony_ci                         int varying_offset,
320bf215546Sopenharmony_ci                         uint32_t varyings,
321bf215546Sopenharmony_ci                         enum V3DX(Varying_Flags_Action) lower,
322bf215546Sopenharmony_ci                         enum V3DX(Varying_Flags_Action) higher)
323bf215546Sopenharmony_ci{
324bf215546Sopenharmony_ci        cl_emit(&job->bcl, NON_PERSPECTIVE_FLAGS, flags) {
325bf215546Sopenharmony_ci                flags.varying_offset_v0 = varying_offset;
326bf215546Sopenharmony_ci                flags.non_perspective_flags_for_varyings_v024 = varyings;
327bf215546Sopenharmony_ci                flags.action_for_non_perspective_flags_of_lower_numbered_varyings =
328bf215546Sopenharmony_ci                        lower;
329bf215546Sopenharmony_ci                flags.action_for_non_perspective_flags_of_higher_numbered_varyings =
330bf215546Sopenharmony_ci                        higher;
331bf215546Sopenharmony_ci        }
332bf215546Sopenharmony_ci}
333bf215546Sopenharmony_ci
334bf215546Sopenharmony_cistatic void
335bf215546Sopenharmony_ciemit_centroid_flags(struct v3d_job *job,
336bf215546Sopenharmony_ci                    int varying_offset,
337bf215546Sopenharmony_ci                    uint32_t varyings,
338bf215546Sopenharmony_ci                    enum V3DX(Varying_Flags_Action) lower,
339bf215546Sopenharmony_ci                    enum V3DX(Varying_Flags_Action) higher)
340bf215546Sopenharmony_ci{
341bf215546Sopenharmony_ci        cl_emit(&job->bcl, CENTROID_FLAGS, flags) {
342bf215546Sopenharmony_ci                flags.varying_offset_v0 = varying_offset;
343bf215546Sopenharmony_ci                flags.centroid_flags_for_varyings_v024 = varyings;
344bf215546Sopenharmony_ci                flags.action_for_centroid_flags_of_lower_numbered_varyings =
345bf215546Sopenharmony_ci                        lower;
346bf215546Sopenharmony_ci                flags.action_for_centroid_flags_of_higher_numbered_varyings =
347bf215546Sopenharmony_ci                        higher;
348bf215546Sopenharmony_ci        }
349bf215546Sopenharmony_ci}
350bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */
351bf215546Sopenharmony_ci
352bf215546Sopenharmony_cistatic bool
353bf215546Sopenharmony_ciemit_varying_flags(struct v3d_job *job, uint32_t *flags,
354bf215546Sopenharmony_ci                   void (*flag_emit_callback)(struct v3d_job *job,
355bf215546Sopenharmony_ci                                              int varying_offset,
356bf215546Sopenharmony_ci                                              uint32_t flags,
357bf215546Sopenharmony_ci                                              enum V3DX(Varying_Flags_Action) lower,
358bf215546Sopenharmony_ci                                              enum V3DX(Varying_Flags_Action) higher))
359bf215546Sopenharmony_ci{
360bf215546Sopenharmony_ci        struct v3d_context *v3d = job->v3d;
361bf215546Sopenharmony_ci        bool emitted_any = false;
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci        for (int i = 0; i < ARRAY_SIZE(v3d->prog.fs->prog_data.fs->flat_shade_flags); i++) {
364bf215546Sopenharmony_ci                if (!flags[i])
365bf215546Sopenharmony_ci                        continue;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci                if (emitted_any) {
368bf215546Sopenharmony_ci                        flag_emit_callback(job, i, flags[i],
369bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_UNCHANGED,
370bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_UNCHANGED);
371bf215546Sopenharmony_ci                } else if (i == 0) {
372bf215546Sopenharmony_ci                        flag_emit_callback(job, i, flags[i],
373bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_UNCHANGED,
374bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_ZEROED);
375bf215546Sopenharmony_ci                } else {
376bf215546Sopenharmony_ci                        flag_emit_callback(job, i, flags[i],
377bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_ZEROED,
378bf215546Sopenharmony_ci                                           V3D_VARYING_FLAGS_ACTION_ZEROED);
379bf215546Sopenharmony_ci                }
380bf215546Sopenharmony_ci                emitted_any = true;
381bf215546Sopenharmony_ci        }
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_ci        return emitted_any;
384bf215546Sopenharmony_ci}
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_cistatic inline struct v3d_uncompiled_shader *
387bf215546Sopenharmony_ciget_tf_shader(struct v3d_context *v3d)
388bf215546Sopenharmony_ci{
389bf215546Sopenharmony_ci        if (v3d->prog.bind_gs)
390bf215546Sopenharmony_ci                return v3d->prog.bind_gs;
391bf215546Sopenharmony_ci        else
392bf215546Sopenharmony_ci                return v3d->prog.bind_vs;
393bf215546Sopenharmony_ci}
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_civoid
396bf215546Sopenharmony_civ3dX(emit_state)(struct pipe_context *pctx)
397bf215546Sopenharmony_ci{
398bf215546Sopenharmony_ci        struct v3d_context *v3d = v3d_context(pctx);
399bf215546Sopenharmony_ci        struct v3d_job *job = v3d->job;
400bf215546Sopenharmony_ci        bool rasterizer_discard = v3d->rasterizer->base.rasterizer_discard;
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci        if (v3d->dirty & (V3D_DIRTY_SCISSOR | V3D_DIRTY_VIEWPORT |
403bf215546Sopenharmony_ci                          V3D_DIRTY_RASTERIZER)) {
404bf215546Sopenharmony_ci                float *vpscale = v3d->viewport.scale;
405bf215546Sopenharmony_ci                float *vptranslate = v3d->viewport.translate;
406bf215546Sopenharmony_ci                float vp_minx = -fabsf(vpscale[0]) + vptranslate[0];
407bf215546Sopenharmony_ci                float vp_maxx = fabsf(vpscale[0]) + vptranslate[0];
408bf215546Sopenharmony_ci                float vp_miny = -fabsf(vpscale[1]) + vptranslate[1];
409bf215546Sopenharmony_ci                float vp_maxy = fabsf(vpscale[1]) + vptranslate[1];
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci                /* Clip to the scissor if it's enabled, but still clip to the
412bf215546Sopenharmony_ci                 * drawable regardless since that controls where the binner
413bf215546Sopenharmony_ci                 * tries to put things.
414bf215546Sopenharmony_ci                 *
415bf215546Sopenharmony_ci                 * Additionally, always clip the rendering to the viewport,
416bf215546Sopenharmony_ci                 * since the hardware does guardband clipping, meaning
417bf215546Sopenharmony_ci                 * primitives would rasterize outside of the view volume.
418bf215546Sopenharmony_ci                 */
419bf215546Sopenharmony_ci                uint32_t minx, miny, maxx, maxy;
420bf215546Sopenharmony_ci                if (!v3d->rasterizer->base.scissor) {
421bf215546Sopenharmony_ci                        minx = MAX2(vp_minx, 0);
422bf215546Sopenharmony_ci                        miny = MAX2(vp_miny, 0);
423bf215546Sopenharmony_ci                        maxx = MIN2(vp_maxx, job->draw_width);
424bf215546Sopenharmony_ci                        maxy = MIN2(vp_maxy, job->draw_height);
425bf215546Sopenharmony_ci                } else {
426bf215546Sopenharmony_ci                        minx = MAX2(vp_minx, v3d->scissor.minx);
427bf215546Sopenharmony_ci                        miny = MAX2(vp_miny, v3d->scissor.miny);
428bf215546Sopenharmony_ci                        maxx = MIN2(vp_maxx, v3d->scissor.maxx);
429bf215546Sopenharmony_ci                        maxy = MIN2(vp_maxy, v3d->scissor.maxy);
430bf215546Sopenharmony_ci                }
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci                cl_emit(&job->bcl, CLIP_WINDOW, clip) {
433bf215546Sopenharmony_ci                        clip.clip_window_left_pixel_coordinate = minx;
434bf215546Sopenharmony_ci                        clip.clip_window_bottom_pixel_coordinate = miny;
435bf215546Sopenharmony_ci                        if (maxx > minx && maxy > miny) {
436bf215546Sopenharmony_ci                                clip.clip_window_width_in_pixels = maxx - minx;
437bf215546Sopenharmony_ci                                clip.clip_window_height_in_pixels = maxy - miny;
438bf215546Sopenharmony_ci                        } else if (V3D_VERSION < 41) {
439bf215546Sopenharmony_ci                                /* The HW won't entirely clip out when scissor
440bf215546Sopenharmony_ci                                 * w/h is 0.  Just treat it the same as
441bf215546Sopenharmony_ci                                 * rasterizer discard.
442bf215546Sopenharmony_ci                                 */
443bf215546Sopenharmony_ci                                rasterizer_discard = true;
444bf215546Sopenharmony_ci                                clip.clip_window_width_in_pixels = 1;
445bf215546Sopenharmony_ci                                clip.clip_window_height_in_pixels = 1;
446bf215546Sopenharmony_ci                        }
447bf215546Sopenharmony_ci                }
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci                job->draw_min_x = MIN2(job->draw_min_x, minx);
450bf215546Sopenharmony_ci                job->draw_min_y = MIN2(job->draw_min_y, miny);
451bf215546Sopenharmony_ci                job->draw_max_x = MAX2(job->draw_max_x, maxx);
452bf215546Sopenharmony_ci                job->draw_max_y = MAX2(job->draw_max_y, maxy);
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci                if (!v3d->rasterizer->base.scissor) {
455bf215546Sopenharmony_ci                    job->scissor.disabled = true;
456bf215546Sopenharmony_ci                } else if (!job->scissor.disabled &&
457bf215546Sopenharmony_ci                           (v3d->dirty & V3D_DIRTY_SCISSOR)) {
458bf215546Sopenharmony_ci                        if (job->scissor.count < MAX_JOB_SCISSORS) {
459bf215546Sopenharmony_ci                                job->scissor.rects[job->scissor.count].min_x =
460bf215546Sopenharmony_ci                                        v3d->scissor.minx;
461bf215546Sopenharmony_ci                                job->scissor.rects[job->scissor.count].min_y =
462bf215546Sopenharmony_ci                                        v3d->scissor.miny;
463bf215546Sopenharmony_ci                                job->scissor.rects[job->scissor.count].max_x =
464bf215546Sopenharmony_ci                                        v3d->scissor.maxx - 1;
465bf215546Sopenharmony_ci                                job->scissor.rects[job->scissor.count].max_y =
466bf215546Sopenharmony_ci                                        v3d->scissor.maxy - 1;
467bf215546Sopenharmony_ci                                job->scissor.count++;
468bf215546Sopenharmony_ci                        } else {
469bf215546Sopenharmony_ci                                job->scissor.disabled = true;
470bf215546Sopenharmony_ci                                perf_debug("Too many scissor rects.");
471bf215546Sopenharmony_ci                        }
472bf215546Sopenharmony_ci                }
473bf215546Sopenharmony_ci        }
474bf215546Sopenharmony_ci
475bf215546Sopenharmony_ci        if (v3d->dirty & (V3D_DIRTY_RASTERIZER |
476bf215546Sopenharmony_ci                          V3D_DIRTY_ZSA |
477bf215546Sopenharmony_ci                          V3D_DIRTY_BLEND |
478bf215546Sopenharmony_ci                          V3D_DIRTY_COMPILED_FS)) {
479bf215546Sopenharmony_ci                cl_emit(&job->bcl, CFG_BITS, config) {
480bf215546Sopenharmony_ci                        config.enable_forward_facing_primitive =
481bf215546Sopenharmony_ci                                !rasterizer_discard &&
482bf215546Sopenharmony_ci                                !(v3d->rasterizer->base.cull_face &
483bf215546Sopenharmony_ci                                  PIPE_FACE_FRONT);
484bf215546Sopenharmony_ci                        config.enable_reverse_facing_primitive =
485bf215546Sopenharmony_ci                                !rasterizer_discard &&
486bf215546Sopenharmony_ci                                !(v3d->rasterizer->base.cull_face &
487bf215546Sopenharmony_ci                                  PIPE_FACE_BACK);
488bf215546Sopenharmony_ci                        /* This seems backwards, but it's what gets the
489bf215546Sopenharmony_ci                         * clipflat test to pass.
490bf215546Sopenharmony_ci                         */
491bf215546Sopenharmony_ci                        config.clockwise_primitives =
492bf215546Sopenharmony_ci                                v3d->rasterizer->base.front_ccw;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci                        config.enable_depth_offset =
495bf215546Sopenharmony_ci                                v3d->rasterizer->base.offset_tri;
496bf215546Sopenharmony_ci
497bf215546Sopenharmony_ci                        /* V3D follows GL behavior where the sample mask only
498bf215546Sopenharmony_ci                         * applies when MSAA is enabled.  Gallium has sample
499bf215546Sopenharmony_ci                         * mask apply anyway, and the MSAA blit shaders will
500bf215546Sopenharmony_ci                         * set sample mask without explicitly setting
501bf215546Sopenharmony_ci                         * rasterizer oversample.  Just force it on here,
502bf215546Sopenharmony_ci                         * since the blit shaders are the only way to have
503bf215546Sopenharmony_ci                         * !multisample && samplemask != 0xf.
504bf215546Sopenharmony_ci                         */
505bf215546Sopenharmony_ci                        config.rasterizer_oversample_mode =
506bf215546Sopenharmony_ci                                v3d->rasterizer->base.multisample ||
507bf215546Sopenharmony_ci                                v3d->sample_mask != 0xf;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci                        config.direct3d_provoking_vertex =
510bf215546Sopenharmony_ci                                v3d->rasterizer->base.flatshade_first;
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci                        config.blend_enable = v3d->blend->blend_enables;
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_ci                        /* Note: EZ state may update based on the compiled FS,
515bf215546Sopenharmony_ci                         * along with ZSA
516bf215546Sopenharmony_ci                         */
517bf215546Sopenharmony_ci                        config.early_z_updates_enable =
518bf215546Sopenharmony_ci                                (job->ez_state != V3D_EZ_DISABLED);
519bf215546Sopenharmony_ci                        if (v3d->zsa->base.depth_enabled) {
520bf215546Sopenharmony_ci                                config.z_updates_enable =
521bf215546Sopenharmony_ci                                        v3d->zsa->base.depth_writemask;
522bf215546Sopenharmony_ci                                config.early_z_enable =
523bf215546Sopenharmony_ci                                        config.early_z_updates_enable;
524bf215546Sopenharmony_ci                                config.depth_test_function =
525bf215546Sopenharmony_ci                                        v3d->zsa->base.depth_func;
526bf215546Sopenharmony_ci                        } else {
527bf215546Sopenharmony_ci                                config.depth_test_function = PIPE_FUNC_ALWAYS;
528bf215546Sopenharmony_ci                        }
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci                        config.stencil_enable =
531bf215546Sopenharmony_ci                                v3d->zsa->base.stencil[0].enabled;
532bf215546Sopenharmony_ci
533bf215546Sopenharmony_ci                        /* Use nicer line caps when line smoothing is
534bf215546Sopenharmony_ci                         * enabled
535bf215546Sopenharmony_ci                         */
536bf215546Sopenharmony_ci                        config.line_rasterization =
537bf215546Sopenharmony_ci                                v3d_line_smoothing_enabled(v3d) ?
538bf215546Sopenharmony_ci                                V3D_LINE_RASTERIZATION_PERP_END_CAPS :
539bf215546Sopenharmony_ci                                V3D_LINE_RASTERIZATION_DIAMOND_EXIT;
540bf215546Sopenharmony_ci                }
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci        }
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_RASTERIZER &&
545bf215546Sopenharmony_ci            v3d->rasterizer->base.offset_tri) {
546bf215546Sopenharmony_ci                if (job->zsbuf &&
547bf215546Sopenharmony_ci                    job->zsbuf->format == PIPE_FORMAT_Z16_UNORM) {
548bf215546Sopenharmony_ci                        cl_emit_prepacked_sized(&job->bcl,
549bf215546Sopenharmony_ci                                                v3d->rasterizer->depth_offset_z16,
550bf215546Sopenharmony_ci                                                cl_packet_length(DEPTH_OFFSET));
551bf215546Sopenharmony_ci                } else {
552bf215546Sopenharmony_ci                        cl_emit_prepacked_sized(&job->bcl,
553bf215546Sopenharmony_ci                                                v3d->rasterizer->depth_offset,
554bf215546Sopenharmony_ci                                                cl_packet_length(DEPTH_OFFSET));
555bf215546Sopenharmony_ci                }
556bf215546Sopenharmony_ci        }
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_RASTERIZER) {
559bf215546Sopenharmony_ci                cl_emit(&job->bcl, POINT_SIZE, point_size) {
560bf215546Sopenharmony_ci                        point_size.point_size = v3d->rasterizer->point_size;
561bf215546Sopenharmony_ci                }
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci                cl_emit(&job->bcl, LINE_WIDTH, line_width) {
564bf215546Sopenharmony_ci                        line_width.line_width = v3d_get_real_line_width(v3d);
565bf215546Sopenharmony_ci                }
566bf215546Sopenharmony_ci        }
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_VIEWPORT) {
569bf215546Sopenharmony_ci                cl_emit(&job->bcl, CLIPPER_XY_SCALING, clip) {
570bf215546Sopenharmony_ci                        clip.viewport_half_width_in_1_256th_of_pixel =
571bf215546Sopenharmony_ci                                v3d->viewport.scale[0] * 256.0f;
572bf215546Sopenharmony_ci                        clip.viewport_half_height_in_1_256th_of_pixel =
573bf215546Sopenharmony_ci                                v3d->viewport.scale[1] * 256.0f;
574bf215546Sopenharmony_ci                }
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci                cl_emit(&job->bcl, CLIPPER_Z_SCALE_AND_OFFSET, clip) {
577bf215546Sopenharmony_ci                        clip.viewport_z_offset_zc_to_zs =
578bf215546Sopenharmony_ci                                v3d->viewport.translate[2];
579bf215546Sopenharmony_ci                        clip.viewport_z_scale_zc_to_zs =
580bf215546Sopenharmony_ci                                v3d->viewport.scale[2];
581bf215546Sopenharmony_ci                }
582bf215546Sopenharmony_ci                cl_emit(&job->bcl, CLIPPER_Z_MIN_MAX_CLIPPING_PLANES, clip) {
583bf215546Sopenharmony_ci                        float z1 = (v3d->viewport.translate[2] -
584bf215546Sopenharmony_ci                                    v3d->viewport.scale[2]);
585bf215546Sopenharmony_ci                        float z2 = (v3d->viewport.translate[2] +
586bf215546Sopenharmony_ci                                    v3d->viewport.scale[2]);
587bf215546Sopenharmony_ci                        clip.minimum_zw = MIN2(z1, z2);
588bf215546Sopenharmony_ci                        clip.maximum_zw = MAX2(z1, z2);
589bf215546Sopenharmony_ci                }
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci                cl_emit(&job->bcl, VIEWPORT_OFFSET, vp) {
592bf215546Sopenharmony_ci                        vp.viewport_centre_x_coordinate =
593bf215546Sopenharmony_ci                                v3d->viewport.translate[0];
594bf215546Sopenharmony_ci                        vp.viewport_centre_y_coordinate =
595bf215546Sopenharmony_ci                                v3d->viewport.translate[1];
596bf215546Sopenharmony_ci                }
597bf215546Sopenharmony_ci        }
598bf215546Sopenharmony_ci
599bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_BLEND) {
600bf215546Sopenharmony_ci                struct v3d_blend_state *blend = v3d->blend;
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci                if (blend->blend_enables) {
603bf215546Sopenharmony_ci#if V3D_VERSION >= 40
604bf215546Sopenharmony_ci                        cl_emit(&job->bcl, BLEND_ENABLES, enables) {
605bf215546Sopenharmony_ci                                enables.mask = blend->blend_enables;
606bf215546Sopenharmony_ci                        }
607bf215546Sopenharmony_ci#endif
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci                        if (blend->base.independent_blend_enable) {
610bf215546Sopenharmony_ci                                for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++)
611bf215546Sopenharmony_ci                                        emit_rt_blend(v3d, job, &blend->base, i,
612bf215546Sopenharmony_ci                                                      (1 << i),
613bf215546Sopenharmony_ci                                                      v3d->blend_dst_alpha_one & (1 << i));
614bf215546Sopenharmony_ci                        } else if (v3d->blend_dst_alpha_one &&
615bf215546Sopenharmony_ci                                   util_bitcount(v3d->blend_dst_alpha_one) < job->nr_cbufs) {
616bf215546Sopenharmony_ci                                /* Even if we don't have independent per-RT
617bf215546Sopenharmony_ci                                 * blending, we may have a combination of RT
618bf215546Sopenharmony_ci                                 * formats were some RTs have an alpha channel
619bf215546Sopenharmony_ci                                 * and others don't. Since this affects how
620bf215546Sopenharmony_ci                                 * blending is performed, we also need to emit
621bf215546Sopenharmony_ci                                 * independent blend configurations in this
622bf215546Sopenharmony_ci                                 * case: one for RTs with alpha and one for
623bf215546Sopenharmony_ci                                 * RTs without.
624bf215546Sopenharmony_ci                                 */
625bf215546Sopenharmony_ci                                emit_rt_blend(v3d, job, &blend->base, 0,
626bf215546Sopenharmony_ci                                              ((1 << V3D_MAX_DRAW_BUFFERS) - 1) &
627bf215546Sopenharmony_ci                                                   v3d->blend_dst_alpha_one,
628bf215546Sopenharmony_ci                                              true);
629bf215546Sopenharmony_ci                                emit_rt_blend(v3d, job, &blend->base, 0,
630bf215546Sopenharmony_ci                                              ((1 << V3D_MAX_DRAW_BUFFERS) - 1) &
631bf215546Sopenharmony_ci                                                   ~v3d->blend_dst_alpha_one,
632bf215546Sopenharmony_ci                                              false);
633bf215546Sopenharmony_ci                        } else {
634bf215546Sopenharmony_ci                                emit_rt_blend(v3d, job, &blend->base, 0,
635bf215546Sopenharmony_ci                                              (1 << V3D_MAX_DRAW_BUFFERS) - 1,
636bf215546Sopenharmony_ci                                              v3d->blend_dst_alpha_one);
637bf215546Sopenharmony_ci                        }
638bf215546Sopenharmony_ci                }
639bf215546Sopenharmony_ci        }
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_BLEND) {
642bf215546Sopenharmony_ci                struct pipe_blend_state *blend = &v3d->blend->base;
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci                cl_emit(&job->bcl, COLOR_WRITE_MASKS, mask) {
645bf215546Sopenharmony_ci                        for (int i = 0; i < 4; i++) {
646bf215546Sopenharmony_ci                                int rt = blend->independent_blend_enable ? i : 0;
647bf215546Sopenharmony_ci                                int rt_mask = blend->rt[rt].colormask;
648bf215546Sopenharmony_ci
649bf215546Sopenharmony_ci                                mask.mask |= translate_colormask(v3d, rt_mask,
650bf215546Sopenharmony_ci                                                                 i) << (4 * i);
651bf215546Sopenharmony_ci                        }
652bf215546Sopenharmony_ci                }
653bf215546Sopenharmony_ci        }
654bf215546Sopenharmony_ci
655bf215546Sopenharmony_ci        /* GFXH-1431: On V3D 3.x, writing BLEND_CONFIG resets the constant
656bf215546Sopenharmony_ci         * color.
657bf215546Sopenharmony_ci         */
658bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_BLEND_COLOR ||
659bf215546Sopenharmony_ci            (V3D_VERSION < 41 && (v3d->dirty & V3D_DIRTY_BLEND))) {
660bf215546Sopenharmony_ci                cl_emit(&job->bcl, BLEND_CONSTANT_COLOR, color) {
661bf215546Sopenharmony_ci                        color.red_f16 = (v3d->swap_color_rb ?
662bf215546Sopenharmony_ci                                          v3d->blend_color.hf[2] :
663bf215546Sopenharmony_ci                                          v3d->blend_color.hf[0]);
664bf215546Sopenharmony_ci                        color.green_f16 = v3d->blend_color.hf[1];
665bf215546Sopenharmony_ci                        color.blue_f16 = (v3d->swap_color_rb ?
666bf215546Sopenharmony_ci                                           v3d->blend_color.hf[0] :
667bf215546Sopenharmony_ci                                           v3d->blend_color.hf[2]);
668bf215546Sopenharmony_ci                        color.alpha_f16 = v3d->blend_color.hf[3];
669bf215546Sopenharmony_ci                }
670bf215546Sopenharmony_ci        }
671bf215546Sopenharmony_ci
672bf215546Sopenharmony_ci        if (v3d->dirty & (V3D_DIRTY_ZSA | V3D_DIRTY_STENCIL_REF)) {
673bf215546Sopenharmony_ci                struct pipe_stencil_state *front = &v3d->zsa->base.stencil[0];
674bf215546Sopenharmony_ci                struct pipe_stencil_state *back = &v3d->zsa->base.stencil[1];
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci                if (front->enabled) {
677bf215546Sopenharmony_ci                        cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
678bf215546Sopenharmony_ci                                               v3d->zsa->stencil_front, config) {
679bf215546Sopenharmony_ci                                config.stencil_ref_value =
680bf215546Sopenharmony_ci                                        v3d->stencil_ref.ref_value[0];
681bf215546Sopenharmony_ci                        }
682bf215546Sopenharmony_ci                }
683bf215546Sopenharmony_ci
684bf215546Sopenharmony_ci                if (back->enabled) {
685bf215546Sopenharmony_ci                        cl_emit_with_prepacked(&job->bcl, STENCIL_CFG,
686bf215546Sopenharmony_ci                                               v3d->zsa->stencil_back, config) {
687bf215546Sopenharmony_ci                                config.stencil_ref_value =
688bf215546Sopenharmony_ci                                        v3d->stencil_ref.ref_value[1];
689bf215546Sopenharmony_ci                        }
690bf215546Sopenharmony_ci                }
691bf215546Sopenharmony_ci        }
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_ci#if V3D_VERSION < 40
694bf215546Sopenharmony_ci        /* Pre-4.x, we have texture state that depends on both the sampler and
695bf215546Sopenharmony_ci         * the view, so we merge them together at draw time.
696bf215546Sopenharmony_ci         */
697bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_FRAGTEX)
698bf215546Sopenharmony_ci                emit_textures(v3d, &v3d->tex[PIPE_SHADER_FRAGMENT]);
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_GEOMTEX)
701bf215546Sopenharmony_ci                emit_textures(v3d, &v3d->tex[PIPE_SHADER_GEOMETRY]);
702bf215546Sopenharmony_ci
703bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_VERTTEX)
704bf215546Sopenharmony_ci                emit_textures(v3d, &v3d->tex[PIPE_SHADER_VERTEX]);
705bf215546Sopenharmony_ci#endif
706bf215546Sopenharmony_ci
707bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_FLAT_SHADE_FLAGS) {
708bf215546Sopenharmony_ci                if (!emit_varying_flags(job,
709bf215546Sopenharmony_ci                                        v3d->prog.fs->prog_data.fs->flat_shade_flags,
710bf215546Sopenharmony_ci                                        emit_flat_shade_flags)) {
711bf215546Sopenharmony_ci                        cl_emit(&job->bcl, ZERO_ALL_FLAT_SHADE_FLAGS, flags);
712bf215546Sopenharmony_ci                }
713bf215546Sopenharmony_ci        }
714bf215546Sopenharmony_ci
715bf215546Sopenharmony_ci#if V3D_VERSION >= 40
716bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_NOPERSPECTIVE_FLAGS) {
717bf215546Sopenharmony_ci                if (!emit_varying_flags(job,
718bf215546Sopenharmony_ci                                        v3d->prog.fs->prog_data.fs->noperspective_flags,
719bf215546Sopenharmony_ci                                        emit_noperspective_flags)) {
720bf215546Sopenharmony_ci                        cl_emit(&job->bcl, ZERO_ALL_NON_PERSPECTIVE_FLAGS, flags);
721bf215546Sopenharmony_ci                }
722bf215546Sopenharmony_ci        }
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_CENTROID_FLAGS) {
725bf215546Sopenharmony_ci                if (!emit_varying_flags(job,
726bf215546Sopenharmony_ci                                        v3d->prog.fs->prog_data.fs->centroid_flags,
727bf215546Sopenharmony_ci                                        emit_centroid_flags)) {
728bf215546Sopenharmony_ci                        cl_emit(&job->bcl, ZERO_ALL_CENTROID_FLAGS, flags);
729bf215546Sopenharmony_ci                }
730bf215546Sopenharmony_ci        }
731bf215546Sopenharmony_ci#endif
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci        /* Set up the transform feedback data specs (which VPM entries to
734bf215546Sopenharmony_ci         * output to which buffers).
735bf215546Sopenharmony_ci         */
736bf215546Sopenharmony_ci        if (v3d->dirty & (V3D_DIRTY_STREAMOUT |
737bf215546Sopenharmony_ci                          V3D_DIRTY_RASTERIZER |
738bf215546Sopenharmony_ci                          V3D_DIRTY_PRIM_MODE)) {
739bf215546Sopenharmony_ci                struct v3d_streamout_stateobj *so = &v3d->streamout;
740bf215546Sopenharmony_ci                if (so->num_targets) {
741bf215546Sopenharmony_ci                        bool psiz_per_vertex = (v3d->prim_mode == PIPE_PRIM_POINTS &&
742bf215546Sopenharmony_ci                                                v3d->rasterizer->base.point_size_per_vertex);
743bf215546Sopenharmony_ci                        struct v3d_uncompiled_shader *tf_shader =
744bf215546Sopenharmony_ci                                get_tf_shader(v3d);
745bf215546Sopenharmony_ci                        uint16_t *tf_specs = (psiz_per_vertex ?
746bf215546Sopenharmony_ci                                              tf_shader->tf_specs_psiz :
747bf215546Sopenharmony_ci                                              tf_shader->tf_specs);
748bf215546Sopenharmony_ci
749bf215546Sopenharmony_ci#if V3D_VERSION >= 40
750bf215546Sopenharmony_ci                        bool tf_enabled = v3d_transform_feedback_enabled(v3d);
751bf215546Sopenharmony_ci                        job->tf_enabled |= tf_enabled;
752bf215546Sopenharmony_ci
753bf215546Sopenharmony_ci                        cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
754bf215546Sopenharmony_ci                                tfe.number_of_16_bit_output_data_specs_following =
755bf215546Sopenharmony_ci                                        tf_shader->num_tf_specs;
756bf215546Sopenharmony_ci                                tfe.enable = tf_enabled;
757bf215546Sopenharmony_ci                        };
758bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */
759bf215546Sopenharmony_ci                        cl_emit(&job->bcl, TRANSFORM_FEEDBACK_ENABLE, tfe) {
760bf215546Sopenharmony_ci                                tfe.number_of_32_bit_output_buffer_address_following =
761bf215546Sopenharmony_ci                                        so->num_targets;
762bf215546Sopenharmony_ci                                tfe.number_of_16_bit_output_data_specs_following =
763bf215546Sopenharmony_ci                                        tf_shader->num_tf_specs;
764bf215546Sopenharmony_ci                        };
765bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */
766bf215546Sopenharmony_ci                        for (int i = 0; i < tf_shader->num_tf_specs; i++) {
767bf215546Sopenharmony_ci                                cl_emit_prepacked(&job->bcl, &tf_specs[i]);
768bf215546Sopenharmony_ci                        }
769bf215546Sopenharmony_ci                } else {
770bf215546Sopenharmony_ci#if V3D_VERSION >= 40
771bf215546Sopenharmony_ci                        cl_emit(&job->bcl, TRANSFORM_FEEDBACK_SPECS, tfe) {
772bf215546Sopenharmony_ci                                tfe.enable = false;
773bf215546Sopenharmony_ci                        };
774bf215546Sopenharmony_ci#endif /* V3D_VERSION >= 40 */
775bf215546Sopenharmony_ci                }
776bf215546Sopenharmony_ci        }
777bf215546Sopenharmony_ci
778bf215546Sopenharmony_ci        /* Set up the transform feedback buffers. */
779bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_STREAMOUT) {
780bf215546Sopenharmony_ci                struct v3d_uncompiled_shader *tf_shader = get_tf_shader(v3d);
781bf215546Sopenharmony_ci                struct v3d_streamout_stateobj *so = &v3d->streamout;
782bf215546Sopenharmony_ci                for (int i = 0; i < so->num_targets; i++) {
783bf215546Sopenharmony_ci                        const struct pipe_stream_output_target *target =
784bf215546Sopenharmony_ci                                so->targets[i];
785bf215546Sopenharmony_ci                        struct v3d_resource *rsc = target ?
786bf215546Sopenharmony_ci                                v3d_resource(target->buffer) : NULL;
787bf215546Sopenharmony_ci                        struct pipe_shader_state *ss = &tf_shader->base;
788bf215546Sopenharmony_ci                        struct pipe_stream_output_info *info = &ss->stream_output;
789bf215546Sopenharmony_ci                        uint32_t offset = (v3d->streamout.offsets[i] *
790bf215546Sopenharmony_ci                                           info->stride[i] * 4);
791bf215546Sopenharmony_ci
792bf215546Sopenharmony_ci#if V3D_VERSION >= 40
793bf215546Sopenharmony_ci                        if (!target)
794bf215546Sopenharmony_ci                                continue;
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci                        cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) {
797bf215546Sopenharmony_ci                                output.buffer_address =
798bf215546Sopenharmony_ci                                        cl_address(rsc->bo,
799bf215546Sopenharmony_ci                                                   target->buffer_offset +
800bf215546Sopenharmony_ci                                                   offset);
801bf215546Sopenharmony_ci                                output.buffer_size_in_32_bit_words =
802bf215546Sopenharmony_ci                                        (target->buffer_size - offset) >> 2;
803bf215546Sopenharmony_ci                                output.buffer_number = i;
804bf215546Sopenharmony_ci                        }
805bf215546Sopenharmony_ci#else /* V3D_VERSION < 40 */
806bf215546Sopenharmony_ci                        cl_emit(&job->bcl, TRANSFORM_FEEDBACK_OUTPUT_ADDRESS, output) {
807bf215546Sopenharmony_ci                                if (target) {
808bf215546Sopenharmony_ci                                        output.address =
809bf215546Sopenharmony_ci                                                cl_address(rsc->bo,
810bf215546Sopenharmony_ci                                                           target->buffer_offset +
811bf215546Sopenharmony_ci                                                           offset);
812bf215546Sopenharmony_ci                                }
813bf215546Sopenharmony_ci                        };
814bf215546Sopenharmony_ci#endif /* V3D_VERSION < 40 */
815bf215546Sopenharmony_ci                        if (target) {
816bf215546Sopenharmony_ci                                v3d_job_add_tf_write_resource(v3d->job,
817bf215546Sopenharmony_ci                                                              target->buffer);
818bf215546Sopenharmony_ci                        }
819bf215546Sopenharmony_ci                        /* XXX: buffer_size? */
820bf215546Sopenharmony_ci                }
821bf215546Sopenharmony_ci        }
822bf215546Sopenharmony_ci
823bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_OQ) {
824bf215546Sopenharmony_ci                cl_emit(&job->bcl, OCCLUSION_QUERY_COUNTER, counter) {
825bf215546Sopenharmony_ci                        if (v3d->active_queries && v3d->current_oq) {
826bf215546Sopenharmony_ci                                counter.address = cl_address(v3d->current_oq, 0);
827bf215546Sopenharmony_ci                        }
828bf215546Sopenharmony_ci                }
829bf215546Sopenharmony_ci        }
830bf215546Sopenharmony_ci
831bf215546Sopenharmony_ci#if V3D_VERSION >= 40
832bf215546Sopenharmony_ci        if (v3d->dirty & V3D_DIRTY_SAMPLE_STATE) {
833bf215546Sopenharmony_ci                cl_emit(&job->bcl, SAMPLE_STATE, state) {
834bf215546Sopenharmony_ci                        /* Note: SampleCoverage was handled at the
835bf215546Sopenharmony_ci                         * frontend level by converting to sample_mask.
836bf215546Sopenharmony_ci                         */
837bf215546Sopenharmony_ci                        state.coverage = 1.0;
838bf215546Sopenharmony_ci                        state.mask = job->msaa ? v3d->sample_mask : 0xf;
839bf215546Sopenharmony_ci                }
840bf215546Sopenharmony_ci        }
841bf215546Sopenharmony_ci#endif
842bf215546Sopenharmony_ci}
843