1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2014 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/u_framebuffer.h"
27bf215546Sopenharmony_ci#include "util/u_inlines.h"
28bf215546Sopenharmony_ci#include "util/u_math.h"
29bf215546Sopenharmony_ci#include "util/u_memory.h"
30bf215546Sopenharmony_ci#include "util/u_helpers.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "vc4_context.h"
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_cistatic void *
35bf215546Sopenharmony_civc4_generic_cso_state_create(const void *src, uint32_t size)
36bf215546Sopenharmony_ci{
37bf215546Sopenharmony_ci        void *dst = calloc(1, size);
38bf215546Sopenharmony_ci        if (!dst)
39bf215546Sopenharmony_ci                return NULL;
40bf215546Sopenharmony_ci        memcpy(dst, src, size);
41bf215546Sopenharmony_ci        return dst;
42bf215546Sopenharmony_ci}
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistatic void
45bf215546Sopenharmony_civc4_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci        free(hwcso);
48bf215546Sopenharmony_ci}
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cistatic void
51bf215546Sopenharmony_civc4_set_blend_color(struct pipe_context *pctx,
52bf215546Sopenharmony_ci                    const struct pipe_blend_color *blend_color)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
55bf215546Sopenharmony_ci        vc4->blend_color.f = *blend_color;
56bf215546Sopenharmony_ci        for (int i = 0; i < 4; i++)
57bf215546Sopenharmony_ci                vc4->blend_color.ub[i] = float_to_ubyte(blend_color->color[i]);
58bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_BLEND_COLOR;
59bf215546Sopenharmony_ci}
60bf215546Sopenharmony_ci
61bf215546Sopenharmony_cistatic void
62bf215546Sopenharmony_civc4_set_stencil_ref(struct pipe_context *pctx,
63bf215546Sopenharmony_ci                    const struct pipe_stencil_ref stencil_ref)
64bf215546Sopenharmony_ci{
65bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
66bf215546Sopenharmony_ci        vc4->stencil_ref = stencil_ref;
67bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_STENCIL_REF;
68bf215546Sopenharmony_ci}
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_cistatic void
71bf215546Sopenharmony_civc4_set_clip_state(struct pipe_context *pctx,
72bf215546Sopenharmony_ci                   const struct pipe_clip_state *clip)
73bf215546Sopenharmony_ci{
74bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
75bf215546Sopenharmony_ci        vc4->clip = *clip;
76bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_CLIP;
77bf215546Sopenharmony_ci}
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_cistatic void
80bf215546Sopenharmony_civc4_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
81bf215546Sopenharmony_ci{
82bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
83bf215546Sopenharmony_ci        vc4->sample_mask = sample_mask & ((1 << VC4_MAX_SAMPLES) - 1);
84bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_SAMPLE_MASK;
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_cistatic uint16_t
88bf215546Sopenharmony_cifloat_to_187_half(float f)
89bf215546Sopenharmony_ci{
90bf215546Sopenharmony_ci        return fui(f) >> 16;
91bf215546Sopenharmony_ci}
92bf215546Sopenharmony_ci
93bf215546Sopenharmony_cistatic void *
94bf215546Sopenharmony_civc4_create_rasterizer_state(struct pipe_context *pctx,
95bf215546Sopenharmony_ci                            const struct pipe_rasterizer_state *cso)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci        struct vc4_rasterizer_state *so;
98bf215546Sopenharmony_ci        struct V3D21_DEPTH_OFFSET depth_offset = { V3D21_DEPTH_OFFSET_header };
99bf215546Sopenharmony_ci        struct V3D21_POINT_SIZE point_size = { V3D21_POINT_SIZE_header };
100bf215546Sopenharmony_ci        struct V3D21_LINE_WIDTH line_width = { V3D21_LINE_WIDTH_header };
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci        so = CALLOC_STRUCT(vc4_rasterizer_state);
103bf215546Sopenharmony_ci        if (!so)
104bf215546Sopenharmony_ci                return NULL;
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci        so->base = *cso;
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci        if (!(cso->cull_face & PIPE_FACE_FRONT))
109bf215546Sopenharmony_ci                so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_FRONT;
110bf215546Sopenharmony_ci        if (!(cso->cull_face & PIPE_FACE_BACK))
111bf215546Sopenharmony_ci                so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_PRIM_BACK;
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci        /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
114bf215546Sopenharmony_ci         * BCM21553).
115bf215546Sopenharmony_ci         */
116bf215546Sopenharmony_ci        point_size.point_size = MAX2(cso->point_size, .125f);
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci        line_width.line_width = cso->line_width;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci        if (cso->front_ccw)
121bf215546Sopenharmony_ci                so->config_bits[0] |= VC4_CONFIG_BITS_CW_PRIMITIVES;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci        if (cso->offset_tri) {
124bf215546Sopenharmony_ci                so->config_bits[0] |= VC4_CONFIG_BITS_ENABLE_DEPTH_OFFSET;
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci                depth_offset.depth_offset_units =
127bf215546Sopenharmony_ci                        float_to_187_half(cso->offset_units);
128bf215546Sopenharmony_ci                depth_offset.depth_offset_factor =
129bf215546Sopenharmony_ci                        float_to_187_half(cso->offset_scale);
130bf215546Sopenharmony_ci        }
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci        if (cso->multisample)
133bf215546Sopenharmony_ci                so->config_bits[0] |= VC4_CONFIG_BITS_RASTERIZER_OVERSAMPLE_4X;
134bf215546Sopenharmony_ci
135bf215546Sopenharmony_ci        V3D21_DEPTH_OFFSET_pack(NULL, so->packed.depth_offset, &depth_offset);
136bf215546Sopenharmony_ci        V3D21_POINT_SIZE_pack(NULL, so->packed.point_size, &point_size);
137bf215546Sopenharmony_ci        V3D21_LINE_WIDTH_pack(NULL, so->packed.line_width, &line_width);
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci        if (cso->tile_raster_order_fixed) {
140bf215546Sopenharmony_ci                so->tile_raster_order_flags |= VC4_SUBMIT_CL_FIXED_RCL_ORDER;
141bf215546Sopenharmony_ci                if (cso->tile_raster_order_increasing_x) {
142bf215546Sopenharmony_ci                        so->tile_raster_order_flags |=
143bf215546Sopenharmony_ci                                VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X;
144bf215546Sopenharmony_ci                }
145bf215546Sopenharmony_ci                if (cso->tile_raster_order_increasing_y) {
146bf215546Sopenharmony_ci                        so->tile_raster_order_flags |=
147bf215546Sopenharmony_ci                                VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y;
148bf215546Sopenharmony_ci                }
149bf215546Sopenharmony_ci        }
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci        return so;
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci/* Blend state is baked into shaders. */
155bf215546Sopenharmony_cistatic void *
156bf215546Sopenharmony_civc4_create_blend_state(struct pipe_context *pctx,
157bf215546Sopenharmony_ci                       const struct pipe_blend_state *cso)
158bf215546Sopenharmony_ci{
159bf215546Sopenharmony_ci        return vc4_generic_cso_state_create(cso, sizeof(*cso));
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci/**
163bf215546Sopenharmony_ci * The TLB_STENCIL_SETUP data has a little bitfield for common writemask
164bf215546Sopenharmony_ci * values, so you don't have to do a separate writemask setup.
165bf215546Sopenharmony_ci */
166bf215546Sopenharmony_cistatic uint8_t
167bf215546Sopenharmony_citlb_stencil_setup_writemask(uint8_t mask)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci        switch (mask) {
170bf215546Sopenharmony_ci        case 0x1: return 0;
171bf215546Sopenharmony_ci        case 0x3: return 1;
172bf215546Sopenharmony_ci        case 0xf: return 2;
173bf215546Sopenharmony_ci        case 0xff: return 3;
174bf215546Sopenharmony_ci        default: return 0xff;
175bf215546Sopenharmony_ci        }
176bf215546Sopenharmony_ci}
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_cistatic uint32_t
179bf215546Sopenharmony_citlb_stencil_setup_bits(const struct pipe_stencil_state *state,
180bf215546Sopenharmony_ci                       uint8_t writemask_bits)
181bf215546Sopenharmony_ci{
182bf215546Sopenharmony_ci        static const uint8_t op_map[] = {
183bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_ZERO] = 0,
184bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_KEEP] = 1,
185bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_REPLACE] = 2,
186bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_INCR] = 3,
187bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_DECR] = 4,
188bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_INVERT] = 5,
189bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_INCR_WRAP] = 6,
190bf215546Sopenharmony_ci                [PIPE_STENCIL_OP_DECR_WRAP] = 7,
191bf215546Sopenharmony_ci        };
192bf215546Sopenharmony_ci        uint32_t bits = 0;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci        if (writemask_bits != 0xff)
195bf215546Sopenharmony_ci                bits |= writemask_bits << 28;
196bf215546Sopenharmony_ci        bits |= op_map[state->zfail_op] << 25;
197bf215546Sopenharmony_ci        bits |= op_map[state->zpass_op] << 22;
198bf215546Sopenharmony_ci        bits |= op_map[state->fail_op] << 19;
199bf215546Sopenharmony_ci        bits |= state->func << 16;
200bf215546Sopenharmony_ci        /* Ref is filled in at uniform upload time */
201bf215546Sopenharmony_ci        bits |= state->valuemask << 0;
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci        return bits;
204bf215546Sopenharmony_ci}
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_cistatic void *
207bf215546Sopenharmony_civc4_create_depth_stencil_alpha_state(struct pipe_context *pctx,
208bf215546Sopenharmony_ci                                     const struct pipe_depth_stencil_alpha_state *cso)
209bf215546Sopenharmony_ci{
210bf215546Sopenharmony_ci        struct vc4_depth_stencil_alpha_state *so;
211bf215546Sopenharmony_ci
212bf215546Sopenharmony_ci        so = CALLOC_STRUCT(vc4_depth_stencil_alpha_state);
213bf215546Sopenharmony_ci        if (!so)
214bf215546Sopenharmony_ci                return NULL;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci        so->base = *cso;
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci        /* We always keep the early Z state correct, since a later state using
219bf215546Sopenharmony_ci         * early Z may want it.
220bf215546Sopenharmony_ci         */
221bf215546Sopenharmony_ci        so->config_bits[2] |= VC4_CONFIG_BITS_EARLY_Z_UPDATE;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci        if (cso->depth_enabled) {
224bf215546Sopenharmony_ci                if (cso->depth_writemask) {
225bf215546Sopenharmony_ci                        so->config_bits[1] |= VC4_CONFIG_BITS_Z_UPDATE;
226bf215546Sopenharmony_ci                }
227bf215546Sopenharmony_ci                so->config_bits[1] |= (cso->depth_func <<
228bf215546Sopenharmony_ci                                       VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT);
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci                /* We only handle early Z in the < direction because otherwise
231bf215546Sopenharmony_ci                 * we'd have to runtime guess which direction to set in the
232bf215546Sopenharmony_ci                 * render config.
233bf215546Sopenharmony_ci                 */
234bf215546Sopenharmony_ci                if ((cso->depth_func == PIPE_FUNC_LESS ||
235bf215546Sopenharmony_ci                     cso->depth_func == PIPE_FUNC_LEQUAL) &&
236bf215546Sopenharmony_ci                    (!cso->stencil[0].enabled ||
237bf215546Sopenharmony_ci                     (cso->stencil[0].zfail_op == PIPE_STENCIL_OP_KEEP &&
238bf215546Sopenharmony_ci                      (!cso->stencil[1].enabled ||
239bf215546Sopenharmony_ci                       cso->stencil[1].zfail_op == PIPE_STENCIL_OP_KEEP)))) {
240bf215546Sopenharmony_ci                        so->config_bits[2] |= VC4_CONFIG_BITS_EARLY_Z;
241bf215546Sopenharmony_ci                }
242bf215546Sopenharmony_ci        } else {
243bf215546Sopenharmony_ci                so->config_bits[1] |= (PIPE_FUNC_ALWAYS <<
244bf215546Sopenharmony_ci                                       VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT);
245bf215546Sopenharmony_ci        }
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci        if (cso->stencil[0].enabled) {
248bf215546Sopenharmony_ci                const struct pipe_stencil_state *front = &cso->stencil[0];
249bf215546Sopenharmony_ci                const struct pipe_stencil_state *back = &cso->stencil[1];
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci                uint8_t front_writemask_bits =
252bf215546Sopenharmony_ci                        tlb_stencil_setup_writemask(front->writemask);
253bf215546Sopenharmony_ci                uint8_t back_writemask = front->writemask;
254bf215546Sopenharmony_ci                uint8_t back_writemask_bits = front_writemask_bits;
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci                so->stencil_uniforms[0] =
257bf215546Sopenharmony_ci                        tlb_stencil_setup_bits(front, front_writemask_bits);
258bf215546Sopenharmony_ci                if (back->enabled) {
259bf215546Sopenharmony_ci                        back_writemask = back->writemask;
260bf215546Sopenharmony_ci                        back_writemask_bits =
261bf215546Sopenharmony_ci                                tlb_stencil_setup_writemask(back->writemask);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci                        so->stencil_uniforms[0] |= (1 << 30);
264bf215546Sopenharmony_ci                        so->stencil_uniforms[1] =
265bf215546Sopenharmony_ci                                tlb_stencil_setup_bits(back, back_writemask_bits);
266bf215546Sopenharmony_ci                        so->stencil_uniforms[1] |= (2 << 30);
267bf215546Sopenharmony_ci                } else {
268bf215546Sopenharmony_ci                        so->stencil_uniforms[0] |= (3 << 30);
269bf215546Sopenharmony_ci                }
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci                if (front_writemask_bits == 0xff ||
272bf215546Sopenharmony_ci                    back_writemask_bits == 0xff) {
273bf215546Sopenharmony_ci                        so->stencil_uniforms[2] = (front->writemask |
274bf215546Sopenharmony_ci                                                   (back_writemask << 8));
275bf215546Sopenharmony_ci                }
276bf215546Sopenharmony_ci        }
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci        return so;
279bf215546Sopenharmony_ci}
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_cistatic void
282bf215546Sopenharmony_civc4_set_polygon_stipple(struct pipe_context *pctx,
283bf215546Sopenharmony_ci                        const struct pipe_poly_stipple *stipple)
284bf215546Sopenharmony_ci{
285bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
286bf215546Sopenharmony_ci        vc4->stipple = *stipple;
287bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_STIPPLE;
288bf215546Sopenharmony_ci}
289bf215546Sopenharmony_ci
290bf215546Sopenharmony_cistatic void
291bf215546Sopenharmony_civc4_set_scissor_states(struct pipe_context *pctx,
292bf215546Sopenharmony_ci                       unsigned start_slot,
293bf215546Sopenharmony_ci                       unsigned num_scissors,
294bf215546Sopenharmony_ci                       const struct pipe_scissor_state *scissor)
295bf215546Sopenharmony_ci{
296bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci        vc4->scissor = *scissor;
299bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_SCISSOR;
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cistatic void
303bf215546Sopenharmony_civc4_set_viewport_states(struct pipe_context *pctx,
304bf215546Sopenharmony_ci                        unsigned start_slot,
305bf215546Sopenharmony_ci                        unsigned num_viewports,
306bf215546Sopenharmony_ci                        const struct pipe_viewport_state *viewport)
307bf215546Sopenharmony_ci{
308bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
309bf215546Sopenharmony_ci        vc4->viewport = *viewport;
310bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_VIEWPORT;
311bf215546Sopenharmony_ci}
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_cistatic void
314bf215546Sopenharmony_civc4_set_vertex_buffers(struct pipe_context *pctx,
315bf215546Sopenharmony_ci                       unsigned start_slot, unsigned count,
316bf215546Sopenharmony_ci                       unsigned unbind_num_trailing_slots,
317bf215546Sopenharmony_ci                       bool take_ownership,
318bf215546Sopenharmony_ci                       const struct pipe_vertex_buffer *vb)
319bf215546Sopenharmony_ci{
320bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
321bf215546Sopenharmony_ci        struct vc4_vertexbuf_stateobj *so = &vc4->vertexbuf;
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci        util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
324bf215546Sopenharmony_ci                                     start_slot, count,
325bf215546Sopenharmony_ci                                     unbind_num_trailing_slots,
326bf215546Sopenharmony_ci                                     take_ownership);
327bf215546Sopenharmony_ci        so->count = util_last_bit(so->enabled_mask);
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_VTXBUF;
330bf215546Sopenharmony_ci}
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_cistatic void
333bf215546Sopenharmony_civc4_blend_state_bind(struct pipe_context *pctx, void *hwcso)
334bf215546Sopenharmony_ci{
335bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
336bf215546Sopenharmony_ci        vc4->blend = hwcso;
337bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_BLEND;
338bf215546Sopenharmony_ci}
339bf215546Sopenharmony_ci
340bf215546Sopenharmony_cistatic void
341bf215546Sopenharmony_civc4_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
342bf215546Sopenharmony_ci{
343bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
344bf215546Sopenharmony_ci        struct vc4_rasterizer_state *rast = hwcso;
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci        if (vc4->rasterizer && rast &&
347bf215546Sopenharmony_ci            vc4->rasterizer->base.flatshade != rast->base.flatshade) {
348bf215546Sopenharmony_ci                vc4->dirty |= VC4_DIRTY_FLAT_SHADE_FLAGS;
349bf215546Sopenharmony_ci        }
350bf215546Sopenharmony_ci
351bf215546Sopenharmony_ci        vc4->rasterizer = hwcso;
352bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_RASTERIZER;
353bf215546Sopenharmony_ci}
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_cistatic void
356bf215546Sopenharmony_civc4_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
359bf215546Sopenharmony_ci        vc4->zsa = hwcso;
360bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_ZSA;
361bf215546Sopenharmony_ci}
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_cistatic void *
364bf215546Sopenharmony_civc4_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
365bf215546Sopenharmony_ci                        const struct pipe_vertex_element *elements)
366bf215546Sopenharmony_ci{
367bf215546Sopenharmony_ci        struct vc4_vertex_stateobj *so = CALLOC_STRUCT(vc4_vertex_stateobj);
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci        if (!so)
370bf215546Sopenharmony_ci                return NULL;
371bf215546Sopenharmony_ci
372bf215546Sopenharmony_ci        memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
373bf215546Sopenharmony_ci        so->num_elements = num_elements;
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci        return so;
376bf215546Sopenharmony_ci}
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_cistatic void
379bf215546Sopenharmony_civc4_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
380bf215546Sopenharmony_ci{
381bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
382bf215546Sopenharmony_ci        vc4->vtx = hwcso;
383bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_VTXSTATE;
384bf215546Sopenharmony_ci}
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_cistatic void
387bf215546Sopenharmony_civc4_set_constant_buffer(struct pipe_context *pctx,
388bf215546Sopenharmony_ci                        enum pipe_shader_type shader, uint index,
389bf215546Sopenharmony_ci                        bool take_ownership,
390bf215546Sopenharmony_ci                        const struct pipe_constant_buffer *cb)
391bf215546Sopenharmony_ci{
392bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
393bf215546Sopenharmony_ci        struct vc4_constbuf_stateobj *so = &vc4->constbuf[shader];
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci        /* Note that the gallium frontend can unbind constant buffers by
396bf215546Sopenharmony_ci         * passing NULL here.
397bf215546Sopenharmony_ci         */
398bf215546Sopenharmony_ci        if (unlikely(!cb)) {
399bf215546Sopenharmony_ci                so->enabled_mask &= ~(1 << index);
400bf215546Sopenharmony_ci                so->dirty_mask &= ~(1 << index);
401bf215546Sopenharmony_ci                return;
402bf215546Sopenharmony_ci        }
403bf215546Sopenharmony_ci
404bf215546Sopenharmony_ci        if (index == 1 && so->cb[index].buffer_size != cb->buffer_size)
405bf215546Sopenharmony_ci                vc4->dirty |= VC4_DIRTY_UBO_1_SIZE;
406bf215546Sopenharmony_ci
407bf215546Sopenharmony_ci        util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci        so->enabled_mask |= 1 << index;
410bf215546Sopenharmony_ci        so->dirty_mask |= 1 << index;
411bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_CONSTBUF;
412bf215546Sopenharmony_ci}
413bf215546Sopenharmony_ci
414bf215546Sopenharmony_cistatic void
415bf215546Sopenharmony_civc4_set_framebuffer_state(struct pipe_context *pctx,
416bf215546Sopenharmony_ci                          const struct pipe_framebuffer_state *framebuffer)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
419bf215546Sopenharmony_ci        struct pipe_framebuffer_state *cso = &vc4->framebuffer;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci        vc4->job = NULL;
422bf215546Sopenharmony_ci
423bf215546Sopenharmony_ci        util_copy_framebuffer_state(cso, framebuffer);
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci        /* Nonzero texture mipmap levels are laid out as if they were in
426bf215546Sopenharmony_ci         * power-of-two-sized spaces.  The renderbuffer config infers its
427bf215546Sopenharmony_ci         * stride from the width parameter, so we need to configure our
428bf215546Sopenharmony_ci         * framebuffer.  Note that if the z/color buffers were mismatched
429bf215546Sopenharmony_ci         * sizes, we wouldn't be able to do this.
430bf215546Sopenharmony_ci         */
431bf215546Sopenharmony_ci        if (cso->cbufs[0] && cso->cbufs[0]->u.tex.level) {
432bf215546Sopenharmony_ci                struct vc4_resource *rsc =
433bf215546Sopenharmony_ci                        vc4_resource(cso->cbufs[0]->texture);
434bf215546Sopenharmony_ci                cso->width =
435bf215546Sopenharmony_ci                        (rsc->slices[cso->cbufs[0]->u.tex.level].stride /
436bf215546Sopenharmony_ci                         rsc->cpp);
437bf215546Sopenharmony_ci        } else if (cso->zsbuf && cso->zsbuf->u.tex.level){
438bf215546Sopenharmony_ci                struct vc4_resource *rsc =
439bf215546Sopenharmony_ci                        vc4_resource(cso->zsbuf->texture);
440bf215546Sopenharmony_ci                cso->width =
441bf215546Sopenharmony_ci                        (rsc->slices[cso->zsbuf->u.tex.level].stride /
442bf215546Sopenharmony_ci                         rsc->cpp);
443bf215546Sopenharmony_ci        }
444bf215546Sopenharmony_ci
445bf215546Sopenharmony_ci        vc4->dirty |= VC4_DIRTY_FRAMEBUFFER;
446bf215546Sopenharmony_ci}
447bf215546Sopenharmony_ci
448bf215546Sopenharmony_cistatic struct vc4_texture_stateobj *
449bf215546Sopenharmony_civc4_get_stage_tex(struct vc4_context *vc4, enum pipe_shader_type shader)
450bf215546Sopenharmony_ci{
451bf215546Sopenharmony_ci        switch (shader) {
452bf215546Sopenharmony_ci        case PIPE_SHADER_FRAGMENT:
453bf215546Sopenharmony_ci                vc4->dirty |= VC4_DIRTY_FRAGTEX;
454bf215546Sopenharmony_ci                return &vc4->fragtex;
455bf215546Sopenharmony_ci                break;
456bf215546Sopenharmony_ci        case PIPE_SHADER_VERTEX:
457bf215546Sopenharmony_ci                vc4->dirty |= VC4_DIRTY_VERTTEX;
458bf215546Sopenharmony_ci                return &vc4->verttex;
459bf215546Sopenharmony_ci                break;
460bf215546Sopenharmony_ci        default:
461bf215546Sopenharmony_ci                fprintf(stderr, "Unknown shader target %d\n", shader);
462bf215546Sopenharmony_ci                abort();
463bf215546Sopenharmony_ci        }
464bf215546Sopenharmony_ci}
465bf215546Sopenharmony_ci
466bf215546Sopenharmony_cistatic uint32_t translate_wrap(uint32_t p_wrap, bool using_nearest)
467bf215546Sopenharmony_ci{
468bf215546Sopenharmony_ci        switch (p_wrap) {
469bf215546Sopenharmony_ci        case PIPE_TEX_WRAP_REPEAT:
470bf215546Sopenharmony_ci                return 0;
471bf215546Sopenharmony_ci        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
472bf215546Sopenharmony_ci                return 1;
473bf215546Sopenharmony_ci        case PIPE_TEX_WRAP_MIRROR_REPEAT:
474bf215546Sopenharmony_ci                return 2;
475bf215546Sopenharmony_ci        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
476bf215546Sopenharmony_ci                return 3;
477bf215546Sopenharmony_ci        case PIPE_TEX_WRAP_CLAMP:
478bf215546Sopenharmony_ci                return (using_nearest ? 1 : 3);
479bf215546Sopenharmony_ci        default:
480bf215546Sopenharmony_ci                fprintf(stderr, "Unknown wrap mode %d\n", p_wrap);
481bf215546Sopenharmony_ci                assert(!"not reached");
482bf215546Sopenharmony_ci                return 0;
483bf215546Sopenharmony_ci        }
484bf215546Sopenharmony_ci}
485bf215546Sopenharmony_ci
486bf215546Sopenharmony_cistatic void *
487bf215546Sopenharmony_civc4_create_sampler_state(struct pipe_context *pctx,
488bf215546Sopenharmony_ci                         const struct pipe_sampler_state *cso)
489bf215546Sopenharmony_ci{
490bf215546Sopenharmony_ci        static const uint8_t minfilter_map[6] = {
491bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_NEAR_MIP_NEAR,
492bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_LIN_MIP_NEAR,
493bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_NEAR_MIP_LIN,
494bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_LIN_MIP_LIN,
495bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_NEAREST,
496bf215546Sopenharmony_ci                VC4_TEX_P1_MINFILT_LINEAR,
497bf215546Sopenharmony_ci        };
498bf215546Sopenharmony_ci        static const uint32_t magfilter_map[] = {
499bf215546Sopenharmony_ci                [PIPE_TEX_FILTER_NEAREST] = VC4_TEX_P1_MAGFILT_NEAREST,
500bf215546Sopenharmony_ci                [PIPE_TEX_FILTER_LINEAR] = VC4_TEX_P1_MAGFILT_LINEAR,
501bf215546Sopenharmony_ci        };
502bf215546Sopenharmony_ci        bool either_nearest =
503bf215546Sopenharmony_ci                (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
504bf215546Sopenharmony_ci                 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
505bf215546Sopenharmony_ci        struct vc4_sampler_state *so = CALLOC_STRUCT(vc4_sampler_state);
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci        if (!so)
508bf215546Sopenharmony_ci                return NULL;
509bf215546Sopenharmony_ci
510bf215546Sopenharmony_ci        memcpy(so, cso, sizeof(*cso));
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci        so->texture_p1 =
513bf215546Sopenharmony_ci                (VC4_SET_FIELD(magfilter_map[cso->mag_img_filter],
514bf215546Sopenharmony_ci                               VC4_TEX_P1_MAGFILT) |
515bf215546Sopenharmony_ci                 VC4_SET_FIELD(minfilter_map[cso->min_mip_filter * 2 +
516bf215546Sopenharmony_ci                                             cso->min_img_filter],
517bf215546Sopenharmony_ci                               VC4_TEX_P1_MINFILT) |
518bf215546Sopenharmony_ci                 VC4_SET_FIELD(translate_wrap(cso->wrap_s, either_nearest),
519bf215546Sopenharmony_ci                               VC4_TEX_P1_WRAP_S) |
520bf215546Sopenharmony_ci                 VC4_SET_FIELD(translate_wrap(cso->wrap_t, either_nearest),
521bf215546Sopenharmony_ci                               VC4_TEX_P1_WRAP_T));
522bf215546Sopenharmony_ci
523bf215546Sopenharmony_ci        return so;
524bf215546Sopenharmony_ci}
525bf215546Sopenharmony_ci
526bf215546Sopenharmony_cistatic void
527bf215546Sopenharmony_civc4_sampler_states_bind(struct pipe_context *pctx,
528bf215546Sopenharmony_ci                        enum pipe_shader_type shader, unsigned start,
529bf215546Sopenharmony_ci                        unsigned nr, void **hwcso)
530bf215546Sopenharmony_ci{
531bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
532bf215546Sopenharmony_ci        struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader);
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci        assert(start == 0);
535bf215546Sopenharmony_ci        unsigned i;
536bf215546Sopenharmony_ci        unsigned new_nr = 0;
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci        for (i = 0; i < nr; i++) {
539bf215546Sopenharmony_ci                if (hwcso[i])
540bf215546Sopenharmony_ci                        new_nr = i + 1;
541bf215546Sopenharmony_ci                stage_tex->samplers[i] = hwcso[i];
542bf215546Sopenharmony_ci        }
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci        for (; i < stage_tex->num_samplers; i++) {
545bf215546Sopenharmony_ci                stage_tex->samplers[i] = NULL;
546bf215546Sopenharmony_ci        }
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci        stage_tex->num_samplers = new_nr;
549bf215546Sopenharmony_ci}
550bf215546Sopenharmony_ci
551bf215546Sopenharmony_cistatic struct pipe_sampler_view *
552bf215546Sopenharmony_civc4_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
553bf215546Sopenharmony_ci                        const struct pipe_sampler_view *cso)
554bf215546Sopenharmony_ci{
555bf215546Sopenharmony_ci        struct vc4_sampler_view *so = CALLOC_STRUCT(vc4_sampler_view);
556bf215546Sopenharmony_ci        struct vc4_resource *rsc = vc4_resource(prsc);
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci        if (!so)
559bf215546Sopenharmony_ci                return NULL;
560bf215546Sopenharmony_ci
561bf215546Sopenharmony_ci        so->base = *cso;
562bf215546Sopenharmony_ci
563bf215546Sopenharmony_ci        so->base.texture = NULL;
564bf215546Sopenharmony_ci        pipe_resource_reference(&so->base.texture, prsc);
565bf215546Sopenharmony_ci        so->base.reference.count = 1;
566bf215546Sopenharmony_ci        so->base.context = pctx;
567bf215546Sopenharmony_ci
568bf215546Sopenharmony_ci        /* There is no hardware level clamping, and the start address of a
569bf215546Sopenharmony_ci         * texture may be misaligned, so in that case we have to copy to a
570bf215546Sopenharmony_ci         * temporary.
571bf215546Sopenharmony_ci         *
572bf215546Sopenharmony_ci         * Also, Raspberry Pi doesn't support sampling from raster textures,
573bf215546Sopenharmony_ci         * so we also have to copy to a temporary then.
574bf215546Sopenharmony_ci         */
575bf215546Sopenharmony_ci        if ((cso->u.tex.first_level &&
576bf215546Sopenharmony_ci             (cso->u.tex.first_level != cso->u.tex.last_level)) ||
577bf215546Sopenharmony_ci            rsc->vc4_format == VC4_TEXTURE_TYPE_RGBA32R ||
578bf215546Sopenharmony_ci            rsc->vc4_format == ~0) {
579bf215546Sopenharmony_ci                struct vc4_resource *shadow_parent = rsc;
580bf215546Sopenharmony_ci                struct pipe_resource tmpl = {
581bf215546Sopenharmony_ci                        .target = prsc->target,
582bf215546Sopenharmony_ci                        .format = prsc->format,
583bf215546Sopenharmony_ci                        .width0 = u_minify(prsc->width0,
584bf215546Sopenharmony_ci                                           cso->u.tex.first_level),
585bf215546Sopenharmony_ci                        .height0 = u_minify(prsc->height0,
586bf215546Sopenharmony_ci                                            cso->u.tex.first_level),
587bf215546Sopenharmony_ci                        .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
588bf215546Sopenharmony_ci                        .last_level = cso->u.tex.last_level - cso->u.tex.first_level,
589bf215546Sopenharmony_ci                        .nr_samples = prsc->nr_samples,
590bf215546Sopenharmony_ci                };
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci                /* Create the shadow texture.  The rest of the texture
593bf215546Sopenharmony_ci                 * parameter setup will use the shadow.
594bf215546Sopenharmony_ci                 */
595bf215546Sopenharmony_ci                prsc = vc4_resource_create(pctx->screen, &tmpl);
596bf215546Sopenharmony_ci                if (!prsc) {
597bf215546Sopenharmony_ci                        free(so);
598bf215546Sopenharmony_ci                        return NULL;
599bf215546Sopenharmony_ci                }
600bf215546Sopenharmony_ci                rsc = vc4_resource(prsc);
601bf215546Sopenharmony_ci                vc4_bo_label(vc4_screen(pctx->screen), rsc->bo,
602bf215546Sopenharmony_ci                            "tiling shadow %dx%d",
603bf215546Sopenharmony_ci                             tmpl.width0, tmpl.height0);
604bf215546Sopenharmony_ci
605bf215546Sopenharmony_ci                /* Flag it as needing update of the contents from the parent. */
606bf215546Sopenharmony_ci                rsc->writes = shadow_parent->writes - 1;
607bf215546Sopenharmony_ci                assert(rsc->vc4_format != VC4_TEXTURE_TYPE_RGBA32R);
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci                so->texture = prsc;
610bf215546Sopenharmony_ci        } else {
611bf215546Sopenharmony_ci                pipe_resource_reference(&so->texture, prsc);
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ci                if (cso->u.tex.first_level) {
614bf215546Sopenharmony_ci                        so->force_first_level = true;
615bf215546Sopenharmony_ci                }
616bf215546Sopenharmony_ci        }
617bf215546Sopenharmony_ci
618bf215546Sopenharmony_ci        so->texture_p0 =
619bf215546Sopenharmony_ci                (VC4_SET_FIELD((rsc->slices[0].offset +
620bf215546Sopenharmony_ci                                cso->u.tex.first_layer *
621bf215546Sopenharmony_ci                                rsc->cube_map_stride) >> 12, VC4_TEX_P0_OFFSET) |
622bf215546Sopenharmony_ci                 VC4_SET_FIELD(rsc->vc4_format & 15, VC4_TEX_P0_TYPE) |
623bf215546Sopenharmony_ci                 VC4_SET_FIELD(so->force_first_level ?
624bf215546Sopenharmony_ci                               cso->u.tex.last_level :
625bf215546Sopenharmony_ci                               cso->u.tex.last_level -
626bf215546Sopenharmony_ci                               cso->u.tex.first_level, VC4_TEX_P0_MIPLVLS) |
627bf215546Sopenharmony_ci                 VC4_SET_FIELD(cso->target == PIPE_TEXTURE_CUBE,
628bf215546Sopenharmony_ci                               VC4_TEX_P0_CMMODE));
629bf215546Sopenharmony_ci        so->texture_p1 =
630bf215546Sopenharmony_ci                (VC4_SET_FIELD(rsc->vc4_format >> 4, VC4_TEX_P1_TYPE4) |
631bf215546Sopenharmony_ci                 VC4_SET_FIELD(prsc->height0 & 2047, VC4_TEX_P1_HEIGHT) |
632bf215546Sopenharmony_ci                 VC4_SET_FIELD(prsc->width0 & 2047, VC4_TEX_P1_WIDTH));
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci        if (prsc->format == PIPE_FORMAT_ETC1_RGB8)
635bf215546Sopenharmony_ci                so->texture_p1 |= VC4_TEX_P1_ETCFLIP_MASK;
636bf215546Sopenharmony_ci
637bf215546Sopenharmony_ci        return &so->base;
638bf215546Sopenharmony_ci}
639bf215546Sopenharmony_ci
640bf215546Sopenharmony_cistatic void
641bf215546Sopenharmony_civc4_sampler_view_destroy(struct pipe_context *pctx,
642bf215546Sopenharmony_ci                         struct pipe_sampler_view *pview)
643bf215546Sopenharmony_ci{
644bf215546Sopenharmony_ci        struct vc4_sampler_view *view = vc4_sampler_view(pview);
645bf215546Sopenharmony_ci        pipe_resource_reference(&pview->texture, NULL);
646bf215546Sopenharmony_ci        pipe_resource_reference(&view->texture, NULL);
647bf215546Sopenharmony_ci        free(view);
648bf215546Sopenharmony_ci}
649bf215546Sopenharmony_ci
650bf215546Sopenharmony_cistatic void
651bf215546Sopenharmony_civc4_set_sampler_views(struct pipe_context *pctx,
652bf215546Sopenharmony_ci                      enum pipe_shader_type shader,
653bf215546Sopenharmony_ci                      unsigned start, unsigned nr,
654bf215546Sopenharmony_ci                      unsigned unbind_num_trailing_slots,
655bf215546Sopenharmony_ci                      bool take_ownership,
656bf215546Sopenharmony_ci                      struct pipe_sampler_view **views)
657bf215546Sopenharmony_ci{
658bf215546Sopenharmony_ci        struct vc4_context *vc4 = vc4_context(pctx);
659bf215546Sopenharmony_ci        struct vc4_texture_stateobj *stage_tex = vc4_get_stage_tex(vc4, shader);
660bf215546Sopenharmony_ci        unsigned i;
661bf215546Sopenharmony_ci        unsigned new_nr = 0;
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ci        assert(start == 0);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci        for (i = 0; i < nr; i++) {
666bf215546Sopenharmony_ci                if (views[i])
667bf215546Sopenharmony_ci                        new_nr = i + 1;
668bf215546Sopenharmony_ci                if (take_ownership) {
669bf215546Sopenharmony_ci                        pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
670bf215546Sopenharmony_ci                        stage_tex->textures[i] = views[i];
671bf215546Sopenharmony_ci                } else {
672bf215546Sopenharmony_ci                        pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
673bf215546Sopenharmony_ci                }
674bf215546Sopenharmony_ci        }
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci        for (; i < stage_tex->num_textures; i++) {
677bf215546Sopenharmony_ci                pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
678bf215546Sopenharmony_ci        }
679bf215546Sopenharmony_ci
680bf215546Sopenharmony_ci        stage_tex->num_textures = new_nr;
681bf215546Sopenharmony_ci}
682bf215546Sopenharmony_ci
683bf215546Sopenharmony_civoid
684bf215546Sopenharmony_civc4_state_init(struct pipe_context *pctx)
685bf215546Sopenharmony_ci{
686bf215546Sopenharmony_ci        pctx->set_blend_color = vc4_set_blend_color;
687bf215546Sopenharmony_ci        pctx->set_stencil_ref = vc4_set_stencil_ref;
688bf215546Sopenharmony_ci        pctx->set_clip_state = vc4_set_clip_state;
689bf215546Sopenharmony_ci        pctx->set_sample_mask = vc4_set_sample_mask;
690bf215546Sopenharmony_ci        pctx->set_constant_buffer = vc4_set_constant_buffer;
691bf215546Sopenharmony_ci        pctx->set_framebuffer_state = vc4_set_framebuffer_state;
692bf215546Sopenharmony_ci        pctx->set_polygon_stipple = vc4_set_polygon_stipple;
693bf215546Sopenharmony_ci        pctx->set_scissor_states = vc4_set_scissor_states;
694bf215546Sopenharmony_ci        pctx->set_viewport_states = vc4_set_viewport_states;
695bf215546Sopenharmony_ci
696bf215546Sopenharmony_ci        pctx->set_vertex_buffers = vc4_set_vertex_buffers;
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ci        pctx->create_blend_state = vc4_create_blend_state;
699bf215546Sopenharmony_ci        pctx->bind_blend_state = vc4_blend_state_bind;
700bf215546Sopenharmony_ci        pctx->delete_blend_state = vc4_generic_cso_state_delete;
701bf215546Sopenharmony_ci
702bf215546Sopenharmony_ci        pctx->create_rasterizer_state = vc4_create_rasterizer_state;
703bf215546Sopenharmony_ci        pctx->bind_rasterizer_state = vc4_rasterizer_state_bind;
704bf215546Sopenharmony_ci        pctx->delete_rasterizer_state = vc4_generic_cso_state_delete;
705bf215546Sopenharmony_ci
706bf215546Sopenharmony_ci        pctx->create_depth_stencil_alpha_state = vc4_create_depth_stencil_alpha_state;
707bf215546Sopenharmony_ci        pctx->bind_depth_stencil_alpha_state = vc4_zsa_state_bind;
708bf215546Sopenharmony_ci        pctx->delete_depth_stencil_alpha_state = vc4_generic_cso_state_delete;
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci        pctx->create_vertex_elements_state = vc4_vertex_state_create;
711bf215546Sopenharmony_ci        pctx->delete_vertex_elements_state = vc4_generic_cso_state_delete;
712bf215546Sopenharmony_ci        pctx->bind_vertex_elements_state = vc4_vertex_state_bind;
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci        pctx->create_sampler_state = vc4_create_sampler_state;
715bf215546Sopenharmony_ci        pctx->delete_sampler_state = vc4_generic_cso_state_delete;
716bf215546Sopenharmony_ci        pctx->bind_sampler_states = vc4_sampler_states_bind;
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci        pctx->create_sampler_view = vc4_create_sampler_view;
719bf215546Sopenharmony_ci        pctx->sampler_view_destroy = vc4_sampler_view_destroy;
720bf215546Sopenharmony_ci        pctx->set_sampler_views = vc4_set_sampler_views;
721bf215546Sopenharmony_ci}
722