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 if (ss
->min_mip_filter
!= PIPE_TEX_MIPFILTER_NONE
) {
67 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(max_lod_fp8
) |
68 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
71 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MAX(min_lod_fp8
) |
72 VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX_MIN(min_lod_fp8
);
75 VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_BIAS(etna_float_to_fixp88(ss
->lod_bias
)) |
76 COND(ss
->lod_bias
!= 0.0, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS_ENABLE
);
82 etna_delete_sampler_state_desc(struct pipe_context
*pctx
, void *ss
)
87 static struct pipe_sampler_view
*
88 etna_create_sampler_view_desc(struct pipe_context
*pctx
, struct pipe_resource
*prsc
,
89 const struct pipe_sampler_view
*so
)
91 struct etna_sampler_view_desc
*sv
= CALLOC_STRUCT(etna_sampler_view_desc
);
92 struct etna_context
*ctx
= etna_context(pctx
);
93 const uint32_t format
= translate_texture_format(so
->format
);
94 const bool ext
= !!(format
& EXT_FORMAT
);
95 const bool astc
= !!(format
& ASTC_FORMAT
);
96 const uint32_t swiz
= get_texture_swiz(so
->format
, so
->swizzle_r
,
97 so
->swizzle_g
, so
->swizzle_b
,
103 struct etna_resource
*res
= etna_texture_handle_incompatible(pctx
, prsc
);
110 pipe_reference_init(&sv
->base
.reference
, 1);
111 sv
->base
.texture
= NULL
;
112 pipe_resource_reference(&sv
->base
.texture
, prsc
);
113 sv
->base
.context
= pctx
;
115 /* Determine whether target supported */
116 uint32_t target_hw
= translate_texture_target(sv
->base
.target
);
117 if (target_hw
== ETNA_NO_MATCH
) {
118 BUG("Unhandled texture target");
123 /* Texture descriptor sampler bits */
124 if (util_format_is_srgb(so
->format
))
125 sv
->SAMP_CTRL1
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL1_SRGB
;
127 if (!util_format_is_float(so
->format
) && so
->target
!= PIPE_TEXTURE_3D
)
128 sv
->SAMP_CTRL0
|= VIVS_NTE_DESCRIPTOR_SAMP_CTRL0_INT_FILTER
;
130 /* Create texture descriptor */
131 sv
->bo
= etna_bo_new(ctx
->screen
->dev
, 0x100, DRM_ETNA_GEM_CACHE_WC
);
135 uint32_t *buf
= etna_bo_map(sv
->bo
);
136 etna_bo_cpu_prep(sv
->bo
, DRM_ETNA_PREP_WRITE
);
137 memset(buf
, 0, 0x100);
139 /** GC7000 needs the size of the BASELOD level */
140 uint32_t base_width
= u_minify(res
->base
.width0
, sv
->base
.u
.tex
.first_level
);
141 uint32_t base_height
= u_minify(res
->base
.height0
, sv
->base
.u
.tex
.first_level
);
143 #define DESC_SET(x, y) buf[(TEXDESC_##x)>>2] = (y)
144 DESC_SET(CONFIG0
, COND(!ext
&& !astc
, VIVS_TE_SAMPLER_CONFIG0_FORMAT(format
))
145 | VIVS_TE_SAMPLER_CONFIG0_TYPE(target_hw
) |
146 COND(res
->layout
== ETNA_LAYOUT_LINEAR
&& !util_format_is_compressed(so
->format
),
147 VIVS_TE_SAMPLER_CONFIG0_ADDRESSING_MODE(TEXTURE_ADDRESSING_MODE_LINEAR
)));
148 DESC_SET(CONFIG1
, COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
149 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
150 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
);
151 DESC_SET(CONFIG2
, 0x00030000);
152 DESC_SET(LINEAR_STRIDE
, res
->levels
[0].stride
);
153 DESC_SET(SLICE
, res
->levels
[0].layer_stride
);
154 DESC_SET(3D_CONFIG
, 0x00000001);
155 DESC_SET(ASTC0
, COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
156 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
157 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
158 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
159 DESC_SET(BASELOD
, TEXDESC_BASELOD_BASELOD(sv
->base
.u
.tex
.first_level
) |
160 TEXDESC_BASELOD_MAXLOD(MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
)));
161 DESC_SET(LOG_SIZE_EXT
, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width
)) |
162 TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height
)));
163 DESC_SET(SIZE
, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width
) |
164 VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height
));
165 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
)
166 DESC_SET(LOD_ADDR(lod
), etna_bo_gpu_va(res
->bo
) + res
->levels
[lod
].offset
);
169 etna_bo_cpu_fini(sv
->bo
);
171 sv
->DESC_ADDR
.bo
= sv
->bo
;
172 sv
->DESC_ADDR
.offset
= 0;
173 sv
->DESC_ADDR
.flags
= ETNA_RELOC_READ
;
182 etna_sampler_view_update_descriptor(struct etna_context
*ctx
,
183 struct etna_cmd_stream
*stream
,
184 struct etna_sampler_view_desc
*sv
)
186 /* TODO: this should instruct the kernel to update the descriptor when the
187 * bo is submitted. For now, just prevent the bo from being freed
188 * while it is in use indirectly.
190 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
192 res
= etna_resource(res
->texture
);
194 /* No need to ref LOD levels individually as they'll always come from the same bo */
195 etna_cmd_stream_ref_bo(stream
, res
->bo
, ETNA_RELOC_READ
);
199 etna_sampler_view_desc_destroy(struct pipe_context
*pctx
,
200 struct pipe_sampler_view
*so
)
202 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(so
);
203 pipe_resource_reference(&sv
->base
.texture
, NULL
);
209 etna_emit_texture_desc(struct etna_context
*ctx
)
211 struct etna_cmd_stream
*stream
= ctx
->stream
;
212 uint32_t active_samplers
= active_samplers_bits(ctx
);
213 uint32_t dirty
= ctx
->dirty
;
215 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
216 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
217 if ((1 << x
) & active_samplers
) {
218 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
219 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
220 struct etna_reloc LOD_ADDR_0
;
225 etna_set_state(stream
, VIVS_TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
226 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
227 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
228 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
230 LOD_ADDR_0
.bo
= res
->bo
;
231 LOD_ADDR_0
.offset
= res
->levels
[0].offset
;
232 LOD_ADDR_0
.flags
= ETNA_RELOC_READ
;
234 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_SURFACE_BASE(x
), &LOD_ADDR_0
);
239 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLERS
| ETNA_DIRTY_SAMPLER_VIEWS
))) {
240 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
241 if ((1 << x
) & active_samplers
) {
242 struct etna_sampler_state_desc
*ss
= etna_sampler_state_desc(ctx
->sampler
[x
]);
243 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
244 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_TX_CTRL(x
),
245 COND(sv
->ts
.enable
, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE
) |
246 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv
->ts
.mode
));
247 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x
), ss
->SAMP_CTRL0
| sv
->SAMP_CTRL0
);
248 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x
), ss
->SAMP_CTRL1
| sv
->SAMP_CTRL1
);
249 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x
), ss
->SAMP_LOD_MINMAX
);
250 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x
), ss
->SAMP_LOD_BIAS
);
255 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
256 /* Set texture descriptors */
257 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
258 if ((1 << x
) & ctx
->dirty_sampler_views
) {
259 if ((1 << x
) & active_samplers
) {
260 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
261 etna_sampler_view_update_descriptor(ctx
, stream
, sv
);
262 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &sv
->DESC_ADDR
);
264 /* dummy texture descriptors for unused samplers */
265 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &ctx
->DUMMY_DESC_ADDR
);
271 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
272 /* Invalidate all dirty sampler views.
274 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
275 if ((1 << x
) & ctx
->dirty_sampler_views
) {
276 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_INVALIDATE
,
277 VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29
|
278 VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x
));
284 static struct etna_sampler_ts
*
285 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
287 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(pview
);
292 etna_texture_desc_init(struct pipe_context
*pctx
)
294 struct etna_context
*ctx
= etna_context(pctx
);
295 DBG("etnaviv: Using descriptor-based texturing\n");
296 ctx
->base
.create_sampler_state
= etna_create_sampler_state_desc
;
297 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_desc
;
298 ctx
->base
.create_sampler_view
= etna_create_sampler_view_desc
;
299 ctx
->base
.sampler_view_destroy
= etna_sampler_view_desc_destroy
;
300 ctx
->emit_texture_state
= etna_emit_texture_desc
;
301 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;