Home | History | Annotate | Download | only in softpipe
      1 /**************************************************************************
      2  *
      3  * Copyright 2003 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 "util/u_inlines.h"
     29 #include "util/u_math.h"
     30 #include "util/u_memory.h"
     31 #include "util/u_pstipple.h"
     32 #include "pipe/p_shader_tokens.h"
     33 #include "draw/draw_context.h"
     34 #include "draw/draw_vertex.h"
     35 #include "sp_context.h"
     36 #include "sp_screen.h"
     37 #include "sp_state.h"
     38 #include "sp_texture.h"
     39 #include "sp_tex_tile_cache.h"
     40 
     41 
     42 /**
     43  * Mark the current vertex layout as "invalid".
     44  * We'll validate the vertex layout later, when we start to actually
     45  * render a point or line or tri.
     46  */
     47 static void
     48 invalidate_vertex_layout(struct softpipe_context *softpipe)
     49 {
     50    softpipe->vertex_info.num_attribs =  0;
     51 }
     52 
     53 
     54 /**
     55  * The vertex info describes how to convert the post-transformed vertices
     56  * (simple float[][4]) used by the 'draw' module into vertices for
     57  * rasterization.
     58  *
     59  * This function validates the vertex layout and returns a pointer to a
     60  * vertex_info object.
     61  */
     62 struct vertex_info *
     63 softpipe_get_vertex_info(struct softpipe_context *softpipe)
     64 {
     65    struct vertex_info *vinfo = &softpipe->vertex_info;
     66 
     67    if (vinfo->num_attribs == 0) {
     68       /* compute vertex layout now */
     69       const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
     70       struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
     71       const uint num = draw_num_shader_outputs(softpipe->draw);
     72       uint i;
     73 
     74       /* Tell draw_vbuf to simply emit the whole post-xform vertex
     75        * as-is.  No longer any need to try and emit draw vertex_header
     76        * info.
     77        */
     78       vinfo_vbuf->num_attribs = 0;
     79       for (i = 0; i < num; i++) {
     80 	 draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
     81       }
     82       draw_compute_vertex_size(vinfo_vbuf);
     83 
     84       /*
     85        * Loop over fragment shader inputs, searching for the matching output
     86        * from the vertex shader.
     87        */
     88       vinfo->num_attribs = 0;
     89       for (i = 0; i < fsInfo->num_inputs; i++) {
     90          int src;
     91          enum interp_mode interp = INTERP_LINEAR;
     92 
     93          switch (fsInfo->input_interpolate[i]) {
     94          case TGSI_INTERPOLATE_CONSTANT:
     95             interp = INTERP_CONSTANT;
     96             break;
     97          case TGSI_INTERPOLATE_LINEAR:
     98             interp = INTERP_LINEAR;
     99             break;
    100          case TGSI_INTERPOLATE_PERSPECTIVE:
    101             interp = INTERP_PERSPECTIVE;
    102             break;
    103          case TGSI_INTERPOLATE_COLOR:
    104             assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
    105             break;
    106          default:
    107             assert(0);
    108          }
    109 
    110          switch (fsInfo->input_semantic_name[i]) {
    111          case TGSI_SEMANTIC_POSITION:
    112             interp = INTERP_POS;
    113             break;
    114 
    115          case TGSI_SEMANTIC_COLOR:
    116             if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
    117                if (softpipe->rasterizer->flatshade)
    118                   interp = INTERP_CONSTANT;
    119                else
    120                   interp = INTERP_PERSPECTIVE;
    121             }
    122             break;
    123          }
    124 
    125          /* this includes texcoords and varying vars */
    126          src = draw_find_shader_output(softpipe->draw,
    127                                        fsInfo->input_semantic_name[i],
    128                                        fsInfo->input_semantic_index[i]);
    129 	 if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == 0)
    130 	   /* try and find a bcolor */
    131 	   src = draw_find_shader_output(softpipe->draw,
    132 					 TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
    133 
    134          draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
    135       }
    136 
    137       softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
    138                                                  TGSI_SEMANTIC_PSIZE, 0);
    139       if (softpipe->psize_slot > 0) {
    140          draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
    141                                softpipe->psize_slot);
    142       }
    143 
    144       draw_compute_vertex_size(vinfo);
    145    }
    146 
    147    return vinfo;
    148 }
    149 
    150 
    151 /**
    152  * Called from vbuf module.
    153  *
    154  * Note that there's actually two different vertex layouts in softpipe.
    155  *
    156  * The normal one is computed in softpipe_get_vertex_info() above and is
    157  * used by the point/line/tri "setup" code.
    158  *
    159  * The other one (this one) is only used by the vbuf module (which is
    160  * not normally used by default but used in testing).  For the vbuf module,
    161  * we basically want to pass-through the draw module's vertex layout as-is.
    162  * When the softpipe vbuf code begins drawing, the normal vertex layout
    163  * will come into play again.
    164  */
    165 struct vertex_info *
    166 softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
    167 {
    168    (void) softpipe_get_vertex_info(softpipe);
    169    return &softpipe->vertex_info_vbuf;
    170 }
    171 
    172 
    173 /**
    174  * Recompute cliprect from scissor bounds, scissor enable and surface size.
    175  */
    176 static void
    177 compute_cliprect(struct softpipe_context *sp)
    178 {
    179    /* SP_NEW_FRAMEBUFFER
    180     */
    181    uint surfWidth = sp->framebuffer.width;
    182    uint surfHeight = sp->framebuffer.height;
    183 
    184    /* SP_NEW_RASTERIZER
    185     */
    186    if (sp->rasterizer->scissor) {
    187 
    188       /* SP_NEW_SCISSOR
    189        *
    190        * clip to scissor rect:
    191        */
    192       sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
    193       sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
    194       sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
    195       sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
    196    }
    197    else {
    198       /* clip to surface bounds */
    199       sp->cliprect.minx = 0;
    200       sp->cliprect.miny = 0;
    201       sp->cliprect.maxx = surfWidth;
    202       sp->cliprect.maxy = surfHeight;
    203    }
    204 }
    205 
    206 
    207 static void
    208 update_tgsi_samplers( struct softpipe_context *softpipe )
    209 {
    210    unsigned i, sh;
    211 
    212    softpipe_reset_sampler_variants( softpipe );
    213 
    214    for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
    215       for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
    216          struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
    217          if (tc && tc->texture) {
    218             struct softpipe_resource *spt = softpipe_resource(tc->texture);
    219             if (spt->timestamp != tc->timestamp) {
    220                sp_tex_tile_cache_validate_texture( tc );
    221                /*
    222                  _debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
    223                */
    224                tc->timestamp = spt->timestamp;
    225             }
    226          }
    227       }
    228    }
    229 }
    230 
    231 
    232 static void
    233 update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
    234 {
    235    struct sp_fragment_shader_variant_key key;
    236 
    237    memset(&key, 0, sizeof(key));
    238 
    239    if (prim == PIPE_PRIM_TRIANGLES)
    240       key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
    241 
    242    if (softpipe->fs) {
    243       softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
    244                                                       softpipe->fs, &key);
    245 
    246       /* prepare the TGSI interpreter for FS execution */
    247       softpipe->fs_variant->prepare(softpipe->fs_variant,
    248                                     softpipe->fs_machine,
    249                                     (struct tgsi_sampler **) softpipe->
    250                                     tgsi.samplers_list[PIPE_SHADER_FRAGMENT]);
    251    }
    252    else {
    253       softpipe->fs_variant = NULL;
    254    }
    255 
    256    /* This would be the logical place to pass the fragment shader
    257     * to the draw module.  However, doing this here, during state
    258     * validation, causes problems with the 'draw' module helpers for
    259     * wide/AA/stippled lines.
    260     * In principle, the draw's fragment shader should be per-variant
    261     * but that doesn't work.  So we use a single draw fragment shader
    262     * per fragment shader, not per variant.
    263     */
    264 #if 0
    265    if (softpipe->fs_variant) {
    266       draw_bind_fragment_shader(softpipe->draw,
    267                                 softpipe->fs_variant->draw_shader);
    268    }
    269    else {
    270       draw_bind_fragment_shader(softpipe->draw, NULL);
    271    }
    272 #endif
    273 }
    274 
    275 
    276 /**
    277  * This should be called when the polygon stipple pattern changes.
    278  * We create a new texture from the stipple pattern and create a new
    279  * sampler view.
    280  */
    281 static void
    282 update_polygon_stipple_pattern(struct softpipe_context *softpipe)
    283 {
    284    struct pipe_resource *tex;
    285    struct pipe_sampler_view *view;
    286 
    287    tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
    288                                               softpipe->poly_stipple.stipple);
    289    pipe_resource_reference(&softpipe->pstipple.texture, tex);
    290    pipe_resource_reference(&tex, NULL);
    291 
    292    view = util_pstipple_create_sampler_view(&softpipe->pipe,
    293                                             softpipe->pstipple.texture);
    294    pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
    295    pipe_sampler_view_reference(&view, NULL);
    296 }
    297 
    298 
    299 /**
    300  * Should be called when polygon stipple is enabled/disabled or when
    301  * the fragment shader changes.
    302  * We add/update the fragment sampler and sampler views to sample from
    303  * the polygon stipple texture.  The texture unit that we use depends on
    304  * the fragment shader (we need to use a unit not otherwise used by the
    305  * shader).
    306  */
    307 static void
    308 update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
    309 {
    310    if (prim == PIPE_PRIM_TRIANGLES &&
    311        softpipe->fs_variant->key.polygon_stipple) {
    312       const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
    313 
    314       /* sampler state */
    315       softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
    316 
    317       /* sampler view */
    318       pipe_sampler_view_reference(&softpipe->sampler_views[PIPE_SHADER_FRAGMENT][unit],
    319                                   softpipe->pstipple.sampler_view);
    320 
    321       sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[PIPE_SHADER_FRAGMENT][unit],
    322                                          softpipe->pstipple.sampler_view);
    323 
    324       softpipe->dirty |= SP_NEW_SAMPLER;
    325    }
    326 }
    327 
    328 
    329 /* Hopefully this will remain quite simple, otherwise need to pull in
    330  * something like the state tracker mechanism.
    331  */
    332 void
    333 softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
    334 {
    335    struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
    336 
    337    /* Check for updated textures.
    338     */
    339    if (softpipe->tex_timestamp != sp_screen->timestamp) {
    340       softpipe->tex_timestamp = sp_screen->timestamp;
    341       softpipe->dirty |= SP_NEW_TEXTURE;
    342    }
    343 
    344 #if DO_PSTIPPLE_IN_HELPER_MODULE
    345    if (softpipe->dirty & SP_NEW_STIPPLE)
    346       /* before updating samplers! */
    347       update_polygon_stipple_pattern(softpipe);
    348 #endif
    349 
    350    if (softpipe->dirty & (SP_NEW_RASTERIZER |
    351                           SP_NEW_FS))
    352       update_fragment_shader(softpipe, prim);
    353 
    354 #if DO_PSTIPPLE_IN_HELPER_MODULE
    355    if (softpipe->dirty & (SP_NEW_RASTERIZER |
    356                           SP_NEW_STIPPLE |
    357                           SP_NEW_FS))
    358       update_polygon_stipple_enable(softpipe, prim);
    359 #endif
    360 
    361    if (softpipe->dirty & (SP_NEW_SAMPLER |
    362                           SP_NEW_TEXTURE |
    363                           SP_NEW_FS |
    364                           SP_NEW_VS))
    365       update_tgsi_samplers( softpipe );
    366 
    367    if (softpipe->dirty & (SP_NEW_RASTERIZER |
    368                           SP_NEW_FS |
    369                           SP_NEW_VS))
    370       invalidate_vertex_layout( softpipe );
    371 
    372    if (softpipe->dirty & (SP_NEW_SCISSOR |
    373                           SP_NEW_RASTERIZER |
    374                           SP_NEW_FRAMEBUFFER))
    375       compute_cliprect(softpipe);
    376 
    377    if (softpipe->dirty & (SP_NEW_BLEND |
    378                           SP_NEW_DEPTH_STENCIL_ALPHA |
    379                           SP_NEW_FRAMEBUFFER |
    380                           SP_NEW_FS))
    381       sp_build_quad_pipeline(softpipe);
    382 
    383    softpipe->dirty = 0;
    384 }
    385