1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2014-2017 Broadcom
3b8e80941Smrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
4b8e80941Smrg *
5b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
7b8e80941Smrg * to deal in the Software without restriction, including without limitation
8b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
10b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
11b8e80941Smrg *
12b8e80941Smrg * The above copyright notice and this permission notice (including the next
13b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
14b8e80941Smrg * Software.
15b8e80941Smrg *
16b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22b8e80941Smrg * IN THE SOFTWARE.
23b8e80941Smrg */
24b8e80941Smrg
25b8e80941Smrg#include "pipe/p_state.h"
26b8e80941Smrg#include "util/u_format.h"
27b8e80941Smrg#include "util/u_framebuffer.h"
28b8e80941Smrg#include "util/u_inlines.h"
29b8e80941Smrg#include "util/u_math.h"
30b8e80941Smrg#include "util/u_memory.h"
31b8e80941Smrg#include "util/u_half.h"
32b8e80941Smrg#include "util/u_helpers.h"
33b8e80941Smrg#include "util/u_upload_mgr.h"
34b8e80941Smrg
35b8e80941Smrg#include "v3d_context.h"
36b8e80941Smrg#include "v3d_tiling.h"
37b8e80941Smrg#include "broadcom/common/v3d_macros.h"
38b8e80941Smrg#include "broadcom/compiler/v3d_compiler.h"
39b8e80941Smrg#include "broadcom/cle/v3dx_pack.h"
40b8e80941Smrg
41b8e80941Smrgstatic void
42b8e80941Smrgv3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
43b8e80941Smrg{
44b8e80941Smrg        free(hwcso);
45b8e80941Smrg}
46b8e80941Smrg
47b8e80941Smrgstatic void
48b8e80941Smrgv3d_set_blend_color(struct pipe_context *pctx,
49b8e80941Smrg                    const struct pipe_blend_color *blend_color)
50b8e80941Smrg{
51b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
52b8e80941Smrg        v3d->blend_color.f = *blend_color;
53b8e80941Smrg        for (int i = 0; i < 4; i++) {
54b8e80941Smrg                v3d->blend_color.hf[i] =
55b8e80941Smrg                        util_float_to_half(blend_color->color[i]);
56b8e80941Smrg        }
57b8e80941Smrg        v3d->dirty |= VC5_DIRTY_BLEND_COLOR;
58b8e80941Smrg}
59b8e80941Smrg
60b8e80941Smrgstatic void
61b8e80941Smrgv3d_set_stencil_ref(struct pipe_context *pctx,
62b8e80941Smrg                    const struct pipe_stencil_ref *stencil_ref)
63b8e80941Smrg{
64b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
65b8e80941Smrg        v3d->stencil_ref = *stencil_ref;
66b8e80941Smrg        v3d->dirty |= VC5_DIRTY_STENCIL_REF;
67b8e80941Smrg}
68b8e80941Smrg
69b8e80941Smrgstatic void
70b8e80941Smrgv3d_set_clip_state(struct pipe_context *pctx,
71b8e80941Smrg                   const struct pipe_clip_state *clip)
72b8e80941Smrg{
73b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
74b8e80941Smrg        v3d->clip = *clip;
75b8e80941Smrg        v3d->dirty |= VC5_DIRTY_CLIP;
76b8e80941Smrg}
77b8e80941Smrg
78b8e80941Smrgstatic void
79b8e80941Smrgv3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
80b8e80941Smrg{
81b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
82b8e80941Smrg        v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1);
83b8e80941Smrg        v3d->dirty |= VC5_DIRTY_SAMPLE_STATE;
84b8e80941Smrg}
85b8e80941Smrg
86b8e80941Smrgstatic void *
87b8e80941Smrgv3d_create_rasterizer_state(struct pipe_context *pctx,
88b8e80941Smrg                            const struct pipe_rasterizer_state *cso)
89b8e80941Smrg{
90b8e80941Smrg        struct v3d_rasterizer_state *so;
91b8e80941Smrg
92b8e80941Smrg        so = CALLOC_STRUCT(v3d_rasterizer_state);
93b8e80941Smrg        if (!so)
94b8e80941Smrg                return NULL;
95b8e80941Smrg
96b8e80941Smrg        so->base = *cso;
97b8e80941Smrg
98b8e80941Smrg        /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
99b8e80941Smrg         * BCM21553).
100b8e80941Smrg         */
101b8e80941Smrg        so->point_size = MAX2(cso->point_size, .125f);
102b8e80941Smrg
103b8e80941Smrg        STATIC_ASSERT(sizeof(so->depth_offset) >=
104b8e80941Smrg                      cl_packet_length(DEPTH_OFFSET));
105b8e80941Smrg        v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) {
106b8e80941Smrg                depth.depth_offset_factor = cso->offset_scale;
107b8e80941Smrg                depth.depth_offset_units = cso->offset_units;
108b8e80941Smrg        }
109b8e80941Smrg
110b8e80941Smrg        /* The HW treats polygon offset units based on a Z24 buffer, so we
111b8e80941Smrg         * need to scale up offset_units if we're only Z16.
112b8e80941Smrg         */
113b8e80941Smrg        v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) {
114b8e80941Smrg                depth.depth_offset_factor = cso->offset_scale;
115b8e80941Smrg                depth.depth_offset_units = cso->offset_units * 256.0;
116b8e80941Smrg        }
117b8e80941Smrg
118b8e80941Smrg        return so;
119b8e80941Smrg}
120b8e80941Smrg
121b8e80941Smrg/* Blend state is baked into shaders. */
122b8e80941Smrgstatic void *
123b8e80941Smrgv3d_create_blend_state(struct pipe_context *pctx,
124b8e80941Smrg                       const struct pipe_blend_state *cso)
125b8e80941Smrg{
126b8e80941Smrg        struct v3d_blend_state *so;
127b8e80941Smrg
128b8e80941Smrg        so = CALLOC_STRUCT(v3d_blend_state);
129b8e80941Smrg        if (!so)
130b8e80941Smrg                return NULL;
131b8e80941Smrg
132b8e80941Smrg        so->base = *cso;
133b8e80941Smrg
134b8e80941Smrg        if (cso->independent_blend_enable) {
135b8e80941Smrg                for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) {
136b8e80941Smrg                        so->blend_enables |= cso->rt[i].blend_enable << i;
137b8e80941Smrg
138b8e80941Smrg                        /* V3D 4.x is when we got independent blend enables. */
139b8e80941Smrg                        assert(V3D_VERSION >= 40 ||
140b8e80941Smrg                               cso->rt[i].blend_enable == cso->rt[0].blend_enable);
141b8e80941Smrg                }
142b8e80941Smrg        } else {
143b8e80941Smrg                if (cso->rt[0].blend_enable)
144b8e80941Smrg                        so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1;
145b8e80941Smrg        }
146b8e80941Smrg
147b8e80941Smrg        return so;
148b8e80941Smrg}
149b8e80941Smrg
150b8e80941Smrgstatic uint32_t
151b8e80941Smrgtranslate_stencil_op(enum pipe_stencil_op op)
152b8e80941Smrg{
153b8e80941Smrg        switch (op) {
154b8e80941Smrg        case PIPE_STENCIL_OP_KEEP:      return V3D_STENCIL_OP_KEEP;
155b8e80941Smrg        case PIPE_STENCIL_OP_ZERO:      return V3D_STENCIL_OP_ZERO;
156b8e80941Smrg        case PIPE_STENCIL_OP_REPLACE:   return V3D_STENCIL_OP_REPLACE;
157b8e80941Smrg        case PIPE_STENCIL_OP_INCR:      return V3D_STENCIL_OP_INCR;
158b8e80941Smrg        case PIPE_STENCIL_OP_DECR:      return V3D_STENCIL_OP_DECR;
159b8e80941Smrg        case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP;
160b8e80941Smrg        case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP;
161b8e80941Smrg        case PIPE_STENCIL_OP_INVERT:    return V3D_STENCIL_OP_INVERT;
162b8e80941Smrg        }
163b8e80941Smrg        unreachable("bad stencil op");
164b8e80941Smrg}
165b8e80941Smrg
166b8e80941Smrgstatic void *
167b8e80941Smrgv3d_create_depth_stencil_alpha_state(struct pipe_context *pctx,
168b8e80941Smrg                                     const struct pipe_depth_stencil_alpha_state *cso)
169b8e80941Smrg{
170b8e80941Smrg        struct v3d_depth_stencil_alpha_state *so;
171b8e80941Smrg
172b8e80941Smrg        so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state);
173b8e80941Smrg        if (!so)
174b8e80941Smrg                return NULL;
175b8e80941Smrg
176b8e80941Smrg        so->base = *cso;
177b8e80941Smrg
178b8e80941Smrg        if (cso->depth.enabled) {
179b8e80941Smrg                switch (cso->depth.func) {
180b8e80941Smrg                case PIPE_FUNC_LESS:
181b8e80941Smrg                case PIPE_FUNC_LEQUAL:
182b8e80941Smrg                        so->ez_state = VC5_EZ_LT_LE;
183b8e80941Smrg                        break;
184b8e80941Smrg                case PIPE_FUNC_GREATER:
185b8e80941Smrg                case PIPE_FUNC_GEQUAL:
186b8e80941Smrg                        so->ez_state = VC5_EZ_GT_GE;
187b8e80941Smrg                        break;
188b8e80941Smrg                case PIPE_FUNC_NEVER:
189b8e80941Smrg                case PIPE_FUNC_EQUAL:
190b8e80941Smrg                        so->ez_state = VC5_EZ_UNDECIDED;
191b8e80941Smrg                        break;
192b8e80941Smrg                default:
193b8e80941Smrg                        so->ez_state = VC5_EZ_DISABLED;
194b8e80941Smrg                        break;
195b8e80941Smrg                }
196b8e80941Smrg
197b8e80941Smrg                /* If stencil is enabled and it's not a no-op, then it would
198b8e80941Smrg                 * break EZ updates.
199b8e80941Smrg                 */
200b8e80941Smrg                if (cso->stencil[0].enabled &&
201b8e80941Smrg                    (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
202b8e80941Smrg                     cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
203b8e80941Smrg                     (cso->stencil[1].enabled &&
204b8e80941Smrg                      (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
205b8e80941Smrg                       cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
206b8e80941Smrg                        so->ez_state = VC5_EZ_DISABLED;
207b8e80941Smrg                }
208b8e80941Smrg        }
209b8e80941Smrg
210b8e80941Smrg        const struct pipe_stencil_state *front = &cso->stencil[0];
211b8e80941Smrg        const struct pipe_stencil_state *back = &cso->stencil[1];
212b8e80941Smrg
213b8e80941Smrg        if (front->enabled) {
214b8e80941Smrg                STATIC_ASSERT(sizeof(so->stencil_front) >=
215b8e80941Smrg                              cl_packet_length(STENCIL_CFG));
216b8e80941Smrg                v3dx_pack(&so->stencil_front, STENCIL_CFG, config) {
217b8e80941Smrg                        config.front_config = true;
218b8e80941Smrg                        /* If !back->enabled, then the front values should be
219b8e80941Smrg                         * used for both front and back-facing primitives.
220b8e80941Smrg                         */
221b8e80941Smrg                        config.back_config = !back->enabled;
222b8e80941Smrg
223b8e80941Smrg                        config.stencil_write_mask = front->writemask;
224b8e80941Smrg                        config.stencil_test_mask = front->valuemask;
225b8e80941Smrg
226b8e80941Smrg                        config.stencil_test_function = front->func;
227b8e80941Smrg                        config.stencil_pass_op =
228b8e80941Smrg                                translate_stencil_op(front->zpass_op);
229b8e80941Smrg                        config.depth_test_fail_op =
230b8e80941Smrg                                translate_stencil_op(front->zfail_op);
231b8e80941Smrg                        config.stencil_test_fail_op =
232b8e80941Smrg                                translate_stencil_op(front->fail_op);
233b8e80941Smrg                }
234b8e80941Smrg        }
235b8e80941Smrg        if (back->enabled) {
236b8e80941Smrg                STATIC_ASSERT(sizeof(so->stencil_back) >=
237b8e80941Smrg                              cl_packet_length(STENCIL_CFG));
238b8e80941Smrg                v3dx_pack(&so->stencil_back, STENCIL_CFG, config) {
239b8e80941Smrg                        config.front_config = false;
240b8e80941Smrg                        config.back_config = true;
241b8e80941Smrg
242b8e80941Smrg                        config.stencil_write_mask = back->writemask;
243b8e80941Smrg                        config.stencil_test_mask = back->valuemask;
244b8e80941Smrg
245b8e80941Smrg                        config.stencil_test_function = back->func;
246b8e80941Smrg                        config.stencil_pass_op =
247b8e80941Smrg                                translate_stencil_op(back->zpass_op);
248b8e80941Smrg                        config.depth_test_fail_op =
249b8e80941Smrg                                translate_stencil_op(back->zfail_op);
250b8e80941Smrg                        config.stencil_test_fail_op =
251b8e80941Smrg                                translate_stencil_op(back->fail_op);
252b8e80941Smrg                }
253b8e80941Smrg        }
254b8e80941Smrg
255b8e80941Smrg        return so;
256b8e80941Smrg}
257b8e80941Smrg
258b8e80941Smrgstatic void
259b8e80941Smrgv3d_set_polygon_stipple(struct pipe_context *pctx,
260b8e80941Smrg                        const struct pipe_poly_stipple *stipple)
261b8e80941Smrg{
262b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
263b8e80941Smrg        v3d->stipple = *stipple;
264b8e80941Smrg        v3d->dirty |= VC5_DIRTY_STIPPLE;
265b8e80941Smrg}
266b8e80941Smrg
267b8e80941Smrgstatic void
268b8e80941Smrgv3d_set_scissor_states(struct pipe_context *pctx,
269b8e80941Smrg                       unsigned start_slot,
270b8e80941Smrg                       unsigned num_scissors,
271b8e80941Smrg                       const struct pipe_scissor_state *scissor)
272b8e80941Smrg{
273b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
274b8e80941Smrg
275b8e80941Smrg        v3d->scissor = *scissor;
276b8e80941Smrg        v3d->dirty |= VC5_DIRTY_SCISSOR;
277b8e80941Smrg}
278b8e80941Smrg
279b8e80941Smrgstatic void
280b8e80941Smrgv3d_set_viewport_states(struct pipe_context *pctx,
281b8e80941Smrg                        unsigned start_slot,
282b8e80941Smrg                        unsigned num_viewports,
283b8e80941Smrg                        const struct pipe_viewport_state *viewport)
284b8e80941Smrg{
285b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
286b8e80941Smrg        v3d->viewport = *viewport;
287b8e80941Smrg        v3d->dirty |= VC5_DIRTY_VIEWPORT;
288b8e80941Smrg}
289b8e80941Smrg
290b8e80941Smrgstatic void
291b8e80941Smrgv3d_set_vertex_buffers(struct pipe_context *pctx,
292b8e80941Smrg                       unsigned start_slot, unsigned count,
293b8e80941Smrg                       const struct pipe_vertex_buffer *vb)
294b8e80941Smrg{
295b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
296b8e80941Smrg        struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf;
297b8e80941Smrg
298b8e80941Smrg        util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
299b8e80941Smrg                                     start_slot, count);
300b8e80941Smrg        so->count = util_last_bit(so->enabled_mask);
301b8e80941Smrg
302b8e80941Smrg        v3d->dirty |= VC5_DIRTY_VTXBUF;
303b8e80941Smrg}
304b8e80941Smrg
305b8e80941Smrgstatic void
306b8e80941Smrgv3d_blend_state_bind(struct pipe_context *pctx, void *hwcso)
307b8e80941Smrg{
308b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
309b8e80941Smrg        v3d->blend = hwcso;
310b8e80941Smrg        v3d->dirty |= VC5_DIRTY_BLEND;
311b8e80941Smrg}
312b8e80941Smrg
313b8e80941Smrgstatic void
314b8e80941Smrgv3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
315b8e80941Smrg{
316b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
317b8e80941Smrg        v3d->rasterizer = hwcso;
318b8e80941Smrg        v3d->dirty |= VC5_DIRTY_RASTERIZER;
319b8e80941Smrg}
320b8e80941Smrg
321b8e80941Smrgstatic void
322b8e80941Smrgv3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
323b8e80941Smrg{
324b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
325b8e80941Smrg        v3d->zsa = hwcso;
326b8e80941Smrg        v3d->dirty |= VC5_DIRTY_ZSA;
327b8e80941Smrg}
328b8e80941Smrg
329b8e80941Smrgstatic void *
330b8e80941Smrgv3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
331b8e80941Smrg                        const struct pipe_vertex_element *elements)
332b8e80941Smrg{
333b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
334b8e80941Smrg        struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj);
335b8e80941Smrg
336b8e80941Smrg        if (!so)
337b8e80941Smrg                return NULL;
338b8e80941Smrg
339b8e80941Smrg        memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
340b8e80941Smrg        so->num_elements = num_elements;
341b8e80941Smrg
342b8e80941Smrg        for (int i = 0; i < so->num_elements; i++) {
343b8e80941Smrg                const struct pipe_vertex_element *elem = &elements[i];
344b8e80941Smrg                const struct util_format_description *desc =
345b8e80941Smrg                        util_format_description(elem->src_format);
346b8e80941Smrg                uint32_t r_size = desc->channel[0].size;
347b8e80941Smrg
348b8e80941Smrg                const uint32_t size =
349b8e80941Smrg                        cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
350b8e80941Smrg
351b8e80941Smrg                v3dx_pack(&so->attrs[i * size],
352b8e80941Smrg                          GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
353b8e80941Smrg                        /* vec_size == 0 means 4 */
354b8e80941Smrg                        attr.vec_size = desc->nr_channels & 3;
355b8e80941Smrg                        attr.signed_int_type = (desc->channel[0].type ==
356b8e80941Smrg                                                UTIL_FORMAT_TYPE_SIGNED);
357b8e80941Smrg
358b8e80941Smrg                        attr.normalized_int_type = desc->channel[0].normalized;
359b8e80941Smrg                        attr.read_as_int_uint = desc->channel[0].pure_integer;
360b8e80941Smrg                        attr.instance_divisor = MIN2(elem->instance_divisor,
361b8e80941Smrg                                                     0xffff);
362b8e80941Smrg
363b8e80941Smrg                        switch (desc->channel[0].type) {
364b8e80941Smrg                        case UTIL_FORMAT_TYPE_FLOAT:
365b8e80941Smrg                                if (r_size == 32) {
366b8e80941Smrg                                        attr.type = ATTRIBUTE_FLOAT;
367b8e80941Smrg                                } else {
368b8e80941Smrg                                        assert(r_size == 16);
369b8e80941Smrg                                        attr.type = ATTRIBUTE_HALF_FLOAT;
370b8e80941Smrg                                }
371b8e80941Smrg                                break;
372b8e80941Smrg
373b8e80941Smrg                        case UTIL_FORMAT_TYPE_SIGNED:
374b8e80941Smrg                        case UTIL_FORMAT_TYPE_UNSIGNED:
375b8e80941Smrg                                switch (r_size) {
376b8e80941Smrg                                case 32:
377b8e80941Smrg                                        attr.type = ATTRIBUTE_INT;
378b8e80941Smrg                                        break;
379b8e80941Smrg                                case 16:
380b8e80941Smrg                                        attr.type = ATTRIBUTE_SHORT;
381b8e80941Smrg                                        break;
382b8e80941Smrg                                case 10:
383b8e80941Smrg                                        attr.type = ATTRIBUTE_INT2_10_10_10;
384b8e80941Smrg                                        break;
385b8e80941Smrg                                case 8:
386b8e80941Smrg                                        attr.type = ATTRIBUTE_BYTE;
387b8e80941Smrg                                        break;
388b8e80941Smrg                                default:
389b8e80941Smrg                                        fprintf(stderr,
390b8e80941Smrg                                                "format %s unsupported\n",
391b8e80941Smrg                                                desc->name);
392b8e80941Smrg                                        attr.type = ATTRIBUTE_BYTE;
393b8e80941Smrg                                        abort();
394b8e80941Smrg                                }
395b8e80941Smrg                                break;
396b8e80941Smrg
397b8e80941Smrg                        default:
398b8e80941Smrg                                fprintf(stderr,
399b8e80941Smrg                                        "format %s unsupported\n",
400b8e80941Smrg                                        desc->name);
401b8e80941Smrg                                abort();
402b8e80941Smrg                        }
403b8e80941Smrg                }
404b8e80941Smrg        }
405b8e80941Smrg
406b8e80941Smrg        /* Set up the default attribute values in case any of the vertex
407b8e80941Smrg         * elements use them.
408b8e80941Smrg         */
409b8e80941Smrg        uint32_t *attrs;
410b8e80941Smrg        u_upload_alloc(v3d->state_uploader, 0,
411b8e80941Smrg                       V3D_MAX_VS_INPUTS * sizeof(float), 16,
412b8e80941Smrg                       &so->defaults_offset, &so->defaults, (void **)&attrs);
413b8e80941Smrg
414b8e80941Smrg        for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) {
415b8e80941Smrg                attrs[i * 4 + 0] = 0;
416b8e80941Smrg                attrs[i * 4 + 1] = 0;
417b8e80941Smrg                attrs[i * 4 + 2] = 0;
418b8e80941Smrg                if (i < so->num_elements &&
419b8e80941Smrg                    util_format_is_pure_integer(so->pipe[i].src_format)) {
420b8e80941Smrg                        attrs[i * 4 + 3] = 1;
421b8e80941Smrg                } else {
422b8e80941Smrg                        attrs[i * 4 + 3] = fui(1.0);
423b8e80941Smrg                }
424b8e80941Smrg        }
425b8e80941Smrg
426b8e80941Smrg        u_upload_unmap(v3d->state_uploader);
427b8e80941Smrg        return so;
428b8e80941Smrg}
429b8e80941Smrg
430b8e80941Smrgstatic void
431b8e80941Smrgv3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
432b8e80941Smrg{
433b8e80941Smrg        struct v3d_vertex_stateobj *so = hwcso;
434b8e80941Smrg
435b8e80941Smrg        pipe_resource_reference(&so->defaults, NULL);
436b8e80941Smrg        free(so);
437b8e80941Smrg}
438b8e80941Smrg
439b8e80941Smrgstatic void
440b8e80941Smrgv3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
441b8e80941Smrg{
442b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
443b8e80941Smrg        v3d->vtx = hwcso;
444b8e80941Smrg        v3d->dirty |= VC5_DIRTY_VTXSTATE;
445b8e80941Smrg}
446b8e80941Smrg
447b8e80941Smrgstatic void
448b8e80941Smrgv3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
449b8e80941Smrg                        const struct pipe_constant_buffer *cb)
450b8e80941Smrg{
451b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
452b8e80941Smrg        struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader];
453b8e80941Smrg
454b8e80941Smrg        util_copy_constant_buffer(&so->cb[index], cb);
455b8e80941Smrg
456b8e80941Smrg        /* Note that the state tracker can unbind constant buffers by
457b8e80941Smrg         * passing NULL here.
458b8e80941Smrg         */
459b8e80941Smrg        if (unlikely(!cb)) {
460b8e80941Smrg                so->enabled_mask &= ~(1 << index);
461b8e80941Smrg                so->dirty_mask &= ~(1 << index);
462b8e80941Smrg                return;
463b8e80941Smrg        }
464b8e80941Smrg
465b8e80941Smrg        so->enabled_mask |= 1 << index;
466b8e80941Smrg        so->dirty_mask |= 1 << index;
467b8e80941Smrg        v3d->dirty |= VC5_DIRTY_CONSTBUF;
468b8e80941Smrg}
469b8e80941Smrg
470b8e80941Smrgstatic void
471b8e80941Smrgv3d_set_framebuffer_state(struct pipe_context *pctx,
472b8e80941Smrg                          const struct pipe_framebuffer_state *framebuffer)
473b8e80941Smrg{
474b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
475b8e80941Smrg        struct pipe_framebuffer_state *cso = &v3d->framebuffer;
476b8e80941Smrg
477b8e80941Smrg        v3d->job = NULL;
478b8e80941Smrg
479b8e80941Smrg        util_copy_framebuffer_state(cso, framebuffer);
480b8e80941Smrg
481b8e80941Smrg        v3d->swap_color_rb = 0;
482b8e80941Smrg        v3d->blend_dst_alpha_one = 0;
483b8e80941Smrg        for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
484b8e80941Smrg                struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
485b8e80941Smrg                if (!cbuf)
486b8e80941Smrg                        continue;
487b8e80941Smrg                struct v3d_surface *v3d_cbuf = v3d_surface(cbuf);
488b8e80941Smrg
489b8e80941Smrg                const struct util_format_description *desc =
490b8e80941Smrg                        util_format_description(cbuf->format);
491b8e80941Smrg
492b8e80941Smrg                /* For BGRA8 formats (DRI window system default format), we
493b8e80941Smrg                 * need to swap R and B, since the HW's format is RGBA8.  On
494b8e80941Smrg                 * V3D 4.1+, the RCL can swap R and B on load/store.
495b8e80941Smrg                 */
496b8e80941Smrg                if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb)
497b8e80941Smrg                        v3d->swap_color_rb |= 1 << i;
498b8e80941Smrg
499b8e80941Smrg                if (desc->swizzle[3] == PIPE_SWIZZLE_1)
500b8e80941Smrg                        v3d->blend_dst_alpha_one |= 1 << i;
501b8e80941Smrg        }
502b8e80941Smrg
503b8e80941Smrg        v3d->dirty |= VC5_DIRTY_FRAMEBUFFER;
504b8e80941Smrg}
505b8e80941Smrg
506b8e80941Smrgstatic enum V3DX(Wrap_Mode)
507b8e80941Smrgtranslate_wrap(uint32_t pipe_wrap, bool using_nearest)
508b8e80941Smrg{
509b8e80941Smrg        switch (pipe_wrap) {
510b8e80941Smrg        case PIPE_TEX_WRAP_REPEAT:
511b8e80941Smrg                return V3D_WRAP_MODE_REPEAT;
512b8e80941Smrg        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
513b8e80941Smrg                return V3D_WRAP_MODE_CLAMP;
514b8e80941Smrg        case PIPE_TEX_WRAP_MIRROR_REPEAT:
515b8e80941Smrg                return V3D_WRAP_MODE_MIRROR;
516b8e80941Smrg        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
517b8e80941Smrg                return V3D_WRAP_MODE_BORDER;
518b8e80941Smrg        case PIPE_TEX_WRAP_CLAMP:
519b8e80941Smrg                return (using_nearest ?
520b8e80941Smrg                        V3D_WRAP_MODE_CLAMP :
521b8e80941Smrg                        V3D_WRAP_MODE_BORDER);
522b8e80941Smrg        default:
523b8e80941Smrg                unreachable("Unknown wrap mode");
524b8e80941Smrg        }
525b8e80941Smrg}
526b8e80941Smrg
527b8e80941Smrg#if V3D_VERSION >= 40
528b8e80941Smrgstatic void
529b8e80941Smrgv3d_upload_sampler_state_variant(void *map,
530b8e80941Smrg                                 const struct pipe_sampler_state *cso,
531b8e80941Smrg                                 enum v3d_sampler_state_variant variant,
532b8e80941Smrg                                 bool either_nearest)
533b8e80941Smrg{
534b8e80941Smrg        v3dx_pack(map, SAMPLER_STATE, sampler) {
535b8e80941Smrg                sampler.wrap_i_border = false;
536b8e80941Smrg
537b8e80941Smrg                sampler.wrap_s = translate_wrap(cso->wrap_s, either_nearest);
538b8e80941Smrg                sampler.wrap_t = translate_wrap(cso->wrap_t, either_nearest);
539b8e80941Smrg                sampler.wrap_r = translate_wrap(cso->wrap_r, either_nearest);
540b8e80941Smrg
541b8e80941Smrg                sampler.fixed_bias = cso->lod_bias;
542b8e80941Smrg                sampler.depth_compare_function = cso->compare_func;
543b8e80941Smrg
544b8e80941Smrg                sampler.min_filter_nearest =
545b8e80941Smrg                        cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
546b8e80941Smrg                sampler.mag_filter_nearest =
547b8e80941Smrg                        cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
548b8e80941Smrg                sampler.mip_filter_nearest =
549b8e80941Smrg                        cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR;
550b8e80941Smrg
551b8e80941Smrg                sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
552b8e80941Smrg                                                   15);
553b8e80941Smrg                sampler.max_level_of_detail = MIN2(cso->max_lod, 15);
554b8e80941Smrg
555b8e80941Smrg                /* If we're not doing inter-miplevel filtering, we need to
556b8e80941Smrg                 * clamp the LOD so that we only sample from baselevel.
557b8e80941Smrg                 * However, we need to still allow the calculated LOD to be
558b8e80941Smrg                 * fractionally over the baselevel, so that the HW can decide
559b8e80941Smrg                 * between the min and mag filters.
560b8e80941Smrg                 */
561b8e80941Smrg                if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
562b8e80941Smrg                        sampler.min_level_of_detail =
563b8e80941Smrg                                MIN2(sampler.min_level_of_detail, 1.0 / 256.0);
564b8e80941Smrg                        sampler.max_level_of_detail =
565b8e80941Smrg                                MIN2(sampler.max_level_of_detail, 1.0 / 256.0);
566b8e80941Smrg                }
567b8e80941Smrg
568b8e80941Smrg                if (cso->max_anisotropy) {
569b8e80941Smrg                        sampler.anisotropy_enable = true;
570b8e80941Smrg
571b8e80941Smrg                        if (cso->max_anisotropy > 8)
572b8e80941Smrg                                sampler.maximum_anisotropy = 3;
573b8e80941Smrg                        else if (cso->max_anisotropy > 4)
574b8e80941Smrg                                sampler.maximum_anisotropy = 2;
575b8e80941Smrg                        else if (cso->max_anisotropy > 2)
576b8e80941Smrg                                sampler.maximum_anisotropy = 1;
577b8e80941Smrg                }
578b8e80941Smrg
579b8e80941Smrg                if (variant == V3D_SAMPLER_STATE_BORDER_0) {
580b8e80941Smrg                        sampler.border_color_mode = V3D_BORDER_COLOR_0000;
581b8e80941Smrg                } else {
582b8e80941Smrg                        sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS;
583b8e80941Smrg
584b8e80941Smrg                        union pipe_color_union border;
585b8e80941Smrg
586b8e80941Smrg                        /* First, reswizzle the border color for any
587b8e80941Smrg                         * mismatching we're doing between the texture's
588b8e80941Smrg                         * channel order in hardware (R) versus what it is at
589b8e80941Smrg                         * the GL level (ALPHA)
590b8e80941Smrg                         */
591b8e80941Smrg                        switch (variant) {
592b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_BGRA:
593b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
594b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
595b8e80941Smrg                                border.i[0] = cso->border_color.i[2];
596b8e80941Smrg                                border.i[1] = cso->border_color.i[1];
597b8e80941Smrg                                border.i[2] = cso->border_color.i[0];
598b8e80941Smrg                                border.i[3] = cso->border_color.i[3];
599b8e80941Smrg                                break;
600b8e80941Smrg
601b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_A:
602b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_A_UNORM:
603b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_A_SNORM:
604b8e80941Smrg                        case V3D_SAMPLER_STATE_32_A:
605b8e80941Smrg                        case V3D_SAMPLER_STATE_32_A_UNORM:
606b8e80941Smrg                        case V3D_SAMPLER_STATE_32_A_SNORM:
607b8e80941Smrg                                border.i[0] = cso->border_color.i[3];
608b8e80941Smrg                                border.i[1] = 0;
609b8e80941Smrg                                border.i[2] = 0;
610b8e80941Smrg                                border.i[3] = 0;
611b8e80941Smrg                                break;
612b8e80941Smrg
613b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_LA:
614b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_LA_UNORM:
615b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_LA_SNORM:
616b8e80941Smrg                                border.i[0] = cso->border_color.i[0];
617b8e80941Smrg                                border.i[1] = cso->border_color.i[3];
618b8e80941Smrg                                border.i[2] = 0;
619b8e80941Smrg                                border.i[3] = 0;
620b8e80941Smrg                                break;
621b8e80941Smrg
622b8e80941Smrg                        default:
623b8e80941Smrg                                border = cso->border_color;
624b8e80941Smrg                        }
625b8e80941Smrg
626b8e80941Smrg                        /* Perform any clamping. */
627b8e80941Smrg                        switch (variant) {
628b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_UNORM:
629b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
630b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_A_UNORM:
631b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_LA_UNORM:
632b8e80941Smrg                        case V3D_SAMPLER_STATE_32_UNORM:
633b8e80941Smrg                        case V3D_SAMPLER_STATE_32_A_UNORM:
634b8e80941Smrg                                for (int i = 0; i < 4; i++)
635b8e80941Smrg                                        border.f[i] = CLAMP(border.f[i], 0, 1);
636b8e80941Smrg                                break;
637b8e80941Smrg
638b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_SNORM:
639b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
640b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_A_SNORM:
641b8e80941Smrg                        case V3D_SAMPLER_STATE_F16_LA_SNORM:
642b8e80941Smrg                        case V3D_SAMPLER_STATE_32_SNORM:
643b8e80941Smrg                        case V3D_SAMPLER_STATE_32_A_SNORM:
644b8e80941Smrg                                for (int i = 0; i < 4; i++)
645b8e80941Smrg                                        border.f[i] = CLAMP(border.f[i], -1, 1);
646b8e80941Smrg                                break;
647b8e80941Smrg
648b8e80941Smrg                        case V3D_SAMPLER_STATE_1010102U:
649b8e80941Smrg                                border.ui[0] = CLAMP(border.ui[0],
650b8e80941Smrg                                                     0, (1 << 10) - 1);
651b8e80941Smrg                                border.ui[1] = CLAMP(border.ui[1],
652b8e80941Smrg                                                     0, (1 << 10) - 1);
653b8e80941Smrg                                border.ui[2] = CLAMP(border.ui[2],
654b8e80941Smrg                                                     0, (1 << 10) - 1);
655b8e80941Smrg                                border.ui[3] = CLAMP(border.ui[3],
656b8e80941Smrg                                                     0, 3);
657b8e80941Smrg                                break;
658b8e80941Smrg
659b8e80941Smrg                        case V3D_SAMPLER_STATE_16U:
660b8e80941Smrg                                for (int i = 0; i < 4; i++)
661b8e80941Smrg                                        border.ui[i] = CLAMP(border.ui[i],
662b8e80941Smrg                                                             0, 0xffff);
663b8e80941Smrg                                break;
664b8e80941Smrg
665b8e80941Smrg                        case V3D_SAMPLER_STATE_16I:
666b8e80941Smrg                                for (int i = 0; i < 4; i++)
667b8e80941Smrg                                        border.i[i] = CLAMP(border.i[i],
668b8e80941Smrg                                                            -32768, 32767);
669b8e80941Smrg                                break;
670b8e80941Smrg
671b8e80941Smrg                        case V3D_SAMPLER_STATE_8U:
672b8e80941Smrg                                for (int i = 0; i < 4; i++)
673b8e80941Smrg                                        border.ui[i] = CLAMP(border.ui[i],
674b8e80941Smrg                                                             0, 0xff);
675b8e80941Smrg                                break;
676b8e80941Smrg
677b8e80941Smrg                        case V3D_SAMPLER_STATE_8I:
678b8e80941Smrg                                for (int i = 0; i < 4; i++)
679b8e80941Smrg                                        border.i[i] = CLAMP(border.i[i],
680b8e80941Smrg                                                            -128, 127);
681b8e80941Smrg                                break;
682b8e80941Smrg
683b8e80941Smrg                        default:
684b8e80941Smrg                                break;
685b8e80941Smrg                        }
686b8e80941Smrg
687b8e80941Smrg                        if (variant >= V3D_SAMPLER_STATE_32) {
688b8e80941Smrg                                sampler.border_color_word_0 = border.ui[0];
689b8e80941Smrg                                sampler.border_color_word_1 = border.ui[1];
690b8e80941Smrg                                sampler.border_color_word_2 = border.ui[2];
691b8e80941Smrg                                sampler.border_color_word_3 = border.ui[3];
692b8e80941Smrg                        } else {
693b8e80941Smrg                                sampler.border_color_word_0 =
694b8e80941Smrg                                        util_float_to_half(border.f[0]);
695b8e80941Smrg                                sampler.border_color_word_1 =
696b8e80941Smrg                                        util_float_to_half(border.f[1]);
697b8e80941Smrg                                sampler.border_color_word_2 =
698b8e80941Smrg                                        util_float_to_half(border.f[2]);
699b8e80941Smrg                                sampler.border_color_word_3 =
700b8e80941Smrg                                        util_float_to_half(border.f[3]);
701b8e80941Smrg                        }
702b8e80941Smrg                }
703b8e80941Smrg        }
704b8e80941Smrg}
705b8e80941Smrg#endif
706b8e80941Smrg
707b8e80941Smrgstatic void *
708b8e80941Smrgv3d_create_sampler_state(struct pipe_context *pctx,
709b8e80941Smrg                         const struct pipe_sampler_state *cso)
710b8e80941Smrg{
711b8e80941Smrg        MAYBE_UNUSED struct v3d_context *v3d = v3d_context(pctx);
712b8e80941Smrg        struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state);
713b8e80941Smrg
714b8e80941Smrg        if (!so)
715b8e80941Smrg                return NULL;
716b8e80941Smrg
717b8e80941Smrg        memcpy(so, cso, sizeof(*cso));
718b8e80941Smrg
719b8e80941Smrg        bool either_nearest =
720b8e80941Smrg                (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
721b8e80941Smrg                 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
722b8e80941Smrg
723b8e80941Smrg        enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s,
724b8e80941Smrg                                                     either_nearest);
725b8e80941Smrg        enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t,
726b8e80941Smrg                                                     either_nearest);
727b8e80941Smrg        enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r,
728b8e80941Smrg                                                     either_nearest);
729b8e80941Smrg
730b8e80941Smrg        bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER ||
731b8e80941Smrg                                  wrap_t == V3D_WRAP_MODE_BORDER ||
732b8e80941Smrg                                  wrap_r == V3D_WRAP_MODE_BORDER);
733b8e80941Smrg        so->border_color_variants = (uses_border_color &&
734b8e80941Smrg                                     (cso->border_color.ui[0] != 0 ||
735b8e80941Smrg                                      cso->border_color.ui[1] != 0 ||
736b8e80941Smrg                                      cso->border_color.ui[2] != 0 ||
737b8e80941Smrg                                      cso->border_color.ui[3] != 0));
738b8e80941Smrg
739b8e80941Smrg#if V3D_VERSION >= 40
740b8e80941Smrg        void *map;
741b8e80941Smrg        int sampler_align = so->border_color_variants ? 32 : 8;
742b8e80941Smrg        int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align);
743b8e80941Smrg        int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1);
744b8e80941Smrg        u_upload_alloc(v3d->state_uploader, 0,
745b8e80941Smrg                       sampler_size * num_variants,
746b8e80941Smrg                       sampler_align,
747b8e80941Smrg                       &so->sampler_state_offset[0],
748b8e80941Smrg                       &so->sampler_state,
749b8e80941Smrg                       &map);
750b8e80941Smrg
751b8e80941Smrg        for (int i = 0; i < num_variants; i++) {
752b8e80941Smrg                so->sampler_state_offset[i] =
753b8e80941Smrg                        so->sampler_state_offset[0] + i * sampler_size;
754b8e80941Smrg                v3d_upload_sampler_state_variant(map + i * sampler_size,
755b8e80941Smrg                                                 cso, i, either_nearest);
756b8e80941Smrg        }
757b8e80941Smrg
758b8e80941Smrg#else /* V3D_VERSION < 40 */
759b8e80941Smrg        v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) {
760b8e80941Smrg                p0.s_wrap_mode = wrap_s;
761b8e80941Smrg                p0.t_wrap_mode = wrap_t;
762b8e80941Smrg                p0.r_wrap_mode = wrap_r;
763b8e80941Smrg        }
764b8e80941Smrg
765b8e80941Smrg        v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
766b8e80941Smrg                tex.depth_compare_function = cso->compare_func;
767b8e80941Smrg                tex.fixed_bias = cso->lod_bias;
768b8e80941Smrg        }
769b8e80941Smrg#endif /* V3D_VERSION < 40 */
770b8e80941Smrg        return so;
771b8e80941Smrg}
772b8e80941Smrg
773b8e80941Smrgstatic void
774b8e80941Smrgv3d_sampler_states_bind(struct pipe_context *pctx,
775b8e80941Smrg                        enum pipe_shader_type shader, unsigned start,
776b8e80941Smrg                        unsigned nr, void **hwcso)
777b8e80941Smrg{
778b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
779b8e80941Smrg        struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
780b8e80941Smrg
781b8e80941Smrg        assert(start == 0);
782b8e80941Smrg        unsigned i;
783b8e80941Smrg        unsigned new_nr = 0;
784b8e80941Smrg
785b8e80941Smrg        for (i = 0; i < nr; i++) {
786b8e80941Smrg                if (hwcso[i])
787b8e80941Smrg                        new_nr = i + 1;
788b8e80941Smrg                stage_tex->samplers[i] = hwcso[i];
789b8e80941Smrg        }
790b8e80941Smrg
791b8e80941Smrg        for (; i < stage_tex->num_samplers; i++) {
792b8e80941Smrg                stage_tex->samplers[i] = NULL;
793b8e80941Smrg        }
794b8e80941Smrg
795b8e80941Smrg        stage_tex->num_samplers = new_nr;
796b8e80941Smrg}
797b8e80941Smrg
798b8e80941Smrgstatic void
799b8e80941Smrgv3d_sampler_state_delete(struct pipe_context *pctx,
800b8e80941Smrg                         void *hwcso)
801b8e80941Smrg{
802b8e80941Smrg        struct pipe_sampler_state *psampler = hwcso;
803b8e80941Smrg        struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
804b8e80941Smrg
805b8e80941Smrg        pipe_resource_reference(&sampler->sampler_state, NULL);
806b8e80941Smrg        free(psampler);
807b8e80941Smrg}
808b8e80941Smrg
809b8e80941Smrg#if V3D_VERSION >= 40
810b8e80941Smrgstatic uint32_t
811b8e80941Smrgtranslate_swizzle(unsigned char pipe_swizzle)
812b8e80941Smrg{
813b8e80941Smrg        switch (pipe_swizzle) {
814b8e80941Smrg        case PIPE_SWIZZLE_0:
815b8e80941Smrg                return 0;
816b8e80941Smrg        case PIPE_SWIZZLE_1:
817b8e80941Smrg                return 1;
818b8e80941Smrg        case PIPE_SWIZZLE_X:
819b8e80941Smrg        case PIPE_SWIZZLE_Y:
820b8e80941Smrg        case PIPE_SWIZZLE_Z:
821b8e80941Smrg        case PIPE_SWIZZLE_W:
822b8e80941Smrg                return 2 + pipe_swizzle;
823b8e80941Smrg        default:
824b8e80941Smrg                unreachable("unknown swizzle");
825b8e80941Smrg        }
826b8e80941Smrg}
827b8e80941Smrg#endif
828b8e80941Smrg
829b8e80941Smrgstatic void
830b8e80941Smrgv3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex,
831b8e80941Smrg                               struct pipe_resource *prsc,
832b8e80941Smrg                               int base_level, int last_level,
833b8e80941Smrg                               int first_layer, int last_layer)
834b8e80941Smrg{
835b8e80941Smrg        struct v3d_resource *rsc = v3d_resource(prsc);
836b8e80941Smrg        int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
837b8e80941Smrg
838b8e80941Smrg        tex->image_width = prsc->width0 * msaa_scale;
839b8e80941Smrg        tex->image_height = prsc->height0 * msaa_scale;
840b8e80941Smrg
841b8e80941Smrg#if V3D_VERSION >= 40
842b8e80941Smrg        /* On 4.x, the height of a 1D texture is redefined to be the
843b8e80941Smrg         * upper 14 bits of the width (which is only usable with txf).
844b8e80941Smrg         */
845b8e80941Smrg        if (prsc->target == PIPE_TEXTURE_1D ||
846b8e80941Smrg            prsc->target == PIPE_TEXTURE_1D_ARRAY) {
847b8e80941Smrg                tex->image_height = tex->image_width >> 14;
848b8e80941Smrg        }
849b8e80941Smrg
850b8e80941Smrg        tex->image_width &= (1 << 14) - 1;
851b8e80941Smrg        tex->image_height &= (1 << 14) - 1;
852b8e80941Smrg#endif
853b8e80941Smrg
854b8e80941Smrg        if (prsc->target == PIPE_TEXTURE_3D) {
855b8e80941Smrg                tex->image_depth = prsc->depth0;
856b8e80941Smrg        } else {
857b8e80941Smrg                tex->image_depth = (last_layer - first_layer) + 1;
858b8e80941Smrg        }
859b8e80941Smrg
860b8e80941Smrg        tex->base_level = base_level;
861b8e80941Smrg#if V3D_VERSION >= 40
862b8e80941Smrg        tex->max_level = last_level;
863b8e80941Smrg        /* Note that we don't have a job to reference the texture's sBO
864b8e80941Smrg         * at state create time, so any time this sampler view is used
865b8e80941Smrg         * we need to add the texture to the job.
866b8e80941Smrg         */
867b8e80941Smrg        tex->texture_base_pointer =
868b8e80941Smrg                cl_address(NULL,
869b8e80941Smrg                           rsc->bo->offset +
870b8e80941Smrg                           v3d_layer_offset(prsc, 0, first_layer));
871b8e80941Smrg#endif
872b8e80941Smrg        tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
873b8e80941Smrg
874b8e80941Smrg        /* Since other platform devices may produce UIF images even
875b8e80941Smrg         * when they're not big enough for V3D to assume they're UIF,
876b8e80941Smrg         * we force images with level 0 as UIF to be always treated
877b8e80941Smrg         * that way.
878b8e80941Smrg         */
879b8e80941Smrg        tex->level_0_is_strictly_uif =
880b8e80941Smrg                (rsc->slices[0].tiling == VC5_TILING_UIF_XOR ||
881b8e80941Smrg                 rsc->slices[0].tiling == VC5_TILING_UIF_NO_XOR);
882b8e80941Smrg        tex->level_0_xor_enable = (rsc->slices[0].tiling == VC5_TILING_UIF_XOR);
883b8e80941Smrg
884b8e80941Smrg        if (tex->level_0_is_strictly_uif)
885b8e80941Smrg                tex->level_0_ub_pad = rsc->slices[0].ub_pad;
886b8e80941Smrg
887b8e80941Smrg#if V3D_VERSION >= 40
888b8e80941Smrg        if (tex->uif_xor_disable ||
889b8e80941Smrg            tex->level_0_is_strictly_uif) {
890b8e80941Smrg                tex->extended = true;
891b8e80941Smrg        }
892b8e80941Smrg#endif /* V3D_VERSION >= 40 */
893b8e80941Smrg}
894b8e80941Smrg
895b8e80941Smrgstatic struct pipe_sampler_view *
896b8e80941Smrgv3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
897b8e80941Smrg                        const struct pipe_sampler_view *cso)
898b8e80941Smrg{
899b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
900b8e80941Smrg        struct v3d_screen *screen = v3d->screen;
901b8e80941Smrg        struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
902b8e80941Smrg        struct v3d_resource *rsc = v3d_resource(prsc);
903b8e80941Smrg
904b8e80941Smrg        if (!so)
905b8e80941Smrg                return NULL;
906b8e80941Smrg
907b8e80941Smrg        so->base = *cso;
908b8e80941Smrg
909b8e80941Smrg        pipe_reference(NULL, &prsc->reference);
910b8e80941Smrg
911b8e80941Smrg        /* Compute the sampler view's swizzle up front. This will be plugged
912b8e80941Smrg         * into either the sampler (for 16-bit returns) or the shader's
913b8e80941Smrg         * texture key (for 32)
914b8e80941Smrg         */
915b8e80941Smrg        uint8_t view_swizzle[4] = {
916b8e80941Smrg                cso->swizzle_r,
917b8e80941Smrg                cso->swizzle_g,
918b8e80941Smrg                cso->swizzle_b,
919b8e80941Smrg                cso->swizzle_a
920b8e80941Smrg        };
921b8e80941Smrg        const uint8_t *fmt_swizzle =
922b8e80941Smrg                v3d_get_format_swizzle(&screen->devinfo, so->base.format);
923b8e80941Smrg        util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
924b8e80941Smrg
925b8e80941Smrg        so->base.texture = prsc;
926b8e80941Smrg        so->base.reference.count = 1;
927b8e80941Smrg        so->base.context = pctx;
928b8e80941Smrg
929b8e80941Smrg        if (rsc->separate_stencil &&
930b8e80941Smrg            cso->format == PIPE_FORMAT_X32_S8X24_UINT) {
931b8e80941Smrg                rsc = rsc->separate_stencil;
932b8e80941Smrg                prsc = &rsc->base;
933b8e80941Smrg        }
934b8e80941Smrg
935b8e80941Smrg        /* If we're sampling depth from depth/stencil, demote the format to
936b8e80941Smrg         * just depth.  u_format will end up giving the answers for the
937b8e80941Smrg         * stencil channel, otherwise.
938b8e80941Smrg         */
939b8e80941Smrg        enum pipe_format sample_format = cso->format;
940b8e80941Smrg        if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM)
941b8e80941Smrg                sample_format = PIPE_FORMAT_X8Z24_UNORM;
942b8e80941Smrg
943b8e80941Smrg#if V3D_VERSION >= 40
944b8e80941Smrg        const struct util_format_description *desc =
945b8e80941Smrg                util_format_description(sample_format);
946b8e80941Smrg
947b8e80941Smrg        if (util_format_is_pure_integer(sample_format) &&
948b8e80941Smrg            !util_format_has_depth(desc)) {
949b8e80941Smrg                int chan = util_format_get_first_non_void_channel(sample_format);
950b8e80941Smrg                if (util_format_is_pure_uint(sample_format)) {
951b8e80941Smrg                        switch (desc->channel[chan].size) {
952b8e80941Smrg                        case 32:
953b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_32;
954b8e80941Smrg                                break;
955b8e80941Smrg                        case 16:
956b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_16U;
957b8e80941Smrg                                break;
958b8e80941Smrg                        case 10:
959b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_1010102U;
960b8e80941Smrg                                break;
961b8e80941Smrg                        case 8:
962b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_8U;
963b8e80941Smrg                                break;
964b8e80941Smrg                        }
965b8e80941Smrg                } else {
966b8e80941Smrg                        switch (desc->channel[chan].size) {
967b8e80941Smrg                        case 32:
968b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_32;
969b8e80941Smrg                                break;
970b8e80941Smrg                        case 16:
971b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_16I;
972b8e80941Smrg                                break;
973b8e80941Smrg                        case 8:
974b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_8I;
975b8e80941Smrg                                break;
976b8e80941Smrg                        }
977b8e80941Smrg                }
978b8e80941Smrg        } else {
979b8e80941Smrg                if (v3d_get_tex_return_size(&screen->devinfo, sample_format,
980b8e80941Smrg                                           PIPE_TEX_COMPARE_NONE) == 32) {
981b8e80941Smrg                        if (util_format_is_alpha(sample_format))
982b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_32_A;
983b8e80941Smrg                        else
984b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_32;
985b8e80941Smrg                } else {
986b8e80941Smrg                        if (util_format_is_luminance_alpha(sample_format))
987b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_F16_LA;
988b8e80941Smrg                        else if (util_format_is_alpha(sample_format))
989b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_F16_A;
990b8e80941Smrg                        else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z)
991b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA;
992b8e80941Smrg                        else
993b8e80941Smrg                                so->sampler_variant = V3D_SAMPLER_STATE_F16;
994b8e80941Smrg
995b8e80941Smrg                }
996b8e80941Smrg
997b8e80941Smrg                if (util_format_is_unorm(sample_format)) {
998b8e80941Smrg                        so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM -
999b8e80941Smrg                                                V3D_SAMPLER_STATE_F16);
1000b8e80941Smrg                } else if (util_format_is_snorm(sample_format)){
1001b8e80941Smrg                        so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM -
1002b8e80941Smrg                                                V3D_SAMPLER_STATE_F16);
1003b8e80941Smrg                }
1004b8e80941Smrg        }
1005b8e80941Smrg#endif
1006b8e80941Smrg
1007b8e80941Smrg        /* V3D still doesn't support sampling from raster textures, so we will
1008b8e80941Smrg         * have to copy to a temporary tiled texture.
1009b8e80941Smrg         */
1010b8e80941Smrg        if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D ||
1011b8e80941Smrg                             prsc->target == PIPE_TEXTURE_1D_ARRAY)) {
1012b8e80941Smrg                struct v3d_resource *shadow_parent = rsc;
1013b8e80941Smrg                struct pipe_resource tmpl = {
1014b8e80941Smrg                        .target = prsc->target,
1015b8e80941Smrg                        .format = prsc->format,
1016b8e80941Smrg                        .width0 = u_minify(prsc->width0,
1017b8e80941Smrg                                           cso->u.tex.first_level),
1018b8e80941Smrg                        .height0 = u_minify(prsc->height0,
1019b8e80941Smrg                                            cso->u.tex.first_level),
1020b8e80941Smrg                        .depth0 = 1,
1021b8e80941Smrg                        .array_size = 1,
1022b8e80941Smrg                        .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
1023b8e80941Smrg                        .last_level = cso->u.tex.last_level - cso->u.tex.first_level,
1024b8e80941Smrg                        .nr_samples = prsc->nr_samples,
1025b8e80941Smrg                };
1026b8e80941Smrg
1027b8e80941Smrg                /* Create the shadow texture.  The rest of the sampler view
1028b8e80941Smrg                 * setup will use the shadow.
1029b8e80941Smrg                 */
1030b8e80941Smrg                prsc = v3d_resource_create(pctx->screen, &tmpl);
1031b8e80941Smrg                if (!prsc) {
1032b8e80941Smrg                        free(so);
1033b8e80941Smrg                        return NULL;
1034b8e80941Smrg                }
1035b8e80941Smrg                rsc = v3d_resource(prsc);
1036b8e80941Smrg
1037b8e80941Smrg                /* Flag it as needing update of the contents from the parent. */
1038b8e80941Smrg                rsc->writes = shadow_parent->writes - 1;
1039b8e80941Smrg                assert(rsc->tiled);
1040b8e80941Smrg
1041b8e80941Smrg                so->texture = prsc;
1042b8e80941Smrg        } else {
1043b8e80941Smrg                pipe_resource_reference(&so->texture, prsc);
1044b8e80941Smrg        }
1045b8e80941Smrg
1046b8e80941Smrg        void *map;
1047b8e80941Smrg#if V3D_VERSION >= 40
1048b8e80941Smrg        so->bo = v3d_bo_alloc(v3d->screen,
1049b8e80941Smrg                              cl_packet_length(TEXTURE_SHADER_STATE), "sampler");
1050b8e80941Smrg        map = v3d_bo_map(so->bo);
1051b8e80941Smrg#else /* V3D_VERSION < 40 */
1052b8e80941Smrg        STATIC_ASSERT(sizeof(so->texture_shader_state) >=
1053b8e80941Smrg                      cl_packet_length(TEXTURE_SHADER_STATE));
1054b8e80941Smrg        map = &so->texture_shader_state;
1055b8e80941Smrg#endif
1056b8e80941Smrg
1057b8e80941Smrg        v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
1058b8e80941Smrg                v3d_setup_texture_shader_state(&tex, prsc,
1059b8e80941Smrg                                               cso->u.tex.first_level,
1060b8e80941Smrg                                               cso->u.tex.last_level,
1061b8e80941Smrg                                               cso->u.tex.first_layer,
1062b8e80941Smrg                                               cso->u.tex.last_layer);
1063b8e80941Smrg
1064b8e80941Smrg                tex.srgb = util_format_is_srgb(cso->format);
1065b8e80941Smrg
1066b8e80941Smrg#if V3D_VERSION >= 40
1067b8e80941Smrg                tex.swizzle_r = translate_swizzle(so->swizzle[0]);
1068b8e80941Smrg                tex.swizzle_g = translate_swizzle(so->swizzle[1]);
1069b8e80941Smrg                tex.swizzle_b = translate_swizzle(so->swizzle[2]);
1070b8e80941Smrg                tex.swizzle_a = translate_swizzle(so->swizzle[3]);
1071b8e80941Smrg#endif
1072b8e80941Smrg
1073b8e80941Smrg                if (prsc->nr_samples > 1 && V3D_VERSION < 40) {
1074b8e80941Smrg                        /* Using texture views to reinterpret formats on our
1075b8e80941Smrg                         * MSAA textures won't work, because we don't lay out
1076b8e80941Smrg                         * the bits in memory as it's expected -- for example,
1077b8e80941Smrg                         * RGBA8 and RGB10_A2 are compatible in the
1078b8e80941Smrg                         * ARB_texture_view spec, but in HW we lay them out as
1079b8e80941Smrg                         * 32bpp RGBA8 and 64bpp RGBA16F.  Just assert for now
1080b8e80941Smrg                         * to catch failures.
1081b8e80941Smrg                         *
1082b8e80941Smrg                         * We explicitly allow remapping S8Z24 to RGBA8888 for
1083b8e80941Smrg                         * v3d_blit.c's stencil blits.
1084b8e80941Smrg                         */
1085b8e80941Smrg                        assert((util_format_linear(cso->format) ==
1086b8e80941Smrg                                util_format_linear(prsc->format)) ||
1087b8e80941Smrg                               (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
1088b8e80941Smrg                                cso->format == PIPE_FORMAT_R8G8B8A8_UNORM));
1089b8e80941Smrg                        uint32_t output_image_format =
1090b8e80941Smrg                                v3d_get_rt_format(&screen->devinfo, cso->format);
1091b8e80941Smrg                        uint32_t internal_type;
1092b8e80941Smrg                        uint32_t internal_bpp;
1093b8e80941Smrg                        v3d_get_internal_type_bpp_for_output_format(&screen->devinfo,
1094b8e80941Smrg                                                                    output_image_format,
1095b8e80941Smrg                                                                    &internal_type,
1096b8e80941Smrg                                                                    &internal_bpp);
1097b8e80941Smrg
1098b8e80941Smrg                        switch (internal_type) {
1099b8e80941Smrg                        case V3D_INTERNAL_TYPE_8:
1100b8e80941Smrg                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
1101b8e80941Smrg                                break;
1102b8e80941Smrg                        case V3D_INTERNAL_TYPE_16F:
1103b8e80941Smrg                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
1104b8e80941Smrg                                break;
1105b8e80941Smrg                        default:
1106b8e80941Smrg                                unreachable("Bad MSAA texture type");
1107b8e80941Smrg                        }
1108b8e80941Smrg
1109b8e80941Smrg                        /* sRGB was stored in the tile buffer as linear and
1110b8e80941Smrg                         * would have been encoded to sRGB on resolved tile
1111b8e80941Smrg                         * buffer store.  Note that this means we would need
1112b8e80941Smrg                         * shader code if we wanted to read an MSAA sRGB
1113b8e80941Smrg                         * texture without sRGB decode.
1114b8e80941Smrg                         */
1115b8e80941Smrg                        tex.srgb = false;
1116b8e80941Smrg                } else {
1117b8e80941Smrg                        tex.texture_type = v3d_get_tex_format(&screen->devinfo,
1118b8e80941Smrg                                                              cso->format);
1119b8e80941Smrg                }
1120b8e80941Smrg        };
1121b8e80941Smrg
1122b8e80941Smrg        return &so->base;
1123b8e80941Smrg}
1124b8e80941Smrg
1125b8e80941Smrgstatic void
1126b8e80941Smrgv3d_sampler_view_destroy(struct pipe_context *pctx,
1127b8e80941Smrg                         struct pipe_sampler_view *psview)
1128b8e80941Smrg{
1129b8e80941Smrg        struct v3d_sampler_view *sview = v3d_sampler_view(psview);
1130b8e80941Smrg
1131b8e80941Smrg        v3d_bo_unreference(&sview->bo);
1132b8e80941Smrg        pipe_resource_reference(&psview->texture, NULL);
1133b8e80941Smrg        pipe_resource_reference(&sview->texture, NULL);
1134b8e80941Smrg        free(psview);
1135b8e80941Smrg}
1136b8e80941Smrg
1137b8e80941Smrgstatic void
1138b8e80941Smrgv3d_set_sampler_views(struct pipe_context *pctx,
1139b8e80941Smrg                      enum pipe_shader_type shader,
1140b8e80941Smrg                      unsigned start, unsigned nr,
1141b8e80941Smrg                      struct pipe_sampler_view **views)
1142b8e80941Smrg{
1143b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
1144b8e80941Smrg        struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
1145b8e80941Smrg        unsigned i;
1146b8e80941Smrg        unsigned new_nr = 0;
1147b8e80941Smrg
1148b8e80941Smrg        assert(start == 0);
1149b8e80941Smrg
1150b8e80941Smrg        for (i = 0; i < nr; i++) {
1151b8e80941Smrg                if (views[i])
1152b8e80941Smrg                        new_nr = i + 1;
1153b8e80941Smrg                pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
1154b8e80941Smrg        }
1155b8e80941Smrg
1156b8e80941Smrg        for (; i < stage_tex->num_textures; i++) {
1157b8e80941Smrg                pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
1158b8e80941Smrg        }
1159b8e80941Smrg
1160b8e80941Smrg        stage_tex->num_textures = new_nr;
1161b8e80941Smrg}
1162b8e80941Smrg
1163b8e80941Smrgstatic struct pipe_stream_output_target *
1164b8e80941Smrgv3d_create_stream_output_target(struct pipe_context *pctx,
1165b8e80941Smrg                                struct pipe_resource *prsc,
1166b8e80941Smrg                                unsigned buffer_offset,
1167b8e80941Smrg                                unsigned buffer_size)
1168b8e80941Smrg{
1169b8e80941Smrg        struct pipe_stream_output_target *target;
1170b8e80941Smrg
1171b8e80941Smrg        target = CALLOC_STRUCT(pipe_stream_output_target);
1172b8e80941Smrg        if (!target)
1173b8e80941Smrg                return NULL;
1174b8e80941Smrg
1175b8e80941Smrg        pipe_reference_init(&target->reference, 1);
1176b8e80941Smrg        pipe_resource_reference(&target->buffer, prsc);
1177b8e80941Smrg
1178b8e80941Smrg        target->context = pctx;
1179b8e80941Smrg        target->buffer_offset = buffer_offset;
1180b8e80941Smrg        target->buffer_size = buffer_size;
1181b8e80941Smrg
1182b8e80941Smrg        return target;
1183b8e80941Smrg}
1184b8e80941Smrg
1185b8e80941Smrgstatic void
1186b8e80941Smrgv3d_stream_output_target_destroy(struct pipe_context *pctx,
1187b8e80941Smrg                                 struct pipe_stream_output_target *target)
1188b8e80941Smrg{
1189b8e80941Smrg        pipe_resource_reference(&target->buffer, NULL);
1190b8e80941Smrg        free(target);
1191b8e80941Smrg}
1192b8e80941Smrg
1193b8e80941Smrgstatic void
1194b8e80941Smrgv3d_set_stream_output_targets(struct pipe_context *pctx,
1195b8e80941Smrg                              unsigned num_targets,
1196b8e80941Smrg                              struct pipe_stream_output_target **targets,
1197b8e80941Smrg                              const unsigned *offsets)
1198b8e80941Smrg{
1199b8e80941Smrg        struct v3d_context *ctx = v3d_context(pctx);
1200b8e80941Smrg        struct v3d_streamout_stateobj *so = &ctx->streamout;
1201b8e80941Smrg        unsigned i;
1202b8e80941Smrg
1203b8e80941Smrg        assert(num_targets <= ARRAY_SIZE(so->targets));
1204b8e80941Smrg
1205b8e80941Smrg        for (i = 0; i < num_targets; i++) {
1206b8e80941Smrg                if (offsets[i] != -1)
1207b8e80941Smrg                        so->offsets[i] = offsets[i];
1208b8e80941Smrg
1209b8e80941Smrg                pipe_so_target_reference(&so->targets[i], targets[i]);
1210b8e80941Smrg        }
1211b8e80941Smrg
1212b8e80941Smrg        for (; i < so->num_targets; i++)
1213b8e80941Smrg                pipe_so_target_reference(&so->targets[i], NULL);
1214b8e80941Smrg
1215b8e80941Smrg        so->num_targets = num_targets;
1216b8e80941Smrg
1217b8e80941Smrg        ctx->dirty |= VC5_DIRTY_STREAMOUT;
1218b8e80941Smrg}
1219b8e80941Smrg
1220b8e80941Smrgstatic void
1221b8e80941Smrgv3d_set_shader_buffers(struct pipe_context *pctx,
1222b8e80941Smrg                       enum pipe_shader_type shader,
1223b8e80941Smrg                       unsigned start, unsigned count,
1224b8e80941Smrg                       const struct pipe_shader_buffer *buffers,
1225b8e80941Smrg                       unsigned writable_bitmask)
1226b8e80941Smrg{
1227b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
1228b8e80941Smrg        struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader];
1229b8e80941Smrg        unsigned mask = 0;
1230b8e80941Smrg
1231b8e80941Smrg        if (buffers) {
1232b8e80941Smrg                for (unsigned i = 0; i < count; i++) {
1233b8e80941Smrg                        unsigned n = i + start;
1234b8e80941Smrg                        struct pipe_shader_buffer *buf = &so->sb[n];
1235b8e80941Smrg
1236b8e80941Smrg                        if ((buf->buffer == buffers[i].buffer) &&
1237b8e80941Smrg                            (buf->buffer_offset == buffers[i].buffer_offset) &&
1238b8e80941Smrg                            (buf->buffer_size == buffers[i].buffer_size))
1239b8e80941Smrg                                continue;
1240b8e80941Smrg
1241b8e80941Smrg                        mask |= 1 << n;
1242b8e80941Smrg
1243b8e80941Smrg                        buf->buffer_offset = buffers[i].buffer_offset;
1244b8e80941Smrg                        buf->buffer_size = buffers[i].buffer_size;
1245b8e80941Smrg                        pipe_resource_reference(&buf->buffer, buffers[i].buffer);
1246b8e80941Smrg
1247b8e80941Smrg                        if (buf->buffer)
1248b8e80941Smrg                                so->enabled_mask |= 1 << n;
1249b8e80941Smrg                        else
1250b8e80941Smrg                                so->enabled_mask &= ~(1 << n);
1251b8e80941Smrg                }
1252b8e80941Smrg        } else {
1253b8e80941Smrg                mask = ((1 << count) - 1) << start;
1254b8e80941Smrg
1255b8e80941Smrg                for (unsigned i = 0; i < count; i++) {
1256b8e80941Smrg                        unsigned n = i + start;
1257b8e80941Smrg                        struct pipe_shader_buffer *buf = &so->sb[n];
1258b8e80941Smrg
1259b8e80941Smrg                        pipe_resource_reference(&buf->buffer, NULL);
1260b8e80941Smrg                }
1261b8e80941Smrg
1262b8e80941Smrg                so->enabled_mask &= ~mask;
1263b8e80941Smrg        }
1264b8e80941Smrg
1265b8e80941Smrg        v3d->dirty |= VC5_DIRTY_SSBO;
1266b8e80941Smrg}
1267b8e80941Smrg
1268b8e80941Smrgstatic void
1269b8e80941Smrgv3d_create_image_view_texture_shader_state(struct v3d_context *v3d,
1270b8e80941Smrg                                           struct v3d_shaderimg_stateobj *so,
1271b8e80941Smrg                                           int img)
1272b8e80941Smrg{
1273b8e80941Smrg#if V3D_VERSION >= 40
1274b8e80941Smrg        struct v3d_image_view *iview = &so->si[img];
1275b8e80941Smrg
1276b8e80941Smrg        void *map;
1277b8e80941Smrg        u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE),
1278b8e80941Smrg                       32,
1279b8e80941Smrg                       &iview->tex_state_offset,
1280b8e80941Smrg                       &iview->tex_state,
1281b8e80941Smrg                       &map);
1282b8e80941Smrg
1283b8e80941Smrg        struct pipe_resource *prsc = iview->base.resource;
1284b8e80941Smrg
1285b8e80941Smrg        v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
1286b8e80941Smrg                v3d_setup_texture_shader_state(&tex, prsc,
1287b8e80941Smrg                                               iview->base.u.tex.level,
1288b8e80941Smrg                                               iview->base.u.tex.level,
1289b8e80941Smrg                                               iview->base.u.tex.first_layer,
1290b8e80941Smrg                                               iview->base.u.tex.last_layer);
1291b8e80941Smrg
1292b8e80941Smrg                tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
1293b8e80941Smrg                tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
1294b8e80941Smrg                tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
1295b8e80941Smrg                tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
1296b8e80941Smrg
1297b8e80941Smrg                tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo,
1298b8e80941Smrg                                                      iview->base.format);
1299b8e80941Smrg        };
1300b8e80941Smrg#else /* V3D_VERSION < 40 */
1301b8e80941Smrg        /* V3D 3.x doesn't use support shader image load/store operations on
1302b8e80941Smrg         * textures, so it would get lowered in the shader to general memory
1303b8e80941Smrg         * acceses.
1304b8e80941Smrg         */
1305b8e80941Smrg#endif
1306b8e80941Smrg}
1307b8e80941Smrg
1308b8e80941Smrgstatic void
1309b8e80941Smrgv3d_set_shader_images(struct pipe_context *pctx,
1310b8e80941Smrg                      enum pipe_shader_type shader,
1311b8e80941Smrg                      unsigned start, unsigned count,
1312b8e80941Smrg                      const struct pipe_image_view *images)
1313b8e80941Smrg{
1314b8e80941Smrg        struct v3d_context *v3d = v3d_context(pctx);
1315b8e80941Smrg        struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader];
1316b8e80941Smrg
1317b8e80941Smrg        if (images) {
1318b8e80941Smrg                for (unsigned i = 0; i < count; i++) {
1319b8e80941Smrg                        unsigned n = i + start;
1320b8e80941Smrg                        struct v3d_image_view *iview = &so->si[n];
1321b8e80941Smrg
1322b8e80941Smrg                        if ((iview->base.resource == images[i].resource) &&
1323b8e80941Smrg                            (iview->base.format == images[i].format) &&
1324b8e80941Smrg                            (iview->base.access == images[i].access) &&
1325b8e80941Smrg                            !memcmp(&iview->base.u, &images[i].u,
1326b8e80941Smrg                                    sizeof(iview->base.u)))
1327b8e80941Smrg                                continue;
1328b8e80941Smrg
1329b8e80941Smrg                        util_copy_image_view(&iview->base, &images[i]);
1330b8e80941Smrg
1331b8e80941Smrg                        if (iview->base.resource) {
1332b8e80941Smrg                                so->enabled_mask |= 1 << n;
1333b8e80941Smrg                                v3d_create_image_view_texture_shader_state(v3d,
1334b8e80941Smrg                                                                           so,
1335b8e80941Smrg                                                                           n);
1336b8e80941Smrg                        } else {
1337b8e80941Smrg                                so->enabled_mask &= ~(1 << n);
1338b8e80941Smrg                                pipe_resource_reference(&iview->tex_state, NULL);
1339b8e80941Smrg                        }
1340b8e80941Smrg                }
1341b8e80941Smrg        } else {
1342b8e80941Smrg                for (unsigned i = 0; i < count; i++) {
1343b8e80941Smrg                        unsigned n = i + start;
1344b8e80941Smrg                        struct v3d_image_view *iview = &so->si[n];
1345b8e80941Smrg
1346b8e80941Smrg                        pipe_resource_reference(&iview->base.resource, NULL);
1347b8e80941Smrg                        pipe_resource_reference(&iview->tex_state, NULL);
1348b8e80941Smrg                }
1349b8e80941Smrg
1350b8e80941Smrg                if (count == 32)
1351b8e80941Smrg                        so->enabled_mask = 0;
1352b8e80941Smrg                else
1353b8e80941Smrg                        so->enabled_mask &= ~(((1 << count) - 1) << start);
1354b8e80941Smrg        }
1355b8e80941Smrg
1356b8e80941Smrg        v3d->dirty |= VC5_DIRTY_SHADER_IMAGE;
1357b8e80941Smrg}
1358b8e80941Smrg
1359b8e80941Smrgvoid
1360b8e80941Smrgv3dX(state_init)(struct pipe_context *pctx)
1361b8e80941Smrg{
1362b8e80941Smrg        pctx->set_blend_color = v3d_set_blend_color;
1363b8e80941Smrg        pctx->set_stencil_ref = v3d_set_stencil_ref;
1364b8e80941Smrg        pctx->set_clip_state = v3d_set_clip_state;
1365b8e80941Smrg        pctx->set_sample_mask = v3d_set_sample_mask;
1366b8e80941Smrg        pctx->set_constant_buffer = v3d_set_constant_buffer;
1367b8e80941Smrg        pctx->set_framebuffer_state = v3d_set_framebuffer_state;
1368b8e80941Smrg        pctx->set_polygon_stipple = v3d_set_polygon_stipple;
1369b8e80941Smrg        pctx->set_scissor_states = v3d_set_scissor_states;
1370b8e80941Smrg        pctx->set_viewport_states = v3d_set_viewport_states;
1371b8e80941Smrg
1372b8e80941Smrg        pctx->set_vertex_buffers = v3d_set_vertex_buffers;
1373b8e80941Smrg
1374b8e80941Smrg        pctx->create_blend_state = v3d_create_blend_state;
1375b8e80941Smrg        pctx->bind_blend_state = v3d_blend_state_bind;
1376b8e80941Smrg        pctx->delete_blend_state = v3d_generic_cso_state_delete;
1377b8e80941Smrg
1378b8e80941Smrg        pctx->create_rasterizer_state = v3d_create_rasterizer_state;
1379b8e80941Smrg        pctx->bind_rasterizer_state = v3d_rasterizer_state_bind;
1380b8e80941Smrg        pctx->delete_rasterizer_state = v3d_generic_cso_state_delete;
1381b8e80941Smrg
1382b8e80941Smrg        pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state;
1383b8e80941Smrg        pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind;
1384b8e80941Smrg        pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete;
1385b8e80941Smrg
1386b8e80941Smrg        pctx->create_vertex_elements_state = v3d_vertex_state_create;
1387b8e80941Smrg        pctx->delete_vertex_elements_state = v3d_vertex_state_delete;
1388b8e80941Smrg        pctx->bind_vertex_elements_state = v3d_vertex_state_bind;
1389b8e80941Smrg
1390b8e80941Smrg        pctx->create_sampler_state = v3d_create_sampler_state;
1391b8e80941Smrg        pctx->delete_sampler_state = v3d_sampler_state_delete;
1392b8e80941Smrg        pctx->bind_sampler_states = v3d_sampler_states_bind;
1393b8e80941Smrg
1394b8e80941Smrg        pctx->create_sampler_view = v3d_create_sampler_view;
1395b8e80941Smrg        pctx->sampler_view_destroy = v3d_sampler_view_destroy;
1396b8e80941Smrg        pctx->set_sampler_views = v3d_set_sampler_views;
1397b8e80941Smrg
1398b8e80941Smrg        pctx->set_shader_buffers = v3d_set_shader_buffers;
1399b8e80941Smrg        pctx->set_shader_images = v3d_set_shader_images;
1400b8e80941Smrg
1401b8e80941Smrg        pctx->create_stream_output_target = v3d_create_stream_output_target;
1402b8e80941Smrg        pctx->stream_output_target_destroy = v3d_stream_output_target_destroy;
1403b8e80941Smrg        pctx->set_stream_output_targets = v3d_set_stream_output_targets;
1404b8e80941Smrg}
1405