Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2007 VMware, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. /* Authors:
  29.  *  Brian Paul
  30.  */
  31.  
  32. #include "util/u_inlines.h"
  33. #include "util/u_memory.h"
  34.  
  35. #include "draw/draw_context.h"
  36.  
  37. #include "lp_context.h"
  38. #include "lp_screen.h"
  39. #include "lp_state.h"
  40. #include "lp_debug.h"
  41. #include "state_tracker/sw_winsys.h"
  42.  
  43.  
  44. static void *
  45. llvmpipe_create_sampler_state(struct pipe_context *pipe,
  46.                               const struct pipe_sampler_state *sampler)
  47. {
  48.    struct pipe_sampler_state *state = mem_dup(sampler, sizeof *sampler);
  49.  
  50.    if (LP_PERF & PERF_NO_MIP_LINEAR) {
  51.       if (state->min_mip_filter == PIPE_TEX_MIPFILTER_LINEAR)
  52.          state->min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
  53.    }
  54.  
  55.    if (LP_PERF & PERF_NO_MIPMAPS)
  56.       state->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
  57.  
  58.    if (LP_PERF & PERF_NO_LINEAR) {
  59.       state->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
  60.       state->min_img_filter = PIPE_TEX_FILTER_NEAREST;
  61.    }
  62.  
  63.    return state;
  64. }
  65.  
  66.  
  67. static void
  68. llvmpipe_bind_sampler_states(struct pipe_context *pipe,
  69.                              unsigned shader,
  70.                              unsigned start,
  71.                              unsigned num,
  72.                              void **samplers)
  73. {
  74.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  75.    unsigned i;
  76.  
  77.    assert(shader < PIPE_SHADER_TYPES);
  78.    assert(start + num <= Elements(llvmpipe->samplers[shader]));
  79.  
  80.    draw_flush(llvmpipe->draw);
  81.  
  82.    /* set the new samplers */
  83.    for (i = 0; i < num; i++) {
  84.       llvmpipe->samplers[shader][start + i] = samplers[i];
  85.    }
  86.  
  87.    /* find highest non-null samplers[] entry */
  88.    {
  89.       unsigned j = MAX2(llvmpipe->num_samplers[shader], start + num);
  90.       while (j > 0 && llvmpipe->samplers[shader][j - 1] == NULL)
  91.          j--;
  92.       llvmpipe->num_samplers[shader] = j;
  93.    }
  94.  
  95.    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
  96.       draw_set_samplers(llvmpipe->draw,
  97.                         shader,
  98.                         llvmpipe->samplers[shader],
  99.                         llvmpipe->num_samplers[shader]);
  100.    }
  101.  
  102.    llvmpipe->dirty |= LP_NEW_SAMPLER;
  103. }
  104.  
  105.  
  106. static void
  107. llvmpipe_set_sampler_views(struct pipe_context *pipe,
  108.                            unsigned shader,
  109.                            unsigned start,
  110.                            unsigned num,
  111.                            struct pipe_sampler_view **views)
  112. {
  113.    struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
  114.    uint i;
  115.  
  116.    assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
  117.  
  118.    assert(shader < PIPE_SHADER_TYPES);
  119.    assert(start + num <= Elements(llvmpipe->sampler_views[shader]));
  120.  
  121.    draw_flush(llvmpipe->draw);
  122.  
  123.    /* set the new sampler views */
  124.    for (i = 0; i < num; i++) {
  125.       /* Note: we're using pipe_sampler_view_release() here to work around
  126.        * a possible crash when the old view belongs to another context that
  127.        * was already destroyed.
  128.        */
  129.       pipe_sampler_view_release(pipe,
  130.                                 &llvmpipe->sampler_views[shader][start + i]);
  131.       pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i],
  132.                                   views[i]);
  133.    }
  134.  
  135.    /* find highest non-null sampler_views[] entry */
  136.    {
  137.       unsigned j = MAX2(llvmpipe->num_sampler_views[shader], start + num);
  138.       while (j > 0 && llvmpipe->sampler_views[shader][j - 1] == NULL)
  139.          j--;
  140.       llvmpipe->num_sampler_views[shader] = j;
  141.    }
  142.  
  143.    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
  144.       draw_set_sampler_views(llvmpipe->draw,
  145.                              shader,
  146.                              llvmpipe->sampler_views[shader],
  147.                              llvmpipe->num_sampler_views[shader]);
  148.    }
  149.  
  150.    llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW;
  151. }
  152.  
  153.  
  154. static struct pipe_sampler_view *
  155. llvmpipe_create_sampler_view(struct pipe_context *pipe,
  156.                             struct pipe_resource *texture,
  157.                             const struct pipe_sampler_view *templ)
  158. {
  159.    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
  160.    /*
  161.     * XXX we REALLY want to see the correct bind flag here but the OpenGL
  162.     * state tracker can't guarantee that at least for texture buffer objects.
  163.     */
  164.    if (!(texture->bind & PIPE_BIND_SAMPLER_VIEW))
  165.       debug_printf("Illegal sampler view creation without bind flag\n");
  166.  
  167.    if (view) {
  168.       *view = *templ;
  169.       view->reference.count = 1;
  170.       view->texture = NULL;
  171.       pipe_resource_reference(&view->texture, texture);
  172.       view->context = pipe;
  173.  
  174. #ifdef DEBUG
  175.      /*
  176.       * This is possibly too lenient, but the primary reason is just
  177.       * to catch state trackers which forget to initialize this, so
  178.       * it only catches clearly impossible view targets.
  179.       */
  180.       if (view->target != texture->target) {
  181.          if (view->target == PIPE_TEXTURE_1D)
  182.             assert(texture->target == PIPE_TEXTURE_1D_ARRAY);
  183.          else if (view->target == PIPE_TEXTURE_1D_ARRAY)
  184.             assert(texture->target == PIPE_TEXTURE_1D);
  185.          else if (view->target == PIPE_TEXTURE_2D)
  186.             assert(texture->target == PIPE_TEXTURE_2D_ARRAY ||
  187.                    texture->target == PIPE_TEXTURE_CUBE ||
  188.                    texture->target == PIPE_TEXTURE_CUBE_ARRAY);
  189.          else if (view->target == PIPE_TEXTURE_2D_ARRAY)
  190.             assert(texture->target == PIPE_TEXTURE_2D ||
  191.                    texture->target == PIPE_TEXTURE_CUBE ||
  192.                    texture->target == PIPE_TEXTURE_CUBE_ARRAY);
  193.          else if (view->target == PIPE_TEXTURE_CUBE)
  194.             assert(texture->target == PIPE_TEXTURE_CUBE_ARRAY ||
  195.                    texture->target == PIPE_TEXTURE_2D_ARRAY);
  196.          else if (view->target == PIPE_TEXTURE_CUBE_ARRAY)
  197.             assert(texture->target == PIPE_TEXTURE_CUBE ||
  198.                    texture->target == PIPE_TEXTURE_2D_ARRAY);
  199.          else
  200.             assert(0);
  201.       }
  202. #endif
  203.    }
  204.  
  205.    return view;
  206. }
  207.  
  208.  
  209. static void
  210. llvmpipe_sampler_view_destroy(struct pipe_context *pipe,
  211.                               struct pipe_sampler_view *view)
  212. {
  213.    pipe_resource_reference(&view->texture, NULL);
  214.    FREE(view);
  215. }
  216.  
  217.  
  218. static void
  219. llvmpipe_delete_sampler_state(struct pipe_context *pipe,
  220.                               void *sampler)
  221. {
  222.    FREE( sampler );
  223. }
  224.  
  225.  
  226. static void
  227. prepare_shader_sampling(
  228.    struct llvmpipe_context *lp,
  229.    unsigned num,
  230.    struct pipe_sampler_view **views,
  231.    unsigned shader_type,
  232.    struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS])
  233. {
  234.  
  235.    unsigned i;
  236.    uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
  237.    uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
  238.    uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
  239.    const void *addr;
  240.  
  241.    assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
  242.    if (!num)
  243.       return;
  244.  
  245.    for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
  246.       struct pipe_sampler_view *view = i < num ? views[i] : NULL;
  247.  
  248.       if (view) {
  249.          struct pipe_resource *tex = view->texture;
  250.          struct llvmpipe_resource *lp_tex = llvmpipe_resource(tex);
  251.          unsigned width0 = tex->width0;
  252.          unsigned num_layers = tex->depth0;
  253.          unsigned first_level = 0;
  254.          unsigned last_level = 0;
  255.  
  256.          /* We're referencing the texture's internal data, so save a
  257.           * reference to it.
  258.           */
  259.          pipe_resource_reference(&mapped_tex[i], tex);
  260.  
  261.          if (!lp_tex->dt) {
  262.             /* regular texture - setup array of mipmap level offsets */
  263.             struct pipe_resource *res = view->texture;
  264.             int j;
  265.  
  266.             if (llvmpipe_resource_is_texture(res)) {
  267.                first_level = view->u.tex.first_level;
  268.                last_level = view->u.tex.last_level;
  269.                assert(first_level <= last_level);
  270.                assert(last_level <= res->last_level);
  271.                addr = lp_tex->tex_data;
  272.  
  273.                for (j = first_level; j <= last_level; j++) {
  274.                   mip_offsets[j] = lp_tex->mip_offsets[j];
  275.                   row_stride[j] = lp_tex->row_stride[j];
  276.                   img_stride[j] = lp_tex->img_stride[j];
  277.                }
  278.                if (view->target == PIPE_TEXTURE_1D_ARRAY ||
  279.                    view->target == PIPE_TEXTURE_2D_ARRAY ||
  280.                    view->target == PIPE_TEXTURE_CUBE ||
  281.                    view->target == PIPE_TEXTURE_CUBE_ARRAY) {
  282.                   num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1;
  283.                   for (j = first_level; j <= last_level; j++) {
  284.                      mip_offsets[j] += view->u.tex.first_layer *
  285.                                        lp_tex->img_stride[j];
  286.                   }
  287.                   if (view->target == PIPE_TEXTURE_CUBE ||
  288.                       view->target == PIPE_TEXTURE_CUBE_ARRAY) {
  289.                      assert(num_layers % 6 == 0);
  290.                   }
  291.                   assert(view->u.tex.first_layer <= view->u.tex.last_layer);
  292.                   assert(view->u.tex.last_layer < res->array_size);
  293.                }
  294.             }
  295.             else {
  296.                unsigned view_blocksize = util_format_get_blocksize(view->format);
  297.                addr = lp_tex->data;
  298.                /* probably don't really need to fill that out */
  299.                mip_offsets[0] = 0;
  300.                row_stride[0] = 0;
  301.                img_stride[0] = 0;
  302.  
  303.                /* everything specified in number of elements here. */
  304.                width0 = view->u.buf.last_element - view->u.buf.first_element + 1;
  305.                addr = (uint8_t *)addr + view->u.buf.first_element *
  306.                                view_blocksize;
  307.                assert(view->u.buf.first_element <= view->u.buf.last_element);
  308.                assert(view->u.buf.last_element * view_blocksize < res->width0);
  309.             }
  310.          }
  311.          else {
  312.             /* display target texture/surface */
  313.             /*
  314.              * XXX: Where should this be unmapped?
  315.              */
  316.             struct llvmpipe_screen *screen = llvmpipe_screen(tex->screen);
  317.             struct sw_winsys *winsys = screen->winsys;
  318.             addr = winsys->displaytarget_map(winsys, lp_tex->dt,
  319.                                                 PIPE_TRANSFER_READ);
  320.             row_stride[0] = lp_tex->row_stride[0];
  321.             img_stride[0] = lp_tex->img_stride[0];
  322.             mip_offsets[0] = 0;
  323.             assert(addr);
  324.          }
  325.          draw_set_mapped_texture(lp->draw,
  326.                                  shader_type,
  327.                                  i,
  328.                                  width0, tex->height0, num_layers,
  329.                                  first_level, last_level,
  330.                                  addr,
  331.                                  row_stride, img_stride, mip_offsets);
  332.       }
  333.    }
  334. }
  335.  
  336.  
  337. /**
  338.  * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
  339.  */
  340. void
  341. llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp,
  342.                                  unsigned num,
  343.                                  struct pipe_sampler_view **views)
  344. {
  345.    prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX,
  346.                            lp->mapped_vs_tex);
  347. }
  348.  
  349. void
  350. llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx)
  351. {
  352.    unsigned i;
  353.    for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) {
  354.       pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL);
  355.    }
  356. }
  357.  
  358.  
  359. /**
  360.  * Called during state validation when LP_NEW_SAMPLER_VIEW is set.
  361.  */
  362. void
  363. llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp,
  364.                                    unsigned num,
  365.                                    struct pipe_sampler_view **views)
  366. {
  367.    prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY,
  368.                            lp->mapped_gs_tex);
  369. }
  370.  
  371. void
  372. llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context *ctx)
  373. {
  374.    unsigned i;
  375.    for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) {
  376.       pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL);
  377.    }
  378. }
  379.  
  380. void
  381. llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
  382. {
  383.    llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
  384.  
  385.    llvmpipe->pipe.bind_sampler_states = llvmpipe_bind_sampler_states;
  386.    llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view;
  387.    llvmpipe->pipe.set_sampler_views = llvmpipe_set_sampler_views;
  388.    llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy;
  389.    llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
  390. }
  391.