2 * Copyright © 2014-2017 Broadcom
3 * Copyright (C) 2012 Rob Clark <robclark@freedesktop.org>
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:
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
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
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"
34 #include "v3d_context.h"
35 #include "v3d_tiling.h"
36 #include "broadcom/common/v3d_macros.h"
37 #include "broadcom/cle/v3dx_pack.h"
40 v3d_generic_cso_state_delete(struct pipe_context
*pctx
, void *hwcso
)
46 v3d_set_blend_color(struct pipe_context
*pctx
,
47 const struct pipe_blend_color
*blend_color
)
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
]);
55 v3d
->dirty
|= VC5_DIRTY_BLEND_COLOR
;
59 v3d_set_stencil_ref(struct pipe_context
*pctx
,
60 const struct pipe_stencil_ref
*stencil_ref
)
62 struct v3d_context
*v3d
= v3d_context(pctx
);
63 v3d
->stencil_ref
= *stencil_ref
;
64 v3d
->dirty
|= VC5_DIRTY_STENCIL_REF
;
68 v3d_set_clip_state(struct pipe_context
*pctx
,
69 const struct pipe_clip_state
*clip
)
71 struct v3d_context
*v3d
= v3d_context(pctx
);
73 v3d
->dirty
|= VC5_DIRTY_CLIP
;
77 v3d_set_sample_mask(struct pipe_context
*pctx
, unsigned sample_mask
)
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
;
85 float_to_187_half(float f
)
91 v3d_create_rasterizer_state(struct pipe_context
*pctx
,
92 const struct pipe_rasterizer_state
*cso
)
94 struct v3d_rasterizer_state
*so
;
96 so
= CALLOC_STRUCT(v3d_rasterizer_state
);
102 /* Workaround: HW-2726 PTB does not handle zero-size points (BCM2835,
105 so
->point_size
= MAX2(cso
->point_size
, .125f
);
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
);
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.
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);
129 /* Blend state is baked into shaders. */
131 v3d_create_blend_state(struct pipe_context
*pctx
,
132 const struct pipe_blend_state
*cso
)
134 struct v3d_blend_state
*so
;
136 so
= CALLOC_STRUCT(v3d_blend_state
);
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
;
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
);
151 if (cso
->rt
[0].blend_enable
)
152 so
->blend_enables
= (1 << VC5_MAX_DRAW_BUFFERS
) - 1;
159 translate_stencil_op(enum pipe_stencil_op 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
;
171 unreachable("bad stencil op");
175 v3d_create_depth_stencil_alpha_state(struct pipe_context
*pctx
,
176 const struct pipe_depth_stencil_alpha_state
*cso
)
178 struct v3d_depth_stencil_alpha_state
*so
;
180 so
= CALLOC_STRUCT(v3d_depth_stencil_alpha_state
);
186 if (cso
->depth
.enabled
) {
187 switch (cso
->depth
.func
) {
189 case PIPE_FUNC_LEQUAL
:
190 so
->ez_state
= VC5_EZ_LT_LE
;
192 case PIPE_FUNC_GREATER
:
193 case PIPE_FUNC_GEQUAL
:
194 so
->ez_state
= VC5_EZ_GT_GE
;
196 case PIPE_FUNC_NEVER
:
197 case PIPE_FUNC_EQUAL
:
198 so
->ez_state
= VC5_EZ_UNDECIDED
;
201 so
->ez_state
= VC5_EZ_DISABLED
;
205 /* If stencil is enabled and it's not a no-op, then it would
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
;
218 const struct pipe_stencil_state
*front
= &cso
->stencil
[0];
219 const struct pipe_stencil_state
*back
= &cso
->stencil
[1];
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.
229 config
.back_config
= !back
->enabled
;
231 config
.stencil_write_mask
= front
->writemask
;
232 config
.stencil_test_mask
= front
->valuemask
;
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
);
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;
250 config
.stencil_write_mask
= back
->writemask
;
251 config
.stencil_test_mask
= back
->valuemask
;
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
);
267 v3d_set_polygon_stipple(struct pipe_context
*pctx
,
268 const struct pipe_poly_stipple
*stipple
)
270 struct v3d_context
*v3d
= v3d_context(pctx
);
271 v3d
->stipple
= *stipple
;
272 v3d
->dirty
|= VC5_DIRTY_STIPPLE
;
276 v3d_set_scissor_states(struct pipe_context
*pctx
,
278 unsigned num_scissors
,
279 const struct pipe_scissor_state
*scissor
)
281 struct v3d_context
*v3d
= v3d_context(pctx
);
283 v3d
->scissor
= *scissor
;
284 v3d
->dirty
|= VC5_DIRTY_SCISSOR
;
288 v3d_set_viewport_states(struct pipe_context
*pctx
,
290 unsigned num_viewports
,
291 const struct pipe_viewport_state
*viewport
)
293 struct v3d_context
*v3d
= v3d_context(pctx
);
294 v3d
->viewport
= *viewport
;
295 v3d
->dirty
|= VC5_DIRTY_VIEWPORT
;
299 v3d_set_vertex_buffers(struct pipe_context
*pctx
,
300 unsigned start_slot
, unsigned count
,
301 const struct pipe_vertex_buffer
*vb
)
303 struct v3d_context
*v3d
= v3d_context(pctx
);
304 struct v3d_vertexbuf_stateobj
*so
= &v3d
->vertexbuf
;
306 util_set_vertex_buffers_mask(so
->vb
, &so
->enabled_mask
, vb
,
308 so
->count
= util_last_bit(so
->enabled_mask
);
310 v3d
->dirty
|= VC5_DIRTY_VTXBUF
;
314 v3d_blend_state_bind(struct pipe_context
*pctx
, void *hwcso
)
316 struct v3d_context
*v3d
= v3d_context(pctx
);
318 v3d
->dirty
|= VC5_DIRTY_BLEND
;
322 v3d_rasterizer_state_bind(struct pipe_context
*pctx
, void *hwcso
)
324 struct v3d_context
*v3d
= v3d_context(pctx
);
325 v3d
->rasterizer
= hwcso
;
326 v3d
->dirty
|= VC5_DIRTY_RASTERIZER
;
330 v3d_zsa_state_bind(struct pipe_context
*pctx
, void *hwcso
)
332 struct v3d_context
*v3d
= v3d_context(pctx
);
334 v3d
->dirty
|= VC5_DIRTY_ZSA
;
338 v3d_vertex_state_create(struct pipe_context
*pctx
, unsigned num_elements
,
339 const struct pipe_vertex_element
*elements
)
341 struct v3d_context
*v3d
= v3d_context(pctx
);
342 struct v3d_vertex_stateobj
*so
= CALLOC_STRUCT(v3d_vertex_stateobj
);
347 memcpy(so
->pipe
, elements
, sizeof(*elements
) * num_elements
);
348 so
->num_elements
= num_elements
;
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
;
356 const uint32_t size
=
357 cl_packet_length(GL_SHADER_STATE_ATTRIBUTE_RECORD
);
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
);
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
,
371 switch (desc
->channel
[0].type
) {
372 case UTIL_FORMAT_TYPE_FLOAT
:
374 attr
.type
= ATTRIBUTE_FLOAT
;
376 assert(r_size
== 16);
377 attr
.type
= ATTRIBUTE_HALF_FLOAT
;
381 case UTIL_FORMAT_TYPE_SIGNED
:
382 case UTIL_FORMAT_TYPE_UNSIGNED
:
385 attr
.type
= ATTRIBUTE_INT
;
388 attr
.type
= ATTRIBUTE_SHORT
;
391 attr
.type
= ATTRIBUTE_INT2_10_10_10
;
394 attr
.type
= ATTRIBUTE_BYTE
;
398 "format %s unsupported\n",
400 attr
.type
= ATTRIBUTE_BYTE
;
407 "format %s unsupported\n",
414 /* Set up the default attribute values in case any of the vertex
417 so
->default_attribute_values
= v3d_bo_alloc(v3d
->screen
,
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;
430 attrs
[i
* 4 + 3] = fui(1.0);
438 v3d_vertex_state_delete(struct pipe_context
*pctx
, void *hwcso
)
440 struct v3d_vertex_stateobj
*so
= hwcso
;
442 v3d_bo_unreference(&so
->default_attribute_values
);
447 v3d_vertex_state_bind(struct pipe_context
*pctx
, void *hwcso
)
449 struct v3d_context
*v3d
= v3d_context(pctx
);
451 v3d
->dirty
|= VC5_DIRTY_VTXSTATE
;
455 v3d_set_constant_buffer(struct pipe_context
*pctx
, uint shader
, uint index
,
456 const struct pipe_constant_buffer
*cb
)
458 struct v3d_context
*v3d
= v3d_context(pctx
);
459 struct v3d_constbuf_stateobj
*so
= &v3d
->constbuf
[shader
];
461 util_copy_constant_buffer(&so
->cb
[index
], cb
);
463 /* Note that the state tracker can unbind constant buffers by
467 so
->enabled_mask
&= ~(1 << index
);
468 so
->dirty_mask
&= ~(1 << index
);
472 so
->enabled_mask
|= 1 << index
;
473 so
->dirty_mask
|= 1 << index
;
474 v3d
->dirty
|= VC5_DIRTY_CONSTBUF
;
478 v3d_set_framebuffer_state(struct pipe_context
*pctx
,
479 const struct pipe_framebuffer_state
*framebuffer
)
481 struct v3d_context
*v3d
= v3d_context(pctx
);
482 struct pipe_framebuffer_state
*cso
= &v3d
->framebuffer
;
486 util_copy_framebuffer_state(cso
, framebuffer
);
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
];
495 const struct util_format_description
*desc
=
496 util_format_description(cbuf
->format
);
498 /* For BGRA8 formats (DRI window system default format), we
499 * need to swap R and B, since the HW's format is RGBA8.
501 if (desc
->swizzle
[0] == PIPE_SWIZZLE_Z
&&
502 cbuf
->format
!= PIPE_FORMAT_B5G6R5_UNORM
) {
503 v3d
->swap_color_rb
|= 1 << i
;
506 if (desc
->swizzle
[3] == PIPE_SWIZZLE_1
)
507 v3d
->blend_dst_alpha_one
|= 1 << i
;
510 v3d
->dirty
|= VC5_DIRTY_FRAMEBUFFER
;
513 static struct v3d_texture_stateobj
*
514 v3d_get_stage_tex(struct v3d_context
*v3d
, enum pipe_shader_type shader
)
517 case PIPE_SHADER_FRAGMENT
:
518 v3d
->dirty
|= VC5_DIRTY_FRAGTEX
;
519 return &v3d
->fragtex
;
521 case PIPE_SHADER_VERTEX
:
522 v3d
->dirty
|= VC5_DIRTY_VERTTEX
;
523 return &v3d
->verttex
;
526 fprintf(stderr
, "Unknown shader target %d\n", shader
);
531 static uint32_t translate_wrap(uint32_t pipe_wrap
, bool using_nearest
)
534 case PIPE_TEX_WRAP_REPEAT
:
536 case PIPE_TEX_WRAP_CLAMP_TO_EDGE
:
538 case PIPE_TEX_WRAP_MIRROR_REPEAT
:
540 case PIPE_TEX_WRAP_CLAMP_TO_BORDER
:
542 case PIPE_TEX_WRAP_CLAMP
:
543 return (using_nearest
? 1 : 3);
545 unreachable("Unknown wrap mode");
551 v3d_create_sampler_state(struct pipe_context
*pctx
,
552 const struct pipe_sampler_state
*cso
)
554 MAYBE_UNUSED
struct v3d_context
*v3d
= v3d_context(pctx
);
555 struct v3d_sampler_state
*so
= CALLOC_STRUCT(v3d_sampler_state
);
560 memcpy(so
, cso
, sizeof(*cso
));
562 bool either_nearest
=
563 (cso
->mag_img_filter
== PIPE_TEX_MIPFILTER_NEAREST
||
564 cso
->min_img_filter
== PIPE_TEX_MIPFILTER_NEAREST
);
566 #if V3D_VERSION >= 40
567 so
->bo
= v3d_bo_alloc(v3d
->screen
, cl_packet_length(SAMPLER_STATE
),
569 void *map
= v3d_bo_map(so
->bo
);
571 v3dx_pack(map
, SAMPLER_STATE
, sampler
) {
572 sampler
.wrap_i_border
= false;
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
);
578 sampler
.fixed_bias
= cso
->lod_bias
;
579 sampler
.depth_compare_function
= cso
->compare_func
;
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
;
588 sampler
.min_level_of_detail
= MIN2(MAX2(0, cso
->min_lod
),
590 sampler
.max_level_of_detail
= MIN2(cso
->max_lod
, 15);
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.
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);
605 if (cso
->max_anisotropy
) {
606 sampler
.anisotropy_enable
= true;
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;
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
621 * XXX: for compat alpha formats, we need the alpha field to
622 * be in the red channel.
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]);
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
);
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
;
645 #endif /* V3D_VERSION < 40 */
650 v3d_sampler_states_bind(struct pipe_context
*pctx
,
651 enum pipe_shader_type shader
, unsigned start
,
652 unsigned nr
, void **hwcso
)
654 struct v3d_context
*v3d
= v3d_context(pctx
);
655 struct v3d_texture_stateobj
*stage_tex
= v3d_get_stage_tex(v3d
, shader
);
661 for (i
= 0; i
< nr
; i
++) {
664 stage_tex
->samplers
[i
] = hwcso
[i
];
667 for (; i
< stage_tex
->num_samplers
; i
++) {
668 stage_tex
->samplers
[i
] = NULL
;
671 stage_tex
->num_samplers
= new_nr
;
675 v3d_sampler_state_delete(struct pipe_context
*pctx
,
678 struct pipe_sampler_state
*psampler
= hwcso
;
679 struct v3d_sampler_state
*sampler
= v3d_sampler_state(psampler
);
681 v3d_bo_unreference(&sampler
->bo
);
685 #if V3D_VERSION >= 40
687 translate_swizzle(unsigned char pipe_swizzle
)
689 switch (pipe_swizzle
) {
698 return 2 + pipe_swizzle
;
700 unreachable("unknown swizzle");
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
)
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
);
719 pipe_reference(NULL
, &prsc
->reference
);
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)
725 uint8_t view_swizzle
[4] = {
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
);
735 so
->base
.texture
= prsc
;
736 so
->base
.reference
.count
= 1;
737 so
->base
.context
= pctx
;
739 int msaa_scale
= prsc
->nr_samples
> 1 ? 2 : 1;
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
);
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
) {
753 tex
.image_width
= prsc
->width0
* msaa_scale
;
754 tex
.image_height
= prsc
->height0
* msaa_scale
;
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).
760 if (prsc
->target
== PIPE_TEXTURE_1D
||
761 prsc
->target
== PIPE_TEXTURE_1D_ARRAY
) {
762 tex
.image_height
= tex
.image_width
>> 14;
766 if (prsc
->target
== PIPE_TEXTURE_3D
) {
767 tex
.image_depth
= prsc
->depth0
;
769 tex
.image_depth
= (cso
->u
.tex
.last_layer
-
770 cso
->u
.tex
.first_layer
) + 1;
773 tex
.srgb
= util_format_is_srgb(cso
->format
);
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.
782 tex
.texture_base_pointer
= cl_address(NULL
,
784 rsc
->slices
[0].offset
+
785 cso
->u
.tex
.first_layer
*
786 rsc
->cube_map_stride
),
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]);
793 tex
.array_stride_64_byte_aligned
= rsc
->cube_map_stride
/ 64;
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
804 * We explicitly allow remapping S8Z24 to RGBA8888 for
805 * v3d_blit.c's stencil blits.
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
,
820 switch (internal_type
) {
821 case V3D_INTERNAL_TYPE_8
:
822 tex
.texture_type
= TEXTURE_DATA_FORMAT_RGBA8
;
824 case V3D_INTERNAL_TYPE_16F
:
825 tex
.texture_type
= TEXTURE_DATA_FORMAT_RGBA16F
;
828 unreachable("Bad MSAA texture type");
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.
839 tex
.texture_type
= v3d_get_tex_format(&screen
->devinfo
,
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
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
==
855 if (tex
.level_0_is_strictly_uif
)
856 tex
.level_0_ub_pad
= rsc
->slices
[0].ub_pad
;
858 #if V3D_VERSION >= 40
859 if (tex
.uif_xor_disable
||
860 tex
.level_0_is_strictly_uif
) {
863 #endif /* V3D_VERSION >= 40 */
870 v3d_sampler_view_destroy(struct pipe_context
*pctx
,
871 struct pipe_sampler_view
*psview
)
873 struct v3d_sampler_view
*sview
= v3d_sampler_view(psview
);
875 v3d_bo_unreference(&sview
->bo
);
876 pipe_resource_reference(&psview
->texture
, NULL
);
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
)
886 struct v3d_context
*v3d
= v3d_context(pctx
);
887 struct v3d_texture_stateobj
*stage_tex
= v3d_get_stage_tex(v3d
, shader
);
893 for (i
= 0; i
< nr
; i
++) {
896 pipe_sampler_view_reference(&stage_tex
->textures
[i
], views
[i
]);
899 for (; i
< stage_tex
->num_textures
; i
++) {
900 pipe_sampler_view_reference(&stage_tex
->textures
[i
], NULL
);
903 stage_tex
->num_textures
= new_nr
;
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
)
912 struct pipe_stream_output_target
*target
;
914 target
= CALLOC_STRUCT(pipe_stream_output_target
);
918 pipe_reference_init(&target
->reference
, 1);
919 pipe_resource_reference(&target
->buffer
, prsc
);
921 target
->context
= pctx
;
922 target
->buffer_offset
= buffer_offset
;
923 target
->buffer_size
= buffer_size
;
929 v3d_stream_output_target_destroy(struct pipe_context
*pctx
,
930 struct pipe_stream_output_target
*target
)
932 pipe_resource_reference(&target
->buffer
, NULL
);
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
)
942 struct v3d_context
*ctx
= v3d_context(pctx
);
943 struct v3d_streamout_stateobj
*so
= &ctx
->streamout
;
946 assert(num_targets
<= ARRAY_SIZE(so
->targets
));
948 for (i
= 0; i
< num_targets
; i
++) {
949 if (offsets
[i
] != -1)
950 so
->offsets
[i
] = offsets
[i
];
952 pipe_so_target_reference(&so
->targets
[i
], targets
[i
]);
955 for (; i
< so
->num_targets
; i
++)
956 pipe_so_target_reference(&so
->targets
[i
], NULL
);
958 so
->num_targets
= num_targets
;
960 ctx
->dirty
|= VC5_DIRTY_STREAMOUT
;
964 v3dX(state_init
)(struct pipe_context
*pctx
)
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
;
976 pctx
->set_vertex_buffers
= v3d_set_vertex_buffers
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;