Home | History | Annotate | Download | only in svga
      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 "draw/draw_context.h"
     27 #include "util/u_inlines.h"
     28 #include "pipe/p_defines.h"
     29 #include "util/u_math.h"
     30 #include "util/u_memory.h"
     31 
     32 #include "svga_context.h"
     33 
     34 #include "svga_hw_reg.h"
     35 
     36 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW.
     37  */
     38 static SVGA3dFace svga_translate_cullmode( unsigned mode,
     39                                            unsigned front_ccw )
     40 {
     41    const int hw_front_ccw = 0;  /* hardware is always CW */
     42    switch (mode) {
     43    case PIPE_FACE_NONE:
     44       return SVGA3D_FACE_NONE;
     45    case PIPE_FACE_FRONT:
     46       return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK;
     47    case PIPE_FACE_BACK:
     48       return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT;
     49    case PIPE_FACE_FRONT_AND_BACK:
     50       return SVGA3D_FACE_FRONT_BACK;
     51    default:
     52       assert(0);
     53       return SVGA3D_FACE_NONE;
     54    }
     55 }
     56 
     57 static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
     58 {
     59    return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
     60 }
     61 
     62 
     63 static void *
     64 svga_create_rasterizer_state(struct pipe_context *pipe,
     65                              const struct pipe_rasterizer_state *templ)
     66 {
     67    struct svga_context *svga = svga_context(pipe);
     68    struct svga_rasterizer_state *rast = CALLOC_STRUCT( svga_rasterizer_state );
     69 
     70    /* need this for draw module. */
     71    rast->templ = *templ;
     72 
     73    /* light_twoside          - XXX: need fragment shader variant */
     74    /* poly_smooth            - XXX: no fallback available */
     75    /* poly_stipple_enable    - draw module */
     76    /* sprite_coord_enable    - ? */
     77    /* point_quad_rasterization - ? */
     78    /* point_size_per_vertex  - ? */
     79    /* sprite_coord_mode      - ??? */
     80    /* flatshade_first        - handled by index translation */
     81    /* gl_rasterization_rules - XXX - viewport code */
     82    /* line_width             - draw module */
     83    /* fill_cw, fill_ccw      - draw module or index translation */
     84 
     85    rast->shademode = svga_translate_flatshade( templ->flatshade );
     86    rast->cullmode = svga_translate_cullmode( templ->cull_face,
     87                                              templ->front_ccw );
     88    rast->scissortestenable = templ->scissor;
     89    rast->multisampleantialias = templ->multisample;
     90    rast->antialiasedlineenable = templ->line_smooth;
     91    rast->lastpixel = templ->line_last_pixel;
     92    rast->pointsprite = templ->sprite_coord_enable != 0x0;
     93    rast->pointsize = templ->point_size;
     94    rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
     95 
     96    /* Use swtnl + decomposition implement these:
     97     */
     98    if (templ->poly_stipple_enable) {
     99       rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
    100       rast->need_pipeline_tris_str = "poly stipple";
    101    }
    102 
    103    if (templ->line_width >= 1.5f &&
    104        !svga->debug.no_line_width) {
    105       rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
    106       rast->need_pipeline_lines_str = "line width";
    107    }
    108 
    109    if (templ->line_stipple_enable) {
    110       /* XXX: LinePattern not implemented on all backends, and there is no
    111        * mechanism to query it.
    112        */
    113       if (!svga->debug.force_hw_line_stipple) {
    114          SVGA3dLinePattern lp;
    115          lp.repeat = templ->line_stipple_factor + 1;
    116          lp.pattern = templ->line_stipple_pattern;
    117          rast->linepattern = lp.uintValue;
    118       }
    119       else {
    120          rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
    121          rast->need_pipeline_lines_str = "line stipple";
    122       }
    123    }
    124 
    125    if (templ->point_smooth) {
    126       rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
    127       rast->need_pipeline_points_str = "smooth points";
    128    }
    129 
    130    if (templ->line_smooth) {
    131       rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES;
    132       rast->need_pipeline_lines_str = "smooth lines";
    133    }
    134 
    135    {
    136       int fill_front = templ->fill_front;
    137       int fill_back = templ->fill_back;
    138       int fill = PIPE_POLYGON_MODE_FILL;
    139       boolean offset_front = util_get_offset(templ, fill_front);
    140       boolean offset_back = util_get_offset(templ, fill_back);
    141       boolean offset  = 0;
    142 
    143       switch (templ->cull_face) {
    144       case PIPE_FACE_FRONT_AND_BACK:
    145          offset = 0;
    146          fill = PIPE_POLYGON_MODE_FILL;
    147          break;
    148 
    149       case PIPE_FACE_FRONT:
    150          offset = offset_front;
    151          fill = fill_front;
    152          break;
    153 
    154       case PIPE_FACE_BACK:
    155          offset = offset_back;
    156          fill = fill_back;
    157          break;
    158 
    159       case PIPE_FACE_NONE:
    160          if (fill_front != fill_back || offset_front != offset_back)
    161          {
    162             /* Always need the draw module to work out different
    163              * front/back fill modes:
    164              */
    165             rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
    166             rast->need_pipeline_tris_str = "different front/back fillmodes";
    167          }
    168          else {
    169             offset = offset_front;
    170             fill = fill_front;
    171          }
    172          break;
    173 
    174       default:
    175          assert(0);
    176          break;
    177       }
    178 
    179       /* Unfilled primitive modes aren't implemented on all virtual
    180        * hardware.  We can do some unfilled processing with index
    181        * translation, but otherwise need the draw module:
    182        */
    183       if (fill != PIPE_POLYGON_MODE_FILL &&
    184           (templ->flatshade ||
    185            templ->light_twoside ||
    186            offset ||
    187            templ->cull_face != PIPE_FACE_NONE))
    188       {
    189          fill = PIPE_POLYGON_MODE_FILL;
    190          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
    191          rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation";
    192       }
    193 
    194       /* If we are decomposing to lines, and lines need the pipeline,
    195        * then we also need the pipeline for tris.
    196        */
    197       if (fill == PIPE_POLYGON_MODE_LINE &&
    198           (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES))
    199       {
    200          fill = PIPE_POLYGON_MODE_FILL;
    201          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
    202          rast->need_pipeline_tris_str = "decomposing lines";
    203       }
    204 
    205       /* Similarly for points:
    206        */
    207       if (fill == PIPE_POLYGON_MODE_POINT &&
    208           (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS))
    209       {
    210          fill = PIPE_POLYGON_MODE_FILL;
    211          rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS;
    212          rast->need_pipeline_tris_str = "decomposing points";
    213       }
    214 
    215       if (offset) {
    216          rast->slopescaledepthbias = templ->offset_scale;
    217          rast->depthbias = templ->offset_units;
    218       }
    219 
    220       rast->hw_unfilled = fill;
    221    }
    222 
    223    if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) {
    224       /* Turn off stuff which will get done in the draw module:
    225        */
    226       rast->hw_unfilled = PIPE_POLYGON_MODE_FILL;
    227       rast->slopescaledepthbias = 0;
    228       rast->depthbias = 0;
    229    }
    230 
    231    return rast;
    232 }
    233 
    234 static void svga_bind_rasterizer_state( struct pipe_context *pipe,
    235                                         void *state )
    236 {
    237    struct svga_context *svga = svga_context(pipe);
    238    struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state;
    239 
    240 
    241    draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL,
    242                              state);
    243    svga->curr.rast = raster;
    244 
    245    svga->dirty |= SVGA_NEW_RAST;
    246 }
    247 
    248 static void svga_delete_rasterizer_state(struct pipe_context *pipe,
    249                                          void *raster)
    250 {
    251    FREE(raster);
    252 }
    253 
    254 
    255 void svga_init_rasterizer_functions( struct svga_context *svga )
    256 {
    257    svga->pipe.create_rasterizer_state = svga_create_rasterizer_state;
    258    svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state;
    259    svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state;
    260 }
    261 
    262 
    263 /***********************************************************************
    264  * Hardware state update
    265  */
    266 
    267