Home | History | Annotate | Download | only in softpipe
      1 /**************************************************************************
      2  *
      3  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
      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 TUNGSTEN GRAPHICS 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_memory.h"
     33 #include "util/u_inlines.h"
     34 
     35 #include "draw/draw_context.h"
     36 
     37 #include "sp_context.h"
     38 #include "sp_state.h"
     39 #include "sp_texture.h"
     40 #include "sp_tex_sample.h"
     41 #include "sp_tex_tile_cache.h"
     42 
     43 
     44 struct sp_sampler {
     45    struct pipe_sampler_state base;
     46    struct sp_sampler_variant *variants;
     47    struct sp_sampler_variant *current;
     48 };
     49 
     50 static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler )
     51 {
     52    return (struct sp_sampler *)sampler;
     53 }
     54 
     55 
     56 static void *
     57 softpipe_create_sampler_state(struct pipe_context *pipe,
     58                               const struct pipe_sampler_state *sampler)
     59 {
     60    struct sp_sampler *sp_sampler = CALLOC_STRUCT(sp_sampler);
     61 
     62    sp_sampler->base = *sampler;
     63    sp_sampler->variants = NULL;
     64 
     65    return (void *)sp_sampler;
     66 }
     67 
     68 
     69 /**
     70  * Bind a range [start, start+num-1] of samplers for a shader stage.
     71  */
     72 static void
     73 softpipe_bind_sampler_states(struct pipe_context *pipe,
     74                              unsigned shader,
     75                              unsigned start,
     76                              unsigned num,
     77                              void **samplers)
     78 {
     79    struct softpipe_context *softpipe = softpipe_context(pipe);
     80    unsigned i;
     81 
     82    assert(shader < PIPE_SHADER_TYPES);
     83    assert(start + num <= Elements(softpipe->samplers[shader]));
     84 
     85    /* Check for no-op */
     86    if (start + num <= softpipe->num_samplers[shader] &&
     87        !memcmp(softpipe->samplers[shader] + start, samplers,
     88                num * sizeof(void *))) {
     89       return;
     90    }
     91 
     92    draw_flush(softpipe->draw);
     93 
     94    /* set the new samplers */
     95    for (i = 0; i < num; i++) {
     96       softpipe->samplers[shader][start + i] = samplers[i];
     97    }
     98 
     99    /* find highest non-null samplers[] entry */
    100    {
    101       unsigned j = MAX2(softpipe->num_samplers[shader], start + num);
    102       while (j > 0 && softpipe->samplers[shader][j - 1] == NULL)
    103          j--;
    104       softpipe->num_samplers[shader] = j;
    105    }
    106 
    107    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
    108       draw_set_samplers(softpipe->draw,
    109                         shader,
    110                         softpipe->samplers[shader],
    111                         softpipe->num_samplers[shader]);
    112    }
    113 
    114    softpipe->dirty |= SP_NEW_SAMPLER;
    115 }
    116 
    117 
    118 
    119 static void
    120 softpipe_bind_fragment_sampler_states(struct pipe_context *pipe,
    121                                       unsigned num, void **samplers)
    122 {
    123    softpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, num, samplers);
    124 }
    125 
    126 
    127 static void
    128 softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
    129                                     unsigned num,
    130                                     void **samplers)
    131 {
    132    softpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, 0, num, samplers);
    133 }
    134 
    135 
    136 static void
    137 softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
    138                                       unsigned num,
    139                                       void **samplers)
    140 {
    141    softpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, 0, num, samplers);
    142 }
    143 
    144 
    145 static struct pipe_sampler_view *
    146 softpipe_create_sampler_view(struct pipe_context *pipe,
    147                              struct pipe_resource *resource,
    148                              const struct pipe_sampler_view *templ)
    149 {
    150    struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view);
    151 
    152    if (view) {
    153       *view = *templ;
    154       view->reference.count = 1;
    155       view->texture = NULL;
    156       pipe_resource_reference(&view->texture, resource);
    157       view->context = pipe;
    158    }
    159 
    160    return view;
    161 }
    162 
    163 
    164 static void
    165 softpipe_sampler_view_destroy(struct pipe_context *pipe,
    166                               struct pipe_sampler_view *view)
    167 {
    168    pipe_resource_reference(&view->texture, NULL);
    169    FREE(view);
    170 }
    171 
    172 
    173 static void
    174 softpipe_set_sampler_views(struct pipe_context *pipe,
    175                            unsigned shader,
    176                            unsigned start,
    177                            unsigned num,
    178                            struct pipe_sampler_view **views)
    179 {
    180    struct softpipe_context *softpipe = softpipe_context(pipe);
    181    uint i;
    182 
    183    assert(shader < PIPE_SHADER_TYPES);
    184    assert(start + num <= Elements(softpipe->sampler_views[shader]));
    185 
    186    /* Check for no-op */
    187    if (start + num <= softpipe->num_sampler_views[shader] &&
    188        !memcmp(softpipe->sampler_views[shader] + start, views,
    189                num * sizeof(struct pipe_sampler_view *))) {
    190       return;
    191    }
    192 
    193    draw_flush(softpipe->draw);
    194 
    195    /* set the new sampler views */
    196    for (i = 0; i < num; i++) {
    197       pipe_sampler_view_reference(&softpipe->sampler_views[shader][start + i],
    198                                   views[i]);
    199       sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][start + i],
    200                                          views[i]);
    201    }
    202 
    203    /* find highest non-null sampler_views[] entry */
    204    {
    205       unsigned j = MAX2(softpipe->num_sampler_views[shader], start + num);
    206       while (j > 0 && softpipe->sampler_views[shader][j - 1] == NULL)
    207          j--;
    208       softpipe->num_sampler_views[shader] = j;
    209    }
    210 
    211    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
    212       draw_set_sampler_views(softpipe->draw,
    213                              shader,
    214                              softpipe->sampler_views[shader],
    215                              softpipe->num_sampler_views[shader]);
    216    }
    217 
    218    softpipe->dirty |= SP_NEW_TEXTURE;
    219 }
    220 
    221 
    222 static void
    223 softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
    224                                     unsigned num,
    225                                     struct pipe_sampler_view **views)
    226 {
    227    softpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num, views);
    228 }
    229 
    230 
    231 static void
    232 softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
    233                                   unsigned num,
    234                                   struct pipe_sampler_view **views)
    235 {
    236    softpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num, views);
    237 }
    238 
    239 
    240 static void
    241 softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
    242                                     unsigned num,
    243                                     struct pipe_sampler_view **views)
    244 {
    245    softpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, num, views);
    246 }
    247 
    248 
    249 /**
    250  * Find/create an sp_sampler_variant object for sampling the given texture,
    251  * sampler and tex unit.
    252  *
    253  * Note that the tex unit is significant.  We can't re-use a sampler
    254  * variant for multiple texture units because the sampler variant contains
    255  * the texture object pointer.  If the texture object pointer were stored
    256  * somewhere outside the sampler variant, we could re-use samplers for
    257  * multiple texture units.
    258  */
    259 static struct sp_sampler_variant *
    260 get_sampler_variant( unsigned unit,
    261                      struct sp_sampler *sampler,
    262                      struct pipe_sampler_view *view,
    263                      unsigned processor )
    264 {
    265    struct softpipe_resource *sp_texture = softpipe_resource(view->texture);
    266    struct sp_sampler_variant *v = NULL;
    267    union sp_sampler_key key;
    268 
    269    /* if this fails, widen the key.unit field and update this assertion */
    270    assert(PIPE_MAX_SAMPLERS <= 16);
    271 
    272    key.bits.target = sp_texture->base.target;
    273    key.bits.is_pot = sp_texture->pot;
    274    key.bits.processor = processor;
    275    key.bits.unit = unit;
    276    key.bits.swizzle_r = view->swizzle_r;
    277    key.bits.swizzle_g = view->swizzle_g;
    278    key.bits.swizzle_b = view->swizzle_b;
    279    key.bits.swizzle_a = view->swizzle_a;
    280    key.bits.pad = 0;
    281 
    282    if (sampler->current &&
    283        key.value == sampler->current->key.value) {
    284       v = sampler->current;
    285    }
    286 
    287    if (v == NULL) {
    288       for (v = sampler->variants; v; v = v->next)
    289          if (v->key.value == key.value)
    290             break;
    291 
    292       if (v == NULL) {
    293          v = sp_create_sampler_variant( &sampler->base, key );
    294          v->next = sampler->variants;
    295          sampler->variants = v;
    296       }
    297    }
    298 
    299    sampler->current = v;
    300    return v;
    301 }
    302 
    303 
    304 /**
    305  * Reset the sampler variants for a shader stage (vert, frag, geom).
    306  */
    307 static void
    308 reset_sampler_variants(struct softpipe_context *softpipe,
    309                        unsigned shader,
    310                        unsigned tgsi_shader,
    311                        int max_sampler)
    312 {
    313    int i;
    314 
    315    for (i = 0; i <= max_sampler; i++) {
    316       if (softpipe->samplers[shader][i]) {
    317          softpipe->tgsi.samplers_list[shader][i] =
    318             get_sampler_variant(i,
    319                                 sp_sampler(softpipe->samplers[shader][i]),
    320                                 softpipe->sampler_views[shader][i],
    321                                 tgsi_shader);
    322 
    323          sp_sampler_variant_bind_view(softpipe->tgsi.samplers_list[shader][i],
    324                                       softpipe->tex_cache[shader][i],
    325                                       softpipe->sampler_views[shader][i]);
    326       }
    327    }
    328 }
    329 
    330 
    331 void
    332 softpipe_reset_sampler_variants(struct softpipe_context *softpipe)
    333 {
    334    /* It's a bit hard to build these samplers ahead of time -- don't
    335     * really know which samplers are going to be used for vertex and
    336     * fragment programs.
    337     */
    338 
    339    /* XXX note: PIPE_SHADER_x != TGSI_PROCESSOR_x (fix that someday) */
    340    reset_sampler_variants(softpipe,
    341                           PIPE_SHADER_VERTEX,
    342                           TGSI_PROCESSOR_VERTEX,
    343                           softpipe->vs->max_sampler);
    344 
    345    reset_sampler_variants(softpipe,
    346                           PIPE_SHADER_FRAGMENT,
    347                           TGSI_PROCESSOR_FRAGMENT,
    348                           softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
    349 
    350    if (softpipe->gs) {
    351       reset_sampler_variants(softpipe,
    352                              PIPE_SHADER_GEOMETRY,
    353                              TGSI_PROCESSOR_GEOMETRY,
    354                              softpipe->gs->max_sampler);
    355    }
    356 }
    357 
    358 
    359 static void
    360 softpipe_delete_sampler_state(struct pipe_context *pipe,
    361                               void *sampler)
    362 {
    363    struct sp_sampler *sp_sampler = (struct sp_sampler *)sampler;
    364    struct sp_sampler_variant *v, *tmp;
    365 
    366    for (v = sp_sampler->variants; v; v = tmp) {
    367       tmp = v->next;
    368       sp_sampler_variant_destroy(v);
    369    }
    370 
    371    FREE( sampler );
    372 }
    373 
    374 
    375 void
    376 softpipe_init_sampler_funcs(struct pipe_context *pipe)
    377 {
    378    pipe->create_sampler_state = softpipe_create_sampler_state;
    379    pipe->bind_fragment_sampler_states  = softpipe_bind_fragment_sampler_states;
    380    pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
    381    pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
    382    pipe->delete_sampler_state = softpipe_delete_sampler_state;
    383 
    384    pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views;
    385    pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
    386    pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
    387 
    388    pipe->create_sampler_view = softpipe_create_sampler_view;
    389    pipe->sampler_view_destroy = softpipe_sampler_view_destroy;
    390 }
    391 
    392