101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2014-2017 Broadcom
301e04c3fSmrg * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
401e04c3fSmrg *
501e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
601e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
701e04c3fSmrg * to deal in the Software without restriction, including without limitation
801e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
901e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
1001e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1101e04c3fSmrg *
1201e04c3fSmrg * The above copyright notice and this permission notice (including the next
1301e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1401e04c3fSmrg * Software.
1501e04c3fSmrg *
1601e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1701e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1801e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1901e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2001e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2101e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2201e04c3fSmrg * IN THE SOFTWARE.
2301e04c3fSmrg */
2401e04c3fSmrg
2501e04c3fSmrg#include "pipe/p_state.h"
267ec681f3Smrg#include "util/format/u_format.h"
2701e04c3fSmrg#include "util/u_framebuffer.h"
2801e04c3fSmrg#include "util/u_inlines.h"
2901e04c3fSmrg#include "util/u_math.h"
3001e04c3fSmrg#include "util/u_memory.h"
317ec681f3Smrg#include "util/half_float.h"
3201e04c3fSmrg#include "util/u_helpers.h"
339f464c52Smaya#include "util/u_upload_mgr.h"
3401e04c3fSmrg
3501e04c3fSmrg#include "v3d_context.h"
367ec681f3Smrg#include "broadcom/common/v3d_tiling.h"
3701e04c3fSmrg#include "broadcom/common/v3d_macros.h"
389f464c52Smaya#include "broadcom/compiler/v3d_compiler.h"
3901e04c3fSmrg#include "broadcom/cle/v3dx_pack.h"
4001e04c3fSmrg
4101e04c3fSmrgstatic void
4201e04c3fSmrgv3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
4301e04c3fSmrg{
4401e04c3fSmrg        free(hwcso);
4501e04c3fSmrg}
4601e04c3fSmrg
4701e04c3fSmrgstatic void
4801e04c3fSmrgv3d_set_blend_color(struct pipe_context *pctx,
4901e04c3fSmrg                    const struct pipe_blend_color *blend_color)
5001e04c3fSmrg{
5101e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
5201e04c3fSmrg        v3d->blend_color.f = *blend_color;
5301e04c3fSmrg        for (int i = 0; i < 4; i++) {
5401e04c3fSmrg                v3d->blend_color.hf[i] =
557ec681f3Smrg                        _mesa_float_to_half(blend_color->color[i]);
5601e04c3fSmrg        }
577ec681f3Smrg        v3d->dirty |= V3D_DIRTY_BLEND_COLOR;
5801e04c3fSmrg}
5901e04c3fSmrg
6001e04c3fSmrgstatic void
6101e04c3fSmrgv3d_set_stencil_ref(struct pipe_context *pctx,
627ec681f3Smrg                    const struct pipe_stencil_ref stencil_ref)
6301e04c3fSmrg{
6401e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
657ec681f3Smrg        v3d->stencil_ref = stencil_ref;
667ec681f3Smrg        v3d->dirty |= V3D_DIRTY_STENCIL_REF;
6701e04c3fSmrg}
6801e04c3fSmrg
6901e04c3fSmrgstatic void
7001e04c3fSmrgv3d_set_clip_state(struct pipe_context *pctx,
7101e04c3fSmrg                   const struct pipe_clip_state *clip)
7201e04c3fSmrg{
7301e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
7401e04c3fSmrg        v3d->clip = *clip;
757ec681f3Smrg        v3d->dirty |= V3D_DIRTY_CLIP;
7601e04c3fSmrg}
7701e04c3fSmrg
7801e04c3fSmrgstatic void
7901e04c3fSmrgv3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
8001e04c3fSmrg{
8101e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
829f464c52Smaya        v3d->sample_mask = sample_mask & ((1 << V3D_MAX_SAMPLES) - 1);
837ec681f3Smrg        v3d->dirty |= V3D_DIRTY_SAMPLE_STATE;
8401e04c3fSmrg}
8501e04c3fSmrg
8601e04c3fSmrgstatic void *
8701e04c3fSmrgv3d_create_rasterizer_state(struct pipe_context *pctx,
8801e04c3fSmrg                            const struct pipe_rasterizer_state *cso)
8901e04c3fSmrg{
9001e04c3fSmrg        struct v3d_rasterizer_state *so;
9101e04c3fSmrg
9201e04c3fSmrg        so = CALLOC_STRUCT(v3d_rasterizer_state);
9301e04c3fSmrg        if (!so)
9401e04c3fSmrg                return NULL;
9501e04c3fSmrg
9601e04c3fSmrg        so->base = *cso;
9701e04c3fSmrg
9801e04c3fSmrg        /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
9901e04c3fSmrg         * BCM21553).
10001e04c3fSmrg         */
10101e04c3fSmrg        so->point_size = MAX2(cso->point_size, .125f);
10201e04c3fSmrg
10301e04c3fSmrg        STATIC_ASSERT(sizeof(so->depth_offset) >=
10401e04c3fSmrg                      cl_packet_length(DEPTH_OFFSET));
10501e04c3fSmrg        v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) {
10601e04c3fSmrg                depth.depth_offset_factor = cso->offset_scale;
10701e04c3fSmrg                depth.depth_offset_units = cso->offset_units;
10801e04c3fSmrg        }
10901e04c3fSmrg
11001e04c3fSmrg        /* The HW treats polygon offset units based on a Z24 buffer, so we
11101e04c3fSmrg         * need to scale up offset_units if we're only Z16.
11201e04c3fSmrg         */
11301e04c3fSmrg        v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) {
11401e04c3fSmrg                depth.depth_offset_factor = cso->offset_scale;
11501e04c3fSmrg                depth.depth_offset_units = cso->offset_units * 256.0;
11601e04c3fSmrg        }
11701e04c3fSmrg
11801e04c3fSmrg        return so;
11901e04c3fSmrg}
12001e04c3fSmrg
12101e04c3fSmrg/* Blend state is baked into shaders. */
12201e04c3fSmrgstatic void *
12301e04c3fSmrgv3d_create_blend_state(struct pipe_context *pctx,
12401e04c3fSmrg                       const struct pipe_blend_state *cso)
12501e04c3fSmrg{
12601e04c3fSmrg        struct v3d_blend_state *so;
12701e04c3fSmrg
12801e04c3fSmrg        so = CALLOC_STRUCT(v3d_blend_state);
12901e04c3fSmrg        if (!so)
13001e04c3fSmrg                return NULL;
13101e04c3fSmrg
13201e04c3fSmrg        so->base = *cso;
13301e04c3fSmrg
13401e04c3fSmrg        if (cso->independent_blend_enable) {
1359f464c52Smaya                for (int i = 0; i < V3D_MAX_DRAW_BUFFERS; i++) {
13601e04c3fSmrg                        so->blend_enables |= cso->rt[i].blend_enable << i;
13701e04c3fSmrg
13801e04c3fSmrg                        /* V3D 4.x is when we got independent blend enables. */
13901e04c3fSmrg                        assert(V3D_VERSION >= 40 ||
14001e04c3fSmrg                               cso->rt[i].blend_enable == cso->rt[0].blend_enable);
14101e04c3fSmrg                }
14201e04c3fSmrg        } else {
14301e04c3fSmrg                if (cso->rt[0].blend_enable)
1449f464c52Smaya                        so->blend_enables = (1 << V3D_MAX_DRAW_BUFFERS) - 1;
14501e04c3fSmrg        }
14601e04c3fSmrg
14701e04c3fSmrg        return so;
14801e04c3fSmrg}
14901e04c3fSmrg
15001e04c3fSmrgstatic uint32_t
15101e04c3fSmrgtranslate_stencil_op(enum pipe_stencil_op op)
15201e04c3fSmrg{
15301e04c3fSmrg        switch (op) {
15401e04c3fSmrg        case PIPE_STENCIL_OP_KEEP:      return V3D_STENCIL_OP_KEEP;
15501e04c3fSmrg        case PIPE_STENCIL_OP_ZERO:      return V3D_STENCIL_OP_ZERO;
15601e04c3fSmrg        case PIPE_STENCIL_OP_REPLACE:   return V3D_STENCIL_OP_REPLACE;
15701e04c3fSmrg        case PIPE_STENCIL_OP_INCR:      return V3D_STENCIL_OP_INCR;
15801e04c3fSmrg        case PIPE_STENCIL_OP_DECR:      return V3D_STENCIL_OP_DECR;
15901e04c3fSmrg        case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP;
16001e04c3fSmrg        case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP;
16101e04c3fSmrg        case PIPE_STENCIL_OP_INVERT:    return V3D_STENCIL_OP_INVERT;
16201e04c3fSmrg        }
16301e04c3fSmrg        unreachable("bad stencil op");
16401e04c3fSmrg}
16501e04c3fSmrg
16601e04c3fSmrgstatic void *
16701e04c3fSmrgv3d_create_depth_stencil_alpha_state(struct pipe_context *pctx,
16801e04c3fSmrg                                     const struct pipe_depth_stencil_alpha_state *cso)
16901e04c3fSmrg{
17001e04c3fSmrg        struct v3d_depth_stencil_alpha_state *so;
17101e04c3fSmrg
17201e04c3fSmrg        so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state);
17301e04c3fSmrg        if (!so)
17401e04c3fSmrg                return NULL;
17501e04c3fSmrg
17601e04c3fSmrg        so->base = *cso;
17701e04c3fSmrg
1787ec681f3Smrg        if (cso->depth_enabled) {
1797ec681f3Smrg                switch (cso->depth_func) {
18001e04c3fSmrg                case PIPE_FUNC_LESS:
18101e04c3fSmrg                case PIPE_FUNC_LEQUAL:
1827ec681f3Smrg                        so->ez_state = V3D_EZ_LT_LE;
18301e04c3fSmrg                        break;
18401e04c3fSmrg                case PIPE_FUNC_GREATER:
18501e04c3fSmrg                case PIPE_FUNC_GEQUAL:
1867ec681f3Smrg                        so->ez_state = V3D_EZ_GT_GE;
18701e04c3fSmrg                        break;
18801e04c3fSmrg                case PIPE_FUNC_NEVER:
18901e04c3fSmrg                case PIPE_FUNC_EQUAL:
1907ec681f3Smrg                        so->ez_state = V3D_EZ_UNDECIDED;
19101e04c3fSmrg                        break;
19201e04c3fSmrg                default:
1937ec681f3Smrg                        so->ez_state = V3D_EZ_DISABLED;
19401e04c3fSmrg                        break;
19501e04c3fSmrg                }
19601e04c3fSmrg
19701e04c3fSmrg                /* If stencil is enabled and it's not a no-op, then it would
19801e04c3fSmrg                 * break EZ updates.
19901e04c3fSmrg                 */
20001e04c3fSmrg                if (cso->stencil[0].enabled &&
20101e04c3fSmrg                    (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
20201e04c3fSmrg                     cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
20301e04c3fSmrg                     (cso->stencil[1].enabled &&
20401e04c3fSmrg                      (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
20501e04c3fSmrg                       cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
2067ec681f3Smrg                        so->ez_state = V3D_EZ_DISABLED;
20701e04c3fSmrg                }
20801e04c3fSmrg        }
20901e04c3fSmrg
21001e04c3fSmrg        const struct pipe_stencil_state *front = &cso->stencil[0];
21101e04c3fSmrg        const struct pipe_stencil_state *back = &cso->stencil[1];
21201e04c3fSmrg
21301e04c3fSmrg        if (front->enabled) {
21401e04c3fSmrg                STATIC_ASSERT(sizeof(so->stencil_front) >=
21501e04c3fSmrg                              cl_packet_length(STENCIL_CFG));
21601e04c3fSmrg                v3dx_pack(&so->stencil_front, STENCIL_CFG, config) {
21701e04c3fSmrg                        config.front_config = true;
21801e04c3fSmrg                        /* If !back->enabled, then the front values should be
21901e04c3fSmrg                         * used for both front and back-facing primitives.
22001e04c3fSmrg                         */
22101e04c3fSmrg                        config.back_config = !back->enabled;
22201e04c3fSmrg
22301e04c3fSmrg                        config.stencil_write_mask = front->writemask;
22401e04c3fSmrg                        config.stencil_test_mask = front->valuemask;
22501e04c3fSmrg
22601e04c3fSmrg                        config.stencil_test_function = front->func;
22701e04c3fSmrg                        config.stencil_pass_op =
22801e04c3fSmrg                                translate_stencil_op(front->zpass_op);
22901e04c3fSmrg                        config.depth_test_fail_op =
23001e04c3fSmrg                                translate_stencil_op(front->zfail_op);
23101e04c3fSmrg                        config.stencil_test_fail_op =
23201e04c3fSmrg                                translate_stencil_op(front->fail_op);
23301e04c3fSmrg                }
23401e04c3fSmrg        }
23501e04c3fSmrg        if (back->enabled) {
23601e04c3fSmrg                STATIC_ASSERT(sizeof(so->stencil_back) >=
23701e04c3fSmrg                              cl_packet_length(STENCIL_CFG));
23801e04c3fSmrg                v3dx_pack(&so->stencil_back, STENCIL_CFG, config) {
23901e04c3fSmrg                        config.front_config = false;
24001e04c3fSmrg                        config.back_config = true;
24101e04c3fSmrg
24201e04c3fSmrg                        config.stencil_write_mask = back->writemask;
24301e04c3fSmrg                        config.stencil_test_mask = back->valuemask;
24401e04c3fSmrg
24501e04c3fSmrg                        config.stencil_test_function = back->func;
24601e04c3fSmrg                        config.stencil_pass_op =
24701e04c3fSmrg                                translate_stencil_op(back->zpass_op);
24801e04c3fSmrg                        config.depth_test_fail_op =
24901e04c3fSmrg                                translate_stencil_op(back->zfail_op);
25001e04c3fSmrg                        config.stencil_test_fail_op =
25101e04c3fSmrg                                translate_stencil_op(back->fail_op);
25201e04c3fSmrg                }
25301e04c3fSmrg        }
25401e04c3fSmrg
25501e04c3fSmrg        return so;
25601e04c3fSmrg}
25701e04c3fSmrg
25801e04c3fSmrgstatic void
25901e04c3fSmrgv3d_set_polygon_stipple(struct pipe_context *pctx,
26001e04c3fSmrg                        const struct pipe_poly_stipple *stipple)
26101e04c3fSmrg{
26201e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
26301e04c3fSmrg        v3d->stipple = *stipple;
2647ec681f3Smrg        v3d->dirty |= V3D_DIRTY_STIPPLE;
26501e04c3fSmrg}
26601e04c3fSmrg
26701e04c3fSmrgstatic void
26801e04c3fSmrgv3d_set_scissor_states(struct pipe_context *pctx,
26901e04c3fSmrg                       unsigned start_slot,
27001e04c3fSmrg                       unsigned num_scissors,
27101e04c3fSmrg                       const struct pipe_scissor_state *scissor)
27201e04c3fSmrg{
27301e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
27401e04c3fSmrg
27501e04c3fSmrg        v3d->scissor = *scissor;
2767ec681f3Smrg        v3d->dirty |= V3D_DIRTY_SCISSOR;
27701e04c3fSmrg}
27801e04c3fSmrg
27901e04c3fSmrgstatic void
28001e04c3fSmrgv3d_set_viewport_states(struct pipe_context *pctx,
28101e04c3fSmrg                        unsigned start_slot,
28201e04c3fSmrg                        unsigned num_viewports,
28301e04c3fSmrg                        const struct pipe_viewport_state *viewport)
28401e04c3fSmrg{
28501e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
28601e04c3fSmrg        v3d->viewport = *viewport;
2877ec681f3Smrg        v3d->dirty |= V3D_DIRTY_VIEWPORT;
28801e04c3fSmrg}
28901e04c3fSmrg
29001e04c3fSmrgstatic void
29101e04c3fSmrgv3d_set_vertex_buffers(struct pipe_context *pctx,
29201e04c3fSmrg                       unsigned start_slot, unsigned count,
2937ec681f3Smrg                       unsigned unbind_num_trailing_slots,
2947ec681f3Smrg                       bool take_ownership,
29501e04c3fSmrg                       const struct pipe_vertex_buffer *vb)
29601e04c3fSmrg{
29701e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
29801e04c3fSmrg        struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf;
29901e04c3fSmrg
30001e04c3fSmrg        util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
3017ec681f3Smrg                                     start_slot, count,
3027ec681f3Smrg                                     unbind_num_trailing_slots,
3037ec681f3Smrg                                     take_ownership);
30401e04c3fSmrg        so->count = util_last_bit(so->enabled_mask);
30501e04c3fSmrg
3067ec681f3Smrg        v3d->dirty |= V3D_DIRTY_VTXBUF;
30701e04c3fSmrg}
30801e04c3fSmrg
30901e04c3fSmrgstatic void
31001e04c3fSmrgv3d_blend_state_bind(struct pipe_context *pctx, void *hwcso)
31101e04c3fSmrg{
31201e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
31301e04c3fSmrg        v3d->blend = hwcso;
3147ec681f3Smrg        v3d->dirty |= V3D_DIRTY_BLEND;
31501e04c3fSmrg}
31601e04c3fSmrg
31701e04c3fSmrgstatic void
31801e04c3fSmrgv3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
31901e04c3fSmrg{
32001e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
32101e04c3fSmrg        v3d->rasterizer = hwcso;
3227ec681f3Smrg        v3d->dirty |= V3D_DIRTY_RASTERIZER;
32301e04c3fSmrg}
32401e04c3fSmrg
32501e04c3fSmrgstatic void
32601e04c3fSmrgv3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
32701e04c3fSmrg{
32801e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
32901e04c3fSmrg        v3d->zsa = hwcso;
3307ec681f3Smrg        v3d->dirty |= V3D_DIRTY_ZSA;
33101e04c3fSmrg}
33201e04c3fSmrg
33301e04c3fSmrgstatic void *
33401e04c3fSmrgv3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
33501e04c3fSmrg                        const struct pipe_vertex_element *elements)
33601e04c3fSmrg{
33701e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
33801e04c3fSmrg        struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj);
33901e04c3fSmrg
34001e04c3fSmrg        if (!so)
34101e04c3fSmrg                return NULL;
34201e04c3fSmrg
34301e04c3fSmrg        memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
34401e04c3fSmrg        so->num_elements = num_elements;
34501e04c3fSmrg
34601e04c3fSmrg        for (int i = 0; i < so->num_elements; i++) {
34701e04c3fSmrg                const struct pipe_vertex_element *elem = &elements[i];
34801e04c3fSmrg                const struct util_format_description *desc =
34901e04c3fSmrg                        util_format_description(elem->src_format);
35001e04c3fSmrg                uint32_t r_size = desc->channel[0].size;
35101e04c3fSmrg
35201e04c3fSmrg                const uint32_t size =
35301e04c3fSmrg                        cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
35401e04c3fSmrg
35501e04c3fSmrg                v3dx_pack(&so->attrs[i * size],
35601e04c3fSmrg                          GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
35701e04c3fSmrg                        /* vec_size == 0 means 4 */
35801e04c3fSmrg                        attr.vec_size = desc->nr_channels & 3;
35901e04c3fSmrg                        attr.signed_int_type = (desc->channel[0].type ==
36001e04c3fSmrg                                                UTIL_FORMAT_TYPE_SIGNED);
36101e04c3fSmrg
36201e04c3fSmrg                        attr.normalized_int_type = desc->channel[0].normalized;
36301e04c3fSmrg                        attr.read_as_int_uint = desc->channel[0].pure_integer;
36401e04c3fSmrg                        attr.instance_divisor = MIN2(elem->instance_divisor,
36501e04c3fSmrg                                                     0xffff);
36601e04c3fSmrg
36701e04c3fSmrg                        switch (desc->channel[0].type) {
36801e04c3fSmrg                        case UTIL_FORMAT_TYPE_FLOAT:
36901e04c3fSmrg                                if (r_size == 32) {
37001e04c3fSmrg                                        attr.type = ATTRIBUTE_FLOAT;
37101e04c3fSmrg                                } else {
37201e04c3fSmrg                                        assert(r_size == 16);
37301e04c3fSmrg                                        attr.type = ATTRIBUTE_HALF_FLOAT;
37401e04c3fSmrg                                }
37501e04c3fSmrg                                break;
37601e04c3fSmrg
37701e04c3fSmrg                        case UTIL_FORMAT_TYPE_SIGNED:
37801e04c3fSmrg                        case UTIL_FORMAT_TYPE_UNSIGNED:
37901e04c3fSmrg                                switch (r_size) {
38001e04c3fSmrg                                case 32:
38101e04c3fSmrg                                        attr.type = ATTRIBUTE_INT;
38201e04c3fSmrg                                        break;
38301e04c3fSmrg                                case 16:
38401e04c3fSmrg                                        attr.type = ATTRIBUTE_SHORT;
38501e04c3fSmrg                                        break;
38601e04c3fSmrg                                case 10:
38701e04c3fSmrg                                        attr.type = ATTRIBUTE_INT2_10_10_10;
38801e04c3fSmrg                                        break;
38901e04c3fSmrg                                case 8:
39001e04c3fSmrg                                        attr.type = ATTRIBUTE_BYTE;
39101e04c3fSmrg                                        break;
39201e04c3fSmrg                                default:
39301e04c3fSmrg                                        fprintf(stderr,
39401e04c3fSmrg                                                "format %s unsupported\n",
39501e04c3fSmrg                                                desc->name);
39601e04c3fSmrg                                        attr.type = ATTRIBUTE_BYTE;
39701e04c3fSmrg                                        abort();
39801e04c3fSmrg                                }
39901e04c3fSmrg                                break;
40001e04c3fSmrg
40101e04c3fSmrg                        default:
40201e04c3fSmrg                                fprintf(stderr,
40301e04c3fSmrg                                        "format %s unsupported\n",
40401e04c3fSmrg                                        desc->name);
40501e04c3fSmrg                                abort();
40601e04c3fSmrg                        }
40701e04c3fSmrg                }
40801e04c3fSmrg        }
40901e04c3fSmrg
41001e04c3fSmrg        /* Set up the default attribute values in case any of the vertex
41101e04c3fSmrg         * elements use them.
41201e04c3fSmrg         */
4139f464c52Smaya        uint32_t *attrs;
4149f464c52Smaya        u_upload_alloc(v3d->state_uploader, 0,
4159f464c52Smaya                       V3D_MAX_VS_INPUTS * sizeof(float), 16,
4169f464c52Smaya                       &so->defaults_offset, &so->defaults, (void **)&attrs);
4179f464c52Smaya
4189f464c52Smaya        for (int i = 0; i < V3D_MAX_VS_INPUTS / 4; i++) {
41901e04c3fSmrg                attrs[i * 4 + 0] = 0;
42001e04c3fSmrg                attrs[i * 4 + 1] = 0;
42101e04c3fSmrg                attrs[i * 4 + 2] = 0;
42201e04c3fSmrg                if (i < so->num_elements &&
42301e04c3fSmrg                    util_format_is_pure_integer(so->pipe[i].src_format)) {
42401e04c3fSmrg                        attrs[i * 4 + 3] = 1;
42501e04c3fSmrg                } else {
42601e04c3fSmrg                        attrs[i * 4 + 3] = fui(1.0);
42701e04c3fSmrg                }
42801e04c3fSmrg        }
42901e04c3fSmrg
4309f464c52Smaya        u_upload_unmap(v3d->state_uploader);
43101e04c3fSmrg        return so;
43201e04c3fSmrg}
43301e04c3fSmrg
43401e04c3fSmrgstatic void
43501e04c3fSmrgv3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
43601e04c3fSmrg{
43701e04c3fSmrg        struct v3d_vertex_stateobj *so = hwcso;
43801e04c3fSmrg
4399f464c52Smaya        pipe_resource_reference(&so->defaults, NULL);
44001e04c3fSmrg        free(so);
44101e04c3fSmrg}
44201e04c3fSmrg
44301e04c3fSmrgstatic void
44401e04c3fSmrgv3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
44501e04c3fSmrg{
44601e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
44701e04c3fSmrg        v3d->vtx = hwcso;
4487ec681f3Smrg        v3d->dirty |= V3D_DIRTY_VTXSTATE;
44901e04c3fSmrg}
45001e04c3fSmrg
45101e04c3fSmrgstatic void
45201e04c3fSmrgv3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
4537ec681f3Smrg                        bool take_ownership,
45401e04c3fSmrg                        const struct pipe_constant_buffer *cb)
45501e04c3fSmrg{
45601e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
45701e04c3fSmrg        struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader];
45801e04c3fSmrg
4597ec681f3Smrg        util_copy_constant_buffer(&so->cb[index], cb, take_ownership);
46001e04c3fSmrg
4617ec681f3Smrg        /* Note that the gallium frontend can unbind constant buffers by
46201e04c3fSmrg         * passing NULL here.
46301e04c3fSmrg         */
46401e04c3fSmrg        if (unlikely(!cb)) {
46501e04c3fSmrg                so->enabled_mask &= ~(1 << index);
46601e04c3fSmrg                so->dirty_mask &= ~(1 << index);
46701e04c3fSmrg                return;
46801e04c3fSmrg        }
46901e04c3fSmrg
47001e04c3fSmrg        so->enabled_mask |= 1 << index;
47101e04c3fSmrg        so->dirty_mask |= 1 << index;
4727ec681f3Smrg        v3d->dirty |= V3D_DIRTY_CONSTBUF;
47301e04c3fSmrg}
47401e04c3fSmrg
47501e04c3fSmrgstatic void
47601e04c3fSmrgv3d_set_framebuffer_state(struct pipe_context *pctx,
47701e04c3fSmrg                          const struct pipe_framebuffer_state *framebuffer)
47801e04c3fSmrg{
47901e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
48001e04c3fSmrg        struct pipe_framebuffer_state *cso = &v3d->framebuffer;
48101e04c3fSmrg
48201e04c3fSmrg        v3d->job = NULL;
48301e04c3fSmrg
48401e04c3fSmrg        util_copy_framebuffer_state(cso, framebuffer);
48501e04c3fSmrg
48601e04c3fSmrg        v3d->swap_color_rb = 0;
48701e04c3fSmrg        v3d->blend_dst_alpha_one = 0;
48801e04c3fSmrg        for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
48901e04c3fSmrg                struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
49001e04c3fSmrg                if (!cbuf)
49101e04c3fSmrg                        continue;
4929f464c52Smaya                struct v3d_surface *v3d_cbuf = v3d_surface(cbuf);
49301e04c3fSmrg
49401e04c3fSmrg                const struct util_format_description *desc =
49501e04c3fSmrg                        util_format_description(cbuf->format);
49601e04c3fSmrg
49701e04c3fSmrg                /* For BGRA8 formats (DRI window system default format), we
4989f464c52Smaya                 * need to swap R and B, since the HW's format is RGBA8.  On
4999f464c52Smaya                 * V3D 4.1+, the RCL can swap R and B on load/store.
50001e04c3fSmrg                 */
5019f464c52Smaya                if (v3d->screen->devinfo.ver < 41 && v3d_cbuf->swap_rb)
50201e04c3fSmrg                        v3d->swap_color_rb |= 1 << i;
50301e04c3fSmrg
50401e04c3fSmrg                if (desc->swizzle[3] == PIPE_SWIZZLE_1)
50501e04c3fSmrg                        v3d->blend_dst_alpha_one |= 1 << i;
50601e04c3fSmrg        }
50701e04c3fSmrg
5087ec681f3Smrg        v3d->dirty |= V3D_DIRTY_FRAMEBUFFER;
50901e04c3fSmrg}
51001e04c3fSmrg
5119f464c52Smayastatic enum V3DX(Wrap_Mode)
5127ec681f3Smrgtranslate_wrap(uint32_t pipe_wrap)
51301e04c3fSmrg{
51401e04c3fSmrg        switch (pipe_wrap) {
51501e04c3fSmrg        case PIPE_TEX_WRAP_REPEAT:
5169f464c52Smaya                return V3D_WRAP_MODE_REPEAT;
51701e04c3fSmrg        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
5189f464c52Smaya                return V3D_WRAP_MODE_CLAMP;
51901e04c3fSmrg        case PIPE_TEX_WRAP_MIRROR_REPEAT:
5209f464c52Smaya                return V3D_WRAP_MODE_MIRROR;
52101e04c3fSmrg        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
5229f464c52Smaya                return V3D_WRAP_MODE_BORDER;
5237ec681f3Smrg        case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
5247ec681f3Smrg                return V3D_WRAP_MODE_MIRROR_ONCE;
52501e04c3fSmrg        default:
52601e04c3fSmrg                unreachable("Unknown wrap mode");
52701e04c3fSmrg        }
52801e04c3fSmrg}
52901e04c3fSmrg
53001e04c3fSmrg#if V3D_VERSION >= 40
5319f464c52Smayastatic void
5329f464c52Smayav3d_upload_sampler_state_variant(void *map,
5339f464c52Smaya                                 const struct pipe_sampler_state *cso,
5347ec681f3Smrg                                 enum v3d_sampler_state_variant variant)
5359f464c52Smaya{
53601e04c3fSmrg        v3dx_pack(map, SAMPLER_STATE, sampler) {
53701e04c3fSmrg                sampler.wrap_i_border = false;
53801e04c3fSmrg
5397ec681f3Smrg                sampler.wrap_s = translate_wrap(cso->wrap_s);
5407ec681f3Smrg                sampler.wrap_t = translate_wrap(cso->wrap_t);
5417ec681f3Smrg                sampler.wrap_r = translate_wrap(cso->wrap_r);
54201e04c3fSmrg
54301e04c3fSmrg                sampler.fixed_bias = cso->lod_bias;
54401e04c3fSmrg                sampler.depth_compare_function = cso->compare_func;
54501e04c3fSmrg
54601e04c3fSmrg                sampler.min_filter_nearest =
54701e04c3fSmrg                        cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
54801e04c3fSmrg                sampler.mag_filter_nearest =
54901e04c3fSmrg                        cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
55001e04c3fSmrg                sampler.mip_filter_nearest =
55101e04c3fSmrg                        cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR;
55201e04c3fSmrg
55301e04c3fSmrg                sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
55401e04c3fSmrg                                                   15);
5557ec681f3Smrg                sampler.max_level_of_detail = MIN2(MAX2(cso->max_lod,
5567ec681f3Smrg                                                        cso->min_lod), 15);
55701e04c3fSmrg
55801e04c3fSmrg                /* If we're not doing inter-miplevel filtering, we need to
55901e04c3fSmrg                 * clamp the LOD so that we only sample from baselevel.
56001e04c3fSmrg                 * However, we need to still allow the calculated LOD to be
56101e04c3fSmrg                 * fractionally over the baselevel, so that the HW can decide
56201e04c3fSmrg                 * between the min and mag filters.
56301e04c3fSmrg                 */
56401e04c3fSmrg                if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
56501e04c3fSmrg                        sampler.min_level_of_detail =
56601e04c3fSmrg                                MIN2(sampler.min_level_of_detail, 1.0 / 256.0);
56701e04c3fSmrg                        sampler.max_level_of_detail =
56801e04c3fSmrg                                MIN2(sampler.max_level_of_detail, 1.0 / 256.0);
56901e04c3fSmrg                }
57001e04c3fSmrg
57101e04c3fSmrg                if (cso->max_anisotropy) {
57201e04c3fSmrg                        sampler.anisotropy_enable = true;
57301e04c3fSmrg
57401e04c3fSmrg                        if (cso->max_anisotropy > 8)
57501e04c3fSmrg                                sampler.maximum_anisotropy = 3;
57601e04c3fSmrg                        else if (cso->max_anisotropy > 4)
57701e04c3fSmrg                                sampler.maximum_anisotropy = 2;
57801e04c3fSmrg                        else if (cso->max_anisotropy > 2)
57901e04c3fSmrg                                sampler.maximum_anisotropy = 1;
58001e04c3fSmrg                }
58101e04c3fSmrg
5829f464c52Smaya                if (variant == V3D_SAMPLER_STATE_BORDER_0) {
5839f464c52Smaya                        sampler.border_color_mode = V3D_BORDER_COLOR_0000;
5849f464c52Smaya                } else {
5859f464c52Smaya                        sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS;
5869f464c52Smaya
5879f464c52Smaya                        union pipe_color_union border;
5889f464c52Smaya
5899f464c52Smaya                        /* First, reswizzle the border color for any
5909f464c52Smaya                         * mismatching we're doing between the texture's
5919f464c52Smaya                         * channel order in hardware (R) versus what it is at
5929f464c52Smaya                         * the GL level (ALPHA)
5939f464c52Smaya                         */
5949f464c52Smaya                        switch (variant) {
5959f464c52Smaya                        case V3D_SAMPLER_STATE_F16_BGRA:
5969f464c52Smaya                        case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
5979f464c52Smaya                        case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
5989f464c52Smaya                                border.i[0] = cso->border_color.i[2];
5999f464c52Smaya                                border.i[1] = cso->border_color.i[1];
6009f464c52Smaya                                border.i[2] = cso->border_color.i[0];
6019f464c52Smaya                                border.i[3] = cso->border_color.i[3];
6029f464c52Smaya                                break;
6039f464c52Smaya
6049f464c52Smaya                        case V3D_SAMPLER_STATE_F16_A:
6059f464c52Smaya                        case V3D_SAMPLER_STATE_F16_A_UNORM:
6069f464c52Smaya                        case V3D_SAMPLER_STATE_F16_A_SNORM:
6079f464c52Smaya                        case V3D_SAMPLER_STATE_32_A:
6089f464c52Smaya                        case V3D_SAMPLER_STATE_32_A_UNORM:
6099f464c52Smaya                        case V3D_SAMPLER_STATE_32_A_SNORM:
6109f464c52Smaya                                border.i[0] = cso->border_color.i[3];
6119f464c52Smaya                                border.i[1] = 0;
6129f464c52Smaya                                border.i[2] = 0;
6139f464c52Smaya                                border.i[3] = 0;
6149f464c52Smaya                                break;
6159f464c52Smaya
6169f464c52Smaya                        case V3D_SAMPLER_STATE_F16_LA:
6179f464c52Smaya                        case V3D_SAMPLER_STATE_F16_LA_UNORM:
6189f464c52Smaya                        case V3D_SAMPLER_STATE_F16_LA_SNORM:
6199f464c52Smaya                                border.i[0] = cso->border_color.i[0];
6209f464c52Smaya                                border.i[1] = cso->border_color.i[3];
6219f464c52Smaya                                border.i[2] = 0;
6229f464c52Smaya                                border.i[3] = 0;
6239f464c52Smaya                                break;
6249f464c52Smaya
6259f464c52Smaya                        default:
6269f464c52Smaya                                border = cso->border_color;
6279f464c52Smaya                        }
6289f464c52Smaya
6299f464c52Smaya                        /* Perform any clamping. */
6309f464c52Smaya                        switch (variant) {
6319f464c52Smaya                        case V3D_SAMPLER_STATE_F16_UNORM:
6329f464c52Smaya                        case V3D_SAMPLER_STATE_F16_BGRA_UNORM:
6339f464c52Smaya                        case V3D_SAMPLER_STATE_F16_A_UNORM:
6349f464c52Smaya                        case V3D_SAMPLER_STATE_F16_LA_UNORM:
6359f464c52Smaya                        case V3D_SAMPLER_STATE_32_UNORM:
6369f464c52Smaya                        case V3D_SAMPLER_STATE_32_A_UNORM:
6379f464c52Smaya                                for (int i = 0; i < 4; i++)
6389f464c52Smaya                                        border.f[i] = CLAMP(border.f[i], 0, 1);
6399f464c52Smaya                                break;
6409f464c52Smaya
6419f464c52Smaya                        case V3D_SAMPLER_STATE_F16_SNORM:
6429f464c52Smaya                        case V3D_SAMPLER_STATE_F16_BGRA_SNORM:
6439f464c52Smaya                        case V3D_SAMPLER_STATE_F16_A_SNORM:
6449f464c52Smaya                        case V3D_SAMPLER_STATE_F16_LA_SNORM:
6459f464c52Smaya                        case V3D_SAMPLER_STATE_32_SNORM:
6469f464c52Smaya                        case V3D_SAMPLER_STATE_32_A_SNORM:
6479f464c52Smaya                                for (int i = 0; i < 4; i++)
6489f464c52Smaya                                        border.f[i] = CLAMP(border.f[i], -1, 1);
6499f464c52Smaya                                break;
6509f464c52Smaya
6519f464c52Smaya                        case V3D_SAMPLER_STATE_1010102U:
6529f464c52Smaya                                border.ui[0] = CLAMP(border.ui[0],
6539f464c52Smaya                                                     0, (1 << 10) - 1);
6549f464c52Smaya                                border.ui[1] = CLAMP(border.ui[1],
6559f464c52Smaya                                                     0, (1 << 10) - 1);
6569f464c52Smaya                                border.ui[2] = CLAMP(border.ui[2],
6579f464c52Smaya                                                     0, (1 << 10) - 1);
6589f464c52Smaya                                border.ui[3] = CLAMP(border.ui[3],
6599f464c52Smaya                                                     0, 3);
6609f464c52Smaya                                break;
6619f464c52Smaya
6629f464c52Smaya                        case V3D_SAMPLER_STATE_16U:
6639f464c52Smaya                                for (int i = 0; i < 4; i++)
6649f464c52Smaya                                        border.ui[i] = CLAMP(border.ui[i],
6659f464c52Smaya                                                             0, 0xffff);
6669f464c52Smaya                                break;
6679f464c52Smaya
6689f464c52Smaya                        case V3D_SAMPLER_STATE_16I:
6699f464c52Smaya                                for (int i = 0; i < 4; i++)
6709f464c52Smaya                                        border.i[i] = CLAMP(border.i[i],
6719f464c52Smaya                                                            -32768, 32767);
6729f464c52Smaya                                break;
6739f464c52Smaya
6749f464c52Smaya                        case V3D_SAMPLER_STATE_8U:
6759f464c52Smaya                                for (int i = 0; i < 4; i++)
6769f464c52Smaya                                        border.ui[i] = CLAMP(border.ui[i],
6779f464c52Smaya                                                             0, 0xff);
6789f464c52Smaya                                break;
6799f464c52Smaya
6809f464c52Smaya                        case V3D_SAMPLER_STATE_8I:
6819f464c52Smaya                                for (int i = 0; i < 4; i++)
6829f464c52Smaya                                        border.i[i] = CLAMP(border.i[i],
6839f464c52Smaya                                                            -128, 127);
6849f464c52Smaya                                break;
6859f464c52Smaya
6869f464c52Smaya                        default:
6879f464c52Smaya                                break;
6889f464c52Smaya                        }
6899f464c52Smaya
6909f464c52Smaya                        if (variant >= V3D_SAMPLER_STATE_32) {
6919f464c52Smaya                                sampler.border_color_word_0 = border.ui[0];
6929f464c52Smaya                                sampler.border_color_word_1 = border.ui[1];
6939f464c52Smaya                                sampler.border_color_word_2 = border.ui[2];
6949f464c52Smaya                                sampler.border_color_word_3 = border.ui[3];
6959f464c52Smaya                        } else {
6969f464c52Smaya                                sampler.border_color_word_0 =
6977ec681f3Smrg                                        _mesa_float_to_half(border.f[0]);
6989f464c52Smaya                                sampler.border_color_word_1 =
6997ec681f3Smrg                                        _mesa_float_to_half(border.f[1]);
7009f464c52Smaya                                sampler.border_color_word_2 =
7017ec681f3Smrg                                        _mesa_float_to_half(border.f[2]);
7029f464c52Smaya                                sampler.border_color_word_3 =
7037ec681f3Smrg                                        _mesa_float_to_half(border.f[3]);
7049f464c52Smaya                        }
7059f464c52Smaya                }
7069f464c52Smaya        }
7079f464c52Smaya}
7089f464c52Smaya#endif
7099f464c52Smaya
7109f464c52Smayastatic void *
7119f464c52Smayav3d_create_sampler_state(struct pipe_context *pctx,
7129f464c52Smaya                         const struct pipe_sampler_state *cso)
7139f464c52Smaya{
7147ec681f3Smrg        UNUSED struct v3d_context *v3d = v3d_context(pctx);
7159f464c52Smaya        struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state);
7169f464c52Smaya
7179f464c52Smaya        if (!so)
7189f464c52Smaya                return NULL;
7199f464c52Smaya
7209f464c52Smaya        memcpy(so, cso, sizeof(*cso));
7219f464c52Smaya
7227ec681f3Smrg        enum V3DX(Wrap_Mode) wrap_s = translate_wrap(cso->wrap_s);
7237ec681f3Smrg        enum V3DX(Wrap_Mode) wrap_t = translate_wrap(cso->wrap_t);
7247ec681f3Smrg        enum V3DX(Wrap_Mode) wrap_r = translate_wrap(cso->wrap_r);
7259f464c52Smaya
7269f464c52Smaya        bool uses_border_color = (wrap_s == V3D_WRAP_MODE_BORDER ||
7279f464c52Smaya                                  wrap_t == V3D_WRAP_MODE_BORDER ||
7289f464c52Smaya                                  wrap_r == V3D_WRAP_MODE_BORDER);
7299f464c52Smaya        so->border_color_variants = (uses_border_color &&
7309f464c52Smaya                                     (cso->border_color.ui[0] != 0 ||
7319f464c52Smaya                                      cso->border_color.ui[1] != 0 ||
7329f464c52Smaya                                      cso->border_color.ui[2] != 0 ||
7339f464c52Smaya                                      cso->border_color.ui[3] != 0));
7349f464c52Smaya
7359f464c52Smaya#if V3D_VERSION >= 40
7369f464c52Smaya        void *map;
7379f464c52Smaya        int sampler_align = so->border_color_variants ? 32 : 8;
7389f464c52Smaya        int sampler_size = align(cl_packet_length(SAMPLER_STATE), sampler_align);
7399f464c52Smaya        int num_variants = (so->border_color_variants ? ARRAY_SIZE(so->sampler_state_offset) : 1);
7409f464c52Smaya        u_upload_alloc(v3d->state_uploader, 0,
7419f464c52Smaya                       sampler_size * num_variants,
7429f464c52Smaya                       sampler_align,
7439f464c52Smaya                       &so->sampler_state_offset[0],
7449f464c52Smaya                       &so->sampler_state,
7459f464c52Smaya                       &map);
7469f464c52Smaya
7479f464c52Smaya        for (int i = 0; i < num_variants; i++) {
7489f464c52Smaya                so->sampler_state_offset[i] =
7499f464c52Smaya                        so->sampler_state_offset[0] + i * sampler_size;
7509f464c52Smaya                v3d_upload_sampler_state_variant(map + i * sampler_size,
7517ec681f3Smrg                                                 cso, i);
75201e04c3fSmrg        }
75301e04c3fSmrg
75401e04c3fSmrg#else /* V3D_VERSION < 40 */
75501e04c3fSmrg        v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) {
7569f464c52Smaya                p0.s_wrap_mode = wrap_s;
7579f464c52Smaya                p0.t_wrap_mode = wrap_t;
7589f464c52Smaya                p0.r_wrap_mode = wrap_r;
75901e04c3fSmrg        }
76001e04c3fSmrg
76101e04c3fSmrg        v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
76201e04c3fSmrg                tex.depth_compare_function = cso->compare_func;
76301e04c3fSmrg                tex.fixed_bias = cso->lod_bias;
76401e04c3fSmrg        }
76501e04c3fSmrg#endif /* V3D_VERSION < 40 */
76601e04c3fSmrg        return so;
76701e04c3fSmrg}
76801e04c3fSmrg
76901e04c3fSmrgstatic void
77001e04c3fSmrgv3d_sampler_states_bind(struct pipe_context *pctx,
77101e04c3fSmrg                        enum pipe_shader_type shader, unsigned start,
77201e04c3fSmrg                        unsigned nr, void **hwcso)
77301e04c3fSmrg{
77401e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
7759f464c52Smaya        struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
77601e04c3fSmrg
77701e04c3fSmrg        assert(start == 0);
77801e04c3fSmrg        unsigned i;
77901e04c3fSmrg        unsigned new_nr = 0;
78001e04c3fSmrg
78101e04c3fSmrg        for (i = 0; i < nr; i++) {
78201e04c3fSmrg                if (hwcso[i])
78301e04c3fSmrg                        new_nr = i + 1;
78401e04c3fSmrg                stage_tex->samplers[i] = hwcso[i];
78501e04c3fSmrg        }
78601e04c3fSmrg
78701e04c3fSmrg        for (; i < stage_tex->num_samplers; i++) {
78801e04c3fSmrg                stage_tex->samplers[i] = NULL;
78901e04c3fSmrg        }
79001e04c3fSmrg
79101e04c3fSmrg        stage_tex->num_samplers = new_nr;
7927ec681f3Smrg
7937ec681f3Smrg        v3d_flag_dirty_sampler_state(v3d, shader);
79401e04c3fSmrg}
79501e04c3fSmrg
79601e04c3fSmrgstatic void
79701e04c3fSmrgv3d_sampler_state_delete(struct pipe_context *pctx,
79801e04c3fSmrg                         void *hwcso)
79901e04c3fSmrg{
80001e04c3fSmrg        struct pipe_sampler_state *psampler = hwcso;
80101e04c3fSmrg        struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
80201e04c3fSmrg
8039f464c52Smaya        pipe_resource_reference(&sampler->sampler_state, NULL);
80401e04c3fSmrg        free(psampler);
80501e04c3fSmrg}
80601e04c3fSmrg
80701e04c3fSmrg#if V3D_VERSION >= 40
80801e04c3fSmrgstatic uint32_t
80901e04c3fSmrgtranslate_swizzle(unsigned char pipe_swizzle)
81001e04c3fSmrg{
81101e04c3fSmrg        switch (pipe_swizzle) {
81201e04c3fSmrg        case PIPE_SWIZZLE_0:
81301e04c3fSmrg                return 0;
81401e04c3fSmrg        case PIPE_SWIZZLE_1:
81501e04c3fSmrg                return 1;
81601e04c3fSmrg        case PIPE_SWIZZLE_X:
81701e04c3fSmrg        case PIPE_SWIZZLE_Y:
81801e04c3fSmrg        case PIPE_SWIZZLE_Z:
81901e04c3fSmrg        case PIPE_SWIZZLE_W:
82001e04c3fSmrg                return 2 + pipe_swizzle;
82101e04c3fSmrg        default:
82201e04c3fSmrg                unreachable("unknown swizzle");
82301e04c3fSmrg        }
82401e04c3fSmrg}
82501e04c3fSmrg#endif
82601e04c3fSmrg
8279f464c52Smayastatic void
8289f464c52Smayav3d_setup_texture_shader_state(struct V3DX(TEXTURE_SHADER_STATE) *tex,
8299f464c52Smaya                               struct pipe_resource *prsc,
8309f464c52Smaya                               int base_level, int last_level,
8319f464c52Smaya                               int first_layer, int last_layer)
8329f464c52Smaya{
8339f464c52Smaya        struct v3d_resource *rsc = v3d_resource(prsc);
8349f464c52Smaya        int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
8359f464c52Smaya
8369f464c52Smaya        tex->image_width = prsc->width0 * msaa_scale;
8379f464c52Smaya        tex->image_height = prsc->height0 * msaa_scale;
8389f464c52Smaya
8399f464c52Smaya#if V3D_VERSION >= 40
8409f464c52Smaya        /* On 4.x, the height of a 1D texture is redefined to be the
8419f464c52Smaya         * upper 14 bits of the width (which is only usable with txf).
8429f464c52Smaya         */
8439f464c52Smaya        if (prsc->target == PIPE_TEXTURE_1D ||
8449f464c52Smaya            prsc->target == PIPE_TEXTURE_1D_ARRAY) {
8459f464c52Smaya                tex->image_height = tex->image_width >> 14;
8469f464c52Smaya        }
8479f464c52Smaya
8489f464c52Smaya        tex->image_width &= (1 << 14) - 1;
8499f464c52Smaya        tex->image_height &= (1 << 14) - 1;
8509f464c52Smaya#endif
8519f464c52Smaya
8529f464c52Smaya        if (prsc->target == PIPE_TEXTURE_3D) {
8539f464c52Smaya                tex->image_depth = prsc->depth0;
8549f464c52Smaya        } else {
8559f464c52Smaya                tex->image_depth = (last_layer - first_layer) + 1;
8569f464c52Smaya        }
8579f464c52Smaya
8589f464c52Smaya        tex->base_level = base_level;
8599f464c52Smaya#if V3D_VERSION >= 40
8609f464c52Smaya        tex->max_level = last_level;
8619f464c52Smaya        /* Note that we don't have a job to reference the texture's sBO
8629f464c52Smaya         * at state create time, so any time this sampler view is used
8639f464c52Smaya         * we need to add the texture to the job.
8649f464c52Smaya         */
8659f464c52Smaya        tex->texture_base_pointer =
8669f464c52Smaya                cl_address(NULL,
8679f464c52Smaya                           rsc->bo->offset +
8689f464c52Smaya                           v3d_layer_offset(prsc, 0, first_layer));
8699f464c52Smaya#endif
8709f464c52Smaya        tex->array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
8719f464c52Smaya
8729f464c52Smaya        /* Since other platform devices may produce UIF images even
8739f464c52Smaya         * when they're not big enough for V3D to assume they're UIF,
8749f464c52Smaya         * we force images with level 0 as UIF to be always treated
8759f464c52Smaya         * that way.
8769f464c52Smaya         */
8779f464c52Smaya        tex->level_0_is_strictly_uif =
8787ec681f3Smrg                (rsc->slices[0].tiling == V3D_TILING_UIF_XOR ||
8797ec681f3Smrg                 rsc->slices[0].tiling == V3D_TILING_UIF_NO_XOR);
8807ec681f3Smrg        tex->level_0_xor_enable = (rsc->slices[0].tiling == V3D_TILING_UIF_XOR);
8819f464c52Smaya
8829f464c52Smaya        if (tex->level_0_is_strictly_uif)
8839f464c52Smaya                tex->level_0_ub_pad = rsc->slices[0].ub_pad;
8849f464c52Smaya
8859f464c52Smaya#if V3D_VERSION >= 40
8869f464c52Smaya        if (tex->uif_xor_disable ||
8879f464c52Smaya            tex->level_0_is_strictly_uif) {
8889f464c52Smaya                tex->extended = true;
8899f464c52Smaya        }
8909f464c52Smaya#endif /* V3D_VERSION >= 40 */
8919f464c52Smaya}
8929f464c52Smaya
8937ec681f3Smrgvoid
8947ec681f3Smrgv3dX(create_texture_shader_state_bo)(struct v3d_context *v3d,
8957ec681f3Smrg                                     struct v3d_sampler_view *so)
8967ec681f3Smrg{
8977ec681f3Smrg        struct pipe_resource *prsc = so->texture;
8987ec681f3Smrg        const struct pipe_sampler_view *cso = &so->base;
8997ec681f3Smrg        struct v3d_screen *screen = v3d->screen;
9007ec681f3Smrg
9017ec681f3Smrg        void *map;
9027ec681f3Smrg
9037ec681f3Smrg#if V3D_VERSION >= 40
9047ec681f3Smrg        v3d_bo_unreference(&so->bo);
9057ec681f3Smrg        so->bo = v3d_bo_alloc(v3d->screen,
9067ec681f3Smrg                              cl_packet_length(TEXTURE_SHADER_STATE), "sampler");
9077ec681f3Smrg        map = v3d_bo_map(so->bo);
9087ec681f3Smrg#else /* V3D_VERSION < 40 */
9097ec681f3Smrg        STATIC_ASSERT(sizeof(so->texture_shader_state) >=
9107ec681f3Smrg                      cl_packet_length(TEXTURE_SHADER_STATE));
9117ec681f3Smrg        map = &so->texture_shader_state;
9127ec681f3Smrg#endif
9137ec681f3Smrg
9147ec681f3Smrg        v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
9157ec681f3Smrg                v3d_setup_texture_shader_state(&tex, prsc,
9167ec681f3Smrg                                               cso->u.tex.first_level,
9177ec681f3Smrg                                               cso->u.tex.last_level,
9187ec681f3Smrg                                               cso->u.tex.first_layer,
9197ec681f3Smrg                                               cso->u.tex.last_layer);
9207ec681f3Smrg
9217ec681f3Smrg                tex.srgb = util_format_is_srgb(cso->format);
9227ec681f3Smrg
9237ec681f3Smrg#if V3D_VERSION >= 40
9247ec681f3Smrg                tex.swizzle_r = translate_swizzle(so->swizzle[0]);
9257ec681f3Smrg                tex.swizzle_g = translate_swizzle(so->swizzle[1]);
9267ec681f3Smrg                tex.swizzle_b = translate_swizzle(so->swizzle[2]);
9277ec681f3Smrg                tex.swizzle_a = translate_swizzle(so->swizzle[3]);
9287ec681f3Smrg#endif
9297ec681f3Smrg
9307ec681f3Smrg                if (prsc->nr_samples > 1 && V3D_VERSION < 40) {
9317ec681f3Smrg                        /* Using texture views to reinterpret formats on our
9327ec681f3Smrg                         * MSAA textures won't work, because we don't lay out
9337ec681f3Smrg                         * the bits in memory as it's expected -- for example,
9347ec681f3Smrg                         * RGBA8 and RGB10_A2 are compatible in the
9357ec681f3Smrg                         * ARB_texture_view spec, but in HW we lay them out as
9367ec681f3Smrg                         * 32bpp RGBA8 and 64bpp RGBA16F.  Just assert for now
9377ec681f3Smrg                         * to catch failures.
9387ec681f3Smrg                         *
9397ec681f3Smrg                         * We explicitly allow remapping S8Z24 to RGBA8888 for
9407ec681f3Smrg                         * v3d_blit.c's stencil blits.
9417ec681f3Smrg                         */
9427ec681f3Smrg                        assert((util_format_linear(cso->format) ==
9437ec681f3Smrg                                util_format_linear(prsc->format)) ||
9447ec681f3Smrg                               (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
9457ec681f3Smrg                                cso->format == PIPE_FORMAT_R8G8B8A8_UNORM));
9467ec681f3Smrg                        uint32_t output_image_format =
9477ec681f3Smrg                                v3d_get_rt_format(&screen->devinfo, cso->format);
9487ec681f3Smrg                        uint32_t internal_type;
9497ec681f3Smrg                        uint32_t internal_bpp;
9507ec681f3Smrg                        v3d_get_internal_type_bpp_for_output_format(&screen->devinfo,
9517ec681f3Smrg                                                                    output_image_format,
9527ec681f3Smrg                                                                    &internal_type,
9537ec681f3Smrg                                                                    &internal_bpp);
9547ec681f3Smrg
9557ec681f3Smrg                        switch (internal_type) {
9567ec681f3Smrg                        case V3D_INTERNAL_TYPE_8:
9577ec681f3Smrg                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
9587ec681f3Smrg                                break;
9597ec681f3Smrg                        case V3D_INTERNAL_TYPE_16F:
9607ec681f3Smrg                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
9617ec681f3Smrg                                break;
9627ec681f3Smrg                        default:
9637ec681f3Smrg                                unreachable("Bad MSAA texture type");
9647ec681f3Smrg                        }
9657ec681f3Smrg
9667ec681f3Smrg                        /* sRGB was stored in the tile buffer as linear and
9677ec681f3Smrg                         * would have been encoded to sRGB on resolved tile
9687ec681f3Smrg                         * buffer store.  Note that this means we would need
9697ec681f3Smrg                         * shader code if we wanted to read an MSAA sRGB
9707ec681f3Smrg                         * texture without sRGB decode.
9717ec681f3Smrg                         */
9727ec681f3Smrg                        tex.srgb = false;
9737ec681f3Smrg                } else {
9747ec681f3Smrg                        tex.texture_type = v3d_get_tex_format(&screen->devinfo,
9757ec681f3Smrg                                                              cso->format);
9767ec681f3Smrg                }
9777ec681f3Smrg        };
9787ec681f3Smrg}
9797ec681f3Smrg
98001e04c3fSmrgstatic struct pipe_sampler_view *
98101e04c3fSmrgv3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
98201e04c3fSmrg                        const struct pipe_sampler_view *cso)
98301e04c3fSmrg{
98401e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
98501e04c3fSmrg        struct v3d_screen *screen = v3d->screen;
98601e04c3fSmrg        struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
98701e04c3fSmrg        struct v3d_resource *rsc = v3d_resource(prsc);
98801e04c3fSmrg
98901e04c3fSmrg        if (!so)
99001e04c3fSmrg                return NULL;
99101e04c3fSmrg
99201e04c3fSmrg        so->base = *cso;
99301e04c3fSmrg
99401e04c3fSmrg        pipe_reference(NULL, &prsc->reference);
99501e04c3fSmrg
99601e04c3fSmrg        /* Compute the sampler view's swizzle up front. This will be plugged
99701e04c3fSmrg         * into either the sampler (for 16-bit returns) or the shader's
99801e04c3fSmrg         * texture key (for 32)
99901e04c3fSmrg         */
100001e04c3fSmrg        uint8_t view_swizzle[4] = {
100101e04c3fSmrg                cso->swizzle_r,
100201e04c3fSmrg                cso->swizzle_g,
100301e04c3fSmrg                cso->swizzle_b,
100401e04c3fSmrg                cso->swizzle_a
100501e04c3fSmrg        };
100601e04c3fSmrg        const uint8_t *fmt_swizzle =
100701e04c3fSmrg                v3d_get_format_swizzle(&screen->devinfo, so->base.format);
100801e04c3fSmrg        util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
100901e04c3fSmrg
101001e04c3fSmrg        so->base.texture = prsc;
101101e04c3fSmrg        so->base.reference.count = 1;
101201e04c3fSmrg        so->base.context = pctx;
101301e04c3fSmrg
10149f464c52Smaya        if (rsc->separate_stencil &&
10159f464c52Smaya            cso->format == PIPE_FORMAT_X32_S8X24_UINT) {
10169f464c52Smaya                rsc = rsc->separate_stencil;
10179f464c52Smaya                prsc = &rsc->base;
10189f464c52Smaya        }
10199f464c52Smaya
10209f464c52Smaya        /* If we're sampling depth from depth/stencil, demote the format to
10219f464c52Smaya         * just depth.  u_format will end up giving the answers for the
10229f464c52Smaya         * stencil channel, otherwise.
10239f464c52Smaya         */
10249f464c52Smaya        enum pipe_format sample_format = cso->format;
10259f464c52Smaya        if (sample_format == PIPE_FORMAT_S8_UINT_Z24_UNORM)
10269f464c52Smaya                sample_format = PIPE_FORMAT_X8Z24_UNORM;
102701e04c3fSmrg
102801e04c3fSmrg#if V3D_VERSION >= 40
10299f464c52Smaya        const struct util_format_description *desc =
10309f464c52Smaya                util_format_description(sample_format);
10319f464c52Smaya
10329f464c52Smaya        if (util_format_is_pure_integer(sample_format) &&
10339f464c52Smaya            !util_format_has_depth(desc)) {
10349f464c52Smaya                int chan = util_format_get_first_non_void_channel(sample_format);
10359f464c52Smaya                if (util_format_is_pure_uint(sample_format)) {
10369f464c52Smaya                        switch (desc->channel[chan].size) {
10379f464c52Smaya                        case 32:
10389f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_32;
10399f464c52Smaya                                break;
10409f464c52Smaya                        case 16:
10419f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_16U;
10429f464c52Smaya                                break;
10439f464c52Smaya                        case 10:
10449f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_1010102U;
10459f464c52Smaya                                break;
10469f464c52Smaya                        case 8:
10479f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_8U;
10489f464c52Smaya                                break;
10499f464c52Smaya                        }
10509f464c52Smaya                } else {
10519f464c52Smaya                        switch (desc->channel[chan].size) {
10529f464c52Smaya                        case 32:
10539f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_32;
10549f464c52Smaya                                break;
10559f464c52Smaya                        case 16:
10569f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_16I;
10579f464c52Smaya                                break;
10589f464c52Smaya                        case 8:
10599f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_8I;
10609f464c52Smaya                                break;
10619f464c52Smaya                        }
10629f464c52Smaya                }
10639f464c52Smaya        } else {
10649f464c52Smaya                if (v3d_get_tex_return_size(&screen->devinfo, sample_format,
10659f464c52Smaya                                           PIPE_TEX_COMPARE_NONE) == 32) {
10669f464c52Smaya                        if (util_format_is_alpha(sample_format))
10679f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_32_A;
10689f464c52Smaya                        else
10699f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_32;
10709f464c52Smaya                } else {
10719f464c52Smaya                        if (util_format_is_luminance_alpha(sample_format))
10729f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_F16_LA;
10739f464c52Smaya                        else if (util_format_is_alpha(sample_format))
10749f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_F16_A;
10759f464c52Smaya                        else if (fmt_swizzle[0] == PIPE_SWIZZLE_Z)
10769f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_F16_BGRA;
10779f464c52Smaya                        else
10789f464c52Smaya                                so->sampler_variant = V3D_SAMPLER_STATE_F16;
107901e04c3fSmrg
10809f464c52Smaya                }
108101e04c3fSmrg
10829f464c52Smaya                if (util_format_is_unorm(sample_format)) {
10839f464c52Smaya                        so->sampler_variant += (V3D_SAMPLER_STATE_F16_UNORM -
10849f464c52Smaya                                                V3D_SAMPLER_STATE_F16);
10859f464c52Smaya                } else if (util_format_is_snorm(sample_format)){
10869f464c52Smaya                        so->sampler_variant += (V3D_SAMPLER_STATE_F16_SNORM -
10879f464c52Smaya                                                V3D_SAMPLER_STATE_F16);
10889f464c52Smaya                }
10899f464c52Smaya        }
10909f464c52Smaya#endif
109101e04c3fSmrg
10929f464c52Smaya        /* V3D still doesn't support sampling from raster textures, so we will
10939f464c52Smaya         * have to copy to a temporary tiled texture.
10949f464c52Smaya         */
10959f464c52Smaya        if (!rsc->tiled && !(prsc->target == PIPE_TEXTURE_1D ||
10969f464c52Smaya                             prsc->target == PIPE_TEXTURE_1D_ARRAY)) {
10979f464c52Smaya                struct v3d_resource *shadow_parent = rsc;
10989f464c52Smaya                struct pipe_resource tmpl = {
10999f464c52Smaya                        .target = prsc->target,
11009f464c52Smaya                        .format = prsc->format,
11019f464c52Smaya                        .width0 = u_minify(prsc->width0,
11029f464c52Smaya                                           cso->u.tex.first_level),
11039f464c52Smaya                        .height0 = u_minify(prsc->height0,
11049f464c52Smaya                                            cso->u.tex.first_level),
11059f464c52Smaya                        .depth0 = 1,
11069f464c52Smaya                        .array_size = 1,
11079f464c52Smaya                        .bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET,
11089f464c52Smaya                        .last_level = cso->u.tex.last_level - cso->u.tex.first_level,
11099f464c52Smaya                        .nr_samples = prsc->nr_samples,
11109f464c52Smaya                };
11119f464c52Smaya
11129f464c52Smaya                /* Create the shadow texture.  The rest of the sampler view
11139f464c52Smaya                 * setup will use the shadow.
111401e04c3fSmrg                 */
11159f464c52Smaya                prsc = v3d_resource_create(pctx->screen, &tmpl);
11169f464c52Smaya                if (!prsc) {
11179f464c52Smaya                        free(so);
11189f464c52Smaya                        return NULL;
111901e04c3fSmrg                }
11209f464c52Smaya                rsc = v3d_resource(prsc);
11219f464c52Smaya
11229f464c52Smaya                /* Flag it as needing update of the contents from the parent. */
11239f464c52Smaya                rsc->writes = shadow_parent->writes - 1;
11249f464c52Smaya                assert(rsc->tiled);
11259f464c52Smaya
11269f464c52Smaya                so->texture = prsc;
11279f464c52Smaya        } else {
11289f464c52Smaya                pipe_resource_reference(&so->texture, prsc);
11299f464c52Smaya        }
11309f464c52Smaya
11317ec681f3Smrg        v3d_create_texture_shader_state_bo(v3d, so);
113201e04c3fSmrg
113301e04c3fSmrg        return &so->base;
113401e04c3fSmrg}
113501e04c3fSmrg
113601e04c3fSmrgstatic void
113701e04c3fSmrgv3d_sampler_view_destroy(struct pipe_context *pctx,
113801e04c3fSmrg                         struct pipe_sampler_view *psview)
113901e04c3fSmrg{
114001e04c3fSmrg        struct v3d_sampler_view *sview = v3d_sampler_view(psview);
114101e04c3fSmrg
114201e04c3fSmrg        v3d_bo_unreference(&sview->bo);
114301e04c3fSmrg        pipe_resource_reference(&psview->texture, NULL);
11449f464c52Smaya        pipe_resource_reference(&sview->texture, NULL);
114501e04c3fSmrg        free(psview);
114601e04c3fSmrg}
114701e04c3fSmrg
114801e04c3fSmrgstatic void
114901e04c3fSmrgv3d_set_sampler_views(struct pipe_context *pctx,
115001e04c3fSmrg                      enum pipe_shader_type shader,
115101e04c3fSmrg                      unsigned start, unsigned nr,
11527ec681f3Smrg                      unsigned unbind_num_trailing_slots,
11537ec681f3Smrg                      bool take_ownership,
115401e04c3fSmrg                      struct pipe_sampler_view **views)
115501e04c3fSmrg{
115601e04c3fSmrg        struct v3d_context *v3d = v3d_context(pctx);
11579f464c52Smaya        struct v3d_texture_stateobj *stage_tex = &v3d->tex[shader];
115801e04c3fSmrg        unsigned i;
115901e04c3fSmrg        unsigned new_nr = 0;
116001e04c3fSmrg
116101e04c3fSmrg        assert(start == 0);
116201e04c3fSmrg
116301e04c3fSmrg        for (i = 0; i < nr; i++) {
116401e04c3fSmrg                if (views[i])
116501e04c3fSmrg                        new_nr = i + 1;
11667ec681f3Smrg                if (take_ownership) {
11677ec681f3Smrg                        pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
11687ec681f3Smrg                        stage_tex->textures[i] = views[i];
11697ec681f3Smrg                } else {
11707ec681f3Smrg                        pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
11717ec681f3Smrg                }
117201e04c3fSmrg        }
117301e04c3fSmrg
117401e04c3fSmrg        for (; i < stage_tex->num_textures; i++) {
117501e04c3fSmrg                pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
117601e04c3fSmrg        }
117701e04c3fSmrg
117801e04c3fSmrg        stage_tex->num_textures = new_nr;
11797ec681f3Smrg
11807ec681f3Smrg        v3d_flag_dirty_sampler_state(v3d, shader);
118101e04c3fSmrg}
118201e04c3fSmrg
118301e04c3fSmrgstatic struct pipe_stream_output_target *
118401e04c3fSmrgv3d_create_stream_output_target(struct pipe_context *pctx,
118501e04c3fSmrg                                struct pipe_resource *prsc,
118601e04c3fSmrg                                unsigned buffer_offset,
118701e04c3fSmrg                                unsigned buffer_size)
118801e04c3fSmrg{
11897ec681f3Smrg        struct v3d_stream_output_target *target;
119001e04c3fSmrg
11917ec681f3Smrg        target = CALLOC_STRUCT(v3d_stream_output_target);
119201e04c3fSmrg        if (!target)
119301e04c3fSmrg                return NULL;
119401e04c3fSmrg
11957ec681f3Smrg        pipe_reference_init(&target->base.reference, 1);
11967ec681f3Smrg        pipe_resource_reference(&target->base.buffer, prsc);
119701e04c3fSmrg
11987ec681f3Smrg        target->base.context = pctx;
11997ec681f3Smrg        target->base.buffer_offset = buffer_offset;
12007ec681f3Smrg        target->base.buffer_size = buffer_size;
120101e04c3fSmrg
12027ec681f3Smrg        return &target->base;
120301e04c3fSmrg}
120401e04c3fSmrg
120501e04c3fSmrgstatic void
120601e04c3fSmrgv3d_stream_output_target_destroy(struct pipe_context *pctx,
120701e04c3fSmrg                                 struct pipe_stream_output_target *target)
120801e04c3fSmrg{
120901e04c3fSmrg        pipe_resource_reference(&target->buffer, NULL);
121001e04c3fSmrg        free(target);
121101e04c3fSmrg}
121201e04c3fSmrg
121301e04c3fSmrgstatic void
121401e04c3fSmrgv3d_set_stream_output_targets(struct pipe_context *pctx,
121501e04c3fSmrg                              unsigned num_targets,
121601e04c3fSmrg                              struct pipe_stream_output_target **targets,
121701e04c3fSmrg                              const unsigned *offsets)
121801e04c3fSmrg{
121901e04c3fSmrg        struct v3d_context *ctx = v3d_context(pctx);
122001e04c3fSmrg        struct v3d_streamout_stateobj *so = &ctx->streamout;
122101e04c3fSmrg        unsigned i;
122201e04c3fSmrg
122301e04c3fSmrg        assert(num_targets <= ARRAY_SIZE(so->targets));
122401e04c3fSmrg
12257ec681f3Smrg        /* Update recorded vertex counts when we are ending the recording of
12267ec681f3Smrg         * transform feedback. We do this when we switch primitive types
12277ec681f3Smrg         * at draw time, but if we haven't switched primitives in our last
12287ec681f3Smrg         * draw we need to do it here as well.
12297ec681f3Smrg         */
12307ec681f3Smrg        if (num_targets == 0 && so->num_targets > 0)
12317ec681f3Smrg                v3d_update_primitive_counters(ctx);
12327ec681f3Smrg
123301e04c3fSmrg        for (i = 0; i < num_targets; i++) {
123401e04c3fSmrg                if (offsets[i] != -1)
123501e04c3fSmrg                        so->offsets[i] = offsets[i];
123601e04c3fSmrg
123701e04c3fSmrg                pipe_so_target_reference(&so->targets[i], targets[i]);
123801e04c3fSmrg        }
123901e04c3fSmrg
124001e04c3fSmrg        for (; i < so->num_targets; i++)
124101e04c3fSmrg                pipe_so_target_reference(&so->targets[i], NULL);
124201e04c3fSmrg
124301e04c3fSmrg        so->num_targets = num_targets;
124401e04c3fSmrg
12457ec681f3Smrg        /* Create primitive counters BO if needed */
12467ec681f3Smrg        if (num_targets > 0)
12477ec681f3Smrg                v3d_ensure_prim_counts_allocated(ctx);
12487ec681f3Smrg
12497ec681f3Smrg        ctx->dirty |= V3D_DIRTY_STREAMOUT;
125001e04c3fSmrg}
125101e04c3fSmrg
12529f464c52Smayastatic void
12539f464c52Smayav3d_set_shader_buffers(struct pipe_context *pctx,
12549f464c52Smaya                       enum pipe_shader_type shader,
12559f464c52Smaya                       unsigned start, unsigned count,
12569f464c52Smaya                       const struct pipe_shader_buffer *buffers,
12579f464c52Smaya                       unsigned writable_bitmask)
12589f464c52Smaya{
12599f464c52Smaya        struct v3d_context *v3d = v3d_context(pctx);
12609f464c52Smaya        struct v3d_ssbo_stateobj *so = &v3d->ssbo[shader];
12619f464c52Smaya        unsigned mask = 0;
12629f464c52Smaya
12639f464c52Smaya        if (buffers) {
12649f464c52Smaya                for (unsigned i = 0; i < count; i++) {
12659f464c52Smaya                        unsigned n = i + start;
12669f464c52Smaya                        struct pipe_shader_buffer *buf = &so->sb[n];
12679f464c52Smaya
12689f464c52Smaya                        if ((buf->buffer == buffers[i].buffer) &&
12699f464c52Smaya                            (buf->buffer_offset == buffers[i].buffer_offset) &&
12709f464c52Smaya                            (buf->buffer_size == buffers[i].buffer_size))
12719f464c52Smaya                                continue;
12729f464c52Smaya
12739f464c52Smaya                        mask |= 1 << n;
12749f464c52Smaya
12759f464c52Smaya                        buf->buffer_offset = buffers[i].buffer_offset;
12769f464c52Smaya                        buf->buffer_size = buffers[i].buffer_size;
12779f464c52Smaya                        pipe_resource_reference(&buf->buffer, buffers[i].buffer);
12789f464c52Smaya
12799f464c52Smaya                        if (buf->buffer)
12809f464c52Smaya                                so->enabled_mask |= 1 << n;
12819f464c52Smaya                        else
12829f464c52Smaya                                so->enabled_mask &= ~(1 << n);
12839f464c52Smaya                }
12849f464c52Smaya        } else {
12859f464c52Smaya                mask = ((1 << count) - 1) << start;
12869f464c52Smaya
12879f464c52Smaya                for (unsigned i = 0; i < count; i++) {
12889f464c52Smaya                        unsigned n = i + start;
12899f464c52Smaya                        struct pipe_shader_buffer *buf = &so->sb[n];
12909f464c52Smaya
12919f464c52Smaya                        pipe_resource_reference(&buf->buffer, NULL);
12929f464c52Smaya                }
12939f464c52Smaya
12949f464c52Smaya                so->enabled_mask &= ~mask;
12959f464c52Smaya        }
12969f464c52Smaya
12977ec681f3Smrg        v3d->dirty |= V3D_DIRTY_SSBO;
12989f464c52Smaya}
12999f464c52Smaya
13009f464c52Smayastatic void
13019f464c52Smayav3d_create_image_view_texture_shader_state(struct v3d_context *v3d,
13029f464c52Smaya                                           struct v3d_shaderimg_stateobj *so,
13039f464c52Smaya                                           int img)
13049f464c52Smaya{
13059f464c52Smaya#if V3D_VERSION >= 40
13069f464c52Smaya        struct v3d_image_view *iview = &so->si[img];
13079f464c52Smaya
13089f464c52Smaya        void *map;
13099f464c52Smaya        u_upload_alloc(v3d->uploader, 0, cl_packet_length(TEXTURE_SHADER_STATE),
13109f464c52Smaya                       32,
13119f464c52Smaya                       &iview->tex_state_offset,
13129f464c52Smaya                       &iview->tex_state,
13139f464c52Smaya                       &map);
13149f464c52Smaya
13159f464c52Smaya        struct pipe_resource *prsc = iview->base.resource;
13169f464c52Smaya
13179f464c52Smaya        v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
13189f464c52Smaya                v3d_setup_texture_shader_state(&tex, prsc,
13199f464c52Smaya                                               iview->base.u.tex.level,
13209f464c52Smaya                                               iview->base.u.tex.level,
13219f464c52Smaya                                               iview->base.u.tex.first_layer,
13229f464c52Smaya                                               iview->base.u.tex.last_layer);
13239f464c52Smaya
13249f464c52Smaya                tex.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
13259f464c52Smaya                tex.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
13269f464c52Smaya                tex.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
13279f464c52Smaya                tex.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
13289f464c52Smaya
13299f464c52Smaya                tex.texture_type = v3d_get_tex_format(&v3d->screen->devinfo,
13309f464c52Smaya                                                      iview->base.format);
13319f464c52Smaya        };
13329f464c52Smaya#else /* V3D_VERSION < 40 */
13339f464c52Smaya        /* V3D 3.x doesn't use support shader image load/store operations on
13349f464c52Smaya         * textures, so it would get lowered in the shader to general memory
13359f464c52Smaya         * acceses.
13369f464c52Smaya         */
13379f464c52Smaya#endif
13389f464c52Smaya}
13399f464c52Smaya
13409f464c52Smayastatic void
13419f464c52Smayav3d_set_shader_images(struct pipe_context *pctx,
13429f464c52Smaya                      enum pipe_shader_type shader,
13439f464c52Smaya                      unsigned start, unsigned count,
13447ec681f3Smrg                      unsigned unbind_num_trailing_slots,
13459f464c52Smaya                      const struct pipe_image_view *images)
13469f464c52Smaya{
13479f464c52Smaya        struct v3d_context *v3d = v3d_context(pctx);
13489f464c52Smaya        struct v3d_shaderimg_stateobj *so = &v3d->shaderimg[shader];
13499f464c52Smaya
13509f464c52Smaya        if (images) {
13519f464c52Smaya                for (unsigned i = 0; i < count; i++) {
13529f464c52Smaya                        unsigned n = i + start;
13539f464c52Smaya                        struct v3d_image_view *iview = &so->si[n];
13549f464c52Smaya
13559f464c52Smaya                        if ((iview->base.resource == images[i].resource) &&
13569f464c52Smaya                            (iview->base.format == images[i].format) &&
13579f464c52Smaya                            (iview->base.access == images[i].access) &&
13589f464c52Smaya                            !memcmp(&iview->base.u, &images[i].u,
13599f464c52Smaya                                    sizeof(iview->base.u)))
13609f464c52Smaya                                continue;
13619f464c52Smaya
13629f464c52Smaya                        util_copy_image_view(&iview->base, &images[i]);
13639f464c52Smaya
13649f464c52Smaya                        if (iview->base.resource) {
13659f464c52Smaya                                so->enabled_mask |= 1 << n;
13669f464c52Smaya                                v3d_create_image_view_texture_shader_state(v3d,
13679f464c52Smaya                                                                           so,
13689f464c52Smaya                                                                           n);
13699f464c52Smaya                        } else {
13709f464c52Smaya                                so->enabled_mask &= ~(1 << n);
13719f464c52Smaya                                pipe_resource_reference(&iview->tex_state, NULL);
13729f464c52Smaya                        }
13739f464c52Smaya                }
13749f464c52Smaya        } else {
13759f464c52Smaya                for (unsigned i = 0; i < count; i++) {
13769f464c52Smaya                        unsigned n = i + start;
13779f464c52Smaya                        struct v3d_image_view *iview = &so->si[n];
13789f464c52Smaya
13799f464c52Smaya                        pipe_resource_reference(&iview->base.resource, NULL);
13809f464c52Smaya                        pipe_resource_reference(&iview->tex_state, NULL);
13819f464c52Smaya                }
13829f464c52Smaya
13839f464c52Smaya                if (count == 32)
13849f464c52Smaya                        so->enabled_mask = 0;
13859f464c52Smaya                else
13869f464c52Smaya                        so->enabled_mask &= ~(((1 << count) - 1) << start);
13879f464c52Smaya        }
13889f464c52Smaya
13897ec681f3Smrg        v3d->dirty |= V3D_DIRTY_SHADER_IMAGE;
13907ec681f3Smrg
13917ec681f3Smrg        if (unbind_num_trailing_slots) {
13927ec681f3Smrg                v3d_set_shader_images(pctx, shader, start + count,
13937ec681f3Smrg                                      unbind_num_trailing_slots, 0, NULL);
13947ec681f3Smrg        }
13959f464c52Smaya}
13969f464c52Smaya
139701e04c3fSmrgvoid
139801e04c3fSmrgv3dX(state_init)(struct pipe_context *pctx)
139901e04c3fSmrg{
140001e04c3fSmrg        pctx->set_blend_color = v3d_set_blend_color;
140101e04c3fSmrg        pctx->set_stencil_ref = v3d_set_stencil_ref;
140201e04c3fSmrg        pctx->set_clip_state = v3d_set_clip_state;
140301e04c3fSmrg        pctx->set_sample_mask = v3d_set_sample_mask;
140401e04c3fSmrg        pctx->set_constant_buffer = v3d_set_constant_buffer;
140501e04c3fSmrg        pctx->set_framebuffer_state = v3d_set_framebuffer_state;
140601e04c3fSmrg        pctx->set_polygon_stipple = v3d_set_polygon_stipple;
140701e04c3fSmrg        pctx->set_scissor_states = v3d_set_scissor_states;
140801e04c3fSmrg        pctx->set_viewport_states = v3d_set_viewport_states;
140901e04c3fSmrg
141001e04c3fSmrg        pctx->set_vertex_buffers = v3d_set_vertex_buffers;
141101e04c3fSmrg
141201e04c3fSmrg        pctx->create_blend_state = v3d_create_blend_state;
141301e04c3fSmrg        pctx->bind_blend_state = v3d_blend_state_bind;
141401e04c3fSmrg        pctx->delete_blend_state = v3d_generic_cso_state_delete;
141501e04c3fSmrg
141601e04c3fSmrg        pctx->create_rasterizer_state = v3d_create_rasterizer_state;
141701e04c3fSmrg        pctx->bind_rasterizer_state = v3d_rasterizer_state_bind;
141801e04c3fSmrg        pctx->delete_rasterizer_state = v3d_generic_cso_state_delete;
141901e04c3fSmrg
142001e04c3fSmrg        pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state;
142101e04c3fSmrg        pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind;
142201e04c3fSmrg        pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete;
142301e04c3fSmrg
142401e04c3fSmrg        pctx->create_vertex_elements_state = v3d_vertex_state_create;
142501e04c3fSmrg        pctx->delete_vertex_elements_state = v3d_vertex_state_delete;
142601e04c3fSmrg        pctx->bind_vertex_elements_state = v3d_vertex_state_bind;
142701e04c3fSmrg
142801e04c3fSmrg        pctx->create_sampler_state = v3d_create_sampler_state;
142901e04c3fSmrg        pctx->delete_sampler_state = v3d_sampler_state_delete;
143001e04c3fSmrg        pctx->bind_sampler_states = v3d_sampler_states_bind;
143101e04c3fSmrg
143201e04c3fSmrg        pctx->create_sampler_view = v3d_create_sampler_view;
143301e04c3fSmrg        pctx->sampler_view_destroy = v3d_sampler_view_destroy;
143401e04c3fSmrg        pctx->set_sampler_views = v3d_set_sampler_views;
143501e04c3fSmrg
14369f464c52Smaya        pctx->set_shader_buffers = v3d_set_shader_buffers;
14379f464c52Smaya        pctx->set_shader_images = v3d_set_shader_images;
14389f464c52Smaya
143901e04c3fSmrg        pctx->create_stream_output_target = v3d_create_stream_output_target;
144001e04c3fSmrg        pctx->stream_output_target_destroy = v3d_stream_output_target_destroy;
144101e04c3fSmrg        pctx->set_stream_output_targets = v3d_set_stream_output_targets;
144201e04c3fSmrg}
1443