2 * Copyright (c) 2017 Etnaviv Project
3 * Copyright (C) 2017 Zodiac Inflight Innovations
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, sub license,
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
13 * next paragraph) shall be included in all copies or substantial portions
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 NON-INFRINGEMENT. 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
22 * DEALINGS IN THE SOFTWARE.
25 * Wladimir J. van der Laan <laanwj@gmail.com>
28 #include "etnaviv_texture_desc.h"
30 #include "hw/common.xml.h"
31 #include "hw/texdesc_3d.xml.h"
33 #include "etnaviv_clear_blit.h"
34 #include "etnaviv_context.h"
35 #include "etnaviv_emit.h"
36 #include "etnaviv_format.h"
37 #include "etnaviv_translate.h"
38 #include "etnaviv_texture.h"
39 #include "util/u_inlines.h"
40 #include "util/u_memory.h"
42 #include <drm_fourcc.h>
45 etna_create_sampler_state_desc(struct pipe_context
*pipe
,
46 const struct pipe_sampler_state
*ss
)
48 struct etna_sampler_state_desc
*cs
= CALLOC_STRUCT(etna_sampler_state_desc
);
54 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UWRAP(translate_texture_wrapmode(ss
->wrap_s
)) |
55 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_VWRAP(translate_texture_wrapmode(ss
->wrap_t
)) |
56 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_WWRAP(translate_texture_wrapmode(ss
->wrap_r
)) |
57 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIN(translate_texture_filter(ss
->min_img_filter
)) |
58 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MIP(translate_texture_mipfilter(ss
->min_mip_filter
)) |
59 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_MAG(translate_texture_filter(ss
->mag_img_filter
)) |
60 VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_UNK21
;
61 /* no ROUND_UV bit? */
62 cs
->SAMP_CTRL1
= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_UNK1
;
63 uint32_t min_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->min_lod
), 0xfff);
64 uint32_t max_lod_fp8
= MIN2(etna_float_to_fixp88(ss
->max_lod
), 0xfff);
65 uint32_t max_lod_min
= ss
->min_img_filter
!= ss
->mag_img_filter
? 4 : 0;
67 if (ss
->min_mip_filter
!= PIPE_TEX_MIPFILTER_NONE
) {
69 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8
, max_lod_min
)) |
70 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
73 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(MAX2(max_lod_fp8
, max_lod_min
)) |
74 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
77 VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_BIAS(etna_float_to_fixp88(ss
->lod_bias
)) |
78 COND(ss
->lod_bias
!= 0.0, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_ENABLE
);
84 etna_delete_sampler_state_desc(struct pipe_context
*pctx
, void *ss
)
89 static struct pipe_sampler_view
*
90 etna_create_sampler_view_desc(struct pipe_context
*pctx
, struct pipe_resource
*prsc
,
91 const struct pipe_sampler_view
*so
)
93 struct etna_sampler_view_desc
*sv
= CALLOC_STRUCT(etna_sampler_view_desc
);
94 struct etna_context
*ctx
= etna_context(pctx
);
95 const uint32_t format
= translate_texture_format(so
->format
);
96 const bool ext
= !!(format
& EXT_FORMAT
);
97 const bool astc
= !!(format
& ASTC_FORMAT
);
98 const uint32_t swiz
= get_texture_swiz(so
->format
, so
->swizzle_r
,
99 so
->swizzle_g
, so
->swizzle_b
,
105 struct etna_resource
*res
= etna_texture_handle_incompatible(pctx
, prsc
);
112 pipe_reference_init(&sv
->base
.reference
, 1);
113 sv
->base
.texture
= NULL
;
114 pipe_resource_reference(&sv
->base
.texture
, prsc
);
115 sv
->base
.context
= pctx
;
117 /* Determine whether target supported */
118 uint32_t target_hw
= translate_texture_target(sv
->base
.target
);
119 if (target_hw
== ETNA_NO_MATCH
) {
120 BUG("Unhandled texture target");
125 /* Texture descriptor sampler bits */
126 if (util_format_is_srgb(so
->format
))
127 sv
->SAMP_CTRL1
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB
;
129 if (!util_format_is_float(so
->format
) && so
->target
!= PIPE_TEXTURE_3D
)
130 sv
->SAMP_CTRL0
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_INT_FILTER
;
132 /* Create texture descriptor */
133 sv
->bo
= etna_bo_new(ctx
->screen
->dev
, 0x100, DRM_ETNA_GEM_CACHE_WC
);
137 uint32_t *buf
= etna_bo_map(sv
->bo
);
138 etna_bo_cpu_prep(sv
->bo
, DRM_ETNA_PREP_WRITE
);
139 memset(buf
, 0, 0x100);
141 /** GC7000 needs the size of the BASELOD level */
142 uint32_t base_width
= u_minify(res
->base
.width0
, sv
->base
.u
.tex
.first_level
);
143 uint32_t base_height
= u_minify(res
->base
.height0
, sv
->base
.u
.tex
.first_level
);
145 #define DESC_SET(x, y) buf[(TEXDESC_##x)>>2] = (y)
146 DESC_SET(CONFIG0
, COND(!ext
&& !astc
, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format
))
147 | VIVS_TE_SAMPLER_CONFIG0_TYPE(target_hw
) |
148 COND(res
->layout
== ETNA_LAYOUT_LINEAR
&& !util_format_is_compressed(so
->format
),
149 VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR
)));
150 DESC_SET(CONFIG1
, COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
151 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
152 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
);
153 DESC_SET(CONFIG2
, 0x00030000);
154 DESC_SET(LINEAR_STRIDE
, res
->levels
[0].stride
);
155 DESC_SET(SLICE
, res
->levels
[0].layer_stride
);
156 DESC_SET(3D_CONFIG
, 0x00000001);
157 DESC_SET(ASTC0
, COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
158 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
159 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
160 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
161 DESC_SET(BASELOD
, TEXDESC_BASELOD_BASELOD(sv
->base
.u
.tex
.first_level
) |
162 TEXDESC_BASELOD_MAXLOD(MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
)));
163 DESC_SET(LOG_SIZE_EXT
, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width
)) |
164 TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height
)));
165 DESC_SET(SIZE
, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width
) |
166 VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height
));
167 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
)
168 DESC_SET(LOD_ADDR(lod
), etna_bo_gpu_va(res
->bo
) + res
->levels
[lod
].offset
);
171 etna_bo_cpu_fini(sv
->bo
);
173 sv
->DESC_ADDR
.bo
= sv
->bo
;
174 sv
->DESC_ADDR
.offset
= 0;
175 sv
->DESC_ADDR
.flags
= ETNA_RELOC_READ
;
184 etna_sampler_view_update_descriptor(struct etna_context
*ctx
,
185 struct etna_cmd_stream
*stream
,
186 struct etna_sampler_view_desc
*sv
)
188 /* TODO: this should instruct the kernel to update the descriptor when the
189 * bo is submitted. For now, just prevent the bo from being freed
190 * while it is in use indirectly.
192 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
194 res
= etna_resource(res
->texture
);
196 /* No need to ref LOD levels individually as they'll always come from the same bo */
197 etna_cmd_stream_ref_bo(stream
, res
->bo
, ETNA_RELOC_READ
);
201 etna_sampler_view_desc_destroy(struct pipe_context
*pctx
,
202 struct pipe_sampler_view
*so
)
204 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(so
);
205 pipe_resource_reference(&sv
->base
.texture
, NULL
);
211 etna_emit_texture_desc(struct etna_context
*ctx
)
213 struct etna_cmd_stream
*stream
= ctx
->stream
;
214 uint32_t active_samplers
= active_samplers_bits(ctx
);
215 uint32_t dirty
= ctx
->dirty
;
217 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
218 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
219 if ((1 << x
) & active_samplers
) {
220 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
221 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
222 struct etna_reloc LOD_ADDR_0
;
227 etna_set_state(stream
, VIVS_TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
228 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
229 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
230 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
232 LOD_ADDR_0
.bo
= res
->bo
;
233 LOD_ADDR_0
.offset
= res
->levels
[0].offset
;
234 LOD_ADDR_0
.flags
= ETNA_RELOC_READ
;
236 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_SURFACE_BASE(x
), &LOD_ADDR_0
);
241 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLERS
| ETNA_DIRTY_SAMPLER_VIEWS
))) {
242 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
243 if ((1 << x
) & active_samplers
) {
244 struct etna_sampler_state_desc
*ss
= etna_sampler_state_desc(ctx
->sampler
[x
]);
245 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
246 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_TX_CTRL(x
),
247 COND(sv
->ts
.enable
, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE
) |
248 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv
->ts
.mode
) |
249 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_INDEX(x
));
250 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x
), ss
->SAMP_CTRL0
| sv
->SAMP_CTRL0
);
251 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x
), ss
->SAMP_CTRL1
| sv
->SAMP_CTRL1
);
252 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x
), ss
->SAMP_LOD_MINMAX
);
253 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x
), ss
->SAMP_LOD_BIAS
);
258 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
259 /* Set texture descriptors */
260 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
261 if ((1 << x
) & ctx
->dirty_sampler_views
) {
262 if ((1 << x
) & active_samplers
) {
263 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
264 etna_sampler_view_update_descriptor(ctx
, stream
, sv
);
265 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &sv
->DESC_ADDR
);
267 /* dummy texture descriptors for unused samplers */
268 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &ctx
->DUMMY_DESC_ADDR
);
274 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
275 /* Invalidate all dirty sampler views.
277 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
278 if ((1 << x
) & ctx
->dirty_sampler_views
) {
279 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_INVALIDATE
,
280 VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29
|
281 VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x
));
287 static struct etna_sampler_ts
*
288 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
290 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(pview
);
295 etna_texture_desc_init(struct pipe_context
*pctx
)
297 struct etna_context
*ctx
= etna_context(pctx
);
298 DBG("etnaviv: Using descriptor-based texturing\n");
299 ctx
->base
.create_sampler_state
= etna_create_sampler_state_desc
;
300 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_desc
;
301 ctx
->base
.create_sampler_view
= etna_create_sampler_view_desc
;
302 ctx
->base
.sampler_view_destroy
= etna_sampler_view_desc_destroy
;
303 ctx
->emit_texture_state
= etna_emit_texture_desc
;
304 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;