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 */ 41static SVGA3dFace 42svga_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 60static SVGA3dShadeMode 61svga_translate_flatshade(unsigned mode) 62{ 63 return mode ? SVGA3D_SHADEMODE_FLAT : SVGA3D_SHADEMODE_SMOOTH; 64} 65 66 67static unsigned 68translate_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 84static unsigned 85translate_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 104int 105svga_define_rasterizer_object(struct svga_context *svga, 106 struct svga_rasterizer_state *rast, 107 unsigned samples) 108{ 109 struct svga_screen *svgascreen = svga_screen(svga->pipe.screen); 110 unsigned fill_mode = translate_fill_mode(rast->templ.fill_front); 111 const unsigned cull_mode = translate_cull_mode(rast->templ.cull_face); 112 const int depth_bias = rast->templ.offset_units; 113 const float slope_scaled_depth_bias = rast->templ.offset_scale; 114 /* PIPE_CAP_POLYGON_OFFSET_CLAMP not supported: */ 115 const float depth_bias_clamp = 0.0; 116 const float line_width = rast->templ.line_width > 0.0f ? 117 rast->templ.line_width : 1.0f; 118 const uint8 line_factor = rast->templ.line_stipple_enable ? 119 rast->templ.line_stipple_factor : 0; 120 const uint16 line_pattern = rast->templ.line_stipple_enable ? 121 rast->templ.line_stipple_pattern : 0; 122 const uint8 pv_last = !rast->templ.flatshade_first && 123 svgascreen->haveProvokingVertex; 124 int rastId; 125 enum pipe_error ret; 126 127 rastId = util_bitmask_add(svga->rast_object_id_bm); 128 129 if (rast->templ.fill_front != rast->templ.fill_back) { 130 /* The VGPU10 device can't handle different front/back fill modes. 131 * We'll handle that with a swtnl/draw fallback. But we need to 132 * make sure we always fill triangles in that case. 133 */ 134 fill_mode = SVGA3D_FILLMODE_FILL; 135 } 136 137 if (samples > 1 && svga_have_gl43(svga) && 138 svgascreen->sws->have_rasterizer_state_v2_cmd) { 139 140 ret = SVGA3D_sm5_DefineRasterizerState_v2(svga->swc, 141 rastId, 142 fill_mode, 143 cull_mode, 144 rast->templ.front_ccw, 145 depth_bias, 146 depth_bias_clamp, 147 slope_scaled_depth_bias, 148 rast->templ.depth_clip_near, 149 rast->templ.scissor, 150 rast->templ.multisample, 151 rast->templ.line_smooth, 152 line_width, 153 rast->templ.line_stipple_enable, 154 line_factor, 155 line_pattern, 156 pv_last, 157 samples); 158 } else { 159 ret = SVGA3D_vgpu10_DefineRasterizerState(svga->swc, 160 rastId, 161 fill_mode, 162 cull_mode, 163 rast->templ.front_ccw, 164 depth_bias, 165 depth_bias_clamp, 166 slope_scaled_depth_bias, 167 rast->templ.depth_clip_near, 168 rast->templ.scissor, 169 rast->templ.multisample, 170 rast->templ.line_smooth, 171 line_width, 172 rast->templ.line_stipple_enable, 173 line_factor, 174 line_pattern, 175 pv_last); 176 } 177 178 if (ret != PIPE_OK) { 179 util_bitmask_clear(svga->rast_object_id_bm, rastId); 180 return SVGA3D_INVALID_ID; 181 } 182 183 return rastId; 184} 185 186 187static void * 188svga_create_rasterizer_state(struct pipe_context *pipe, 189 const struct pipe_rasterizer_state *templ) 190{ 191 struct svga_context *svga = svga_context(pipe); 192 struct svga_rasterizer_state *rast = CALLOC_STRUCT(svga_rasterizer_state); 193 struct svga_screen *screen = svga_screen(pipe->screen); 194 195 if (!rast) 196 return NULL; 197 198 /* need this for draw module. */ 199 rast->templ = *templ; 200 201 rast->shademode = svga_translate_flatshade(templ->flatshade); 202 rast->cullmode = svga_translate_cullmode(templ->cull_face, templ->front_ccw); 203 rast->scissortestenable = templ->scissor; 204 rast->multisampleantialias = templ->multisample; 205 rast->antialiasedlineenable = templ->line_smooth; 206 rast->lastpixel = templ->line_last_pixel; 207 rast->pointsprite = templ->point_quad_rasterization; 208 209 if (rast->templ.multisample) { 210 /* The OpenGL 3.0 spec says points are always drawn as circles when 211 * MSAA is enabled. Note that our implementation isn't 100% correct, 212 * though. Our smooth point implementation involves drawing a square, 213 * computing fragment distance from point center, then attenuating 214 * the fragment alpha value. We should not attenuate alpha if msaa 215 * is enabled. We should discard fragments entirely outside the circle 216 * and let the GPU compute per-fragment coverage. 217 * But as-is, our implementation gives acceptable results and passes 218 * Piglit's MSAA point smooth test. 219 */ 220 rast->templ.point_smooth = TRUE; 221 } 222 223 if (rast->templ.point_smooth && 224 rast->templ.point_size_per_vertex == 0 && 225 rast->templ.point_size <= screen->pointSmoothThreshold) { 226 /* If the point size is less than the threshold, deactivate smoothing. 227 * Note that this only effects point rendering when we use the 228 * pipe_rasterizer_state::point_size value, not when the point size 229 * is set in the VS. 230 */ 231 rast->templ.point_smooth = FALSE; 232 } 233 234 if (rast->templ.point_smooth) { 235 /* For smooth points we need to generate fragments for at least 236 * a 2x2 region. Otherwise the quad we draw may be too small and 237 * we may generate no fragments at all. 238 */ 239 rast->pointsize = MAX2(2.0f, templ->point_size); 240 } 241 else { 242 rast->pointsize = templ->point_size; 243 } 244 245 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; 246 247 /* Use swtnl + decomposition implement these: 248 */ 249 250 if (templ->line_width <= screen->maxLineWidth) { 251 /* pass line width to device */ 252 rast->linewidth = MAX2(1.0F, templ->line_width); 253 } 254 else if (svga->debug.no_line_width) { 255 /* nothing */ 256 } 257 else { 258 /* use 'draw' pipeline for wide line */ 259 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 260 rast->need_pipeline_lines_str = "line width"; 261 } 262 263 if (templ->line_stipple_enable) { 264 if (screen->haveLineStipple || svga->debug.force_hw_line_stipple) { 265 SVGA3dLinePattern lp; 266 lp.repeat = templ->line_stipple_factor + 1; 267 lp.pattern = templ->line_stipple_pattern; 268 rast->linepattern = lp.uintValue; 269 } 270 else { 271 /* use 'draw' module to decompose into short line segments */ 272 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 273 rast->need_pipeline_lines_str = "line stipple"; 274 } 275 } 276 277 if (!svga_have_vgpu10(svga) && rast->templ.point_smooth) { 278 rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; 279 rast->need_pipeline_points_str = "smooth points"; 280 } 281 282 if (templ->line_smooth && !screen->haveLineSmooth) { 283 /* 284 * XXX: Enabling the pipeline slows down performance immensely, so ignore 285 * line smooth state, where there is very little visual improvement. 286 * Smooth lines will still be drawn for wide lines. 287 */ 288#if 0 289 rast->need_pipeline |= SVGA_PIPELINE_FLAG_LINES; 290 rast->need_pipeline_lines_str = "smooth lines"; 291#endif 292 } 293 294 { 295 int fill_front = templ->fill_front; 296 int fill_back = templ->fill_back; 297 int fill = PIPE_POLYGON_MODE_FILL; 298 boolean offset_front = util_get_offset(templ, fill_front); 299 boolean offset_back = util_get_offset(templ, fill_back); 300 boolean offset = FALSE; 301 302 switch (templ->cull_face) { 303 case PIPE_FACE_FRONT_AND_BACK: 304 offset = FALSE; 305 fill = PIPE_POLYGON_MODE_FILL; 306 break; 307 308 case PIPE_FACE_FRONT: 309 offset = offset_back; 310 fill = fill_back; 311 break; 312 313 case PIPE_FACE_BACK: 314 offset = offset_front; 315 fill = fill_front; 316 break; 317 318 case PIPE_FACE_NONE: 319 if (fill_front != fill_back || offset_front != offset_back) { 320 /* Always need the draw module to work out different 321 * front/back fill modes: 322 */ 323 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 324 rast->need_pipeline_tris_str = "different front/back fillmodes"; 325 fill = PIPE_POLYGON_MODE_FILL; 326 } 327 else { 328 offset = offset_front; 329 fill = fill_front; 330 } 331 break; 332 333 default: 334 assert(0); 335 break; 336 } 337 338 /* Unfilled primitive modes aren't implemented on all virtual 339 * hardware. We can do some unfilled processing with index 340 * translation, but otherwise need the draw module: 341 */ 342 if (fill != PIPE_POLYGON_MODE_FILL && 343 (templ->flatshade || 344 templ->light_twoside || 345 offset)) { 346 fill = PIPE_POLYGON_MODE_FILL; 347 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 348 rast->need_pipeline_tris_str = "unfilled primitives with no index manipulation"; 349 } 350 351 /* If we are decomposing to lines, and lines need the pipeline, 352 * then we also need the pipeline for tris. 353 */ 354 if (fill == PIPE_POLYGON_MODE_LINE && 355 (rast->need_pipeline & SVGA_PIPELINE_FLAG_LINES)) { 356 fill = PIPE_POLYGON_MODE_FILL; 357 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 358 rast->need_pipeline_tris_str = "decomposing lines"; 359 } 360 361 /* Similarly for points: 362 */ 363 if (fill == PIPE_POLYGON_MODE_POINT && 364 (rast->need_pipeline & SVGA_PIPELINE_FLAG_POINTS)) { 365 fill = PIPE_POLYGON_MODE_FILL; 366 rast->need_pipeline |= SVGA_PIPELINE_FLAG_TRIS; 367 rast->need_pipeline_tris_str = "decomposing points"; 368 } 369 370 if (offset) { 371 rast->slopescaledepthbias = templ->offset_scale; 372 rast->depthbias = templ->offset_units; 373 } 374 375 rast->hw_fillmode = fill; 376 } 377 378 if (rast->need_pipeline & SVGA_PIPELINE_FLAG_TRIS) { 379 /* Turn off stuff which will get done in the draw module: 380 */ 381 rast->hw_fillmode = PIPE_POLYGON_MODE_FILL; 382 rast->slopescaledepthbias = 0; 383 rast->depthbias = 0; 384 } 385 386 if (0 && rast->need_pipeline) { 387 debug_printf("svga: rast need_pipeline = 0x%x\n", rast->need_pipeline); 388 debug_printf(" pnts: %s \n", rast->need_pipeline_points_str); 389 debug_printf(" lins: %s \n", rast->need_pipeline_lines_str); 390 debug_printf(" tris: %s \n", rast->need_pipeline_tris_str); 391 } 392 393 if (svga_have_vgpu10(svga)) { 394 rast->id = svga_define_rasterizer_object(svga, rast, 0); 395 if (rast->id == SVGA3D_INVALID_ID) { 396 svga_context_flush(svga, NULL); 397 rast->id = svga_define_rasterizer_object(svga, rast, 0); 398 assert(rast->id != SVGA3D_INVALID_ID); 399 } 400 } 401 402 if (svga_have_gl43(svga)) { 403 /* initialize the alternate rasterizer state ids. 404 * For 0 and 1 sample count, we can use the same rasterizer object. 405 */ 406 rast->altRastIds[0] = rast->altRastIds[1] = rast->id; 407 408 for (unsigned i = 2; i < ARRAY_SIZE(rast->altRastIds); i++) { 409 rast->altRastIds[i] = SVGA3D_INVALID_ID; 410 } 411 } 412 413 if (templ->poly_smooth) { 414 util_debug_message(&svga->debug.callback, CONFORMANCE, 415 "GL_POLYGON_SMOOTH not supported"); 416 } 417 418 svga->hud.num_rasterizer_objects++; 419 SVGA_STATS_COUNT_INC(svga_screen(svga->pipe.screen)->sws, 420 SVGA_STATS_COUNT_RASTERIZERSTATE); 421 422 return rast; 423} 424 425 426static void 427svga_bind_rasterizer_state(struct pipe_context *pipe, void *state) 428{ 429 struct svga_context *svga = svga_context(pipe); 430 struct svga_rasterizer_state *raster = (struct svga_rasterizer_state *)state; 431 432 if (!raster || !svga->curr.rast) { 433 svga->dirty |= SVGA_NEW_STIPPLE | SVGA_NEW_DEPTH_STENCIL_ALPHA; 434 } 435 else { 436 if (raster->templ.poly_stipple_enable != 437 svga->curr.rast->templ.poly_stipple_enable) { 438 svga->dirty |= SVGA_NEW_STIPPLE; 439 } 440 if (raster->templ.rasterizer_discard != 441 svga->curr.rast->templ.rasterizer_discard) { 442 svga->dirty |= SVGA_NEW_DEPTH_STENCIL_ALPHA; 443 } 444 } 445 446 svga->curr.rast = raster; 447 448 svga->dirty |= SVGA_NEW_RAST; 449} 450 451 452static void 453svga_delete_rasterizer_state(struct pipe_context *pipe, void *state) 454{ 455 struct svga_context *svga = svga_context(pipe); 456 struct svga_rasterizer_state *raster = 457 (struct svga_rasterizer_state *) state; 458 459 /* free any alternate rasterizer state used for point sprite */ 460 if (raster->no_cull_rasterizer) 461 svga_delete_rasterizer_state(pipe, (void *)(raster->no_cull_rasterizer)); 462 463 if (svga_have_vgpu10(svga)) { 464 SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRasterizerState(svga->swc, 465 raster->id)); 466 467 if (raster->id == svga->state.hw_draw.rasterizer_id) 468 svga->state.hw_draw.rasterizer_id = SVGA3D_INVALID_ID; 469 470 util_bitmask_clear(svga->rast_object_id_bm, raster->id); 471 } 472 473 FREE(state); 474 svga->hud.num_rasterizer_objects--; 475} 476 477 478void 479svga_init_rasterizer_functions(struct svga_context *svga) 480{ 481 svga->pipe.create_rasterizer_state = svga_create_rasterizer_state; 482 svga->pipe.bind_rasterizer_state = svga_bind_rasterizer_state; 483 svga->pipe.delete_rasterizer_state = svga_delete_rasterizer_state; 484} 485