• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/compiler.h"
27 #include "util/u_memory.h"
28 #include "util/u_upload_mgr.h"
29 #include "util/u_math.h"
30 #include "util/u_debug.h"
31 #include "util/u_transfer.h"
32 
33 #include "lima_bo.h"
34 #include "lima_context.h"
35 #include "lima_screen.h"
36 #include "lima_texture.h"
37 #include "lima_resource.h"
38 #include "lima_job.h"
39 #include "lima_util.h"
40 #include "lima_format.h"
41 
42 #include <drm-uapi/lima_drm.h>
43 
44 
45 #define lima_tex_list_size 64
46 
47 static_assert(offsetof(lima_tex_desc, va) == 24, "lima_tex_desc->va offset isn't 24");
48 
49 
50 static void
lima_texture_desc_set_va(lima_tex_desc * desc,int idx,uint32_t va)51 lima_texture_desc_set_va(lima_tex_desc *desc,
52                          int idx,
53                          uint32_t va)
54 {
55    unsigned va_bit_idx = VA_BIT_OFFSET + (VA_BIT_SIZE * idx);
56    unsigned va_idx = va_bit_idx / 32;
57    va_bit_idx %= 32;
58 
59    va >>= 6;
60 
61    desc->va[va_idx] |= va << va_bit_idx;
62    if (va_bit_idx <= 6)
63       return;
64    desc->va[va_idx + 1] |= va >> (32 - va_bit_idx);
65 }
66 
67 /*
68  * Note: this function is used by both draw and flush code path,
69  * make sure no lima_job_get() is called inside this.
70  */
71 void
lima_texture_desc_set_res(struct lima_context * ctx,lima_tex_desc * desc,struct pipe_resource * prsc,unsigned first_level,unsigned last_level,unsigned first_layer,unsigned mrt_idx)72 lima_texture_desc_set_res(struct lima_context *ctx, lima_tex_desc *desc,
73                           struct pipe_resource *prsc,
74                           unsigned first_level, unsigned last_level,
75                           unsigned first_layer, unsigned mrt_idx)
76 {
77    unsigned width, height, depth, layout, i;
78    struct lima_resource *lima_res = lima_resource(prsc);
79 
80    width = prsc->width0;
81    height = prsc->height0;
82    depth = prsc->depth0;
83    if (first_level != 0) {
84       width = u_minify(width, first_level);
85       height = u_minify(height, first_level);
86       depth = u_minify(depth, first_level);
87    }
88 
89    desc->format = lima_format_get_texel(prsc->format);
90    desc->swap_r_b = lima_format_get_texel_swap_rb(prsc->format);
91    desc->width  = width;
92    desc->height = height;
93    desc->depth = depth;
94 
95    if (lima_res->tiled)
96       layout = 3;
97    else {
98       desc->stride = lima_res->levels[first_level].stride;
99       desc->has_stride = 1;
100       layout = 0;
101    }
102 
103    uint32_t base_va = lima_res->bo->va;
104 
105    /* attach first level */
106    uint32_t first_va = base_va + lima_res->levels[first_level].offset +
107                        first_layer * lima_res->levels[first_level].layer_stride +
108                        mrt_idx * lima_res->mrt_pitch;
109    desc->va_s.va_0 = first_va >> 6;
110    desc->va_s.layout = layout;
111 
112    /* Attach remaining levels.
113     * Each subsequent mipmap address is specified using the 26 msbs.
114     * These addresses are then packed continuously in memory */
115    for (i = 1; i <= (last_level - first_level); i++) {
116       uint32_t address = base_va + lima_res->levels[first_level + i].offset;
117       lima_texture_desc_set_va(desc, i, address);
118    }
119 }
120 
121 static unsigned
pipe_wrap_to_lima(unsigned pipe_wrap,bool using_nearest)122 pipe_wrap_to_lima(unsigned pipe_wrap, bool using_nearest)
123 {
124    switch (pipe_wrap) {
125    case PIPE_TEX_WRAP_REPEAT:
126       return LIMA_TEX_WRAP_REPEAT;
127    case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
128       return LIMA_TEX_WRAP_CLAMP_TO_EDGE;
129    case PIPE_TEX_WRAP_CLAMP:
130       if (using_nearest)
131          return LIMA_TEX_WRAP_CLAMP_TO_EDGE;
132       else
133          return LIMA_TEX_WRAP_CLAMP;
134    case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
135       return LIMA_TEX_WRAP_CLAMP_TO_BORDER;
136    case PIPE_TEX_WRAP_MIRROR_REPEAT:
137       return LIMA_TEX_WRAP_MIRROR_REPEAT;
138    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
139       return LIMA_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
140    case PIPE_TEX_WRAP_MIRROR_CLAMP:
141       if (using_nearest)
142          return LIMA_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
143       else
144          return LIMA_TEX_WRAP_MIRROR_CLAMP;
145    case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
146       return LIMA_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
147    default:
148       return LIMA_TEX_WRAP_REPEAT;
149    }
150 }
151 
152 static void
lima_update_tex_desc(struct lima_context * ctx,struct lima_sampler_state * sampler,struct lima_sampler_view * texture,void * pdesc,unsigned desc_size)153 lima_update_tex_desc(struct lima_context *ctx, struct lima_sampler_state *sampler,
154                      struct lima_sampler_view *texture, void *pdesc,
155                      unsigned desc_size)
156 {
157    /* unit is 1/16 since lod_bias is in fixed format */
158    int lod_bias_delta = 0;
159    lima_tex_desc *desc = pdesc;
160    unsigned first_level;
161    unsigned last_level;
162    unsigned first_layer;
163    float max_lod;
164 
165    memset(desc, 0, desc_size);
166 
167    if (!texture)
168       return;
169 
170    switch (texture->base.target) {
171    case PIPE_TEXTURE_1D:
172       desc->sampler_dim = LIMA_SAMPLER_DIM_1D;
173       break;
174    case PIPE_TEXTURE_2D:
175    case PIPE_TEXTURE_RECT:
176       desc->sampler_dim = LIMA_SAMPLER_DIM_2D;
177       break;
178    case PIPE_TEXTURE_CUBE:
179       desc->cube_map = 1;
180       FALLTHROUGH;
181    case PIPE_TEXTURE_3D:
182       desc->sampler_dim = LIMA_SAMPLER_DIM_3D;
183       break;
184    default:
185       break;
186    }
187 
188    if (!sampler->base.normalized_coords)
189       desc->unnorm_coords = 1;
190 
191    first_level = texture->base.u.tex.first_level;
192    last_level = texture->base.u.tex.last_level;
193    first_layer = texture->base.u.tex.first_layer;
194    if (last_level - first_level >= LIMA_MAX_MIP_LEVELS)
195       last_level = first_level + LIMA_MAX_MIP_LEVELS - 1;
196 
197    desc->min_lod = lima_float_to_fixed8(sampler->base.min_lod);
198    max_lod = MIN2(sampler->base.max_lod, sampler->base.min_lod +
199                                          (last_level - first_level));
200    desc->max_lod = lima_float_to_fixed8(max_lod);
201    desc->lod_bias = lima_float_to_fixed8(sampler->base.lod_bias);
202 
203    switch (sampler->base.min_mip_filter) {
204       case PIPE_TEX_MIPFILTER_LINEAR:
205          desc->min_mipfilter_2 = 3;
206          break;
207       case PIPE_TEX_MIPFILTER_NEAREST:
208          desc->min_mipfilter_2 = 0;
209          break;
210       case PIPE_TEX_MIPFILTER_NONE:
211          desc->max_lod = desc->min_lod;
212          break;
213       default:
214          break;
215    }
216 
217    switch (sampler->base.mag_img_filter) {
218    case PIPE_TEX_FILTER_LINEAR:
219       desc->mag_img_filter_nearest = 0;
220       break;
221    case PIPE_TEX_FILTER_NEAREST:
222    default:
223       desc->mag_img_filter_nearest = 1;
224       break;
225    }
226 
227    switch (sampler->base.min_img_filter) {
228       break;
229    case PIPE_TEX_FILTER_LINEAR:
230       desc->min_img_filter_nearest = 0;
231       break;
232    case PIPE_TEX_FILTER_NEAREST:
233    default:
234       lod_bias_delta = 8;
235       desc->min_img_filter_nearest = 1;
236       break;
237    }
238 
239    /* Panfrost mentions that GL_CLAMP is broken for NEAREST filter on Midgard,
240     * looks like it also broken on Utgard, since it fails in piglit
241     */
242    bool using_nearest = sampler->base.min_img_filter == PIPE_TEX_FILTER_NEAREST;
243 
244    desc->wrap_s = pipe_wrap_to_lima(sampler->base.wrap_s, using_nearest);
245    desc->wrap_t = pipe_wrap_to_lima(sampler->base.wrap_t, using_nearest);
246    desc->wrap_r = pipe_wrap_to_lima(sampler->base.wrap_r, using_nearest);
247 
248    desc->border_red = float_to_ushort(sampler->base.border_color.f[0]);
249    desc->border_green = float_to_ushort(sampler->base.border_color.f[1]);
250    desc->border_blue = float_to_ushort(sampler->base.border_color.f[2]);
251    desc->border_alpha = float_to_ushort(sampler->base.border_color.f[3]);
252 
253    if (desc->min_img_filter_nearest && desc->mag_img_filter_nearest &&
254        desc->min_mipfilter_2 == 0 &&
255        (desc->min_lod != desc->max_lod))
256      lod_bias_delta = -1;
257 
258    desc->lod_bias += lod_bias_delta;
259 
260    lima_texture_desc_set_res(ctx, desc, texture->base.texture,
261                              first_level, last_level, first_layer, 0);
262 }
263 
264 static unsigned
lima_calc_tex_desc_size(struct lima_sampler_view * texture)265 lima_calc_tex_desc_size(struct lima_sampler_view *texture)
266 {
267    unsigned size = offsetof(lima_tex_desc, va);
268    unsigned va_bit_size;
269 
270    if (!texture)
271       return lima_min_tex_desc_size;
272 
273    unsigned first_level = texture->base.u.tex.first_level;
274    unsigned last_level = texture->base.u.tex.last_level;
275 
276    if (last_level - first_level >= LIMA_MAX_MIP_LEVELS)
277       last_level = first_level + LIMA_MAX_MIP_LEVELS - 1;
278 
279    va_bit_size = VA_BIT_OFFSET + VA_BIT_SIZE * (last_level - first_level + 1);
280    size += (va_bit_size + 7) >> 3;
281    size = align(size, lima_min_tex_desc_size);
282 
283    return size;
284 }
285 
286 void
lima_update_textures(struct lima_context * ctx)287 lima_update_textures(struct lima_context *ctx)
288 {
289    struct lima_job *job = lima_job_get(ctx);
290    struct lima_texture_stateobj *lima_tex = &ctx->tex_stateobj;
291 
292    assert (lima_tex->num_samplers <= 16);
293 
294    /* Nothing to do - we have no samplers or textures */
295    if (!lima_tex->num_samplers || !lima_tex->num_textures)
296       return;
297 
298    /* we always need to add texture bo to job */
299    for (int i = 0; i < lima_tex->num_samplers; i++) {
300       struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
301       if (!texture)
302          continue;
303       struct lima_resource *rsc = lima_resource(texture->base.texture);
304       lima_flush_previous_job_writing_resource(ctx, texture->base.texture);
305       lima_job_add_bo(job, LIMA_PIPE_PP, rsc->bo, LIMA_SUBMIT_BO_READ);
306    }
307 
308    /* do not regenerate texture desc if no change */
309    if (!(ctx->dirty & LIMA_CONTEXT_DIRTY_TEXTURES))
310       return;
311 
312    unsigned size = lima_tex_list_size;
313    for (int i = 0; i < lima_tex->num_samplers; i++) {
314       struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
315       size += lima_calc_tex_desc_size(texture);
316    }
317 
318    uint32_t *descs =
319       lima_ctx_buff_alloc(ctx, lima_ctx_buff_pp_tex_desc, size);
320 
321    off_t offset = lima_tex_list_size;
322    for (int i = 0; i < lima_tex->num_samplers; i++) {
323       struct lima_sampler_state *sampler = lima_sampler_state(lima_tex->samplers[i]);
324       struct lima_sampler_view *texture = lima_sampler_view(lima_tex->textures[i]);
325       unsigned desc_size = lima_calc_tex_desc_size(texture);
326 
327       descs[i] = lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc) + offset;
328       lima_update_tex_desc(ctx, sampler, texture, (void *)descs + offset, desc_size);
329       offset += desc_size;
330    }
331 
332    lima_dump_command_stream_print(
333       job->dump, descs, size, false, "add textures_desc at va %x\n",
334       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc));
335 
336    lima_dump_texture_descriptor(
337       job->dump, descs, size,
338       lima_ctx_buff_va(ctx, lima_ctx_buff_pp_tex_desc) + lima_tex_list_size,
339       lima_tex_list_size);
340 }
341