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