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