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