2 * Copyright (c) 2012-2015 Etnaviv Project
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
24 * Wladimir J. van der Laan <laanwj@gmail.com>
27 #include "etnaviv_texture_state.h"
29 #include "hw/common.xml.h"
31 #include "etnaviv_clear_blit.h"
32 #include "etnaviv_context.h"
33 #include "etnaviv_emit.h"
34 #include "etnaviv_format.h"
35 #include "etnaviv_texture.h"
36 #include "etnaviv_translate.h"
37 #include "util/u_inlines.h"
38 #include "util/u_memory.h"
40 #include <drm_fourcc.h>
43 etna_create_sampler_state_state(struct pipe_context
*pipe
,
44 const struct pipe_sampler_state
*ss
)
46 struct etna_sampler_state
*cs
= CALLOC_STRUCT(etna_sampler_state
);
51 cs
->TE_SAMPLER_CONFIG0
=
52 VIVS_TE_SAMPLER_CONFIG0_UWRAP(translate_texture_wrapmode(ss
->wrap_s
)) |
53 VIVS_TE_SAMPLER_CONFIG0_VWRAP(translate_texture_wrapmode(ss
->wrap_t
)) |
54 VIVS_TE_SAMPLER_CONFIG0_MIN(translate_texture_filter(ss
->min_img_filter
)) |
55 VIVS_TE_SAMPLER_CONFIG0_MIP(translate_texture_mipfilter(ss
->min_mip_filter
)) |
56 VIVS_TE_SAMPLER_CONFIG0_MAG(translate_texture_filter(ss
->mag_img_filter
)) |
57 COND(ss
->normalized_coords
, VIVS_TE_SAMPLER_CONFIG0_ROUND_UV
);
58 cs
->TE_SAMPLER_CONFIG1
= 0; /* VIVS_TE_SAMPLER_CONFIG1 (swizzle, extended
59 format) fully determined by sampler view */
60 cs
->TE_SAMPLER_LOD_CONFIG
=
61 COND(ss
->lod_bias
!= 0.0, VIVS_TE_SAMPLER_LOD_CONFIG_BIAS_ENABLE
) |
62 VIVS_TE_SAMPLER_LOD_CONFIG_BIAS(etna_float_to_fixp55(ss
->lod_bias
));
64 if (ss
->min_mip_filter
!= PIPE_TEX_MIPFILTER_NONE
) {
65 cs
->min_lod
= etna_float_to_fixp55(ss
->min_lod
);
66 cs
->max_lod
= etna_float_to_fixp55(ss
->max_lod
);
68 /* when not mipmapping, we need to set max/min lod so that always
69 * lowest LOD is selected */
70 cs
->min_lod
= cs
->max_lod
= etna_float_to_fixp55(ss
->min_lod
);
77 etna_delete_sampler_state_state(struct pipe_context
*pctx
, void *ss
)
82 static struct pipe_sampler_view
*
83 etna_create_sampler_view_state(struct pipe_context
*pctx
, struct pipe_resource
*prsc
,
84 const struct pipe_sampler_view
*so
)
86 struct etna_sampler_view
*sv
= CALLOC_STRUCT(etna_sampler_view
);
87 struct etna_context
*ctx
= etna_context(pctx
);
88 const uint32_t format
= translate_texture_format(so
->format
);
89 const bool ext
= !!(format
& EXT_FORMAT
);
90 const bool astc
= !!(format
& ASTC_FORMAT
);
91 const uint32_t swiz
= get_texture_swiz(so
->format
, so
->swizzle_r
,
92 so
->swizzle_g
, so
->swizzle_b
,
98 struct etna_resource
*res
= etna_texture_handle_incompatible(pctx
, prsc
);
105 pipe_reference_init(&sv
->base
.reference
, 1);
106 sv
->base
.texture
= NULL
;
107 pipe_resource_reference(&sv
->base
.texture
, prsc
);
108 sv
->base
.context
= pctx
;
110 /* merged with sampler state */
111 sv
->TE_SAMPLER_CONFIG0
= COND(!ext
&& !astc
, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format
));
112 sv
->TE_SAMPLER_CONFIG0_MASK
= 0xffffffff;
114 switch (sv
->base
.target
) {
115 case PIPE_TEXTURE_1D
:
116 /* For 1D textures, we will have a height of 1, so we can use 2D
117 * but set T wrap to repeat */
118 sv
->TE_SAMPLER_CONFIG0_MASK
= ~VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK
;
119 sv
->TE_SAMPLER_CONFIG0
|= VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_REPEAT
);
121 case PIPE_TEXTURE_2D
:
122 case PIPE_TEXTURE_RECT
:
123 sv
->TE_SAMPLER_CONFIG0
|= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_2D
);
125 case PIPE_TEXTURE_CUBE
:
126 sv
->TE_SAMPLER_CONFIG0
|= VIVS_TE_SAMPLER_CONFIG0_TYPE(TEXTURE_TYPE_CUBE_MAP
);
129 BUG("Unhandled texture target");
134 sv
->TE_SAMPLER_CONFIG1
= COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
135 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
136 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
;
137 sv
->TE_SAMPLER_ASTC0
= COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
138 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
139 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
140 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc);
141 sv
->TE_SAMPLER_SIZE
= VIVS_TE_SAMPLER_SIZE_WIDTH(res
->base
.width0
) |
142 VIVS_TE_SAMPLER_SIZE_HEIGHT(res
->base
.height0
);
143 sv
->TE_SAMPLER_LOG_SIZE
=
144 VIVS_TE_SAMPLER_LOG_SIZE_WIDTH(etna_log2_fixp55(res
->base
.width0
)) |
145 VIVS_TE_SAMPLER_LOG_SIZE_HEIGHT(etna_log2_fixp55(res
->base
.height0
)) |
146 COND(util_format_is_srgb(so
->format
) && !astc
, VIVS_TE_SAMPLER_LOG_SIZE_SRGB
) |
147 COND(astc
, VIVS_TE_SAMPLER_LOG_SIZE_ASTC
);
149 /* Set up levels-of-detail */
150 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
) {
151 sv
->TE_SAMPLER_LOD_ADDR
[lod
].bo
= res
->bo
;
152 sv
->TE_SAMPLER_LOD_ADDR
[lod
].offset
= res
->levels
[lod
].offset
;
153 sv
->TE_SAMPLER_LOD_ADDR
[lod
].flags
= ETNA_RELOC_READ
;
155 sv
->min_lod
= sv
->base
.u
.tex
.first_level
<< 5;
156 sv
->max_lod
= MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
) << 5;
158 /* Workaround for npot textures -- it appears that only CLAMP_TO_EDGE is
159 * supported when the appropriate capability is not set. */
160 if (!ctx
->specs
.npot_tex_any_wrap
&&
161 (!util_is_power_of_two_or_zero(res
->base
.width0
) ||
162 !util_is_power_of_two_or_zero(res
->base
.height0
))) {
163 sv
->TE_SAMPLER_CONFIG0_MASK
= ~(VIVS_TE_SAMPLER_CONFIG0_UWRAP__MASK
|
164 VIVS_TE_SAMPLER_CONFIG0_VWRAP__MASK
);
165 sv
->TE_SAMPLER_CONFIG0
|=
166 VIVS_TE_SAMPLER_CONFIG0_UWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE
) |
167 VIVS_TE_SAMPLER_CONFIG0_VWRAP(TEXTURE_WRAPMODE_CLAMP_TO_EDGE
);
174 etna_sampler_view_state_destroy(struct pipe_context
*pctx
,
175 struct pipe_sampler_view
*view
)
177 pipe_resource_reference(&view
->texture
, NULL
);
181 #define EMIT_STATE(state_name, src_value) \
182 etna_coalsence_emit(stream, &coalesce, VIVS_##state_name, src_value)
184 #define EMIT_STATE_FIXP(state_name, src_value) \
185 etna_coalsence_emit_fixp(stream, &coalesce, VIVS_##state_name, src_value)
187 #define EMIT_STATE_RELOC(state_name, src_value) \
188 etna_coalsence_emit_reloc(stream, &coalesce, VIVS_##state_name, src_value)
190 /* Emit plain (non-descriptor) texture state */
192 etna_emit_texture_state(struct etna_context
*ctx
)
194 struct etna_cmd_stream
*stream
= ctx
->stream
;
195 uint32_t active_samplers
= active_samplers_bits(ctx
);
196 uint32_t dirty
= ctx
->dirty
;
197 struct etna_coalesce coalesce
;
199 etna_coalesce_start(stream
, &coalesce
);
201 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
202 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
203 if ((1 << x
) & active_samplers
) {
204 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
205 /*01720*/ EMIT_STATE(TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
208 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
209 if ((1 << x
) & active_samplers
) {
210 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
211 /*01740*/ EMIT_STATE_RELOC(TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
214 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
215 if ((1 << x
) & active_samplers
) {
216 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
217 /*01760*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
220 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
221 if ((1 << x
) & active_samplers
) {
222 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
223 /*01780*/ EMIT_STATE(TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
227 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLER_VIEWS
| ETNA_DIRTY_SAMPLERS
))) {
228 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
229 uint32_t val
= 0; /* 0 == sampler inactive */
231 /* set active samplers to their configuration value (determined by both
232 * the sampler state and sampler view) */
233 if ((1 << x
) & active_samplers
) {
234 struct etna_sampler_state
*ss
= etna_sampler_state(ctx
->sampler
[x
]);
235 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
237 val
= (ss
->TE_SAMPLER_CONFIG0
& sv
->TE_SAMPLER_CONFIG0_MASK
) |
238 sv
->TE_SAMPLER_CONFIG0
;
241 /*02000*/ EMIT_STATE(TE_SAMPLER_CONFIG0(x
), val
);
244 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLER_VIEWS
))) {
245 struct etna_sampler_view
*sv
;
247 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
248 if ((1 << x
) & active_samplers
) {
249 sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
250 /*02040*/ EMIT_STATE(TE_SAMPLER_SIZE(x
), sv
->TE_SAMPLER_SIZE
);
253 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
254 if ((1 << x
) & active_samplers
) {
255 sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
256 /*02080*/ EMIT_STATE(TE_SAMPLER_LOG_SIZE(x
), sv
->TE_SAMPLER_LOG_SIZE
);
260 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLER_VIEWS
| ETNA_DIRTY_SAMPLERS
))) {
261 struct etna_sampler_state
*ss
;
262 struct etna_sampler_view
*sv
;
264 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
265 if ((1 << x
) & active_samplers
) {
266 ss
= etna_sampler_state(ctx
->sampler
[x
]);
267 sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
269 /* min and max lod is determined both by the sampler and the view */
270 /*020C0*/ EMIT_STATE(TE_SAMPLER_LOD_CONFIG(x
),
271 ss
->TE_SAMPLER_LOD_CONFIG
|
272 VIVS_TE_SAMPLER_LOD_CONFIG_MAX(MIN2(ss
->max_lod
, sv
->max_lod
)) |
273 VIVS_TE_SAMPLER_LOD_CONFIG_MIN(MAX2(ss
->min_lod
, sv
->min_lod
)));
276 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
277 if ((1 << x
) & active_samplers
) {
278 ss
= etna_sampler_state(ctx
->sampler
[x
]);
279 sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
281 /*021C0*/ EMIT_STATE(TE_SAMPLER_CONFIG1(x
), ss
->TE_SAMPLER_CONFIG1
|
282 sv
->TE_SAMPLER_CONFIG1
|
283 COND(sv
->ts
.enable
, VIVS_TE_SAMPLER_CONFIG1_USE_TS
));
287 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLER_VIEWS
))) {
288 for (int y
= 0; y
< VIVS_TE_SAMPLER_LOD_ADDR__LEN
; ++y
) {
289 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
290 if ((1 << x
) & active_samplers
) {
291 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
292 /*02400*/ EMIT_STATE_RELOC(TE_SAMPLER_LOD_ADDR(x
, y
),&sv
->TE_SAMPLER_LOD_ADDR
[y
]);
297 if (unlikely(ctx
->specs
.tex_astc
&& (dirty
& (ETNA_DIRTY_SAMPLER_VIEWS
)))) {
298 for (int x
= 0; x
< VIVS_TE_SAMPLER__LEN
; ++x
) {
299 if ((1 << x
) & active_samplers
) {
300 struct etna_sampler_view
*sv
= etna_sampler_view(ctx
->sampler_view
[x
]);
301 /*10500*/ EMIT_STATE(NTE_SAMPLER_ASTC0(x
), sv
->TE_SAMPLER_ASTC0
);
305 etna_coalesce_end(stream
, &coalesce
);
309 #undef EMIT_STATE_FIXP
310 #undef EMIT_STATE_RELOC
312 static struct etna_sampler_ts
*
313 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
315 struct etna_sampler_view
*sv
= etna_sampler_view(pview
);
320 etna_texture_state_init(struct pipe_context
*pctx
)
322 struct etna_context
*ctx
= etna_context(pctx
);
323 DBG("etnaviv: Using state-based texturing");
324 ctx
->base
.create_sampler_state
= etna_create_sampler_state_state
;
325 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_state
;
326 ctx
->base
.create_sampler_view
= etna_create_sampler_view_state
;
327 ctx
->base
.sampler_view_destroy
= etna_sampler_view_state_destroy
;
328 ctx
->emit_texture_state
= etna_emit_texture_state
;
329 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;