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 *
vc5_generic_cso_state_create(const void * src,uint32_t size)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
vc5_generic_cso_state_delete(struct pipe_context * pctx,void * hwcso)48 vc5_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
49 {
50 free(hwcso);
51 }
52
53 static void
vc5_set_blend_color(struct pipe_context * pctx,const struct pipe_blend_color * blend_color)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
vc5_set_stencil_ref(struct pipe_context * pctx,const struct pipe_stencil_ref * stencil_ref)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
vc5_set_clip_state(struct pipe_context * pctx,const struct pipe_clip_state * clip)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
vc5_set_sample_mask(struct pipe_context * pctx,unsigned sample_mask)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
float_to_187_half(float f)93 float_to_187_half(float f)
94 {
95 return fui(f) >> 16;
96 }
97
98 static void *
vc5_create_rasterizer_state(struct pipe_context * pctx,const struct pipe_rasterizer_state * cso)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 *
vc5_create_blend_state(struct pipe_context * pctx,const struct pipe_blend_state * cso)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
translate_stencil_op(enum pipe_stencil_op op)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 *
vc5_create_depth_stencil_alpha_state(struct pipe_context * pctx,const struct pipe_depth_stencil_alpha_state * cso)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
vc5_set_polygon_stipple(struct pipe_context * pctx,const struct pipe_poly_stipple * stipple)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
vc5_set_scissor_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_scissors,const struct pipe_scissor_state * scissor)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
vc5_set_viewport_states(struct pipe_context * pctx,unsigned start_slot,unsigned num_viewports,const struct pipe_viewport_state * viewport)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
vc5_set_vertex_buffers(struct pipe_context * pctx,unsigned start_slot,unsigned count,const struct pipe_vertex_buffer * vb)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
vc5_blend_state_bind(struct pipe_context * pctx,void * hwcso)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
vc5_rasterizer_state_bind(struct pipe_context * pctx,void * hwcso)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
vc5_zsa_state_bind(struct pipe_context * pctx,void * hwcso)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 *
vc5_vertex_state_create(struct pipe_context * pctx,unsigned num_elements,const struct pipe_vertex_element * elements)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
vc5_vertex_state_bind(struct pipe_context * pctx,void * hwcso)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
vc5_set_constant_buffer(struct pipe_context * pctx,uint shader,uint index,const struct pipe_constant_buffer * cb)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
vc5_set_framebuffer_state(struct pipe_context * pctx,const struct pipe_framebuffer_state * framebuffer)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 const struct util_format_description *desc =
447 util_format_description(cbuf->format);
448
449 /* For BGRA8 formats (DRI window system default format), we
450 * need to swap R and B, since the HW's format is RGBA8.
451 */
452 if (desc->swizzle[0] == PIPE_SWIZZLE_Z &&
453 cbuf->format != PIPE_FORMAT_B5G6R5_UNORM) {
454 vc5->swap_color_rb |= 1 << i;
455 }
456
457 if (desc->swizzle[3] == PIPE_SWIZZLE_1)
458 vc5->blend_dst_alpha_one |= 1 << i;
459 }
460
461 vc5->dirty |= VC5_DIRTY_FRAMEBUFFER;
462 }
463
464 static struct vc5_texture_stateobj *
vc5_get_stage_tex(struct vc5_context * vc5,enum pipe_shader_type shader)465 vc5_get_stage_tex(struct vc5_context *vc5, enum pipe_shader_type shader)
466 {
467 switch (shader) {
468 case PIPE_SHADER_FRAGMENT:
469 vc5->dirty |= VC5_DIRTY_FRAGTEX;
470 return &vc5->fragtex;
471 break;
472 case PIPE_SHADER_VERTEX:
473 vc5->dirty |= VC5_DIRTY_VERTTEX;
474 return &vc5->verttex;
475 break;
476 default:
477 fprintf(stderr, "Unknown shader target %d\n", shader);
478 abort();
479 }
480 }
481
translate_wrap(uint32_t pipe_wrap,bool using_nearest)482 static uint32_t translate_wrap(uint32_t pipe_wrap, bool using_nearest)
483 {
484 switch (pipe_wrap) {
485 case PIPE_TEX_WRAP_REPEAT:
486 return 0;
487 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
488 return 1;
489 case PIPE_TEX_WRAP_MIRROR_REPEAT:
490 return 2;
491 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
492 return 3;
493 case PIPE_TEX_WRAP_CLAMP:
494 return (using_nearest ? 1 : 3);
495 default:
496 unreachable("Unknown wrap mode");
497 }
498 }
499
500
501 static void *
vc5_create_sampler_state(struct pipe_context * pctx,const struct pipe_sampler_state * cso)502 vc5_create_sampler_state(struct pipe_context *pctx,
503 const struct pipe_sampler_state *cso)
504 {
505 MAYBE_UNUSED struct vc5_context *vc5 = vc5_context(pctx);
506 struct vc5_sampler_state *so = CALLOC_STRUCT(vc5_sampler_state);
507
508 if (!so)
509 return NULL;
510
511 memcpy(so, cso, sizeof(*cso));
512
513 bool either_nearest =
514 (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
515 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
516
517 #if V3D_VERSION >= 40
518 so->bo = vc5_bo_alloc(vc5->screen, cl_packet_length(SAMPLER_STATE),
519 "sampler");
520 void *map = vc5_bo_map(so->bo);
521
522 v3dx_pack(map, SAMPLER_STATE, sampler) {
523 sampler.wrap_i_border = false;
524
525 sampler.wrap_s = translate_wrap(cso->wrap_s, either_nearest);
526 sampler.wrap_t = translate_wrap(cso->wrap_t, either_nearest);
527 sampler.wrap_r = translate_wrap(cso->wrap_r, either_nearest);
528
529 sampler.fixed_bias = cso->lod_bias;
530 sampler.depth_compare_function = cso->compare_func;
531
532 sampler.min_filter_nearest =
533 cso->min_img_filter == PIPE_TEX_FILTER_NEAREST;
534 sampler.mag_filter_nearest =
535 cso->mag_img_filter == PIPE_TEX_FILTER_NEAREST;
536 sampler.mip_filter_nearest =
537 cso->min_mip_filter == PIPE_TEX_MIPFILTER_NEAREST;
538
539 sampler.min_level_of_detail = MIN2(MAX2(0, cso->min_lod),
540 15);
541 sampler.max_level_of_detail = MIN2(cso->max_lod, 15);
542
543 if (cso->max_anisotropy) {
544 sampler.anisotropy_enable = true;
545
546 if (cso->max_anisotropy > 8)
547 sampler.maximum_anisotropy = 3;
548 else if (cso->max_anisotropy > 4)
549 sampler.maximum_anisotropy = 2;
550 else if (cso->max_anisotropy > 2)
551 sampler.maximum_anisotropy = 1;
552 }
553
554 sampler.border_colour_mode = V3D_BORDER_COLOUR_FOLLOWS;
555 /* XXX: The border colour field is in the TMU blending format
556 * (32, f16, or i16), and we need to customize it based on
557 * that.
558 *
559 * XXX: for compat alpha formats, we need the alpha field to
560 * be in the red channel.
561 */
562 sampler.border_colour_red =
563 util_float_to_half(cso->border_color.f[0]);
564 sampler.border_colour_green =
565 util_float_to_half(cso->border_color.f[1]);
566 sampler.border_colour_blue =
567 util_float_to_half(cso->border_color.f[2]);
568 sampler.border_colour_alpha =
569 util_float_to_half(cso->border_color.f[3]);
570 }
571
572 #else /* V3D_VERSION < 40 */
573 v3dx_pack(&so->p0, TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1, p0) {
574 p0.s_wrap_mode = translate_wrap(cso->wrap_s, either_nearest);
575 p0.t_wrap_mode = translate_wrap(cso->wrap_t, either_nearest);
576 p0.r_wrap_mode = translate_wrap(cso->wrap_r, either_nearest);
577 }
578
579 v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
580 tex.depth_compare_function = cso->compare_func;
581 tex.fixed_bias = cso->lod_bias;
582 }
583 #endif /* V3D_VERSION < 40 */
584 return so;
585 }
586
587 static void
vc5_sampler_states_bind(struct pipe_context * pctx,enum pipe_shader_type shader,unsigned start,unsigned nr,void ** hwcso)588 vc5_sampler_states_bind(struct pipe_context *pctx,
589 enum pipe_shader_type shader, unsigned start,
590 unsigned nr, void **hwcso)
591 {
592 struct vc5_context *vc5 = vc5_context(pctx);
593 struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);
594
595 assert(start == 0);
596 unsigned i;
597 unsigned new_nr = 0;
598
599 for (i = 0; i < nr; i++) {
600 if (hwcso[i])
601 new_nr = i + 1;
602 stage_tex->samplers[i] = hwcso[i];
603 }
604
605 for (; i < stage_tex->num_samplers; i++) {
606 stage_tex->samplers[i] = NULL;
607 }
608
609 stage_tex->num_samplers = new_nr;
610 }
611
612 static void
vc5_sampler_state_delete(struct pipe_context * pctx,void * hwcso)613 vc5_sampler_state_delete(struct pipe_context *pctx,
614 void *hwcso)
615 {
616 struct pipe_sampler_state *psampler = hwcso;
617 struct vc5_sampler_state *sampler = vc5_sampler_state(psampler);
618
619 vc5_bo_unreference(&sampler->bo);
620 free(psampler);
621 }
622
623 #if V3D_VERSION >= 40
624 static uint32_t
translate_swizzle(unsigned char pipe_swizzle)625 translate_swizzle(unsigned char pipe_swizzle)
626 {
627 switch (pipe_swizzle) {
628 case PIPE_SWIZZLE_0:
629 return 0;
630 case PIPE_SWIZZLE_1:
631 return 1;
632 case PIPE_SWIZZLE_X:
633 case PIPE_SWIZZLE_Y:
634 case PIPE_SWIZZLE_Z:
635 case PIPE_SWIZZLE_W:
636 return 2 + pipe_swizzle;
637 default:
638 unreachable("unknown swizzle");
639 }
640 }
641 #endif
642
643 static struct pipe_sampler_view *
vc5_create_sampler_view(struct pipe_context * pctx,struct pipe_resource * prsc,const struct pipe_sampler_view * cso)644 vc5_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
645 const struct pipe_sampler_view *cso)
646 {
647 struct vc5_context *vc5 = vc5_context(pctx);
648 struct vc5_screen *screen = vc5->screen;
649 struct vc5_sampler_view *so = CALLOC_STRUCT(vc5_sampler_view);
650 struct vc5_resource *rsc = vc5_resource(prsc);
651
652 if (!so)
653 return NULL;
654
655 so->base = *cso;
656
657 pipe_reference(NULL, &prsc->reference);
658
659 /* Compute the sampler view's swizzle up front. This will be plugged
660 * into either the sampler (for 16-bit returns) or the shader's
661 * texture key (for 32)
662 */
663 uint8_t view_swizzle[4] = {
664 cso->swizzle_r,
665 cso->swizzle_g,
666 cso->swizzle_b,
667 cso->swizzle_a
668 };
669 const uint8_t *fmt_swizzle =
670 vc5_get_format_swizzle(&screen->devinfo, so->base.format);
671 util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
672
673 so->base.texture = prsc;
674 so->base.reference.count = 1;
675 so->base.context = pctx;
676
677 int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
678
679 #if V3D_VERSION >= 40
680 so->bo = vc5_bo_alloc(vc5->screen, cl_packet_length(SAMPLER_STATE),
681 "sampler");
682 void *map = vc5_bo_map(so->bo);
683
684 v3dx_pack(map, TEXTURE_SHADER_STATE, tex) {
685 #else /* V3D_VERSION < 40 */
686 v3dx_pack(&so->texture_shader_state, TEXTURE_SHADER_STATE, tex) {
687 #endif
688
689 tex.image_width = prsc->width0 * msaa_scale;
690 tex.image_height = prsc->height0 * msaa_scale;
691
692 #if V3D_VERSION >= 40
693 /* On 4.x, the height of a 1D texture is redefined to be the
694 * upper 14 bits of the width (which is only usable with txf).
695 */
696 if (prsc->target == PIPE_TEXTURE_1D ||
697 prsc->target == PIPE_TEXTURE_1D_ARRAY) {
698 tex.image_height = tex.image_width >> 14;
699 }
700 #endif
701
702 if (prsc->target == PIPE_TEXTURE_3D) {
703 tex.image_depth = prsc->depth0;
704 } else {
705 tex.image_depth = (cso->u.tex.last_layer -
706 cso->u.tex.first_layer) + 1;
707 }
708
709 tex.srgb = util_format_is_srgb(cso->format);
710
711 tex.base_level = cso->u.tex.first_level;
712 #if V3D_VERSION >= 40
713 tex.max_level = cso->u.tex.last_level;
714 /* Note that we don't have a job to reference the texture's sBO
715 * at state create time, so any time this sampler view is used
716 * we need to add the texture to the job.
717 */
718 tex.texture_base_pointer = cl_address(NULL,
719 rsc->bo->offset +
720 rsc->slices[0].offset),
721
722 tex.swizzle_r = translate_swizzle(so->swizzle[0]);
723 tex.swizzle_g = translate_swizzle(so->swizzle[1]);
724 tex.swizzle_b = translate_swizzle(so->swizzle[2]);
725 tex.swizzle_a = translate_swizzle(so->swizzle[3]);
726 #endif
727 tex.array_stride_64_byte_aligned = rsc->cube_map_stride / 64;
728
729 if (prsc->nr_samples > 1) {
730 /* Using texture views to reinterpret formats on our
731 * MSAA textures won't work, because we don't lay out
732 * the bits in memory as it's expected -- for example,
733 * RGBA8 and RGB10_A2 are compatible in the
734 * ARB_texture_view spec, but in HW we lay them out as
735 * 32bpp RGBA8 and 64bpp RGBA16F. Just assert for now
736 * to catch failures.
737 */
738 assert(util_format_linear(cso->format) ==
739 util_format_linear(prsc->format));
740 uint32_t output_image_format =
741 vc5_get_rt_format(&screen->devinfo, cso->format);
742 uint32_t internal_type;
743 uint32_t internal_bpp;
744 vc5_get_internal_type_bpp_for_output_format(&screen->devinfo,
745 output_image_format,
746 &internal_type,
747 &internal_bpp);
748
749 switch (internal_type) {
750 case V3D_INTERNAL_TYPE_8:
751 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
752 break;
753 case V3D_INTERNAL_TYPE_16F:
754 tex.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
755 break;
756 default:
757 unreachable("Bad MSAA texture type");
758 }
759
760 /* sRGB was stored in the tile buffer as linear and
761 * would have been encoded to sRGB on resolved tile
762 * buffer store. Note that this means we would need
763 * shader code if we wanted to read an MSAA sRGB
764 * texture without sRGB decode.
765 */
766 tex.srgb = false;
767 } else {
768 tex.texture_type = vc5_get_tex_format(&screen->devinfo,
769 cso->format);
770 }
771
772 tex.uif_xor_disable = (rsc->slices[0].tiling ==
773 VC5_TILING_UIF_NO_XOR);
774
775 /* Since other platform devices may produce UIF images even
776 * when they're not big enough for V3D to assume they're UIF,
777 * we force images with level 0 as UIF to be always treated
778 * that way.
779 */
780 tex.level_0_is_strictly_uif = (rsc->slices[0].tiling ==
781 VC5_TILING_UIF_XOR ||
782 rsc->slices[0].tiling ==
783 VC5_TILING_UIF_NO_XOR);
784 tex.level_0_xor_enable = (rsc->slices[0].tiling ==
785 VC5_TILING_UIF_XOR);
786
787 #if V3D_VERSION >= 40
788 if (tex.uif_xor_disable ||
789 tex.level_0_is_strictly_uif) {
790 tex.extended = true;
791 }
792 #endif /* V3D_VERSION >= 40 */
793 };
794
795 return &so->base;
796 }
797
798 static void
799 vc5_sampler_view_destroy(struct pipe_context *pctx,
800 struct pipe_sampler_view *psview)
801 {
802 struct vc5_sampler_view *sview = vc5_sampler_view(psview);
803
804 vc5_bo_unreference(&sview->bo);
805 pipe_resource_reference(&psview->texture, NULL);
806 free(psview);
807 }
808
809 static void
810 vc5_set_sampler_views(struct pipe_context *pctx,
811 enum pipe_shader_type shader,
812 unsigned start, unsigned nr,
813 struct pipe_sampler_view **views)
814 {
815 struct vc5_context *vc5 = vc5_context(pctx);
816 struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);
817 unsigned i;
818 unsigned new_nr = 0;
819
820 assert(start == 0);
821
822 for (i = 0; i < nr; i++) {
823 if (views[i])
824 new_nr = i + 1;
825 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
826 }
827
828 for (; i < stage_tex->num_textures; i++) {
829 pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
830 }
831
832 stage_tex->num_textures = new_nr;
833 }
834
835 static struct pipe_stream_output_target *
836 vc5_create_stream_output_target(struct pipe_context *pctx,
837 struct pipe_resource *prsc,
838 unsigned buffer_offset,
839 unsigned buffer_size)
840 {
841 struct pipe_stream_output_target *target;
842
843 target = CALLOC_STRUCT(pipe_stream_output_target);
844 if (!target)
845 return NULL;
846
847 pipe_reference_init(&target->reference, 1);
848 pipe_resource_reference(&target->buffer, prsc);
849
850 target->context = pctx;
851 target->buffer_offset = buffer_offset;
852 target->buffer_size = buffer_size;
853
854 return target;
855 }
856
857 static void
858 vc5_stream_output_target_destroy(struct pipe_context *pctx,
859 struct pipe_stream_output_target *target)
860 {
861 pipe_resource_reference(&target->buffer, NULL);
862 free(target);
863 }
864
865 static void
866 vc5_set_stream_output_targets(struct pipe_context *pctx,
867 unsigned num_targets,
868 struct pipe_stream_output_target **targets,
869 const unsigned *offsets)
870 {
871 struct vc5_context *ctx = vc5_context(pctx);
872 struct vc5_streamout_stateobj *so = &ctx->streamout;
873 unsigned i;
874
875 assert(num_targets <= ARRAY_SIZE(so->targets));
876
877 for (i = 0; i < num_targets; i++)
878 pipe_so_target_reference(&so->targets[i], targets[i]);
879
880 for (; i < so->num_targets; i++)
881 pipe_so_target_reference(&so->targets[i], NULL);
882
883 so->num_targets = num_targets;
884
885 ctx->dirty |= VC5_DIRTY_STREAMOUT;
886 }
887
888 void
889 v3dX(state_init)(struct pipe_context *pctx)
890 {
891 pctx->set_blend_color = vc5_set_blend_color;
892 pctx->set_stencil_ref = vc5_set_stencil_ref;
893 pctx->set_clip_state = vc5_set_clip_state;
894 pctx->set_sample_mask = vc5_set_sample_mask;
895 pctx->set_constant_buffer = vc5_set_constant_buffer;
896 pctx->set_framebuffer_state = vc5_set_framebuffer_state;
897 pctx->set_polygon_stipple = vc5_set_polygon_stipple;
898 pctx->set_scissor_states = vc5_set_scissor_states;
899 pctx->set_viewport_states = vc5_set_viewport_states;
900
901 pctx->set_vertex_buffers = vc5_set_vertex_buffers;
902
903 pctx->create_blend_state = vc5_create_blend_state;
904 pctx->bind_blend_state = vc5_blend_state_bind;
905 pctx->delete_blend_state = vc5_generic_cso_state_delete;
906
907 pctx->create_rasterizer_state = vc5_create_rasterizer_state;
908 pctx->bind_rasterizer_state = vc5_rasterizer_state_bind;
909 pctx->delete_rasterizer_state = vc5_generic_cso_state_delete;
910
911 pctx->create_depth_stencil_alpha_state = vc5_create_depth_stencil_alpha_state;
912 pctx->bind_depth_stencil_alpha_state = vc5_zsa_state_bind;
913 pctx->delete_depth_stencil_alpha_state = vc5_generic_cso_state_delete;
914
915 pctx->create_vertex_elements_state = vc5_vertex_state_create;
916 pctx->delete_vertex_elements_state = vc5_generic_cso_state_delete;
917 pctx->bind_vertex_elements_state = vc5_vertex_state_bind;
918
919 pctx->create_sampler_state = vc5_create_sampler_state;
920 pctx->delete_sampler_state = vc5_sampler_state_delete;
921 pctx->bind_sampler_states = vc5_sampler_states_bind;
922
923 pctx->create_sampler_view = vc5_create_sampler_view;
924 pctx->sampler_view_destroy = vc5_sampler_view_destroy;
925 pctx->set_sampler_views = vc5_set_sampler_views;
926
927 pctx->create_stream_output_target = vc5_create_stream_output_target;
928 pctx->stream_output_target_destroy = vc5_stream_output_target_destroy;
929 pctx->set_stream_output_targets = vc5_set_stream_output_targets;
930 }
931