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