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