broadcom/vc5: Force blending to treat alpha as 1 for formats without alpha.
[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/cle/v3d_packet_v33_pack.h"
35
36 static void *
37 vc5_generic_cso_state_create(const void *src, uint32_t size)
38 {
39 void *dst = calloc(1, size);
40 if (!dst)
41 return NULL;
42 memcpy(dst, src, size);
43 return dst;
44 }
45
46 static void
47 vc5_generic_cso_state_delete(struct pipe_context *pctx, void *hwcso)
48 {
49 free(hwcso);
50 }
51
52 static void
53 vc5_set_blend_color(struct pipe_context *pctx,
54 const struct pipe_blend_color *blend_color)
55 {
56 struct vc5_context *vc5 = vc5_context(pctx);
57 vc5->blend_color.f = *blend_color;
58 for (int i = 0; i < 4; i++) {
59 vc5->blend_color.hf[i] =
60 util_float_to_half(blend_color->color[i]);
61 }
62 vc5->dirty |= VC5_DIRTY_BLEND_COLOR;
63 }
64
65 static void
66 vc5_set_stencil_ref(struct pipe_context *pctx,
67 const struct pipe_stencil_ref *stencil_ref)
68 {
69 struct vc5_context *vc5 = vc5_context(pctx);
70 vc5->stencil_ref = *stencil_ref;
71 vc5->dirty |= VC5_DIRTY_STENCIL_REF;
72 }
73
74 static void
75 vc5_set_clip_state(struct pipe_context *pctx,
76 const struct pipe_clip_state *clip)
77 {
78 struct vc5_context *vc5 = vc5_context(pctx);
79 vc5->clip = *clip;
80 vc5->dirty |= VC5_DIRTY_CLIP;
81 }
82
83 static void
84 vc5_set_sample_mask(struct pipe_context *pctx, unsigned sample_mask)
85 {
86 struct vc5_context *vc5 = vc5_context(pctx);
87 vc5->sample_mask = sample_mask & ((1 << VC5_MAX_SAMPLES) - 1);
88 vc5->dirty |= VC5_DIRTY_SAMPLE_MASK;
89 }
90
91 static uint16_t
92 float_to_187_half(float f)
93 {
94 return fui(f) >> 16;
95 }
96
97 static void *
98 vc5_create_rasterizer_state(struct pipe_context *pctx,
99 const struct pipe_rasterizer_state *cso)
100 {
101 struct vc5_rasterizer_state *so;
102
103 so = CALLOC_STRUCT(vc5_rasterizer_state);
104 if (!so)
105 return NULL;
106
107 so->base = *cso;
108
109 /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
110 * BCM21553).
111 */
112 so->point_size = MAX2(cso->point_size, .125f);
113
114 if (cso->offset_tri) {
115 so->offset_units = float_to_187_half(cso->offset_units);
116 so->offset_factor = float_to_187_half(cso->offset_scale);
117 }
118
119 return so;
120 }
121
122 /* Blend state is baked into shaders. */
123 static void *
124 vc5_create_blend_state(struct pipe_context *pctx,
125 const struct pipe_blend_state *cso)
126 {
127 return vc5_generic_cso_state_create(cso, sizeof(*cso));
128 }
129
130 static void *
131 vc5_create_depth_stencil_alpha_state(struct pipe_context *pctx,
132 const struct pipe_depth_stencil_alpha_state *cso)
133 {
134 struct vc5_depth_stencil_alpha_state *so;
135
136 so = CALLOC_STRUCT(vc5_depth_stencil_alpha_state);
137 if (!so)
138 return NULL;
139
140 so->base = *cso;
141
142 if (cso->depth.enabled) {
143 /* We only handle early Z in the < direction because otherwise
144 * we'd have to runtime guess which direction to set in the
145 * render config.
146 */
147 so->early_z_enable =
148 ((cso->depth.func == PIPE_FUNC_LESS ||
149 cso->depth.func == PIPE_FUNC_LEQUAL) &&
150 (!cso->stencil[0].enabled ||
151 (cso->stencil[0].zfail_op == PIPE_STENCIL_OP_KEEP &&
152 (!cso->stencil[1].enabled ||
153 cso->stencil[1].zfail_op == PIPE_STENCIL_OP_KEEP))));
154 }
155
156 return so;
157 }
158
159 static void
160 vc5_set_polygon_stipple(struct pipe_context *pctx,
161 const struct pipe_poly_stipple *stipple)
162 {
163 struct vc5_context *vc5 = vc5_context(pctx);
164 vc5->stipple = *stipple;
165 vc5->dirty |= VC5_DIRTY_STIPPLE;
166 }
167
168 static void
169 vc5_set_scissor_states(struct pipe_context *pctx,
170 unsigned start_slot,
171 unsigned num_scissors,
172 const struct pipe_scissor_state *scissor)
173 {
174 struct vc5_context *vc5 = vc5_context(pctx);
175
176 vc5->scissor = *scissor;
177 vc5->dirty |= VC5_DIRTY_SCISSOR;
178 }
179
180 static void
181 vc5_set_viewport_states(struct pipe_context *pctx,
182 unsigned start_slot,
183 unsigned num_viewports,
184 const struct pipe_viewport_state *viewport)
185 {
186 struct vc5_context *vc5 = vc5_context(pctx);
187 vc5->viewport = *viewport;
188 vc5->dirty |= VC5_DIRTY_VIEWPORT;
189 }
190
191 static void
192 vc5_set_vertex_buffers(struct pipe_context *pctx,
193 unsigned start_slot, unsigned count,
194 const struct pipe_vertex_buffer *vb)
195 {
196 struct vc5_context *vc5 = vc5_context(pctx);
197 struct vc5_vertexbuf_stateobj *so = &vc5->vertexbuf;
198
199 util_set_vertex_buffers_mask(so->vb, &so->enabled_mask, vb,
200 start_slot, count);
201 so->count = util_last_bit(so->enabled_mask);
202
203 vc5->dirty |= VC5_DIRTY_VTXBUF;
204 }
205
206 static void
207 vc5_blend_state_bind(struct pipe_context *pctx, void *hwcso)
208 {
209 struct vc5_context *vc5 = vc5_context(pctx);
210 vc5->blend = hwcso;
211 vc5->dirty |= VC5_DIRTY_BLEND;
212 }
213
214 static void
215 vc5_rasterizer_state_bind(struct pipe_context *pctx, void *hwcso)
216 {
217 struct vc5_context *vc5 = vc5_context(pctx);
218 struct vc5_rasterizer_state *rast = hwcso;
219
220 if (vc5->rasterizer && rast &&
221 vc5->rasterizer->base.flatshade != rast->base.flatshade) {
222 vc5->dirty |= VC5_DIRTY_FLAT_SHADE_FLAGS;
223 }
224
225 vc5->rasterizer = hwcso;
226 vc5->dirty |= VC5_DIRTY_RASTERIZER;
227 }
228
229 static void
230 vc5_zsa_state_bind(struct pipe_context *pctx, void *hwcso)
231 {
232 struct vc5_context *vc5 = vc5_context(pctx);
233 vc5->zsa = hwcso;
234 vc5->dirty |= VC5_DIRTY_ZSA;
235 }
236
237 static void *
238 vc5_vertex_state_create(struct pipe_context *pctx, unsigned num_elements,
239 const struct pipe_vertex_element *elements)
240 {
241 struct vc5_context *vc5 = vc5_context(pctx);
242 struct vc5_vertex_stateobj *so = CALLOC_STRUCT(vc5_vertex_stateobj);
243
244 if (!so)
245 return NULL;
246
247 memcpy(so->pipe, elements, sizeof(*elements) * num_elements);
248 so->num_elements = num_elements;
249
250 for (int i = 0; i < so->num_elements; i++) {
251 const struct pipe_vertex_element *elem = &elements[i];
252 const struct util_format_description *desc =
253 util_format_description(elem->src_format);
254 uint32_t r_size = desc->channel[0].size;
255
256 struct V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD attr_unpacked = {
257 /* vec_size == 0 means 4 */
258 .vec_size = desc->nr_channels & 3,
259 .signed_int_type = (desc->channel[0].type ==
260 UTIL_FORMAT_TYPE_SIGNED),
261
262 .normalized_int_type = desc->channel[0].normalized,
263 .read_as_int_uint = desc->channel[0].pure_integer,
264 .instance_divisor = elem->instance_divisor,
265 };
266
267 switch (desc->channel[0].type) {
268 case UTIL_FORMAT_TYPE_FLOAT:
269 if (r_size == 32) {
270 attr_unpacked.type = ATTRIBUTE_FLOAT;
271 } else {
272 assert(r_size == 16);
273 attr_unpacked.type = ATTRIBUTE_HALF_FLOAT;
274 }
275 break;
276
277 case UTIL_FORMAT_TYPE_SIGNED:
278 case UTIL_FORMAT_TYPE_UNSIGNED:
279 switch (r_size) {
280 case 32:
281 attr_unpacked.type = ATTRIBUTE_INT;
282 break;
283 case 16:
284 attr_unpacked.type = ATTRIBUTE_SHORT;
285 break;
286 case 10:
287 attr_unpacked.type = ATTRIBUTE_INT2_10_10_10;
288 break;
289 case 8:
290 attr_unpacked.type = ATTRIBUTE_BYTE;
291 break;
292 default:
293 fprintf(stderr,
294 "format %s unsupported\n",
295 desc->name);
296 attr_unpacked.type = ATTRIBUTE_BYTE;
297 abort();
298 }
299 break;
300
301 default:
302 fprintf(stderr,
303 "format %s unsupported\n",
304 desc->name);
305 abort();
306 }
307
308 const uint32_t size =
309 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD);
310 V3D33_GL_SHADER_STATE_ATTRIBUTE_RECORD_pack(NULL,
311 (uint8_t *)&so->attrs[i * size],
312 &attr_unpacked);
313 }
314
315 /* Set up the default attribute values in case any of the vertex
316 * elements use them.
317 */
318 so->default_attribute_values = vc5_bo_alloc(vc5->screen,
319 VC5_MAX_ATTRIBUTES *
320 4 * sizeof(float),
321 "default attributes");
322 uint32_t *attrs = vc5_bo_map(so->default_attribute_values);
323 for (int i = 0; i < VC5_MAX_ATTRIBUTES; i++) {
324 attrs[i * 4 + 0] = 0;
325 attrs[i * 4 + 1] = 0;
326 attrs[i * 4 + 2] = 0;
327 if (i < so->num_elements &&
328 util_format_is_pure_integer(so->pipe[i].src_format)) {
329 attrs[i * 4 + 3] = 1;
330 } else {
331 attrs[i * 4 + 3] = fui(1.0);
332 }
333 }
334
335 return so;
336 }
337
338 static void
339 vc5_vertex_state_bind(struct pipe_context *pctx, void *hwcso)
340 {
341 struct vc5_context *vc5 = vc5_context(pctx);
342 vc5->vtx = hwcso;
343 vc5->dirty |= VC5_DIRTY_VTXSTATE;
344 }
345
346 static void
347 vc5_set_constant_buffer(struct pipe_context *pctx, uint shader, uint index,
348 const struct pipe_constant_buffer *cb)
349 {
350 struct vc5_context *vc5 = vc5_context(pctx);
351 struct vc5_constbuf_stateobj *so = &vc5->constbuf[shader];
352
353 util_copy_constant_buffer(&so->cb[index], cb);
354
355 /* Note that the state tracker can unbind constant buffers by
356 * passing NULL here.
357 */
358 if (unlikely(!cb)) {
359 so->enabled_mask &= ~(1 << index);
360 so->dirty_mask &= ~(1 << index);
361 return;
362 }
363
364 so->enabled_mask |= 1 << index;
365 so->dirty_mask |= 1 << index;
366 vc5->dirty |= VC5_DIRTY_CONSTBUF;
367 }
368
369 static void
370 vc5_set_framebuffer_state(struct pipe_context *pctx,
371 const struct pipe_framebuffer_state *framebuffer)
372 {
373 struct vc5_context *vc5 = vc5_context(pctx);
374 struct pipe_framebuffer_state *cso = &vc5->framebuffer;
375 unsigned i;
376
377 vc5->job = NULL;
378
379 for (i = 0; i < framebuffer->nr_cbufs; i++)
380 pipe_surface_reference(&cso->cbufs[i], framebuffer->cbufs[i]);
381 for (; i < vc5->framebuffer.nr_cbufs; i++)
382 pipe_surface_reference(&cso->cbufs[i], NULL);
383
384 cso->nr_cbufs = framebuffer->nr_cbufs;
385
386 pipe_surface_reference(&cso->zsbuf, framebuffer->zsbuf);
387
388 cso->width = framebuffer->width;
389 cso->height = framebuffer->height;
390
391 vc5->swap_color_rb = 0;
392 vc5->blend_dst_alpha_one = 0;
393 for (int i = 0; i < vc5->framebuffer.nr_cbufs; i++) {
394 struct pipe_surface *cbuf = vc5->framebuffer.cbufs[i];
395 const struct util_format_description *desc =
396 util_format_description(cbuf->format);
397
398 /* For BGRA8 formats (DRI window system default format), we
399 * need to swap R and B, since the HW's format is RGBA8.
400 */
401 if (desc->swizzle[0] == PIPE_SWIZZLE_Z &&
402 cbuf->format != PIPE_FORMAT_B5G6R5_UNORM) {
403 vc5->swap_color_rb |= 1 << i;
404 }
405
406 if (desc->swizzle[3] == PIPE_SWIZZLE_1)
407 vc5->blend_dst_alpha_one |= 1 << i;
408 }
409
410 vc5->dirty |= VC5_DIRTY_FRAMEBUFFER;
411 }
412
413 static struct vc5_texture_stateobj *
414 vc5_get_stage_tex(struct vc5_context *vc5, enum pipe_shader_type shader)
415 {
416 switch (shader) {
417 case PIPE_SHADER_FRAGMENT:
418 vc5->dirty |= VC5_DIRTY_FRAGTEX;
419 return &vc5->fragtex;
420 break;
421 case PIPE_SHADER_VERTEX:
422 vc5->dirty |= VC5_DIRTY_VERTTEX;
423 return &vc5->verttex;
424 break;
425 default:
426 fprintf(stderr, "Unknown shader target %d\n", shader);
427 abort();
428 }
429 }
430
431 static uint32_t translate_wrap(uint32_t pipe_wrap, bool using_nearest)
432 {
433 switch (pipe_wrap) {
434 case PIPE_TEX_WRAP_REPEAT:
435 return 0;
436 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
437 return 1;
438 case PIPE_TEX_WRAP_MIRROR_REPEAT:
439 return 2;
440 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
441 return 3;
442 case PIPE_TEX_WRAP_CLAMP:
443 return (using_nearest ? 1 : 3);
444 default:
445 unreachable("Unknown wrap mode");
446 }
447 }
448
449
450 static void *
451 vc5_create_sampler_state(struct pipe_context *pctx,
452 const struct pipe_sampler_state *cso)
453 {
454 struct vc5_sampler_state *so = CALLOC_STRUCT(vc5_sampler_state);
455
456 if (!so)
457 return NULL;
458
459 memcpy(so, cso, sizeof(*cso));
460
461 bool either_nearest =
462 (cso->mag_img_filter == PIPE_TEX_MIPFILTER_NEAREST ||
463 cso->min_img_filter == PIPE_TEX_MIPFILTER_NEAREST);
464
465 struct V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1 p0_unpacked = {
466 .s_wrap_mode = translate_wrap(cso->wrap_s, either_nearest),
467 .t_wrap_mode = translate_wrap(cso->wrap_t, either_nearest),
468 .r_wrap_mode = translate_wrap(cso->wrap_r, either_nearest),
469 };
470 V3D33_TEXTURE_UNIFORM_PARAMETER_0_CFG_MODE1_pack(NULL,
471 (uint8_t *)&so->p0,
472 &p0_unpacked);
473
474 struct V3D33_TEXTURE_SHADER_STATE state_unpacked = {
475 cl_packet_header(TEXTURE_SHADER_STATE),
476
477 .min_level_of_detail = MAX2(cso->min_lod, 0.0),
478 .depth_compare_function = cso->compare_func,
479 .fixed_bias = cso->lod_bias,
480 };
481 STATIC_ASSERT(ARRAY_SIZE(so->texture_shader_state) ==
482 cl_packet_length(TEXTURE_SHADER_STATE));
483 cl_packet_pack(TEXTURE_SHADER_STATE)(NULL, so->texture_shader_state,
484 &state_unpacked);
485
486 return so;
487 }
488
489 static void
490 vc5_sampler_states_bind(struct pipe_context *pctx,
491 enum pipe_shader_type shader, unsigned start,
492 unsigned nr, void **hwcso)
493 {
494 struct vc5_context *vc5 = vc5_context(pctx);
495 struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);
496
497 assert(start == 0);
498 unsigned i;
499 unsigned new_nr = 0;
500
501 for (i = 0; i < nr; i++) {
502 if (hwcso[i])
503 new_nr = i + 1;
504 stage_tex->samplers[i] = hwcso[i];
505 }
506
507 for (; i < stage_tex->num_samplers; i++) {
508 stage_tex->samplers[i] = NULL;
509 }
510
511 stage_tex->num_samplers = new_nr;
512 }
513
514 static uint32_t
515 translate_swizzle(unsigned char pipe_swizzle)
516 {
517 switch (pipe_swizzle) {
518 case PIPE_SWIZZLE_0:
519 return 0;
520 case PIPE_SWIZZLE_1:
521 return 1;
522 case PIPE_SWIZZLE_X:
523 case PIPE_SWIZZLE_Y:
524 case PIPE_SWIZZLE_Z:
525 case PIPE_SWIZZLE_W:
526 return 2 + pipe_swizzle;
527 default:
528 unreachable("unknown swizzle");
529 }
530 }
531
532 static struct pipe_sampler_view *
533 vc5_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *prsc,
534 const struct pipe_sampler_view *cso)
535 {
536 struct vc5_sampler_view *so = CALLOC_STRUCT(vc5_sampler_view);
537 struct vc5_resource *rsc = vc5_resource(prsc);
538
539 if (!so)
540 return NULL;
541
542 so->base = *cso;
543
544 pipe_reference(NULL, &prsc->reference);
545
546 struct V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1 unpacked = {
547 };
548
549 unpacked.return_word_0_of_texture_data = true;
550 if (vc5_get_tex_return_size(cso->format) == 16) {
551 unpacked.return_word_1_of_texture_data = true;
552 } else {
553 int chans = vc5_get_tex_return_channels(cso->format);
554
555 if (chans > 1)
556 unpacked.return_word_1_of_texture_data = true;
557 if (chans > 2)
558 unpacked.return_word_2_of_texture_data = true;
559 if (chans > 3)
560 unpacked.return_word_3_of_texture_data = true;
561 }
562
563 V3D33_TEXTURE_UNIFORM_PARAMETER_1_CFG_MODE1_pack(NULL,
564 (uint8_t *)&so->p1,
565 &unpacked);
566
567 /* Compute the sampler view's swizzle up front. This will be plugged
568 * into either the sampler (for 16-bit returns) or the shader's
569 * texture key (for 32)
570 */
571 uint8_t view_swizzle[4] = {
572 cso->swizzle_r,
573 cso->swizzle_g,
574 cso->swizzle_b,
575 cso->swizzle_a
576 };
577 const uint8_t *fmt_swizzle = vc5_get_format_swizzle(so->base.format);
578 util_format_compose_swizzles(fmt_swizzle, view_swizzle, so->swizzle);
579
580 so->base.texture = prsc;
581 so->base.reference.count = 1;
582 so->base.context = pctx;
583
584 int msaa_scale = prsc->nr_samples > 1 ? 2 : 1;
585
586 struct V3D33_TEXTURE_SHADER_STATE state_unpacked = {
587 cl_packet_header(TEXTURE_SHADER_STATE),
588
589 .image_width = prsc->width0 * msaa_scale,
590 .image_height = prsc->height0 * msaa_scale,
591 .image_depth = prsc->depth0,
592
593 .srgb = util_format_is_srgb(cso->format),
594
595 .base_level = cso->u.tex.first_level,
596 .array_stride_64_byte_aligned = rsc->cube_map_stride / 64,
597 };
598
599 if (prsc->nr_samples > 1) {
600 /* Using texture views to reinterpret formats on our MSAA
601 * textures won't work, because we don't lay out the bits in
602 * memory as it's expected -- for example, RGBA8 and RGB10_A2
603 * are compatible in the ARB_texture_view spec, but in HW we
604 * lay them out as 32bpp RGBA8 and 64bpp RGBA16F. Just assert
605 * for now to catch failures.
606 */
607 assert(util_format_linear(cso->format) ==
608 util_format_linear(prsc->format));
609 uint32_t output_image_format = vc5_get_rt_format(cso->format);
610 uint32_t internal_type;
611 uint32_t internal_bpp;
612 vc5_get_internal_type_bpp_for_output_format(output_image_format,
613 &internal_type,
614 &internal_bpp);
615
616 switch (internal_type) {
617 case INTERNAL_TYPE_8:
618 state_unpacked.texture_type = TEXTURE_DATA_FORMAT_RGBA8;
619 break;
620 case INTERNAL_TYPE_16F:
621 state_unpacked.texture_type = TEXTURE_DATA_FORMAT_RGBA16F;
622 break;
623 default:
624 unreachable("Bad MSAA texture type");
625 }
626
627 /* sRGB was stored in the tile buffer as linear and would have
628 * been encoded to sRGB on resolved tile buffer store. Note
629 * that this means we would need shader code if we wanted to
630 * read an MSAA sRGB texture without sRGB decode.
631 */
632 state_unpacked.srgb = false;
633 } else {
634 state_unpacked.texture_type = vc5_get_tex_format(cso->format);
635 }
636
637 /* Note: Contrary to the docs, the swizzle still applies even
638 * if the return size is 32. It's just that you probably want
639 * to swizzle in the shader, because you need the Y/Z/W
640 * channels to be defined.
641 */
642 if (vc5_get_tex_return_size(cso->format) != 32) {
643 state_unpacked.swizzle_r = translate_swizzle(so->swizzle[0]);
644 state_unpacked.swizzle_g = translate_swizzle(so->swizzle[1]);
645 state_unpacked.swizzle_b = translate_swizzle(so->swizzle[2]);
646 state_unpacked.swizzle_a = translate_swizzle(so->swizzle[3]);
647 } else {
648 state_unpacked.swizzle_r = translate_swizzle(PIPE_SWIZZLE_X);
649 state_unpacked.swizzle_g = translate_swizzle(PIPE_SWIZZLE_Y);
650 state_unpacked.swizzle_b = translate_swizzle(PIPE_SWIZZLE_Z);
651 state_unpacked.swizzle_a = translate_swizzle(PIPE_SWIZZLE_W);
652 }
653
654 /* XXX: While we need to use this flag to enable tiled
655 * resource sharing (even a small shared buffer should be UIF,
656 * not UBLINEAR or raster), this is also at the moment
657 * patching up the fact that our resource layout's decisions
658 * about XOR don't quite match the HW's.
659 */
660 switch (rsc->slices[0].tiling) {
661 case VC5_TILING_UIF_NO_XOR:
662 case VC5_TILING_UIF_XOR:
663 state_unpacked.level_0_is_strictly_uif = true;
664 state_unpacked.level_0_xor_enable = false;
665 break;
666 default:
667 break;
668 }
669
670 STATIC_ASSERT(ARRAY_SIZE(so->texture_shader_state) ==
671 cl_packet_length(TEXTURE_SHADER_STATE));
672 cl_packet_pack(TEXTURE_SHADER_STATE)(NULL, so->texture_shader_state,
673 &state_unpacked);
674
675 return &so->base;
676 }
677
678 static void
679 vc5_sampler_view_destroy(struct pipe_context *pctx,
680 struct pipe_sampler_view *view)
681 {
682 pipe_resource_reference(&view->texture, NULL);
683 free(view);
684 }
685
686 static void
687 vc5_set_sampler_views(struct pipe_context *pctx,
688 enum pipe_shader_type shader,
689 unsigned start, unsigned nr,
690 struct pipe_sampler_view **views)
691 {
692 struct vc5_context *vc5 = vc5_context(pctx);
693 struct vc5_texture_stateobj *stage_tex = vc5_get_stage_tex(vc5, shader);
694 unsigned i;
695 unsigned new_nr = 0;
696
697 assert(start == 0);
698
699 for (i = 0; i < nr; i++) {
700 if (views[i])
701 new_nr = i + 1;
702 pipe_sampler_view_reference(&stage_tex->textures[i], views[i]);
703 }
704
705 for (; i < stage_tex->num_textures; i++) {
706 pipe_sampler_view_reference(&stage_tex->textures[i], NULL);
707 }
708
709 stage_tex->num_textures = new_nr;
710 }
711
712 static struct pipe_stream_output_target *
713 vc5_create_stream_output_target(struct pipe_context *pctx,
714 struct pipe_resource *prsc,
715 unsigned buffer_offset,
716 unsigned buffer_size)
717 {
718 struct pipe_stream_output_target *target;
719
720 target = CALLOC_STRUCT(pipe_stream_output_target);
721 if (!target)
722 return NULL;
723
724 pipe_reference_init(&target->reference, 1);
725 pipe_resource_reference(&target->buffer, prsc);
726
727 target->context = pctx;
728 target->buffer_offset = buffer_offset;
729 target->buffer_size = buffer_size;
730
731 return target;
732 }
733
734 static void
735 vc5_stream_output_target_destroy(struct pipe_context *pctx,
736 struct pipe_stream_output_target *target)
737 {
738 pipe_resource_reference(&target->buffer, NULL);
739 free(target);
740 }
741
742 static void
743 vc5_set_stream_output_targets(struct pipe_context *pctx,
744 unsigned num_targets,
745 struct pipe_stream_output_target **targets,
746 const unsigned *offsets)
747 {
748 struct vc5_context *ctx = vc5_context(pctx);
749 struct vc5_streamout_stateobj *so = &ctx->streamout;
750 unsigned i;
751
752 assert(num_targets <= ARRAY_SIZE(so->targets));
753
754 for (i = 0; i < num_targets; i++)
755 pipe_so_target_reference(&so->targets[i], targets[i]);
756
757 for (; i < so->num_targets; i++)
758 pipe_so_target_reference(&so->targets[i], NULL);
759
760 so->num_targets = num_targets;
761
762 ctx->dirty |= VC5_DIRTY_STREAMOUT;
763 }
764
765 void
766 vc5_state_init(struct pipe_context *pctx)
767 {
768 pctx->set_blend_color = vc5_set_blend_color;
769 pctx->set_stencil_ref = vc5_set_stencil_ref;
770 pctx->set_clip_state = vc5_set_clip_state;
771 pctx->set_sample_mask = vc5_set_sample_mask;
772 pctx->set_constant_buffer = vc5_set_constant_buffer;
773 pctx->set_framebuffer_state = vc5_set_framebuffer_state;
774 pctx->set_polygon_stipple = vc5_set_polygon_stipple;
775 pctx->set_scissor_states = vc5_set_scissor_states;
776 pctx->set_viewport_states = vc5_set_viewport_states;
777
778 pctx->set_vertex_buffers = vc5_set_vertex_buffers;
779
780 pctx->create_blend_state = vc5_create_blend_state;
781 pctx->bind_blend_state = vc5_blend_state_bind;
782 pctx->delete_blend_state = vc5_generic_cso_state_delete;
783
784 pctx->create_rasterizer_state = vc5_create_rasterizer_state;
785 pctx->bind_rasterizer_state = vc5_rasterizer_state_bind;
786 pctx->delete_rasterizer_state = vc5_generic_cso_state_delete;
787
788 pctx->create_depth_stencil_alpha_state = vc5_create_depth_stencil_alpha_state;
789 pctx->bind_depth_stencil_alpha_state = vc5_zsa_state_bind;
790 pctx->delete_depth_stencil_alpha_state = vc5_generic_cso_state_delete;
791
792 pctx->create_vertex_elements_state = vc5_vertex_state_create;
793 pctx->delete_vertex_elements_state = vc5_generic_cso_state_delete;
794 pctx->bind_vertex_elements_state = vc5_vertex_state_bind;
795
796 pctx->create_sampler_state = vc5_create_sampler_state;
797 pctx->delete_sampler_state = vc5_generic_cso_state_delete;
798 pctx->bind_sampler_states = vc5_sampler_states_bind;
799
800 pctx->create_sampler_view = vc5_create_sampler_view;
801 pctx->sampler_view_destroy = vc5_sampler_view_destroy;
802 pctx->set_sampler_views = vc5_set_sampler_views;
803
804 pctx->create_stream_output_target = vc5_create_stream_output_target;
805 pctx->stream_output_target_destroy = vc5_stream_output_target_destroy;
806 pctx->set_stream_output_targets = vc5_set_stream_output_targets;
807 }