lima: introduce a struct describing texture descriptor
[mesa.git] / src / gallium / drivers / lima / lima_texture.c
1 /*
2 * Copyright (c) 2011-2013 Luc Verhaegen <libv@skynet.be>
3 * Copyright (c) 2018-2019 Lima Project
4 *
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:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
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.
23 *
24 */
25
26 #include "util/u_memory.h"
27 #include "util/u_upload_mgr.h"
28 #include "util/u_math.h"
29 #include "util/u_debug.h"
30 #include "util/u_transfer.h"
31
32 #include "lima_bo.h"
33 #include "lima_context.h"
34 #include "lima_screen.h"
35 #include "lima_texture.h"
36 #include "lima_resource.h"
37 #include "lima_submit.h"
38 #include "lima_util.h"
39
40 #include <drm-uapi/lima_drm.h>
41
42 #define LIMA_TEXEL_FORMAT_L8 0x09
43 #define LIMA_TEXEL_FORMAT_A8 0x0a
44 #define LIMA_TEXEL_FORMAT_I8 0x0b
45 #define LIMA_TEXEL_FORMAT_BGR_565 0x0e
46 #define LIMA_TEXEL_FORMAT_L8A8 0x11
47 #define LIMA_TEXEL_FORMAT_L16 0x12
48 #define LIMA_TEXEL_FORMAT_A16 0x13
49 #define LIMA_TEXEL_FORMAT_I16 0x14
50 #define LIMA_TEXEL_FORMAT_RGB_888 0x15
51 #define LIMA_TEXEL_FORMAT_RGBA_8888 0x16
52 #define LIMA_TEXEL_FORMAT_RGBX_8888 0x17
53 #define LIMA_TEXEL_FORMAT_Z24S8 0x2c
54
55 #define lima_tex_list_size 64
56
57 typedef struct {
58 bool present;
59 uint32_t lima_format;
60 bool swap_r_b;
61 } lima_format;
62
63 #define LIMA_FORMAT(pipe, lima, swap) \
64 [PIPE_FORMAT_##pipe] = { .present = true, .lima_format = lima, \
65 .swap_r_b = swap }
66
67 static const lima_format lima_format_table[] = {
68 LIMA_FORMAT(R8G8B8A8_UNORM, LIMA_TEXEL_FORMAT_RGBA_8888, true),
69 LIMA_FORMAT(B8G8R8A8_UNORM, LIMA_TEXEL_FORMAT_RGBA_8888, false),
70 LIMA_FORMAT(R8G8B8A8_SRGB, LIMA_TEXEL_FORMAT_RGBA_8888, true),
71 LIMA_FORMAT(B8G8R8A8_SRGB, LIMA_TEXEL_FORMAT_RGBA_8888, false),
72 LIMA_FORMAT(R8G8B8X8_UNORM, LIMA_TEXEL_FORMAT_RGBX_8888, true),
73 LIMA_FORMAT(B8G8R8X8_UNORM, LIMA_TEXEL_FORMAT_RGBX_8888, false),
74 LIMA_FORMAT(R8G8B8_UNORM, LIMA_TEXEL_FORMAT_RGB_888, true),
75 LIMA_FORMAT(B5G6R5_UNORM, LIMA_TEXEL_FORMAT_BGR_565, false),
76 LIMA_FORMAT(Z24_UNORM_S8_UINT, LIMA_TEXEL_FORMAT_Z24S8, false),
77 LIMA_FORMAT(Z24X8_UNORM, LIMA_TEXEL_FORMAT_Z24S8, false),
78 /* Blob uses L16 for Z16 */
79 LIMA_FORMAT(Z16_UNORM, LIMA_TEXEL_FORMAT_L16, false),
80 LIMA_FORMAT(L16_UNORM, LIMA_TEXEL_FORMAT_L16, false),
81 LIMA_FORMAT(L8_UNORM, LIMA_TEXEL_FORMAT_L8, false),
82 LIMA_FORMAT(A16_UNORM, LIMA_TEXEL_FORMAT_A16, false),
83 LIMA_FORMAT(A8_UNORM, LIMA_TEXEL_FORMAT_A8, false),
84 LIMA_FORMAT(I16_UNORM, LIMA_TEXEL_FORMAT_I16, false),
85 LIMA_FORMAT(I8_UNORM, LIMA_TEXEL_FORMAT_I8, false),
86 LIMA_FORMAT(L8A8_UNORM, LIMA_TEXEL_FORMAT_L8A8, false),
87 };
88
89 static_assert(offsetof(lima_tex_desc, va) == 24, "lima_tex_desc->va offset isn't 24");
90
91 bool
92 lima_texel_format_supported(enum pipe_format pformat)
93 {
94 if (pformat >= ARRAY_SIZE(lima_format_table))
95 return false;
96
97 return lima_format_table[pformat].present;
98 }
99
100 static void
101 lima_texture_desc_set_va(lima_tex_desc *desc,
102 int idx,
103 uint32_t va)
104 {
105 unsigned va_bit_idx = VA_BIT_OFFSET + (VA_BIT_SIZE * idx);
106 unsigned va_idx = va_bit_idx / 32;
107 va_bit_idx %= 32;
108
109 va >>= 6;
110
111 desc->va[va_idx] |= va << va_bit_idx;
112 if (va_bit_idx <= 6)
113 return;
114 desc->va[va_idx + 1] |= va >> (32 - va_bit_idx);
115 }
116
117 void
118 lima_texture_desc_set_res(struct lima_context *ctx, lima_tex_desc *desc,
119 struct pipe_resource *prsc,
120 unsigned first_level, unsigned last_level)
121 {
122 unsigned width, height, layout, i;
123 struct lima_resource *lima_res = lima_resource(prsc);
124
125 width = prsc->width0;
126 height = prsc->height0;
127 if (first_level != 0) {
128 width = u_minify(width, first_level);
129 height = u_minify(height, first_level);
130 }
131
132 assert(prsc->format < ARRAY_SIZE(lima_format_table));
133 assert(lima_format_table[prsc->format].present);
134
135 desc->format = lima_format_table[prsc->format].lima_format;
136 desc->swap_r_b = lima_format_table[prsc->format].swap_r_b;
137 desc->width = width;
138 desc->height = height;
139 desc->unknown_3_1 = 1;
140
141 if (lima_res->tiled)
142 layout = 3;
143 else {
144 /* for padded linear texture */
145 if (lima_res->levels[first_level].width != width) {
146 desc->stride = lima_res->levels[first_level].width;
147 desc->has_stride = 1;
148 }
149 layout = 0;
150 }
151
152 lima_submit_add_bo(ctx->pp_submit, lima_res->bo, LIMA_SUBMIT_BO_READ);
153
154 uint32_t base_va = lima_res->bo->va;
155
156 /* attach first level */
157 uint32_t first_va = base_va + lima_res->levels[first_level].offset;
158 desc->va_s.va_0 = first_va >> 6;
159 desc->va_s.layout = layout;
160
161 /* Attach remaining levels.
162 * Each subsequent mipmap address is specified using the 26 msbs.
163 * These addresses are then packed continuously in memory */
164 for (i = 1; i <= (last_level - first_level); i++) {
165 uint32_t address = base_va + lima_res->levels[first_level + i].offset;
166 lima_texture_desc_set_va(desc, i, address);
167 }
168 }
169
170 static void
171 lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sampler,
172 struct lima_sampler_view *texture, void *pdesc,
173 unsigned desc_size)
174 {
175 lima_tex_desc *desc = pdesc;
176 unsigned first_level;
177 unsigned last_level;
178 bool mipmapping;
179
180 memset(desc, 0, desc_size);
181
182 /* 2D texture */
183 desc->texture_2d = 1;
184
185 first_level = texture->base.u.tex.first_level;
186 last_level = texture->base.u.tex.last_level;
187 if (last_level - first_level >= LIMA_MAX_MIP_LEVELS)
188 last_level = first_level + LIMA_MAX_MIP_LEVELS - 1;
189
190 switch (sampler->base.min_mip_filter) {
191 case PIPE_TEX_MIPFILTER_LINEAR:
192 desc->min_mipfilter = 3;
193 case PIPE_TEX_MIPFILTER_NEAREST:
194 mipmapping = true;
195 desc->miplevels = (last_level - first_level);
196 break;
197 case PIPE_TEX_MIPFILTER_NONE:
198 default:
199 mipmapping = false;
200 break;
201 }
202
203 switch (sampler->base.mag_img_filter) {
204 case PIPE_TEX_FILTER_LINEAR:
205 desc->mag_img_filter_nearest = 0;
206 /* no mipmap, filter_mag = linear */
207 if (!mipmapping)
208 desc->disable_mipmap = 1;
209 break;
210 case PIPE_TEX_FILTER_NEAREST:
211 default:
212 desc->mag_img_filter_nearest = 1;
213 break;
214 }
215
216 switch (sampler->base.min_img_filter) {
217 break;
218 case PIPE_TEX_FILTER_LINEAR:
219 desc->min_img_filter_nearest = 0;
220 break;
221 case PIPE_TEX_FILTER_NEAREST:
222 default:
223 desc->min_img_filter_nearest = 1;
224 break;
225 }
226
227 /* Only clamp, clamp to edge, repeat and mirror repeat are supported */
228 switch (sampler->base.wrap_s) {
229 case PIPE_TEX_WRAP_CLAMP:
230 desc->wrap_s_clamp = 1;
231 break;
232 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
233 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
234 desc->wrap_s_clamp_to_edge = 1;
235 break;
236 case PIPE_TEX_WRAP_MIRROR_REPEAT:
237 desc->wrap_s_mirror_repeat = 1;
238 break;
239 case PIPE_TEX_WRAP_REPEAT:
240 default:
241 break;
242 }
243
244 /* Only clamp, clamp to edge, repeat and mirror repeat are supported */
245 switch (sampler->base.wrap_t) {
246 case PIPE_TEX_WRAP_CLAMP:
247 desc->wrap_t_clamp = 1;
248 break;
249 case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
250 case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
251 desc->wrap_t_clamp_to_edge = 1;
252 break;
253 case PIPE_TEX_WRAP_MIRROR_REPEAT:
254 desc->wrap_t_mirror_repeat = 1;
255 break;
256 case PIPE_TEX_WRAP_REPEAT:
257 default:
258 break;
259 }
260
261 lima_texture_desc_set_res(ctx, desc, texture->base.texture,
262 first_level, last_level);
263 }
264
265 static unsigned
266 lima_calc_tex_desc_size(struct lima_sampler_view *texture)
267 {
268 unsigned size = offsetof(lima_tex_desc, va);
269 unsigned va_bit_size;
270 unsigned first_level = texture->base.u.tex.first_level;
271 unsigned last_level = texture->base.u.tex.last_level;
272
273 if (last_level - first_level >= LIMA_MAX_MIP_LEVELS)
274 last_level = first_level + LIMA_MAX_MIP_LEVELS - 1;
275
276 va_bit_size = VA_BIT_OFFSET + VA_BIT_SIZE * (last_level - first_level + 1);
277 size += (va_bit_size + 7) >> 3;
278 size = align(size, lima_min_tex_desc_size);
279
280 return size;
281 }
282
283 void
284 lima_update_textures(struct lima_context *ctx)
285 {
286 struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
287
288 assert (lima_tex->num_samplers <= 16);
289
290 /* Nothing to do - we have no samplers or textures */
291 if (!lima_tex->num_samplers || !lima_tex->num_textures)
292 return;
293
294 unsigned size = lima_tex_list_size;
295 for (int i = 0; i < lima_tex->num_samplers; i++) {
296 struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
297 size += lima_calc_tex_desc_size(texture);
298 }
299
300 uint32_t *descs =
301 lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_tex_desc, size, true);
302
303 off_t offset = lima_tex_list_size;
304 for (int i = 0; i < lima_tex->num_samplers; i++) {
305 struct lima_sampler_state *sampler = lima_sampler_state(lima_tex->samplers[i]);
306 struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
307 unsigned desc_size = lima_calc_tex_desc_size(texture);
308
309 descs[i] = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc,
310 LIMA_CTX_BUFF_SUBMIT_PP) + offset;
311 lima_update_tex_desc(ctx, sampler, texture, (void *)descs + offset, desc_size);
312 offset += desc_size;
313 }
314
315 lima_dump_command_stream_print(
316 descs, size, false, "add textures_desc at va %x\n",
317 lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc, 0));
318 }