v3dx_state.c revision 01e04c3f
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/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/u_half.h"
32#include "util/u_helpers.h"
33
34#include "v3d_context.h"
35#include "v3d_tiling.h"
36#include "broadcom/common/v3d_macros.h"
37#include "broadcom/cle/v3dx_pack.h"
38
39static void
40v3d_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
41{
42        free(hwcso);
43}
44
45static void
46v3d_set_blend_color(struct pipe_context *pctx,
47                    const struct pipe_blend_color *blend_color)
48{
49        struct v3d_context *v3d = v3d_context(pctx);
50        v3d->blend_color.f = *blend_color;
51        for (int i = 0; i < 4; i++) {
52                v3d->blend_color.hf[i] =
53                        util_float_to_half(blend_color->color[i]);
54        }
55        v3d->dirty |= VC5_DIRTY_BLEND_COLOR;
56}
57
58static void
59v3d_set_stencil_ref(struct pipe_context *pctx,
60                    const struct pipe_stencil_ref *stencil_ref)
61{
62        struct v3d_context *v3d = v3d_context(pctx);
63        v3d->stencil_ref = *stencil_ref;
64        v3d->dirty |= VC5_DIRTY_STENCIL_REF;
65}
66
67static void
68v3d_set_clip_state(struct pipe_context *pctx,
69                   const struct pipe_clip_state *clip)
70{
71        struct v3d_context *v3d = v3d_context(pctx);
72        v3d->clip = *clip;
73        v3d->dirty |= VC5_DIRTY_CLIP;
74}
75
76static void
77v3d_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
78{
79        struct v3d_context *v3d = v3d_context(pctx);
80        v3d->sample_mask = sample_mask & ((1 << VC5_MAX_SAMPLES) - 1);
81        v3d->dirty |= VC5_DIRTY_SAMPLE_STATE;
82}
83
84static void *
85v3d_create_rasterizer_state(struct pipe_context *pctx,
86                            const struct pipe_rasterizer_state *cso)
87{
88        struct v3d_rasterizer_state *so;
89
90        so = CALLOC_STRUCT(v3d_rasterizer_state);
91        if (!so)
92                return NULL;
93
94        so->base = *cso;
95
96        /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
97         * BCM21553).
98         */
99        so->point_size = MAX2(cso->point_size, .125f);
100
101        STATIC_ASSERT(sizeof(so->depth_offset) >=
102                      cl_packet_length(DEPTH_OFFSET));
103        v3dx_pack(&so->depth_offset, DEPTH_OFFSET, depth) {
104                depth.depth_offset_factor = cso->offset_scale;
105                depth.depth_offset_units = cso->offset_units;
106        }
107
108        /* The HW treats polygon offset units based on a Z24 buffer, so we
109         * need to scale up offset_units if we're only Z16.
110         */
111        v3dx_pack(&so->depth_offset_z16, DEPTH_OFFSET, depth) {
112                depth.depth_offset_factor = cso->offset_scale;
113                depth.depth_offset_units = cso->offset_units * 256.0;
114        }
115
116        return so;
117}
118
119/* Blend state is baked into shaders. */
120static void *
121v3d_create_blend_state(struct pipe_context *pctx,
122                       const struct pipe_blend_state *cso)
123{
124        struct v3d_blend_state *so;
125
126        so = CALLOC_STRUCT(v3d_blend_state);
127        if (!so)
128                return NULL;
129
130        so->base = *cso;
131
132        if (cso->independent_blend_enable) {
133                for (int i = 0; i < VC5_MAX_DRAW_BUFFERS; i++) {
134                        so->blend_enables |= cso->rt[i].blend_enable << i;
135
136                        /* V3D 4.x is when we got independent blend enables. */
137                        assert(V3D_VERSION >= 40 ||
138                               cso->rt[i].blend_enable == cso->rt[0].blend_enable);
139                }
140        } else {
141                if (cso->rt[0].blend_enable)
142                        so->blend_enables = (1 << VC5_MAX_DRAW_BUFFERS) - 1;
143        }
144
145        return so;
146}
147
148static uint32_t
149translate_stencil_op(enum pipe_stencil_op op)
150{
151        switch (op) {
152        case PIPE_STENCIL_OP_KEEP:      return V3D_STENCIL_OP_KEEP;
153        case PIPE_STENCIL_OP_ZERO:      return V3D_STENCIL_OP_ZERO;
154        case PIPE_STENCIL_OP_REPLACE:   return V3D_STENCIL_OP_REPLACE;
155        case PIPE_STENCIL_OP_INCR:      return V3D_STENCIL_OP_INCR;
156        case PIPE_STENCIL_OP_DECR:      return V3D_STENCIL_OP_DECR;
157        case PIPE_STENCIL_OP_INCR_WRAP: return V3D_STENCIL_OP_INCWRAP;
158        case PIPE_STENCIL_OP_DECR_WRAP: return V3D_STENCIL_OP_DECWRAP;
159        case PIPE_STENCIL_OP_INVERT:    return V3D_STENCIL_OP_INVERT;
160        }
161        unreachable("bad stencil op");
162}
163
164static void *
165v3d_create_depth_stencil_alpha_state(struct pipe_context *pctx,
166                                     const struct pipe_depth_stencil_alpha_state *cso)
167{
168        struct v3d_depth_stencil_alpha_state *so;
169
170        so = CALLOC_STRUCT(v3d_depth_stencil_alpha_state);
171        if (!so)
172                return NULL;
173
174        so->base = *cso;
175
176        if (cso->depth.enabled) {
177                switch (cso->depth.func) {
178                case PIPE_FUNC_LESS:
179                case PIPE_FUNC_LEQUAL:
180                        so->ez_state = VC5_EZ_LT_LE;
181                        break;
182                case PIPE_FUNC_GREATER:
183                case PIPE_FUNC_GEQUAL:
184                        so->ez_state = VC5_EZ_GT_GE;
185                        break;
186                case PIPE_FUNC_NEVER:
187                case PIPE_FUNC_EQUAL:
188                        so->ez_state = VC5_EZ_UNDECIDED;
189                        break;
190                default:
191                        so->ez_state = VC5_EZ_DISABLED;
192                        break;
193                }
194
195                /* If stencil is enabled and it's not a no-op, then it would
196                 * break EZ updates.
197                 */
198                if (cso->stencil[0].enabled &&
199                    (cso->stencil[0].zfail_op != PIPE_STENCIL_OP_KEEP ||
200                     cso->stencil[0].func != PIPE_FUNC_ALWAYS ||
201                     (cso->stencil[1].enabled &&
202                      (cso->stencil[1].zfail_op != PIPE_STENCIL_OP_KEEP &&
203                       cso->stencil[1].func != PIPE_FUNC_ALWAYS)))) {
204                        so->ez_state = VC5_EZ_DISABLED;
205                }
206        }
207
208        const struct pipe_stencil_state *front = &cso->stencil[0];
209        const struct pipe_stencil_state *back = &cso->stencil[1];
210
211        if (front->enabled) {
212                STATIC_ASSERT(sizeof(so->stencil_front) >=
213                              cl_packet_length(STENCIL_CFG));
214                v3dx_pack(&so->stencil_front, STENCIL_CFG, config) {
215                        config.front_config = true;
216                        /* If !back->enabled, then the front values should be
217                         * used for both front and back-facing primitives.
218                         */
219                        config.back_config = !back->enabled;
220
221                        config.stencil_write_mask = front->writemask;
222                        config.stencil_test_mask = front->valuemask;
223
224                        config.stencil_test_function = front->func;
225                        config.stencil_pass_op =
226                                translate_stencil_op(front->zpass_op);
227                        config.depth_test_fail_op =
228                                translate_stencil_op(front->zfail_op);
229                        config.stencil_test_fail_op =
230                                translate_stencil_op(front->fail_op);
231                }
232        }
233        if (back->enabled) {
234                STATIC_ASSERT(sizeof(so->stencil_back) >=
235                              cl_packet_length(STENCIL_CFG));
236                v3dx_pack(&so->stencil_back, STENCIL_CFG, config) {
237                        config.front_config = false;
238                        config.back_config = true;
239
240                        config.stencil_write_mask = back->writemask;
241                        config.stencil_test_mask = back->valuemask;
242
243                        config.stencil_test_function = back->func;
244                        config.stencil_pass_op =
245                                translate_stencil_op(back->zpass_op);
246                        config.depth_test_fail_op =
247                                translate_stencil_op(back->zfail_op);
248                        config.stencil_test_fail_op =
249                                translate_stencil_op(back->fail_op);
250                }
251        }
252
253        return so;
254}
255
256static void
257v3d_set_polygon_stipple(struct pipe_context *pctx,
258                        const struct pipe_poly_stipple *stipple)
259{
260        struct v3d_context *v3d = v3d_context(pctx);
261        v3d->stipple = *stipple;
262        v3d->dirty |= VC5_DIRTY_STIPPLE;
263}
264
265static void
266v3d_set_scissor_states(struct pipe_context *pctx,
267                       unsigned start_slot,
268                       unsigned num_scissors,
269                       const struct pipe_scissor_state *scissor)
270{
271        struct v3d_context *v3d = v3d_context(pctx);
272
273        v3d->scissor = *scissor;
274        v3d->dirty |= VC5_DIRTY_SCISSOR;
275}
276
277static void
278v3d_set_viewport_states(struct pipe_context *pctx,
279                        unsigned start_slot,
280                        unsigned num_viewports,
281                        const struct pipe_viewport_state *viewport)
282{
283        struct v3d_context *v3d = v3d_context(pctx);
284        v3d->viewport = *viewport;
285        v3d->dirty |= VC5_DIRTY_VIEWPORT;
286}
287
288static void
289v3d_set_vertex_buffers(struct pipe_context *pctx,
290                       unsigned start_slot, unsigned count,
291                       const struct pipe_vertex_buffer *vb)
292{
293        struct v3d_context *v3d = v3d_context(pctx);
294        struct v3d_vertexbuf_stateobj *so = &v3d->vertexbuf;
295
296        util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
297                                     start_slot, count);
298        so->count = util_last_bit(so->enabled_mask);
299
300        v3d->dirty |= VC5_DIRTY_VTXBUF;
301}
302
303static void
304v3d_blend_state_bind(struct pipe_context *pctx, void *hwcso)
305{
306        struct v3d_context *v3d = v3d_context(pctx);
307        v3d->blend = hwcso;
308        v3d->dirty |= VC5_DIRTY_BLEND;
309}
310
311static void
312v3d_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
313{
314        struct v3d_context *v3d = v3d_context(pctx);
315        v3d->rasterizer = hwcso;
316        v3d->dirty |= VC5_DIRTY_RASTERIZER;
317}
318
319static void
320v3d_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
321{
322        struct v3d_context *v3d = v3d_context(pctx);
323        v3d->zsa = hwcso;
324        v3d->dirty |= VC5_DIRTY_ZSA;
325}
326
327static void *
328v3d_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
329                        const struct pipe_vertex_element *elements)
330{
331        struct v3d_context *v3d = v3d_context(pctx);
332        struct v3d_vertex_stateobj *so = CALLOC_STRUCT(v3d_vertex_stateobj);
333
334        if (!so)
335                return NULL;
336
337        memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
338        so->num_elements = num_elements;
339
340        for (int i = 0; i < so->num_elements; i++) {
341                const struct pipe_vertex_element *elem = &elements[i];
342                const struct util_format_description *desc =
343                        util_format_description(elem->src_format);
344                uint32_t r_size = desc->channel[0].size;
345
346                const uint32_t size =
347                        cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
348
349                v3dx_pack(&so->attrs[i * size],
350                          GL_SHADER_STATE_ATTRIBUTE_RECORD, attr) {
351                        /* vec_size == 0 means 4 */
352                        attr.vec_size = desc->nr_channels & 3;
353                        attr.signed_int_type = (desc->channel[0].type ==
354                                                UTIL_FORMAT_TYPE_SIGNED);
355
356                        attr.normalized_int_type = desc->channel[0].normalized;
357                        attr.read_as_int_uint = desc->channel[0].pure_integer;
358                        attr.instance_divisor = MIN2(elem->instance_divisor,
359                                                     0xffff);
360
361                        switch (desc->channel[0].type) {
362                        case UTIL_FORMAT_TYPE_FLOAT:
363                                if (r_size == 32) {
364                                        attr.type = ATTRIBUTE_FLOAT;
365                                } else {
366                                        assert(r_size == 16);
367                                        attr.type = ATTRIBUTE_HALF_FLOAT;
368                                }
369                                break;
370
371                        case UTIL_FORMAT_TYPE_SIGNED:
372                        case UTIL_FORMAT_TYPE_UNSIGNED:
373                                switch (r_size) {
374                                case 32:
375                                        attr.type = ATTRIBUTE_INT;
376                                        break;
377                                case 16:
378                                        attr.type = ATTRIBUTE_SHORT;
379                                        break;
380                                case 10:
381                                        attr.type = ATTRIBUTE_INT2_10_10_10;
382                                        break;
383                                case 8:
384                                        attr.type = ATTRIBUTE_BYTE;
385                                        break;
386                                default:
387                                        fprintf(stderr,
388                                                "format %s unsupported\n",
389                                                desc->name);
390                                        attr.type = ATTRIBUTE_BYTE;
391                                        abort();
392                                }
393                                break;
394
395                        default:
396                                fprintf(stderr,
397                                        "format %s unsupported\n",
398                                        desc->name);
399                                abort();
400                        }
401                }
402        }
403
404        /* Set up the default attribute values in case any of the vertex
405         * elements use them.
406         */
407        so->default_attribute_values = v3d_bo_alloc(v3d->screen,
408                                                    VC5_MAX_ATTRIBUTES *
409                                                    4 * sizeof(float),
410                                                    "default_attributes");
411        uint32_t *attrs = v3d_bo_map(so->default_attribute_values);
412        for (int i = 0; i < VC5_MAX_ATTRIBUTES; i++) {
413                attrs[i * 4 + 0] = 0;
414                attrs[i * 4 + 1] = 0;
415                attrs[i * 4 + 2] = 0;
416                if (i < so->num_elements &&
417                    util_format_is_pure_integer(so->pipe[i].src_format)) {
418                        attrs[i * 4 + 3] = 1;
419                } else {
420                        attrs[i * 4 + 3] = fui(1.0);
421                }
422        }
423
424        return so;
425}
426
427static void
428v3d_vertex_state_delete(struct pipe_context *pctx, void *hwcso)
429{
430        struct v3d_vertex_stateobj *so = hwcso;
431
432        v3d_bo_unreference(&so->default_attribute_values);
433        free(so);
434}
435
436static void
437v3d_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
438{
439        struct v3d_context *v3d = v3d_context(pctx);
440        v3d->vtx = hwcso;
441        v3d->dirty |= VC5_DIRTY_VTXSTATE;
442}
443
444static void
445v3d_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
446                        const struct pipe_constant_buffer *cb)
447{
448        struct v3d_context *v3d = v3d_context(pctx);
449        struct v3d_constbuf_stateobj *so = &v3d->constbuf[shader];
450
451        util_copy_constant_buffer(&so->cb[index], cb);
452
453        /* Note that the state tracker can unbind constant buffers by
454         * passing NULL here.
455         */
456        if (unlikely(!cb)) {
457                so->enabled_mask &= ~(1 << index);
458                so->dirty_mask &= ~(1 << index);
459                return;
460        }
461
462        so->enabled_mask |= 1 << index;
463        so->dirty_mask |= 1 << index;
464        v3d->dirty |= VC5_DIRTY_CONSTBUF;
465}
466
467static void
468v3d_set_framebuffer_state(struct pipe_context *pctx,
469                          const struct pipe_framebuffer_state *framebuffer)
470{
471        struct v3d_context *v3d = v3d_context(pctx);
472        struct pipe_framebuffer_state *cso = &v3d->framebuffer;
473
474        v3d->job = NULL;
475
476        util_copy_framebuffer_state(cso, framebuffer);
477
478        v3d->swap_color_rb = 0;
479        v3d->blend_dst_alpha_one = 0;
480        for (int i = 0; i < v3d->framebuffer.nr_cbufs; i++) {
481                struct pipe_surface *cbuf = v3d->framebuffer.cbufs[i];
482                if (!cbuf)
483                        continue;
484
485                const struct util_format_description *desc =
486                        util_format_description(cbuf->format);
487
488                /* For BGRA8 formats (DRI window system default format), we
489                 * need to swap R and B, since the HW's format is RGBA8.
490                 */
491                if (desc->swizzle[0] == PIPE_SWIZZLE_Z &&
492                    cbuf->format != PIPE_FORMAT_B5G6R5_UNORM) {
493                        v3d->swap_color_rb |= 1 << i;
494                }
495
496                if (desc->swizzle[3] == PIPE_SWIZZLE_1)
497                        v3d->blend_dst_alpha_one |= 1 << i;
498        }
499
500        v3d->dirty |= VC5_DIRTY_FRAMEBUFFER;
501}
502
503static struct v3d_texture_stateobj *
504v3d_get_stage_tex(struct v3d_context *v3d, enum pipe_shader_type shader)
505{
506        switch (shader) {
507        case PIPE_SHADER_FRAGMENT:
508                v3d->dirty |= VC5_DIRTY_FRAGTEX;
509                return &v3d->fragtex;
510                break;
511        case PIPE_SHADER_VERTEX:
512                v3d->dirty |= VC5_DIRTY_VERTTEX;
513                return &v3d->verttex;
514                break;
515        default:
516                fprintf(stderr, "Unknown shader target %d\n", shader);
517                abort();
518        }
519}
520
521static uint32_t translate_wrap(uint32_t pipe_wrap, bool using_nearest)
522{
523        switch (pipe_wrap) {
524        case PIPE_TEX_WRAP_REPEAT:
525                return 0;
526        case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
527                return 1;
528        case PIPE_TEX_WRAP_MIRROR_REPEAT:
529                return 2;
530        case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
531                return 3;
532        case PIPE_TEX_WRAP_CLAMP:
533                return (using_nearest ? 1 : 3);
534        default:
535                unreachable("Unknown wrap mode");
536        }
537}
538
539
540static void *
541v3d_create_sampler_state(struct pipe_context *pctx,
542                         const struct pipe_sampler_state *cso)
543{
544        MAYBE_UNUSED struct v3d_context *v3d = v3d_context(pctx);
545        struct v3d_sampler_state *so = CALLOC_STRUCT(v3d_sampler_state);
546
547        if (!so)
548                return NULL;
549
550        memcpy(so, cso, sizeof(*cso));
551
552        bool either_nearest =
553                (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
554                 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
555
556#if V3D_VERSION >= 40
557        so->bo = v3d_bo_alloc(v3d->screen, cl_packet_length(SAMPLER_STATE),
558                              "sampler");
559        void *map = v3d_bo_map(so->bo);
560
561        v3dx_pack(map, SAMPLER_STATE, sampler) {
562                sampler.wrap_i_border = false;
563
564                sampler.wrap_s = translate_wrap(cso->wrap_s, either_nearest);
565                sampler.wrap_t = translate_wrap(cso->wrap_t, either_nearest);
566                sampler.wrap_r = translate_wrap(cso->wrap_r, either_nearest);
567
568                sampler.fixed_bias = cso->lod_bias;
569                sampler.depth_compare_function = cso->compare_func;
570
571                sampler.min_filter_nearest =
572                        cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
573                sampler.mag_filter_nearest =
574                        cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
575                sampler.mip_filter_nearest =
576                        cso->min_mip_filter != PIPE_TEX_MIPFILTER_LINEAR;
577
578                sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
579                                                   15);
580                sampler.max_level_of_detail = MIN2(cso->max_lod, 15);
581
582                /* If we're not doing inter-miplevel filtering, we need to
583                 * clamp the LOD so that we only sample from baselevel.
584                 * However, we need to still allow the calculated LOD to be
585                 * fractionally over the baselevel, so that the HW can decide
586                 * between the min and mag filters.
587                 */
588                if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_NONE) {
589                        sampler.min_level_of_detail =
590                                MIN2(sampler.min_level_of_detail, 1.0 / 256.0);
591                        sampler.max_level_of_detail =
592                                MIN2(sampler.max_level_of_detail, 1.0 / 256.0);
593                }
594
595                if (cso->max_anisotropy) {
596                        sampler.anisotropy_enable = true;
597
598                        if (cso->max_anisotropy > 8)
599                                sampler.maximum_anisotropy = 3;
600                        else if (cso->max_anisotropy > 4)
601                                sampler.maximum_anisotropy = 2;
602                        else if (cso->max_anisotropy > 2)
603                                sampler.maximum_anisotropy = 1;
604                }
605
606                sampler.border_color_mode = V3D_BORDER_COLOR_FOLLOWS;
607                /* XXX: The border color field is in the TMU blending format
608                 * (32, f16, or i16), and we need to customize it based on
609                 * that.
610                 *
611                 * XXX: for compat alpha formats, we need the alpha field to
612                 * be in the red channel.
613                 */
614                sampler.border_color_red =
615                        util_float_to_half(cso->border_color.f[0]);
616                sampler.border_color_green =
617                        util_float_to_half(cso->border_color.f[1]);
618                sampler.border_color_blue =
619                        util_float_to_half(cso->border_color.f[2]);
620                sampler.border_color_alpha =
621                        util_float_to_half(cso->border_color.f[3]);
622        }
623
624#else /* V3D_VERSION < 40 */
625        v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) {
626                p0.s_wrap_mode = translate_wrap(cso->wrap_s, either_nearest);
627                p0.t_wrap_mode = translate_wrap(cso->wrap_t, either_nearest);
628                p0.r_wrap_mode = translate_wrap(cso->wrap_r, either_nearest);
629        }
630
631        v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
632                tex.depth_compare_function = cso->compare_func;
633                tex.fixed_bias = cso->lod_bias;
634        }
635#endif /* V3D_VERSION < 40 */
636        return so;
637}
638
639static void
640v3d_sampler_states_bind(struct pipe_context *pctx,
641                        enum pipe_shader_type shader, unsigned start,
642                        unsigned nr, void **hwcso)
643{
644        struct v3d_context *v3d = v3d_context(pctx);
645        struct v3d_texture_stateobj *stage_tex = v3d_get_stage_tex(v3d, shader);
646
647        assert(start == 0);
648        unsigned i;
649        unsigned new_nr = 0;
650
651        for (i = 0; i < nr; i++) {
652                if (hwcso[i])
653                        new_nr = i + 1;
654                stage_tex->samplers[i] = hwcso[i];
655        }
656
657        for (; i < stage_tex->num_samplers; i++) {
658                stage_tex->samplers[i] = NULL;
659        }
660
661        stage_tex->num_samplers = new_nr;
662}
663
664static void
665v3d_sampler_state_delete(struct pipe_context *pctx,
666                         void *hwcso)
667{
668        struct pipe_sampler_state *psampler = hwcso;
669        struct v3d_sampler_state *sampler = v3d_sampler_state(psampler);
670
671        v3d_bo_unreference(&sampler->bo);
672        free(psampler);
673}
674
675#if V3D_VERSION >= 40
676static uint32_t
677translate_swizzle(unsigned char pipe_swizzle)
678{
679        switch (pipe_swizzle) {
680        case PIPE_SWIZZLE_0:
681                return 0;
682        case PIPE_SWIZZLE_1:
683                return 1;
684        case PIPE_SWIZZLE_X:
685        case PIPE_SWIZZLE_Y:
686        case PIPE_SWIZZLE_Z:
687        case PIPE_SWIZZLE_W:
688                return 2 + pipe_swizzle;
689        default:
690                unreachable("unknown swizzle");
691        }
692}
693#endif
694
695static struct pipe_sampler_view *
696v3d_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
697                        const struct pipe_sampler_view *cso)
698{
699        struct v3d_context *v3d = v3d_context(pctx);
700        struct v3d_screen *screen = v3d->screen;
701        struct v3d_sampler_view *so = CALLOC_STRUCT(v3d_sampler_view);
702        struct v3d_resource *rsc = v3d_resource(prsc);
703
704        if (!so)
705                return NULL;
706
707        so->base = *cso;
708
709        pipe_reference(NULL, &prsc->reference);
710
711        /* Compute the sampler view's swizzle up front. This will be plugged
712         * into either the sampler (for 16-bit returns) or the shader's
713         * texture key (for 32)
714         */
715        uint8_t view_swizzle[4] = {
716                cso->swizzle_r,
717                cso->swizzle_g,
718                cso->swizzle_b,
719                cso->swizzle_a
720        };
721        const uint8_t *fmt_swizzle =
722                v3d_get_format_swizzle(&screen->devinfo, so->base.format);
723        util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
724
725        so->base.texture = prsc;
726        so->base.reference.count = 1;
727        so->base.context = pctx;
728
729        int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
730
731#if V3D_VERSION >= 40
732        so->bo = v3d_bo_alloc(v3d->screen,
733                              cl_packet_length(TEXTURE_SHADER_STATE), "sampler");
734        void *map = v3d_bo_map(so->bo);
735
736        v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
737#else /* V3D_VERSION < 40 */
738        STATIC_ASSERT(sizeof(so->texture_shader_state) >=
739                      cl_packet_length(TEXTURE_SHADER_STATE));
740        v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
741#endif
742
743                tex.image_width = prsc->width0 * msaa_scale;
744                tex.image_height = prsc->height0 * msaa_scale;
745
746#if V3D_VERSION >= 40
747                /* On 4.x, the height of a 1D texture is redefined to be the
748                 * upper 14 bits of the width (which is only usable with txf).
749                 */
750                if (prsc->target == PIPE_TEXTURE_1D ||
751                    prsc->target == PIPE_TEXTURE_1D_ARRAY) {
752                        tex.image_height = tex.image_width >> 14;
753                }
754#endif
755
756                if (prsc->target == PIPE_TEXTURE_3D) {
757                        tex.image_depth = prsc->depth0;
758                } else {
759                        tex.image_depth = (cso->u.tex.last_layer -
760                                           cso->u.tex.first_layer) + 1;
761                }
762
763                tex.srgb = util_format_is_srgb(cso->format);
764
765                tex.base_level = cso->u.tex.first_level;
766#if V3D_VERSION >= 40
767                tex.max_level = cso->u.tex.last_level;
768                /* Note that we don't have a job to reference the texture's sBO
769                 * at state create time, so any time this sampler view is used
770                 * we need to add the texture to the job.
771                 */
772                tex.texture_base_pointer = cl_address(NULL,
773                                                      rsc->bo->offset +
774                                                      rsc->slices[0].offset +
775                                                      cso->u.tex.first_layer *
776                                                      rsc->cube_map_stride),
777
778                tex.swizzle_r = translate_swizzle(so->swizzle[0]);
779                tex.swizzle_g = translate_swizzle(so->swizzle[1]);
780                tex.swizzle_b = translate_swizzle(so->swizzle[2]);
781                tex.swizzle_a = translate_swizzle(so->swizzle[3]);
782#endif
783                tex.array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
784
785                if (prsc->nr_samples > 1 && V3D_VERSION < 40) {
786                        /* Using texture views to reinterpret formats on our
787                         * MSAA textures won't work, because we don't lay out
788                         * the bits in memory as it's expected -- for example,
789                         * RGBA8 and RGB10_A2 are compatible in the
790                         * ARB_texture_view spec, but in HW we lay them out as
791                         * 32bpp RGBA8 and 64bpp RGBA16F.  Just assert for now
792                         * to catch failures.
793                         *
794                         * We explicitly allow remapping S8Z24 to RGBA8888 for
795                         * v3d_blit.c's stencil blits.
796                         */
797                        assert((util_format_linear(cso->format) ==
798                                util_format_linear(prsc->format)) ||
799                               (prsc->format == PIPE_FORMAT_S8_UINT_Z24_UNORM &&
800                                cso->format == PIPE_FORMAT_R8G8B8A8_UNORM));
801                        uint32_t output_image_format =
802                                v3d_get_rt_format(&screen->devinfo, cso->format);
803                        uint32_t internal_type;
804                        uint32_t internal_bpp;
805                        v3d_get_internal_type_bpp_for_output_format(&screen->devinfo,
806                                                                    output_image_format,
807                                                                    &internal_type,
808                                                                    &internal_bpp);
809
810                        switch (internal_type) {
811                        case V3D_INTERNAL_TYPE_8:
812                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
813                                break;
814                        case V3D_INTERNAL_TYPE_16F:
815                                tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
816                                break;
817                        default:
818                                unreachable("Bad MSAA texture type");
819                        }
820
821                        /* sRGB was stored in the tile buffer as linear and
822                         * would have been encoded to sRGB on resolved tile
823                         * buffer store.  Note that this means we would need
824                         * shader code if we wanted to read an MSAA sRGB
825                         * texture without sRGB decode.
826                         */
827                        tex.srgb = false;
828                } else {
829                        tex.texture_type = v3d_get_tex_format(&screen->devinfo,
830                                                              cso->format);
831                }
832
833                /* Since other platform devices may produce UIF images even
834                 * when they're not big enough for V3D to assume they're UIF,
835                 * we force images with level 0 as UIF to be always treated
836                 * that way.
837                 */
838                tex.level_0_is_strictly_uif = (rsc->slices[0].tiling ==
839                                               VC5_TILING_UIF_XOR ||
840                                               rsc->slices[0].tiling ==
841                                               VC5_TILING_UIF_NO_XOR);
842                tex.level_0_xor_enable = (rsc->slices[0].tiling ==
843                                          VC5_TILING_UIF_XOR);
844
845                if (tex.level_0_is_strictly_uif)
846                        tex.level_0_ub_pad = rsc->slices[0].ub_pad;
847
848#if V3D_VERSION >= 40
849                if (tex.uif_xor_disable ||
850                    tex.level_0_is_strictly_uif) {
851                        tex.extended = true;
852                }
853#endif /* V3D_VERSION >= 40 */
854        };
855
856        return &so->base;
857}
858
859static void
860v3d_sampler_view_destroy(struct pipe_context *pctx,
861                         struct pipe_sampler_view *psview)
862{
863        struct v3d_sampler_view *sview = v3d_sampler_view(psview);
864
865        v3d_bo_unreference(&sview->bo);
866        pipe_resource_reference(&psview->texture, NULL);
867        free(psview);
868}
869
870static void
871v3d_set_sampler_views(struct pipe_context *pctx,
872                      enum pipe_shader_type shader,
873                      unsigned start, unsigned nr,
874                      struct pipe_sampler_view **views)
875{
876        struct v3d_context *v3d = v3d_context(pctx);
877        struct v3d_texture_stateobj *stage_tex = v3d_get_stage_tex(v3d, shader);
878        unsigned i;
879        unsigned new_nr = 0;
880
881        assert(start == 0);
882
883        for (i = 0; i < nr; i++) {
884                if (views[i])
885                        new_nr = i + 1;
886                pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
887        }
888
889        for (; i < stage_tex->num_textures; i++) {
890                pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
891        }
892
893        stage_tex->num_textures = new_nr;
894}
895
896static struct pipe_stream_output_target *
897v3d_create_stream_output_target(struct pipe_context *pctx,
898                                struct pipe_resource *prsc,
899                                unsigned buffer_offset,
900                                unsigned buffer_size)
901{
902        struct pipe_stream_output_target *target;
903
904        target = CALLOC_STRUCT(pipe_stream_output_target);
905        if (!target)
906                return NULL;
907
908        pipe_reference_init(&target->reference, 1);
909        pipe_resource_reference(&target->buffer, prsc);
910
911        target->context = pctx;
912        target->buffer_offset = buffer_offset;
913        target->buffer_size = buffer_size;
914
915        return target;
916}
917
918static void
919v3d_stream_output_target_destroy(struct pipe_context *pctx,
920                                 struct pipe_stream_output_target *target)
921{
922        pipe_resource_reference(&target->buffer, NULL);
923        free(target);
924}
925
926static void
927v3d_set_stream_output_targets(struct pipe_context *pctx,
928                              unsigned num_targets,
929                              struct pipe_stream_output_target **targets,
930                              const unsigned *offsets)
931{
932        struct v3d_context *ctx = v3d_context(pctx);
933        struct v3d_streamout_stateobj *so = &ctx->streamout;
934        unsigned i;
935
936        assert(num_targets <= ARRAY_SIZE(so->targets));
937
938        for (i = 0; i < num_targets; i++) {
939                if (offsets[i] != -1)
940                        so->offsets[i] = offsets[i];
941
942                pipe_so_target_reference(&so->targets[i], targets[i]);
943        }
944
945        for (; i < so->num_targets; i++)
946                pipe_so_target_reference(&so->targets[i], NULL);
947
948        so->num_targets = num_targets;
949
950        ctx->dirty |= VC5_DIRTY_STREAMOUT;
951}
952
953void
954v3dX(state_init)(struct pipe_context *pctx)
955{
956        pctx->set_blend_color = v3d_set_blend_color;
957        pctx->set_stencil_ref = v3d_set_stencil_ref;
958        pctx->set_clip_state = v3d_set_clip_state;
959        pctx->set_sample_mask = v3d_set_sample_mask;
960        pctx->set_constant_buffer = v3d_set_constant_buffer;
961        pctx->set_framebuffer_state = v3d_set_framebuffer_state;
962        pctx->set_polygon_stipple = v3d_set_polygon_stipple;
963        pctx->set_scissor_states = v3d_set_scissor_states;
964        pctx->set_viewport_states = v3d_set_viewport_states;
965
966        pctx->set_vertex_buffers = v3d_set_vertex_buffers;
967
968        pctx->create_blend_state = v3d_create_blend_state;
969        pctx->bind_blend_state = v3d_blend_state_bind;
970        pctx->delete_blend_state = v3d_generic_cso_state_delete;
971
972        pctx->create_rasterizer_state = v3d_create_rasterizer_state;
973        pctx->bind_rasterizer_state = v3d_rasterizer_state_bind;
974        pctx->delete_rasterizer_state = v3d_generic_cso_state_delete;
975
976        pctx->create_depth_stencil_alpha_state = v3d_create_depth_stencil_alpha_state;
977        pctx->bind_depth_stencil_alpha_state = v3d_zsa_state_bind;
978        pctx->delete_depth_stencil_alpha_state = v3d_generic_cso_state_delete;
979
980        pctx->create_vertex_elements_state = v3d_vertex_state_create;
981        pctx->delete_vertex_elements_state = v3d_vertex_state_delete;
982        pctx->bind_vertex_elements_state = v3d_vertex_state_bind;
983
984        pctx->create_sampler_state = v3d_create_sampler_state;
985        pctx->delete_sampler_state = v3d_sampler_state_delete;
986        pctx->bind_sampler_states = v3d_sampler_states_bind;
987
988        pctx->create_sampler_view = v3d_create_sampler_view;
989        pctx->sampler_view_destroy = v3d_sampler_view_destroy;
990        pctx->set_sampler_views = v3d_set_sampler_views;
991
992        pctx->create_stream_output_target = v3d_create_stream_output_target;
993        pctx->stream_output_target_destroy = v3d_stream_output_target_destroy;
994        pctx->set_stream_output_targets = v3d_set_stream_output_targets;
995}
996