Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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_sampler_view.h"
  32. #include "svga_winsys.h"
  33. #include "svga_context.h"
  34. #include "svga_state.h"
  35. #include "svga_cmd.h"
  36.  
  37.  
  38. void svga_cleanup_tss_binding(struct svga_context *svga)
  39. {
  40.    unsigned i;
  41.    unsigned count = MAX2( svga->curr.num_sampler_views,
  42.                           svga->state.hw_draw.num_views );
  43.  
  44.    for (i = 0; i < count; i++) {
  45.       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
  46.  
  47.       svga_sampler_view_reference(&view->v, NULL);
  48.       pipe_sampler_view_release(&svga->pipe, &svga->curr.sampler_views[i]);
  49.       pipe_resource_reference( &view->texture, NULL );
  50.  
  51.       view->dirty = 1;
  52.    }
  53. }
  54.  
  55.  
  56. struct bind_queue {
  57.    struct {
  58.       unsigned unit;
  59.       struct svga_hw_view_state *view;
  60.    } bind[PIPE_MAX_SAMPLERS];
  61.  
  62.    unsigned bind_count;
  63. };
  64.  
  65.  
  66. static enum pipe_error
  67. update_tss_binding(struct svga_context *svga,
  68.                    unsigned dirty )
  69. {
  70.    boolean reemit = svga->rebind.texture_samplers;
  71.    unsigned i;
  72.    unsigned count = MAX2( svga->curr.num_sampler_views,
  73.                           svga->state.hw_draw.num_views );
  74.    unsigned min_lod;
  75.    unsigned max_lod;
  76.  
  77.    struct bind_queue queue;
  78.  
  79.    queue.bind_count = 0;
  80.    
  81.    for (i = 0; i < count; i++) {
  82.       const struct svga_sampler_state *s = svga->curr.sampler[i];
  83.       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
  84.       struct pipe_resource *texture = NULL;
  85.       struct pipe_sampler_view *sv = svga->curr.sampler_views[i];
  86.  
  87.       /* get min max lod */
  88.       if (sv && s) {
  89.          min_lod = MAX2(0, (s->view_min_lod + sv->u.tex.first_level));
  90.          max_lod = MIN2(s->view_max_lod + sv->u.tex.first_level,
  91.                         sv->texture->last_level);
  92.          texture = sv->texture;
  93.       } else {
  94.          min_lod = 0;
  95.          max_lod = 0;
  96.       }
  97.  
  98.       if (view->texture != texture ||
  99.           view->min_lod != min_lod ||
  100.           view->max_lod != max_lod) {
  101.  
  102.          svga_sampler_view_reference(&view->v, NULL);
  103.          pipe_resource_reference( &view->texture, texture );
  104.  
  105.          view->dirty = TRUE;
  106.          view->min_lod = min_lod;
  107.          view->max_lod = max_lod;
  108.  
  109.          if (texture)
  110.             view->v = svga_get_tex_sampler_view(&svga->pipe,
  111.                                                 texture,
  112.                                                 min_lod,
  113.                                                 max_lod);
  114.       }
  115.  
  116.       /*
  117.        * We need to reemit non-null texture bindings, even when they are not
  118.        * dirty, to ensure that the resources are paged in.
  119.        */
  120.  
  121.       if (view->dirty ||
  122.           (reemit && view->v)) {
  123.          queue.bind[queue.bind_count].unit = i;
  124.          queue.bind[queue.bind_count].view = view;
  125.          queue.bind_count++;
  126.       }
  127.       if (!view->dirty && view->v) {
  128.          svga_validate_sampler_view(svga, view->v);
  129.       }
  130.    }
  131.  
  132.    svga->state.hw_draw.num_views = svga->curr.num_sampler_views;
  133.  
  134.    if (queue.bind_count) {
  135.       SVGA3dTextureState *ts;
  136.  
  137.       if (SVGA3D_BeginSetTextureState( svga->swc,
  138.                                        &ts,
  139.                                        queue.bind_count ) != PIPE_OK)
  140.          goto fail;
  141.  
  142.       for (i = 0; i < queue.bind_count; i++) {
  143.          struct svga_winsys_surface *handle;
  144.  
  145.          ts[i].stage = queue.bind[i].unit;
  146.          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
  147.  
  148.          if (queue.bind[i].view->v) {
  149.             handle = queue.bind[i].view->v->handle;
  150.          }
  151.          else {
  152.             handle = NULL;
  153.          }
  154.          svga->swc->surface_relocation(svga->swc,
  155.                                        &ts[i].value,
  156.                                        NULL,
  157.                                        handle,
  158.                                        SVGA_RELOC_READ);
  159.          
  160.          queue.bind[i].view->dirty = FALSE;
  161.       }
  162.  
  163.       SVGA_FIFOCommitAll( svga->swc );
  164.    }
  165.  
  166.    svga->rebind.texture_samplers = FALSE;
  167.  
  168.    return PIPE_OK;
  169.  
  170. fail:
  171.    return PIPE_ERROR_OUT_OF_MEMORY;
  172. }
  173.  
  174.  
  175. /*
  176.  * Rebind textures.
  177.  *
  178.  * Similar to update_tss_binding, but without any state checking/update.
  179.  *
  180.  * Called at the beginning of every new command buffer to ensure that
  181.  * non-dirty textures are properly paged-in.
  182.  */
  183. enum pipe_error
  184. svga_reemit_tss_bindings(struct svga_context *svga)
  185. {
  186.    unsigned i;
  187.    enum pipe_error ret;
  188.    struct bind_queue queue;
  189.  
  190.    assert(svga->rebind.texture_samplers);
  191.  
  192.    queue.bind_count = 0;
  193.  
  194.    for (i = 0; i < svga->state.hw_draw.num_views; i++) {
  195.       struct svga_hw_view_state *view = &svga->state.hw_draw.views[i];
  196.  
  197.       if (view->v) {
  198.          queue.bind[queue.bind_count].unit = i;
  199.          queue.bind[queue.bind_count].view = view;
  200.          queue.bind_count++;
  201.       }
  202.    }
  203.  
  204.    if (queue.bind_count) {
  205.       SVGA3dTextureState *ts;
  206.  
  207.       ret = SVGA3D_BeginSetTextureState(svga->swc,
  208.                                         &ts,
  209.                                         queue.bind_count);
  210.       if (ret != PIPE_OK) {
  211.          return ret;
  212.       }
  213.  
  214.       for (i = 0; i < queue.bind_count; i++) {
  215.          struct svga_winsys_surface *handle;
  216.  
  217.          ts[i].stage = queue.bind[i].unit;
  218.          ts[i].name = SVGA3D_TS_BIND_TEXTURE;
  219.  
  220.          assert(queue.bind[i].view->v);
  221.          handle = queue.bind[i].view->v->handle;
  222.          svga->swc->surface_relocation(svga->swc,
  223.                                        &ts[i].value,
  224.                                        NULL,
  225.                                        handle,
  226.                                        SVGA_RELOC_READ);
  227.       }
  228.  
  229.       SVGA_FIFOCommitAll(svga->swc);
  230.    }
  231.  
  232.    svga->rebind.texture_samplers = FALSE;
  233.  
  234.    return PIPE_OK;
  235. }
  236.  
  237.  
  238. struct svga_tracked_state svga_hw_tss_binding = {
  239.    "texture binding emit",
  240.    SVGA_NEW_TEXTURE_BINDING |
  241.    SVGA_NEW_SAMPLER,
  242.    update_tss_binding
  243. };
  244.  
  245.  
  246. /***********************************************************************
  247.  */
  248.  
  249. struct ts_queue {
  250.    unsigned ts_count;
  251.    SVGA3dTextureState ts[PIPE_MAX_SAMPLERS*SVGA3D_TS_MAX];
  252. };
  253.  
  254.  
  255. #define EMIT_TS(svga, unit, val, token, fail)                           \
  256. do {                                                                    \
  257.    assert(unit < Elements(svga->state.hw_draw.ts));                     \
  258.    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
  259.    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
  260.       svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
  261.       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
  262.    }                                                                    \
  263. } while (0)
  264.  
  265. #define EMIT_TS_FLOAT(svga, unit, fvalue, token, fail)                  \
  266. do {                                                                    \
  267.    unsigned val = fui(fvalue);                                          \
  268.    assert(unit < Elements(svga->state.hw_draw.ts));                     \
  269.    assert(SVGA3D_TS_##token < Elements(svga->state.hw_draw.ts[unit]));  \
  270.    if (svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] != val) {        \
  271.       svga_queue_tss( &queue, unit, SVGA3D_TS_##token, val );           \
  272.       svga->state.hw_draw.ts[unit][SVGA3D_TS_##token] = val;            \
  273.    }                                                                    \
  274. } while (0)
  275.  
  276.  
  277. static INLINE void
  278. svga_queue_tss( struct ts_queue *q,
  279.                 unsigned unit,
  280.                 unsigned tss,
  281.                 unsigned value )
  282. {
  283.    assert(q->ts_count < sizeof(q->ts)/sizeof(q->ts[0]));
  284.    q->ts[q->ts_count].stage = unit;
  285.    q->ts[q->ts_count].name = tss;
  286.    q->ts[q->ts_count].value = value;
  287.    q->ts_count++;
  288. }
  289.  
  290.  
  291. static enum pipe_error
  292. update_tss(struct svga_context *svga,
  293.            unsigned dirty )
  294. {
  295.    unsigned i;
  296.    struct ts_queue queue;
  297.  
  298.    queue.ts_count = 0;
  299.    for (i = 0; i < svga->curr.num_samplers; i++) {
  300.       if (svga->curr.sampler[i]) {
  301.          const struct svga_sampler_state *curr = svga->curr.sampler[i];
  302.  
  303.          EMIT_TS(svga, i, curr->mipfilter, MIPFILTER, fail);
  304.          EMIT_TS(svga, i, curr->min_lod, TEXTURE_MIPMAP_LEVEL, fail);
  305.          EMIT_TS(svga, i, curr->magfilter, MAGFILTER, fail);
  306.          EMIT_TS(svga, i, curr->minfilter, MINFILTER, fail);
  307.          EMIT_TS(svga, i, curr->aniso_level, TEXTURE_ANISOTROPIC_LEVEL, fail);
  308.          EMIT_TS_FLOAT(svga, i, curr->lod_bias, TEXTURE_LOD_BIAS, fail);
  309.          EMIT_TS(svga, i, curr->addressu, ADDRESSU, fail);
  310.          EMIT_TS(svga, i, curr->addressw, ADDRESSW, fail);
  311.          EMIT_TS(svga, i, curr->bordercolor, BORDERCOLOR, fail);
  312.          // TEXCOORDINDEX -- hopefully not needed
  313.  
  314.          if (svga->curr.tex_flags.flag_1d & (1 << i)) {
  315.             EMIT_TS(svga, i, SVGA3D_TEX_ADDRESS_WRAP, ADDRESSV, fail);
  316.          }
  317.          else
  318.             EMIT_TS(svga, i, curr->addressv, ADDRESSV, fail);
  319.  
  320.          if (svga->curr.tex_flags.flag_srgb & (1 << i))
  321.             EMIT_TS_FLOAT(svga, i, 2.2f, GAMMA, fail);
  322.          else
  323.             EMIT_TS_FLOAT(svga, i, 1.0f, GAMMA, fail);
  324.  
  325.       }
  326.    }
  327.  
  328.    if (queue.ts_count) {
  329.       SVGA3dTextureState *ts;
  330.  
  331.       if (SVGA3D_BeginSetTextureState( svga->swc,
  332.                                        &ts,
  333.                                        queue.ts_count ) != PIPE_OK)
  334.          goto fail;
  335.  
  336.       memcpy( ts,
  337.               queue.ts,
  338.               queue.ts_count * sizeof queue.ts[0]);
  339.      
  340.       SVGA_FIFOCommitAll( svga->swc );
  341.    }
  342.  
  343.    return PIPE_OK;
  344.  
  345. fail:
  346.    /* XXX: need to poison cached hardware state on failure to ensure
  347.     * dirty state gets re-emitted.  Fix this by re-instating partial
  348.     * FIFOCommit command and only updating cached hw state once the
  349.     * initial allocation has succeeded.
  350.     */
  351.    memset(svga->state.hw_draw.ts, 0xcd, sizeof(svga->state.hw_draw.ts));
  352.  
  353.    return PIPE_ERROR_OUT_OF_MEMORY;
  354. }
  355.  
  356.  
  357. struct svga_tracked_state svga_hw_tss = {
  358.    "texture state emit",
  359.    (SVGA_NEW_SAMPLER |
  360.     SVGA_NEW_TEXTURE_FLAGS),
  361.    update_tss
  362. };
  363.  
  364.