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 #include "sp_context.h"
     29 #include "sp_state.h"
     30 #include "sp_fs.h"
     31 #include "sp_texture.h"
     32 
     33 #include "pipe/p_defines.h"
     34 #include "util/u_memory.h"
     35 #include "util/u_inlines.h"
     36 #include "util/u_pstipple.h"
     37 #include "draw/draw_context.h"
     38 #include "draw/draw_vs.h"
     39 #include "draw/draw_gs.h"
     40 #include "tgsi/tgsi_dump.h"
     41 #include "tgsi/tgsi_scan.h"
     42 #include "tgsi/tgsi_parse.h"
     43 
     44 
     45 /**
     46  * Create a new fragment shader variant.
     47  */
     48 static struct sp_fragment_shader_variant *
     49 create_fs_variant(struct softpipe_context *softpipe,
     50                   struct sp_fragment_shader *fs,
     51                   const struct sp_fragment_shader_variant_key *key)
     52 {
     53    struct sp_fragment_shader_variant *var;
     54    struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
     55    unsigned unit = 0;
     56 
     57 #if DO_PSTIPPLE_IN_HELPER_MODULE
     58    if (key->polygon_stipple) {
     59       /* get new shader that implements polygon stippling */
     60       stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
     61                                                         curfs, &unit);
     62       curfs = stipple_fs;
     63    }
     64 #endif
     65 
     66    /* codegen, create variant object */
     67    var = softpipe_create_fs_variant_exec(softpipe, curfs);
     68 
     69    if (var) {
     70       var->key = *key;
     71       var->tokens = tgsi_dup_tokens(curfs->tokens);
     72       var->stipple_sampler_unit = unit;
     73 
     74       tgsi_scan_shader(var->tokens, &var->info);
     75 
     76       /* See comments elsewhere about draw fragment shaders */
     77 #if 0
     78       /* draw's fs state */
     79       var->draw_shader = draw_create_fragment_shader(softpipe->draw,
     80                                                      &fs->shader);
     81       if (!var->draw_shader) {
     82          var->delete(var);
     83          FREE((void *) var->tokens);
     84          return NULL;
     85       }
     86 #endif
     87 
     88       /* insert variant into linked list */
     89       var->next = fs->variants;
     90       fs->variants = var;
     91    }
     92 
     93    if (stipple_fs) {
     94       FREE((void *) stipple_fs->tokens);
     95       FREE(stipple_fs);
     96    }
     97 
     98    return var;
     99 }
    100 
    101 
    102 struct sp_fragment_shader_variant *
    103 softpipe_find_fs_variant(struct softpipe_context *sp,
    104                          struct sp_fragment_shader *fs,
    105                          const struct sp_fragment_shader_variant_key *key)
    106 {
    107    struct sp_fragment_shader_variant *var;
    108 
    109    for (var = fs->variants; var; var = var->next) {
    110       if (memcmp(&var->key, key, sizeof(*key)) == 0) {
    111          /* found it */
    112          return var;
    113       }
    114    }
    115 
    116    return create_fs_variant(sp, fs, key);
    117 }
    118 
    119 
    120 static void *
    121 softpipe_create_fs_state(struct pipe_context *pipe,
    122                          const struct pipe_shader_state *templ)
    123 {
    124    struct softpipe_context *softpipe = softpipe_context(pipe);
    125    struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
    126 
    127    /* debug */
    128    if (softpipe->dump_fs)
    129       tgsi_dump(templ->tokens, 0);
    130 
    131    /* we need to keep a local copy of the tokens */
    132    state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    133 
    134    /* draw's fs state */
    135    state->draw_shader = draw_create_fragment_shader(softpipe->draw,
    136                                                     &state->shader);
    137    if (!state->draw_shader) {
    138       FREE((void *) state->shader.tokens);
    139       FREE(state);
    140       return NULL;
    141    }
    142 
    143    return state;
    144 }
    145 
    146 
    147 static void
    148 softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
    149 {
    150    struct softpipe_context *softpipe = softpipe_context(pipe);
    151    struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
    152 
    153    if (softpipe->fs == fs)
    154       return;
    155 
    156    draw_flush(softpipe->draw);
    157 
    158    softpipe->fs = fs;
    159 
    160    /* This depends on the current fragment shader and must always be
    161     * re-validated before use.
    162     */
    163    softpipe->fs_variant = NULL;
    164 
    165    if (state)
    166       draw_bind_fragment_shader(softpipe->draw,
    167                                 state->draw_shader);
    168    else
    169       draw_bind_fragment_shader(softpipe->draw, NULL);
    170 
    171    softpipe->dirty |= SP_NEW_FS;
    172 }
    173 
    174 
    175 static void
    176 softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
    177 {
    178    struct softpipe_context *softpipe = softpipe_context(pipe);
    179    struct sp_fragment_shader *state = fs;
    180    struct sp_fragment_shader_variant *var, *next_var;
    181 
    182    assert(fs != softpipe->fs);
    183 
    184    /* delete variants */
    185    for (var = state->variants; var; var = next_var) {
    186       next_var = var->next;
    187 
    188       assert(var != softpipe->fs_variant);
    189 
    190       /* See comments elsewhere about draw fragment shaders */
    191 #if 0
    192       draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
    193 #endif
    194 
    195       var->delete(var, softpipe->fs_machine);
    196    }
    197 
    198    draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
    199 
    200    FREE((void *) state->shader.tokens);
    201    FREE(state);
    202 }
    203 
    204 
    205 static void *
    206 softpipe_create_vs_state(struct pipe_context *pipe,
    207                          const struct pipe_shader_state *templ)
    208 {
    209    struct softpipe_context *softpipe = softpipe_context(pipe);
    210    struct sp_vertex_shader *state;
    211 
    212    state = CALLOC_STRUCT(sp_vertex_shader);
    213    if (state == NULL )
    214       goto fail;
    215 
    216    /* copy shader tokens, the ones passed in will go away.
    217     */
    218    state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    219    if (state->shader.tokens == NULL)
    220       goto fail;
    221 
    222    state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
    223    if (state->draw_data == NULL)
    224       goto fail;
    225 
    226    state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
    227 
    228    return state;
    229 
    230 fail:
    231    if (state) {
    232       FREE( (void *)state->shader.tokens );
    233       FREE( state->draw_data );
    234       FREE( state );
    235    }
    236    return NULL;
    237 }
    238 
    239 
    240 static void
    241 softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
    242 {
    243    struct softpipe_context *softpipe = softpipe_context(pipe);
    244 
    245    softpipe->vs = (struct sp_vertex_shader *) vs;
    246 
    247    draw_bind_vertex_shader(softpipe->draw,
    248                            (softpipe->vs ? softpipe->vs->draw_data : NULL));
    249 
    250    softpipe->dirty |= SP_NEW_VS;
    251 }
    252 
    253 
    254 static void
    255 softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
    256 {
    257    struct softpipe_context *softpipe = softpipe_context(pipe);
    258 
    259    struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
    260 
    261    draw_delete_vertex_shader(softpipe->draw, state->draw_data);
    262    FREE( (void *)state->shader.tokens );
    263    FREE( state );
    264 }
    265 
    266 
    267 static void *
    268 softpipe_create_gs_state(struct pipe_context *pipe,
    269                          const struct pipe_shader_state *templ)
    270 {
    271    struct softpipe_context *softpipe = softpipe_context(pipe);
    272    struct sp_geometry_shader *state;
    273 
    274    state = CALLOC_STRUCT(sp_geometry_shader);
    275    if (state == NULL )
    276       goto fail;
    277 
    278    /* debug */
    279    if (softpipe->dump_gs)
    280       tgsi_dump(templ->tokens, 0);
    281 
    282    /* copy shader tokens, the ones passed in will go away.
    283     */
    284    state->shader.tokens = tgsi_dup_tokens(templ->tokens);
    285    if (state->shader.tokens == NULL)
    286       goto fail;
    287 
    288    state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
    289    if (state->draw_data == NULL)
    290       goto fail;
    291 
    292    state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
    293 
    294    return state;
    295 
    296 fail:
    297    if (state) {
    298       FREE( (void *)state->shader.tokens );
    299       FREE( state->draw_data );
    300       FREE( state );
    301    }
    302    return NULL;
    303 }
    304 
    305 
    306 static void
    307 softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
    308 {
    309    struct softpipe_context *softpipe = softpipe_context(pipe);
    310 
    311    softpipe->gs = (struct sp_geometry_shader *)gs;
    312 
    313    draw_bind_geometry_shader(softpipe->draw,
    314                              (softpipe->gs ? softpipe->gs->draw_data : NULL));
    315 
    316    softpipe->dirty |= SP_NEW_GS;
    317 }
    318 
    319 
    320 static void
    321 softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
    322 {
    323    struct softpipe_context *softpipe = softpipe_context(pipe);
    324 
    325    struct sp_geometry_shader *state =
    326       (struct sp_geometry_shader *)gs;
    327 
    328    draw_delete_geometry_shader(softpipe->draw,
    329                                (state) ? state->draw_data : 0);
    330 
    331    FREE((void *) state->shader.tokens);
    332    FREE(state);
    333 }
    334 
    335 
    336 static void
    337 softpipe_set_constant_buffer(struct pipe_context *pipe,
    338                              uint shader, uint index,
    339                              struct pipe_constant_buffer *cb)
    340 {
    341    struct softpipe_context *softpipe = softpipe_context(pipe);
    342    struct pipe_resource *constants = cb ? cb->buffer : NULL;
    343    unsigned size;
    344    const void *data;
    345 
    346    if (cb && cb->user_buffer) {
    347       constants = softpipe_user_buffer_create(pipe->screen,
    348                                               (void *) cb->user_buffer,
    349                                               cb->buffer_size,
    350                                               PIPE_BIND_CONSTANT_BUFFER);
    351    }
    352 
    353    size = constants ? constants->width0 : 0;
    354    data = constants ? softpipe_resource(constants)->data : NULL;
    355 
    356    assert(shader < PIPE_SHADER_TYPES);
    357 
    358    draw_flush(softpipe->draw);
    359 
    360    /* note: reference counting */
    361    pipe_resource_reference(&softpipe->constants[shader][index], constants);
    362 
    363    if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
    364       draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
    365    }
    366 
    367    softpipe->mapped_constants[shader][index] = data;
    368    softpipe->const_buffer_size[shader][index] = size;
    369 
    370    softpipe->dirty |= SP_NEW_CONSTANTS;
    371 
    372    if (cb && cb->user_buffer) {
    373       pipe_resource_reference(&constants, NULL);
    374    }
    375 }
    376 
    377 
    378 void
    379 softpipe_init_shader_funcs(struct pipe_context *pipe)
    380 {
    381    pipe->create_fs_state = softpipe_create_fs_state;
    382    pipe->bind_fs_state   = softpipe_bind_fs_state;
    383    pipe->delete_fs_state = softpipe_delete_fs_state;
    384 
    385    pipe->create_vs_state = softpipe_create_vs_state;
    386    pipe->bind_vs_state   = softpipe_bind_vs_state;
    387    pipe->delete_vs_state = softpipe_delete_vs_state;
    388 
    389    pipe->create_gs_state = softpipe_create_gs_state;
    390    pipe->bind_gs_state   = softpipe_bind_gs_state;
    391    pipe->delete_gs_state = softpipe_delete_gs_state;
    392 
    393    pipe->set_constant_buffer = softpipe_set_constant_buffer;
    394 }
    395