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