Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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