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 "pipe/p_defines.h" 27 #include "draw/draw_context.h" 28 #include "util/u_bitmask.h" 29 #include "util/u_inlines.h" 30 #include "util/u_math.h" 31 #include "util/u_memory.h" 32 33 #include "svga_cmd.h" 34 #include "svga_context.h" 35 #include "svga_hw_reg.h" 36 #include "svga_screen.h" 37 38 39 /* Hardware frontwinding is always set up as SVGA3D_FRONTWINDING_CW. 40 */ 41 static SVGA3dFace 42 svga_translate_cullmode(unsigned mode, unsigned front_ccw) 43 { 44 const int hw_front_ccw = 0; /* hardware is always CW */ 45 switch (mode) { 46 case PIPE_FACE_NONE: 47 return SVGA3D_FACE_NONE; 48 case PIPE_FACE_FRONT: 49 return front_ccw == hw_front_ccw ? SVGA3D_FACE_FRONT : SVGA3D_FACE_BACK; 50 case PIPE_FACE_BACK: 51 return front_ccw == hw_front_ccw ? SVGA3D_FACE_BACK : SVGA3D_FACE_FRONT; 52 case PIPE_FACE_FRONT_AND_BACK: 53 return SVGA3D_FACE_FRONT_BACK; 54 default: 55 assert(0); 56 return SVGA3D_FACE_NONE; 57 } 58 } 59 60 static SVGA3dShadeMode 61 svga_translate_flatshade(unsigned mode) 62 { 63 return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH; 64 } 65 66 67 static unsigned 68 translate_fill_mode(unsigned fill) 69 { 70 switch (fill) { 71 case PIPE_POLYGON_MODE_POINT: 72 return SVGA3D_FILLMODE_POINT; 73 case PIPE_POLYGON_MODE_LINE: 74 return SVGA3D_FILLMODE_LINE; 75 case PIPE_POLYGON_MODE_FILL: 76 return SVGA3D_FILLMODE_FILL; 77 default: 78 assert(!"Bad fill mode"); 79 return SVGA3D_FILLMODE_FILL; 80 } 81 } 82 83 84 static unsigned 85 translate_cull_mode(unsigned cull) 86 { 87 switch (cull) { 88 case PIPE_FACE_NONE: 89 return SVGA3D_CULL_NONE; 90 case PIPE_FACE_FRONT: 91 return SVGA3D_CULL_FRONT; 92 case PIPE_FACE_BACK: 93 return SVGA3D_CULL_BACK; 94 case PIPE_FACE_FRONT_AND_BACK: 95 /* NOTE: we simply no-op polygon drawing in svga_draw_vbo() */ 96 return SVGA3D_CULL_NONE; 97 default: 98 assert(!"Bad cull mode"); 99 return SVGA3D_CULL_NONE; 100 } 101 } 102 103 104 static void 105 define_rasterizer_object(struct svga_context *svga, 106 struct svga_rasterizer_state *rast) 107 { 108 struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 109 unsigned fill_mode = translate_fill_mode(rast->templ.fill_front); 110 const unsigned cull_mode = translate_cull_mode(rast->templ.cull_face); 111 const int depth_bias = rast->templ.offset_units; 112 const float slope_scaled_depth_bias = rast->templ.offset_scale; 113 /* PIPE_CAP_POLYGON_OFFSET_CLAMP not supported: */ 114 const float depth_bias_clamp = 0.0; 115 const float line_width = rast->templ.line_width > 0.0f ? 116 rast->templ.line_width : 1.0f; 117 const uint8 line_factor = rast->templ.line_stipple_enable ? 118 rast->templ.line_stipple_factor : 0; 119 const uint16 line_pattern = rast->templ.line_stipple_enable ? 120 rast->templ.line_stipple_pattern : 0; 121 unsigned try; 122 123 rast->id = util_bitmask_add(svga->rast_object_id_bm); 124 125 if (rast->templ.fill_front != rast->templ.fill_back) { 126 /* The VGPU10 device can't handle different front/back fill modes. 127 * We'll handle that with a swtnl/draw fallback. But we need to 128 * make sure we always fill triangles in that case. 129 */ 130 fill_mode = SVGA3D_FILLMODE_FILL; 131 } 132 133 for (try = 0; try < 2; try++) { 134 const uint8 pv_last = !rast->templ.flatshade_first && 135 svgascreen->haveProvokingVertex; 136 enum pipe_error ret = 137 SVGA3D_vgpu10_DefineRasterizerState(svga->swc, 138 rast->id, 139 fill_mode, 140 cull_mode, 141 rast->templ.front_ccw, 142 depth_bias, 143 depth_bias_clamp, 144 slope_scaled_depth_bias, 145 rast->templ.depth_clip, 146 rast->templ.scissor, 147 rast->templ.multisample, 148 rast->templ.line_smooth, 149 line_width, 150 rast->templ.line_stipple_enable, 151 line_factor, 152 line_pattern, 153 pv_last); 154 if (ret == PIPE_OK) 155 return; 156 svga_context_flush(svga, NULL); 157 } 158 } 159 160 161 static void * 162 svga_create_rasterizer_state(struct pipe_context *pipe, 163 const struct pipe_rasterizer_state *templ) 164 { 165 struct svga_context *svga = svga_context(pipe); 166 struct svga_rasterizer_state *rast = CALLOC_STRUCT(svga_rasterizer_state); 167 struct svga_screen *screen = svga_screen(pipe->screen); 168 169 if (!rast) 170 return NULL; 171 172 /* need this for draw module. */ 173 rast->templ = *templ; 174 175 /* light_twoside - XXX: need fragment shader variant */ 176 /* poly_smooth - XXX: no fallback available */ 177 /* poly_stipple_enable - draw module */ 178 /* sprite_coord_enable - ? */ 179 /* point_quad_rasterization - ? */ 180 /* point_size_per_vertex - ? */ 181 /* sprite_coord_mode - ??? */ 182 /* flatshade_first - handled by index translation */ 183 /* half_pixel_center - XXX - viewport code */ 184 /* line_width - draw module */ 185 /* fill_cw, fill_ccw - draw module or index translation */ 186 187 rast->shademode = svga_translate_flatshade(templ->flatshade); 188 rast->cullmode = svga_translate_cullmode(templ->cull_face, templ->front_ccw); 189 rast->scissortestenable = templ->scissor; 190 rast->multisampleantialias = templ->multisample; 191 rast->antialiasedlineenable = templ->line_smooth; 192 rast->lastpixel = templ->line_last_pixel; 193 rast->pointsprite = templ->sprite_coord_enable != 0x0; 194 195 if (templ->point_smooth) { 196 /* For smooth points we need to generate fragments for at least 197 * a 2x2 region. Otherwise the quad we draw may be too small and 198 * we may generate no fragments at all. 199 */ 200 rast->pointsize = MAX2(2.0f, templ->point_size); 201 } 202 else { 203 rast->pointsize = templ->point_size; 204 } 205 206 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; 207 208 /* Use swtnl + decomposition implement these: 209 */ 210 211 if (templ->line_width <= screen->maxLineWidth) { 212 /* pass line width to device */ 213 rast->linewidth = MAX2(1.0F, templ->line_width); 214 } 215 else if (svga->debug.no_line_width) { 216 /* nothing */ 217 } 218 else { 219 /* use 'draw' pipeline for wide line */ 220 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 221 rast->need_pipeline_lines_str = "line width"; 222 } 223 224 if (templ->line_stipple_enable) { 225 if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) { 226 SVGA3dLinePattern lp; 227 lp.repeat = templ->line_stipple_factor + 1; 228 lp.pattern = templ->line_stipple_pattern; 229 rast->linepattern = lp.uintValue; 230 } 231 else { 232 /* use 'draw' module to decompose into short line segments */ 233 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 234 rast->need_pipeline_lines_str = "line stipple"; 235 } 236 } 237 238 if (!svga_have_vgpu10(svga) && templ->point_smooth) { 239 rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; 240 rast->need_pipeline_points_str = "smooth points"; 241 } 242 243 if (templ->line_smooth && !screen->haveLineSmooth) { 244 /* 245 * XXX: Enabling the pipeline slows down performance immensely, so ignore 246 * line smooth state, where there is very little visual improvement. 247 * Smooth lines will still be drawn for wide lines. 248 */ 249 #if 0 250 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 251 rast->need_pipeline_lines_str = "smooth lines"; 252 #endif 253 } 254 255 { 256 int fill_front = templ->fill_front; 257 int fill_back = templ->fill_back; 258 int fill = PIPE_POLYGON_MODE_FILL; 259 boolean offset_front = util_get_offset(templ, fill_front); 260 boolean offset_back = util_get_offset(templ, fill_back); 261 boolean offset = FALSE; 262 263 switch (templ->cull_face) { 264 case PIPE_FACE_FRONT_AND_BACK: 265 offset = FALSE; 266 fill = PIPE_POLYGON_MODE_FILL; 267 break; 268 269 case PIPE_FACE_FRONT: 270 offset = offset_front; 271 fill = fill_front; 272 break; 273 274 case PIPE_FACE_BACK: 275 offset = offset_back; 276 fill = fill_back; 277 break; 278 279 case PIPE_FACE_NONE: 280 if (fill_front != fill_back || offset_front != offset_back) 281 { 282 /* Always need the draw module to work out different 283 * front/back fill modes: 284 */ 285 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 286 rast->need_pipeline_tris_str = "different front/back fillmodes"; 287 } 288 else { 289 offset = offset_front; 290 fill = fill_front; 291 } 292 break; 293 294 default: 295 assert(0); 296 break; 297 } 298 299 /* Unfilled primitive modes aren't implemented on all virtual 300 * hardware. We can do some unfilled processing with index 301 * translation, but otherwise need the draw module: 302 */ 303 if (fill != PIPE_POLYGON_MODE_FILL && 304 (templ->flatshade || 305 templ->light_twoside || 306 offset || 307 templ->cull_face != PIPE_FACE_NONE)) 308 { 309 fill = PIPE_POLYGON_MODE_FILL; 310 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 311 rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation"; 312 } 313 314 /* If we are decomposing to lines, and lines need the pipeline, 315 * then we also need the pipeline for tris. 316 */ 317 if (fill == PIPE_POLYGON_MODE_LINE && 318 (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) 319 { 320 fill = PIPE_POLYGON_MODE_FILL; 321 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 322 rast->need_pipeline_tris_str = "decomposing lines"; 323 } 324 325 /* Similarly for points: 326 */ 327 if (fill == PIPE_POLYGON_MODE_POINT && 328 (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) 329 { 330 fill = PIPE_POLYGON_MODE_FILL; 331 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 332 rast->need_pipeline_tris_str = "decomposing points"; 333 } 334 335 if (offset) { 336 rast->slopescaledepthbias = templ->offset_scale; 337 rast->depthbias = templ->offset_units; 338 } 339 340 rast->hw_fillmode = fill; 341 } 342 343 if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) { 344 /* Turn off stuff which will get done in the draw module: 345 */ 346 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; 347 rast->slopescaledepthbias = 0; 348 rast->depthbias = 0; 349 } 350 351 if (0 && rast->need_pipeline) { 352 debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline); 353 debug_printf(" pnts: %s \n", rast->need_pipeline_points_str); 354 debug_printf(" lins: %s \n", rast->need_pipeline_lines_str); 355 debug_printf(" tris: %s \n", rast->need_pipeline_tris_str); 356 } 357 358 if (svga_have_vgpu10(svga)) { 359 define_rasterizer_object(svga, rast); 360 } 361 362 if (templ->poly_smooth) { 363 pipe_debug_message(&svga->debug.callback, CONFORMANCE, 364 "GL_POLYGON_SMOOTH not supported"); 365 } 366 367 svga->hud.num_rasterizer_objects++; 368 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 369 SVGA_STATS_COUNT_RASTERIZERSTATE); 370 371 return rast; 372 } 373 374 375 static void 376 svga_bind_rasterizer_state(struct pipe_context *pipe, void *state) 377 { 378 struct svga_context *svga = svga_context(pipe); 379 struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state; 380 381 if (!raster || 382 !svga->curr.rast || 383 raster->templ.poly_stipple_enable != 384 svga->curr.rast->templ.poly_stipple_enable) { 385 svga->dirty |= SVGA_NEW_STIPPLE; 386 } 387 388 svga->curr.rast = raster; 389 390 svga->dirty |= SVGA_NEW_RAST; 391 } 392 393 394 static void 395 svga_delete_rasterizer_state(struct pipe_context *pipe, void *state) 396 { 397 struct svga_context *svga = svga_context(pipe); 398 struct svga_rasterizer_state *raster = 399 (struct svga_rasterizer_state *) state; 400 401 if (svga_have_vgpu10(svga)) { 402 enum pipe_error ret = 403 SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, raster->id); 404 if (ret != PIPE_OK) { 405 svga_context_flush(svga, NULL); 406 ret = SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, raster->id); 407 } 408 409 if (raster->id == svga->state.hw_draw.rasterizer_id) 410 svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID; 411 412 util_bitmask_clear(svga->rast_object_id_bm, raster->id); 413 } 414 415 FREE(state); 416 svga->hud.num_rasterizer_objects--; 417 } 418 419 420 void 421 svga_init_rasterizer_functions(struct svga_context *svga) 422 { 423 svga->pipe.create_rasterizer_state = svga_create_rasterizer_state; 424 svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state; 425 svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state; 426 } 427