"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/freedreno/a3xx/fd3_texture.c" (16 Sep 2020, 9160 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "fd3_texture.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 20.1.5_vs_20.2.0-rc1.

    1 /*
    2  * Copyright (C) 2013 Rob Clark <robclark@freedesktop.org>
    3  *
    4  * Permission is hereby granted, free of charge, to any person obtaining a
    5  * copy of this software and associated documentation files (the "Software"),
    6  * to deal in the Software without restriction, including without limitation
    7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
    8  * and/or sell copies of the Software, and to permit persons to whom the
    9  * Software is furnished to do so, subject to the following conditions:
   10  *
   11  * The above copyright notice and this permission notice (including the next
   12  * paragraph) shall be included in all copies or substantial portions of the
   13  * Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
   18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   21  * SOFTWARE.
   22  *
   23  * Authors:
   24  *    Rob Clark <robclark@freedesktop.org>
   25  */
   26 
   27 #include "pipe/p_state.h"
   28 #include "util/u_string.h"
   29 #include "util/u_memory.h"
   30 #include "util/u_inlines.h"
   31 #include "util/format/u_format.h"
   32 
   33 #include "fd3_texture.h"
   34 #include "fd3_format.h"
   35 
   36 static enum a3xx_tex_clamp
   37 tex_clamp(unsigned wrap, bool clamp_to_edge, bool *needs_border)
   38 {
   39     /* Hardware does not support _CLAMP, but we emulate it: */
   40     if (wrap == PIPE_TEX_WRAP_CLAMP) {
   41         wrap = (clamp_to_edge) ?
   42             PIPE_TEX_WRAP_CLAMP_TO_EDGE : PIPE_TEX_WRAP_CLAMP_TO_BORDER;
   43     }
   44 
   45     switch (wrap) {
   46     case PIPE_TEX_WRAP_REPEAT:
   47         return A3XX_TEX_REPEAT;
   48     case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
   49         return A3XX_TEX_CLAMP_TO_EDGE;
   50     case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
   51         *needs_border = true;
   52         return A3XX_TEX_CLAMP_TO_BORDER;
   53     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
   54         /* only works for PoT.. need to emulate otherwise! */
   55         return A3XX_TEX_MIRROR_CLAMP;
   56     case PIPE_TEX_WRAP_MIRROR_REPEAT:
   57         return A3XX_TEX_MIRROR_REPEAT;
   58     case PIPE_TEX_WRAP_MIRROR_CLAMP:
   59     case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
   60         /* these two we could perhaps emulate, but we currently
   61          * just don't advertise PIPE_CAP_TEXTURE_MIRROR_CLAMP
   62          */
   63     default:
   64         DBG("invalid wrap: %u", wrap);
   65         return 0;
   66     }
   67 }
   68 
   69 static enum a3xx_tex_filter
   70 tex_filter(unsigned filter, bool aniso)
   71 {
   72     switch (filter) {
   73     case PIPE_TEX_FILTER_NEAREST:
   74         return A3XX_TEX_NEAREST;
   75     case PIPE_TEX_FILTER_LINEAR:
   76         return aniso ? A3XX_TEX_ANISO : A3XX_TEX_LINEAR;
   77     default:
   78         DBG("invalid filter: %u", filter);
   79         return 0;
   80     }
   81 }
   82 
   83 static void *
   84 fd3_sampler_state_create(struct pipe_context *pctx,
   85         const struct pipe_sampler_state *cso)
   86 {
   87     struct fd3_sampler_stateobj *so = CALLOC_STRUCT(fd3_sampler_stateobj);
   88     unsigned aniso = util_last_bit(MIN2(cso->max_anisotropy >> 1, 8));
   89     bool miplinear = false;
   90     bool clamp_to_edge;
   91 
   92     if (!so)
   93         return NULL;
   94 
   95     if (cso->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
   96         miplinear = true;
   97 
   98     so->base = *cso;
   99 
  100     /*
  101      * For nearest filtering, _CLAMP means _CLAMP_TO_EDGE;  for linear
  102      * filtering, _CLAMP means _CLAMP_TO_BORDER while additionally
  103      * clamping the texture coordinates to [0.0, 1.0].
  104      *
  105      * The clamping will be taken care of in the shaders.  There are two
  106      * filters here, but let the minification one has a say.
  107      */
  108     clamp_to_edge = (cso->min_img_filter == PIPE_TEX_FILTER_NEAREST);
  109     if (!clamp_to_edge) {
  110         so->saturate_s = (cso->wrap_s == PIPE_TEX_WRAP_CLAMP);
  111         so->saturate_t = (cso->wrap_t == PIPE_TEX_WRAP_CLAMP);
  112         so->saturate_r = (cso->wrap_r == PIPE_TEX_WRAP_CLAMP);
  113     }
  114 
  115     so->needs_border = false;
  116     so->texsamp0 =
  117             COND(!cso->normalized_coords, A3XX_TEX_SAMP_0_UNNORM_COORDS) |
  118             COND(!cso->seamless_cube_map, A3XX_TEX_SAMP_0_CUBEMAPSEAMLESSFILTOFF) |
  119             COND(miplinear, A3XX_TEX_SAMP_0_MIPFILTER_LINEAR) |
  120             A3XX_TEX_SAMP_0_XY_MAG(tex_filter(cso->mag_img_filter, aniso)) |
  121             A3XX_TEX_SAMP_0_XY_MIN(tex_filter(cso->min_img_filter, aniso)) |
  122             A3XX_TEX_SAMP_0_ANISO(aniso) |
  123             A3XX_TEX_SAMP_0_WRAP_S(tex_clamp(cso->wrap_s, clamp_to_edge, &so->needs_border)) |
  124             A3XX_TEX_SAMP_0_WRAP_T(tex_clamp(cso->wrap_t, clamp_to_edge, &so->needs_border)) |
  125             A3XX_TEX_SAMP_0_WRAP_R(tex_clamp(cso->wrap_r, clamp_to_edge, &so->needs_border));
  126 
  127     if (cso->compare_mode)
  128         so->texsamp0 |= A3XX_TEX_SAMP_0_COMPARE_FUNC(cso->compare_func); /* maps 1:1 */
  129 
  130     so->texsamp1 = A3XX_TEX_SAMP_1_LOD_BIAS(cso->lod_bias);
  131 
  132     if (cso->min_mip_filter != PIPE_TEX_MIPFILTER_NONE) {
  133         so->texsamp1 |=
  134             A3XX_TEX_SAMP_1_MIN_LOD(cso->min_lod) |
  135             A3XX_TEX_SAMP_1_MAX_LOD(cso->max_lod);
  136     } else {
  137         /* If we're not doing mipmap filtering, we still need a slightly > 0
  138          * LOD clamp so the HW can decide between min and mag filtering of
  139          * level 0.
  140          */
  141         so->texsamp1 |=
  142             A3XX_TEX_SAMP_1_MIN_LOD(MIN2(cso->min_lod, 0.125)) |
  143             A3XX_TEX_SAMP_1_MAX_LOD(MIN2(cso->max_lod, 0.125));
  144     }
  145 
  146     return so;
  147 }
  148 
  149 static void
  150 fd3_sampler_states_bind(struct pipe_context *pctx,
  151         enum pipe_shader_type shader, unsigned start,
  152         unsigned nr, void **hwcso)
  153 {
  154     struct fd_context *ctx = fd_context(pctx);
  155     struct fd3_context *fd3_ctx = fd3_context(ctx);
  156     uint16_t saturate_s = 0, saturate_t = 0, saturate_r = 0;
  157     unsigned i;
  158 
  159     if (!hwcso)
  160         nr = 0;
  161 
  162     for (i = 0; i < nr; i++) {
  163         if (hwcso[i]) {
  164             struct fd3_sampler_stateobj *sampler =
  165                     fd3_sampler_stateobj(hwcso[i]);
  166             if (sampler->saturate_s)
  167                 saturate_s |= (1 << i);
  168             if (sampler->saturate_t)
  169                 saturate_t |= (1 << i);
  170             if (sampler->saturate_r)
  171                 saturate_r |= (1 << i);
  172         }
  173     }
  174 
  175     fd_sampler_states_bind(pctx, shader, start, nr, hwcso);
  176 
  177     if (shader == PIPE_SHADER_FRAGMENT) {
  178         fd3_ctx->fsaturate =
  179             (saturate_s != 0) ||
  180             (saturate_t != 0) ||
  181             (saturate_r != 0);
  182         fd3_ctx->fsaturate_s = saturate_s;
  183         fd3_ctx->fsaturate_t = saturate_t;
  184         fd3_ctx->fsaturate_r = saturate_r;
  185     } else if (shader == PIPE_SHADER_VERTEX) {
  186         fd3_ctx->vsaturate =
  187             (saturate_s != 0) ||
  188             (saturate_t != 0) ||
  189             (saturate_r != 0);
  190         fd3_ctx->vsaturate_s = saturate_s;
  191         fd3_ctx->vsaturate_t = saturate_t;
  192         fd3_ctx->vsaturate_r = saturate_r;
  193     }
  194 }
  195 
  196 static enum a3xx_tex_type
  197 tex_type(unsigned target)
  198 {
  199     switch (target) {
  200     default:
  201         assert(0);
  202     case PIPE_BUFFER:
  203     case PIPE_TEXTURE_1D:
  204     case PIPE_TEXTURE_1D_ARRAY:
  205         return A3XX_TEX_1D;
  206     case PIPE_TEXTURE_RECT:
  207     case PIPE_TEXTURE_2D:
  208     case PIPE_TEXTURE_2D_ARRAY:
  209         return A3XX_TEX_2D;
  210     case PIPE_TEXTURE_3D:
  211         return A3XX_TEX_3D;
  212     case PIPE_TEXTURE_CUBE:
  213     case PIPE_TEXTURE_CUBE_ARRAY:
  214         return A3XX_TEX_CUBE;
  215     }
  216 }
  217 
  218 static struct pipe_sampler_view *
  219 fd3_sampler_view_create(struct pipe_context *pctx, struct pipe_resource *prsc,
  220         const struct pipe_sampler_view *cso)
  221 {
  222     struct fd3_pipe_sampler_view *so = CALLOC_STRUCT(fd3_pipe_sampler_view);
  223     struct fd_resource *rsc = fd_resource(prsc);
  224     unsigned lvl;
  225 
  226     if (!so)
  227         return NULL;
  228 
  229     so->base = *cso;
  230     pipe_reference(NULL, &prsc->reference);
  231     so->base.texture = prsc;
  232     so->base.reference.count = 1;
  233     so->base.context = pctx;
  234 
  235     so->texconst0 =
  236             A3XX_TEX_CONST_0_TILE_MODE(rsc->layout.tile_mode) |
  237             A3XX_TEX_CONST_0_TYPE(tex_type(prsc->target)) |
  238             A3XX_TEX_CONST_0_FMT(fd3_pipe2tex(cso->format)) |
  239             fd3_tex_swiz(cso->format, cso->swizzle_r, cso->swizzle_g,
  240                         cso->swizzle_b, cso->swizzle_a);
  241 
  242     if (prsc->target == PIPE_BUFFER || util_format_is_pure_integer(cso->format))
  243         so->texconst0 |= A3XX_TEX_CONST_0_NOCONVERT;
  244     if (util_format_is_srgb(cso->format))
  245         so->texconst0 |= A3XX_TEX_CONST_0_SRGB;
  246 
  247     if (prsc->target == PIPE_BUFFER) {
  248         lvl = 0;
  249         so->texconst1 =
  250             A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
  251             A3XX_TEX_CONST_1_WIDTH(cso->u.buf.size / util_format_get_blocksize(cso->format)) |
  252             A3XX_TEX_CONST_1_HEIGHT(1);
  253     } else {
  254         unsigned miplevels;
  255 
  256         lvl = fd_sampler_first_level(cso);
  257         miplevels = fd_sampler_last_level(cso) - lvl;
  258 
  259         so->texconst0 |= A3XX_TEX_CONST_0_MIPLVLS(miplevels);
  260         so->texconst1 =
  261             A3XX_TEX_CONST_1_FETCHSIZE(fd3_pipe2fetchsize(cso->format)) |
  262             A3XX_TEX_CONST_1_WIDTH(u_minify(prsc->width0, lvl)) |
  263             A3XX_TEX_CONST_1_HEIGHT(u_minify(prsc->height0, lvl));
  264     }
  265     /* when emitted, A3XX_TEX_CONST_2_INDX() must be OR'd in: */
  266     struct fdl_slice *slice = fd_resource_slice(rsc, lvl);
  267     so->texconst2 =
  268             A3XX_TEX_CONST_2_PITCH(slice->pitch);
  269     switch (prsc->target) {
  270     case PIPE_TEXTURE_1D_ARRAY:
  271     case PIPE_TEXTURE_2D_ARRAY:
  272         so->texconst3 =
  273                 A3XX_TEX_CONST_3_DEPTH(prsc->array_size - 1) |
  274                 A3XX_TEX_CONST_3_LAYERSZ1(slice->size0);
  275         break;
  276     case PIPE_TEXTURE_3D:
  277         so->texconst3 =
  278                 A3XX_TEX_CONST_3_DEPTH(u_minify(prsc->depth0, lvl)) |
  279                 A3XX_TEX_CONST_3_LAYERSZ1(slice->size0);
  280         so->texconst3 |= A3XX_TEX_CONST_3_LAYERSZ2(
  281                 fd_resource_slice(rsc, prsc->last_level)->size0);
  282         break;
  283     default:
  284         so->texconst3 = 0x00000000;
  285         break;
  286     }
  287 
  288     return &so->base;
  289 }
  290 
  291 void
  292 fd3_texture_init(struct pipe_context *pctx)
  293 {
  294     pctx->create_sampler_state = fd3_sampler_state_create;
  295     pctx->bind_sampler_states = fd3_sampler_states_bind;
  296     pctx->create_sampler_view = fd3_sampler_view_create;
  297     pctx->set_sampler_views = fd_set_sampler_views;
  298 }