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