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