"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/drivers/svga/svga_state_tss.c" (16 Sep 2020, 13643 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 "svga_state_tss.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 2008-2009 VMware, Inc.  All rights reserved.
    3  *
    4  * Permission is hereby granted, free of charge, to any person
    5  * obtaining a copy of this software and associated documentation
    6  * files (the "Software"), to deal in the Software without
    7  * restriction, including without limitation the rights to use, copy,
    8  * modify, merge, publish, distribute, sublicense, and/or sell copies
    9  * of the Software, and to permit persons to whom the Software is
   10  * furnished to do so, subject to the following conditions:
   11  *
   12  * The above copyright notice and this permission notice shall be
   13  * included in all copies or substantial portions of the Software.
   14  *
   15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
   19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
   20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   22  * SOFTWARE.
   23  *
   24  **********************************************************/
   25 
   26 #include "util/u_inlines.h"
   27 #include "util/u_memory.h"
   28 #include "pipe/p_defines.h"
   29 #include "util/u_math.h"
   30 
   31 #include "svga_resource_texture.h"
   32 #include "svga_sampler_view.h"
   33 #include "svga_winsys.h"
   34 #include "svga_context.h"
   35 #include "svga_shader.h"
   36 #include "svga_state.h"
   37 #include "svga_cmd.h"
   38 
   39 
   40 /**
   41  * Called when tearing down a context to free resources and samplers.
   42  */
   43 void
   44 svga_cleanup_tss_binding(struct svga_context *svga)
   45 {
   46    const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
   47    unsigned i;
   48 
   49    for (i = 0; i < ARRAY_SIZE(svga->state.hw_draw.views); i++) {
   50       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
   51       if (view) {
   52          svga_sampler_view_reference(&view->v, NULL);
   53          pipe_sampler_view_reference(&svga->curr.sampler_views[shader][i],
   54                                      NULL);
   55          pipe_resource_reference(&view->texture, NULL);
   56          view->dirty = TRUE;
   57       }
   58    }
   59 }
   60 
   61 
   62 struct bind_queue {
   63    struct {
   64       unsigned unit;
   65       struct svga_hw_view_state *view;
   66    } bind[PIPE_MAX_SAMPLERS];
   67 
   68    unsigned bind_count;
   69 };
   70 
   71 
   72 /**
   73  * Update the texture binding for one texture unit.
   74  */
   75 static void
   76 emit_tex_binding_unit(struct svga_context *svga,
   77                       unsigned unit,
   78                       const struct svga_sampler_state *s,
   79                       const struct pipe_sampler_view *sv,
   80                       struct svga_hw_view_state *view,
   81                       boolean reemit,
   82                       struct bind_queue *queue)
   83 {
   84    struct pipe_resource *texture = NULL;
   85    unsigned last_level, min_lod, max_lod;
   86 
   87    /* get min max lod */
   88    if (sv && s) {
   89       if (s->mipfilter == SVGA3D_TEX_FILTER_NONE) {
   90          /* just use the base level image */
   91          min_lod = max_lod = sv->u.tex.first_level;
   92       }
   93       else {
   94          last_level = MIN2(sv->u.tex.last_level, sv->texture->last_level);
   95          min_lod = s->view_min_lod + sv->u.tex.first_level;
   96          min_lod = MIN2(min_lod, last_level);
   97          max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level, last_level);
   98       }
   99       texture = sv->texture;
  100    }
  101    else {
  102       min_lod = 0;
  103       max_lod = 0;
  104    }
  105 
  106    if (view->texture != texture ||
  107        view->min_lod != min_lod ||
  108        view->max_lod != max_lod) {
  109 
  110       svga_sampler_view_reference(&view->v, NULL);
  111       pipe_resource_reference(&view->texture, texture);
  112 
  113       view->dirty = TRUE;
  114       view->min_lod = min_lod;
  115       view->max_lod = max_lod;
  116 
  117       if (texture) {
  118          view->v = svga_get_tex_sampler_view(&svga->pipe,
  119                                              texture,
  120                                              min_lod,
  121                                              max_lod);
  122       }
  123    }
  124 
  125    /*
  126     * We need to reemit non-null texture bindings, even when they are not
  127     * dirty, to ensure that the resources are paged in.
  128     */
  129    if (view->dirty || (reemit && view->v)) {
  130       queue->bind[queue->bind_count].unit = unit;
  131       queue->bind[queue->bind_count].view = view;
  132       queue->bind_count++;
  133    }
  134 
  135    if (!view->dirty && view->v) {
  136       svga_validate_sampler_view(svga, view->v);
  137    }
  138 }
  139 
  140 
  141 static enum pipe_error
  142 update_tss_binding(struct svga_context *svga, unsigned dirty)
  143 {
  144    const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
  145    boolean reemit = svga->rebind.flags.texture_samplers;
  146    unsigned i;
  147    unsigned count = MAX2(svga->curr.num_sampler_views[shader],
  148                          svga->state.hw_draw.num_views);
  149 
  150    struct bind_queue queue;
  151 
  152    if (svga_have_vgpu10(svga))
  153       return PIPE_OK;
  154 
  155    queue.bind_count = 0;
  156 
  157    for (i = 0; i < count; i++) {
  158       emit_tex_binding_unit(svga, i,
  159                             svga->curr.sampler[shader][i],
  160                             svga->curr.sampler_views[shader][i],
  161                             &svga->state.hw_draw.views[i],
  162                             reemit,
  163                             &queue);
  164    }
  165 
  166    svga->state.hw_draw.num_views = svga->curr.num_sampler_views[shader];
  167 
  168    /* Polygon stipple */
  169    if (svga->curr.rast->templ.poly_stipple_enable) {
  170       const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
  171       emit_tex_binding_unit(svga, unit,
  172                             svga->polygon_stipple.sampler,
  173                             &svga->polygon_stipple.sampler_view->base,
  174                             &svga->state.hw_draw.views[unit],
  175                             reemit,
  176                             &queue);
  177    }
  178 
  179    svga->state.hw_draw.num_backed_views = 0;
  180 
  181    if (queue.bind_count) {
  182       SVGA3dTextureState *ts;
  183 
  184       if (SVGA3D_BeginSetTextureState(svga->swc, &ts,
  185                                       queue.bind_count) != PIPE_OK)
  186          goto fail;
  187 
  188       for (i = 0; i < queue.bind_count; i++) {
  189          struct svga_winsys_surface *handle;
  190          struct svga_hw_view_state *view = queue.bind[i].view;
  191 
  192          ts[i].stage = queue.bind[i].unit;
  193          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
  194 
  195          if (view->v) {
  196             handle = view->v->handle;
  197 
  198             /* Keep track of number of views with a backing copy
  199              * of texture.
  200              */
  201             if (handle != svga_texture(view->texture)->handle)
  202                svga->state.hw_draw.num_backed_views++;
  203          }
  204          else {
  205             handle = NULL;
  206          }
  207          svga->swc->surface_relocation(svga->swc,
  208                                        &ts[i].value,
  209                                        NULL,
  210                                        handle,
  211                                        SVGA_RELOC_READ);
  212 
  213          queue.bind[i].view->dirty = FALSE;
  214       }
  215 
  216       SVGA_FIFOCommitAll(svga->swc);
  217    }
  218 
  219    svga->rebind.flags.texture_samplers = FALSE;
  220 
  221    return PIPE_OK;
  222 
  223 fail:
  224    return PIPE_ERROR_OUT_OF_MEMORY;
  225 }
  226 
  227 
  228 /*
  229  * Rebind textures.
  230  *
  231  * Similar to update_tss_binding, but without any state checking/update.
  232  *
  233  * Called at the beginning of every new command buffer to ensure that
  234  * non-dirty textures are properly paged-in.
  235  */
  236 enum pipe_error
  237 svga_reemit_tss_bindings(struct svga_context *svga)
  238 {
  239    unsigned i;
  240    enum pipe_error ret;
  241    struct bind_queue queue;
  242 
  243    assert(!svga_have_vgpu10(svga));
  244    assert(svga->rebind.flags.texture_samplers);
  245 
  246    queue.bind_count = 0;
  247 
  248    for (i = 0; i < svga->state.hw_draw.num_views; i++) {
  249       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
  250 
  251       if (view->v) {
  252          queue.bind[queue.bind_count].unit = i;
  253          queue.bind[queue.bind_count].view = view;
  254          queue.bind_count++;
  255       }
  256    }
  257 
  258    /* Polygon stipple */
  259    if (svga->curr.rast && svga->curr.rast->templ.poly_stipple_enable) {
  260       const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
  261       struct svga_hw_view_state *view = &svga->state.hw_draw.views[unit];
  262 
  263       if (view->v) {
  264          queue.bind[queue.bind_count].unit = unit;
  265          queue.bind[queue.bind_count].view = view;
  266          queue.bind_count++;
  267       }
  268    }
  269 
  270    if (queue.bind_count) {
  271       SVGA3dTextureState *ts;
  272 
  273       ret = SVGA3D_BeginSetTextureState(svga->swc, &ts, queue.bind_count);
  274       if (ret != PIPE_OK) {
  275          return ret;
  276       }
  277 
  278       for (i = 0; i < queue.bind_count; i++) {
  279          struct svga_winsys_surface *handle;
  280 
  281          ts[i].stage = queue.bind[i].unit;
  282          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
  283 
  284          assert(queue.bind[i].view->v);
  285          handle = queue.bind[i].view->v->handle;
  286          svga->swc->surface_relocation(svga->swc,
  287                                        &ts[i].value,
  288                                        NULL,
  289                                        handle,
  290                                        SVGA_RELOC_READ);
  291       }
  292 
  293       SVGA_FIFOCommitAll(svga->swc);
  294    }
  295 
  296    svga->rebind.flags.texture_samplers = FALSE;
  297 
  298    return PIPE_OK;
  299 }
  300 
  301 
  302 struct svga_tracked_state svga_hw_tss_binding = {
  303    "texture binding emit",
  304    SVGA_NEW_FRAME_BUFFER |
  305    SVGA_NEW_TEXTURE_BINDING |
  306    SVGA_NEW_STIPPLE |
  307    SVGA_NEW_SAMPLER,
  308    update_tss_binding
  309 };
  310 
  311 
  312 
  313 struct ts_queue {
  314    unsigned ts_count;
  315    SVGA3dTextureState ts[PIPE_MAX_SAMPLERS*SVGA3D_TS_MAX];
  316 };
  317 
  318 
  319 static inline void
  320 svga_queue_tss(struct ts_queue *q, unsigned unit, unsigned tss, unsigned value)
  321 {
  322    assert(q->ts_count < ARRAY_SIZE(q->ts));
  323    q->ts[q->ts_count].stage = unit;
  324    q->ts[q->ts_count].name = tss;
  325    q->ts[q->ts_count].value = value;
  326    q->ts_count++;
  327 }
  328 
  329 
  330 #define EMIT_TS(svga, unit, val, token)                                 \
  331 do {                                                                    \
  332    assert(unit < ARRAY_SIZE(svga->state.hw_draw.ts));                     \
  333    STATIC_ASSERT(SVGA3D_TS_##token < ARRAY_SIZE(svga->state.hw_draw.ts[unit])); \
  334    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
  335       svga_queue_tss(queue, unit, SVGA3D_TS_##token, val);             \
  336       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
  337    }                                                                    \
  338 } while (0)
  339 
  340 #define EMIT_TS_FLOAT(svga, unit, fvalue, token)                        \
  341 do {                                                                    \
  342    unsigned val = fui(fvalue);                                          \
  343    assert(unit < ARRAY_SIZE(svga->state.hw_draw.ts));                     \
  344    STATIC_ASSERT(SVGA3D_TS_##token < ARRAY_SIZE(svga->state.hw_draw.ts[unit])); \
  345    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
  346       svga_queue_tss(queue, unit, SVGA3D_TS_##token, val);              \
  347       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
  348    }                                                                    \
  349 } while (0)
  350 
  351 
  352 /**
  353  * Emit texture sampler state (tss) for one texture unit.
  354  */
  355 static void
  356 emit_tss_unit(struct svga_context *svga, unsigned unit,
  357               const struct svga_sampler_state *state,
  358               struct ts_queue *queue)
  359 {
  360    EMIT_TS(svga, unit, state->mipfilter, MIPFILTER);
  361    EMIT_TS(svga, unit, state->min_lod, TEXTURE_MIPMAP_LEVEL);
  362    EMIT_TS(svga, unit, state->magfilter, MAGFILTER);
  363    EMIT_TS(svga, unit, state->minfilter, MINFILTER);
  364    EMIT_TS(svga, unit, state->aniso_level, TEXTURE_ANISOTROPIC_LEVEL);
  365    EMIT_TS_FLOAT(svga, unit, state->lod_bias, TEXTURE_LOD_BIAS);
  366    EMIT_TS(svga, unit, state->addressu, ADDRESSU);
  367    EMIT_TS(svga, unit, state->addressw, ADDRESSW);
  368    EMIT_TS(svga, unit, state->bordercolor, BORDERCOLOR);
  369    // TEXCOORDINDEX -- hopefully not needed
  370 
  371    if (svga->curr.tex_flags.flag_1d & (1 << unit))
  372       EMIT_TS(svga, unit, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV);
  373    else
  374       EMIT_TS(svga, unit, state->addressv, ADDRESSV);
  375 
  376    if (svga->curr.tex_flags.flag_srgb & (1 << unit))
  377       EMIT_TS_FLOAT(svga, unit, 2.2f, GAMMA);
  378    else
  379       EMIT_TS_FLOAT(svga, unit, 1.0f, GAMMA);
  380 }
  381 
  382 static enum pipe_error
  383 update_tss(struct svga_context *svga, unsigned dirty)
  384 {
  385    const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
  386    unsigned i;
  387    struct ts_queue queue;
  388 
  389    if (svga_have_vgpu10(svga))
  390       return PIPE_OK;
  391 
  392    queue.ts_count = 0;
  393    for (i = 0; i < svga->curr.num_samplers[shader]; i++) {
  394       if (svga->curr.sampler[shader][i]) {
  395          const struct svga_sampler_state *curr = svga->curr.sampler[shader][i];
  396          emit_tss_unit(svga, i, curr, &queue);
  397       }
  398    }
  399 
  400    /* polygon stipple sampler */
  401    if (svga->curr.rast->templ.poly_stipple_enable) {
  402       emit_tss_unit(svga,
  403                     svga->state.hw_draw.fs->pstipple_sampler_unit,
  404                     svga->polygon_stipple.sampler,
  405                     &queue);
  406    }
  407 
  408    if (queue.ts_count) {
  409       SVGA3dTextureState *ts;
  410 
  411       if (SVGA3D_BeginSetTextureState(svga->swc, &ts, queue.ts_count) != PIPE_OK)
  412          goto fail;
  413 
  414       memcpy(ts, queue.ts, queue.ts_count * sizeof queue.ts[0]);
  415 
  416       SVGA_FIFOCommitAll(svga->swc);
  417    }
  418 
  419    return PIPE_OK;
  420 
  421 fail:
  422    /* XXX: need to poison cached hardware state on failure to ensure
  423     * dirty state gets re-emitted.  Fix this by re-instating partial
  424     * FIFOCommit command and only updating cached hw state once the
  425     * initial allocation has succeeded.
  426     */
  427    memset(svga->state.hw_draw.ts, 0xcd, sizeof(svga->state.hw_draw.ts));
  428 
  429    return PIPE_ERROR_OUT_OF_MEMORY;
  430 }
  431 
  432 
  433 struct svga_tracked_state svga_hw_tss = {
  434    "texture state emit",
  435    (SVGA_NEW_SAMPLER |
  436     SVGA_NEW_STIPPLE |
  437     SVGA_NEW_TEXTURE_FLAGS),
  438    update_tss
  439 };
  440