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