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 */
38static 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
57static SVGA3dShadeMode svga_translate_flatshade( unsigned mode )
58{
59   return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH;
60}
61
62
63static void *
64svga_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
234static 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
248static void svga_delete_rasterizer_state(struct pipe_context *pipe,
249                                         void *raster)
250{
251   FREE(raster);
252}
253
254
255void 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