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