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 DESC_SET(CONFIG1
, COND(ext
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(format
)) |
147 COND(astc
, VIVS_TE_SAMPLER_CONFIG1_FORMAT_EXT(TEXTURE_FORMAT_EXT_ASTC
)) |
148 VIVS_TE_SAMPLER_CONFIG1_HALIGN(res
->halign
) | swiz
);
149 DESC_SET(CONFIG2
, 0x00030000);
150 DESC_SET(LINEAR_STRIDE
, res
->levels
[0].stride
);
151 DESC_SET(SLICE
, res
->levels
[0].layer_stride
);
152 DESC_SET(3D_CONFIG
, 0x00000001);
153 DESC_SET(ASTC0
, COND(astc
, VIVS_NTE_SAMPLER_ASTC0_ASTC_FORMAT(format
)) |
154 VIVS_NTE_SAMPLER_ASTC0_UNK8(0xc) |
155 VIVS_NTE_SAMPLER_ASTC0_UNK16(0xc) |
156 VIVS_NTE_SAMPLER_ASTC0_UNK24(0xc));
157 DESC_SET(BASELOD
, TEXDESC_BASELOD_BASELOD(sv
->base
.u
.tex
.first_level
) |
158 TEXDESC_BASELOD_MAXLOD(MIN2(sv
->base
.u
.tex
.last_level
, res
->base
.last_level
)));
159 DESC_SET(LOG_SIZE_EXT
, TEXDESC_LOG_SIZE_EXT_WIDTH(etna_log2_fixp88(base_width
)) |
160 TEXDESC_LOG_SIZE_EXT_HEIGHT(etna_log2_fixp88(base_height
)));
161 DESC_SET(SIZE
, VIVS_TE_SAMPLER_SIZE_WIDTH(base_width
) |
162 VIVS_TE_SAMPLER_SIZE_HEIGHT(base_height
));
163 for (int lod
= 0; lod
<= res
->base
.last_level
; ++lod
)
164 DESC_SET(LOD_ADDR(lod
), etna_bo_gpu_va(res
->bo
) + res
->levels
[lod
].offset
);
167 etna_bo_cpu_fini(sv
->bo
);
169 sv
->DESC_ADDR
.bo
= sv
->bo
;
170 sv
->DESC_ADDR
.offset
= 0;
171 sv
->DESC_ADDR
.flags
= ETNA_RELOC_READ
;
180 etna_sampler_view_update_descriptor(struct etna_context
*ctx
,
181 struct etna_cmd_stream
*stream
,
182 struct etna_sampler_view_desc
*sv
)
184 /* TODO: this should instruct the kernel to update the descriptor when the
185 * bo is submitted. For now, just prevent the bo from being freed
186 * while it is in use indirectly.
188 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
190 res
= etna_resource(res
->texture
);
192 /* No need to ref LOD levels individually as they'll always come from the same bo */
193 etna_cmd_stream_ref_bo(stream
, res
->bo
, ETNA_RELOC_READ
);
197 etna_sampler_view_desc_destroy(struct pipe_context
*pctx
,
198 struct pipe_sampler_view
*so
)
200 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(so
);
201 pipe_resource_reference(&sv
->base
.texture
, NULL
);
207 etna_emit_texture_desc(struct etna_context
*ctx
)
209 struct etna_cmd_stream
*stream
= ctx
->stream
;
210 uint32_t active_samplers
= active_samplers_bits(ctx
);
211 uint32_t dirty
= ctx
->dirty
;
213 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
214 for (int x
= 0; x
< VIVS_TS_SAMPLER__LEN
; ++x
) {
215 if ((1 << x
) & active_samplers
) {
216 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
217 struct etna_resource
*res
= etna_resource(sv
->base
.texture
);
218 struct etna_reloc LOD_ADDR_0
;
223 etna_set_state(stream
, VIVS_TS_SAMPLER_CONFIG(x
), sv
->ts
.TS_SAMPLER_CONFIG
);
224 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_STATUS_BASE(x
), &sv
->ts
.TS_SAMPLER_STATUS_BASE
);
225 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE
);
226 etna_set_state(stream
, VIVS_TS_SAMPLER_CLEAR_VALUE2(x
), sv
->ts
.TS_SAMPLER_CLEAR_VALUE2
);
228 LOD_ADDR_0
.bo
= res
->bo
;
229 LOD_ADDR_0
.offset
= res
->levels
[0].offset
;
230 LOD_ADDR_0
.flags
= ETNA_RELOC_READ
;
232 etna_set_state_reloc(stream
, VIVS_TS_SAMPLER_SURFACE_BASE(x
), &LOD_ADDR_0
);
237 if (unlikely(dirty
& (ETNA_DIRTY_SAMPLERS
| ETNA_DIRTY_SAMPLER_VIEWS
))) {
238 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
239 if ((1 << x
) & active_samplers
) {
240 struct etna_sampler_state_desc
*ss
= etna_sampler_state_desc(ctx
->sampler
[x
]);
241 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
242 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_TX_CTRL(x
),
243 COND(sv
->ts
.enable
, VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_ENABLE
) |
244 VIVS_NTE_DESCRIPTOR_TX_CTRL_TS_MODE(sv
->ts
.mode
));
245 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL0(x
), ss
->SAMP_CTRL0
| sv
->SAMP_CTRL0
);
246 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_CTRL1(x
), ss
->SAMP_CTRL1
| sv
->SAMP_CTRL1
);
247 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_MINMAX(x
), ss
->SAMP_LOD_MINMAX
);
248 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_SAMP_LOD_BIAS(x
), ss
->SAMP_LOD_BIAS
);
253 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
254 /* Set texture descriptors */
255 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
256 if ((1 << x
) & ctx
->dirty_sampler_views
) {
257 if ((1 << x
) & active_samplers
) {
258 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(ctx
->sampler_view
[x
]);
259 etna_sampler_view_update_descriptor(ctx
, stream
, sv
);
260 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &sv
->DESC_ADDR
);
262 /* dummy texture descriptors for unused samplers */
263 etna_set_state_reloc(stream
, VIVS_NTE_DESCRIPTOR_ADDR(x
), &ctx
->DUMMY_DESC_ADDR
);
269 if (unlikely(dirty
& ETNA_DIRTY_SAMPLER_VIEWS
)) {
270 /* Invalidate all dirty sampler views.
272 for (int x
= 0; x
< PIPE_MAX_SAMPLERS
; ++x
) {
273 if ((1 << x
) & ctx
->dirty_sampler_views
) {
274 etna_set_state(stream
, VIVS_NTE_DESCRIPTOR_INVALIDATE
,
275 VIVS_NTE_DESCRIPTOR_INVALIDATE_UNK29
|
276 VIVS_NTE_DESCRIPTOR_INVALIDATE_IDX(x
));
282 static struct etna_sampler_ts
*
283 etna_ts_for_sampler_view_state(struct pipe_sampler_view
*pview
)
285 struct etna_sampler_view_desc
*sv
= etna_sampler_view_desc(pview
);
290 etna_texture_desc_init(struct pipe_context
*pctx
)
292 struct etna_context
*ctx
= etna_context(pctx
);
293 DBG("etnaviv: Using descriptor-based texturing\n");
294 ctx
->base
.create_sampler_state
= etna_create_sampler_state_desc
;
295 ctx
->base
.delete_sampler_state
= etna_delete_sampler_state_desc
;
296 ctx
->base
.create_sampler_view
= etna_create_sampler_view_desc
;
297 ctx
->base
.sampler_view_destroy
= etna_sampler_view_desc_destroy
;
298 ctx
->emit_texture_state
= etna_emit_texture_desc
;
299 ctx
->ts_for_sampler_view
= etna_ts_for_sampler_view_state
;