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