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