1 /************************************************************************** 2 * 3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* Authors: Keith Whitwell <keith (at) tungstengraphics.com> 29 */ 30 31 #include "util/u_memory.h" 32 #include "util/u_math.h" 33 #include "pipe/p_defines.h" 34 #include "draw_private.h" 35 #include "draw_pipe.h" 36 #include "draw_context.h" 37 #include "draw_vbuf.h" 38 39 static boolean points( unsigned prim ) 40 { 41 return (prim == PIPE_PRIM_POINTS); 42 } 43 44 static boolean lines( unsigned prim ) 45 { 46 return (prim == PIPE_PRIM_LINES || 47 prim == PIPE_PRIM_LINE_STRIP || 48 prim == PIPE_PRIM_LINE_LOOP); 49 } 50 51 static boolean triangles( unsigned prim ) 52 { 53 return prim >= PIPE_PRIM_TRIANGLES; 54 } 55 56 /** 57 * Default version of a function to check if we need any special 58 * pipeline stages, or whether prims/verts can go through untouched. 59 * Don't test for bypass clipping or vs modes, this function is just 60 * about the primitive pipeline stages. 61 * 62 * This can be overridden by the driver. 63 */ 64 boolean 65 draw_need_pipeline(const struct draw_context *draw, 66 const struct pipe_rasterizer_state *rasterizer, 67 unsigned int prim ) 68 { 69 /* If the driver has overridden this, use that version: 70 */ 71 if (draw->render && 72 draw->render->need_pipeline) 73 { 74 return draw->render->need_pipeline( draw->render, 75 rasterizer, 76 prim ); 77 } 78 79 /* Don't have to worry about triangles turning into lines/points 80 * and triggering the pipeline, because we have to trigger the 81 * pipeline *anyway* if unfilled mode is active. 82 */ 83 if (lines(prim)) 84 { 85 /* line stipple */ 86 if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple) 87 return TRUE; 88 89 /* wide lines */ 90 if (roundf(rasterizer->line_width) > draw->pipeline.wide_line_threshold) 91 return TRUE; 92 93 /* AA lines */ 94 if (rasterizer->line_smooth && draw->pipeline.aaline) 95 return TRUE; 96 } 97 98 if (points(prim)) 99 { 100 /* large points */ 101 if (rasterizer->point_size > draw->pipeline.wide_point_threshold) 102 return TRUE; 103 104 /* sprite points */ 105 if (rasterizer->point_quad_rasterization 106 && draw->pipeline.wide_point_sprites) 107 return TRUE; 108 109 /* AA points */ 110 if (rasterizer->point_smooth && draw->pipeline.aapoint) 111 return TRUE; 112 113 /* point sprites */ 114 if (rasterizer->sprite_coord_enable && draw->pipeline.point_sprite) 115 return TRUE; 116 } 117 118 119 if (triangles(prim)) 120 { 121 /* polygon stipple */ 122 if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple) 123 return TRUE; 124 125 /* unfilled polygons */ 126 if (rasterizer->fill_front != PIPE_POLYGON_MODE_FILL || 127 rasterizer->fill_back != PIPE_POLYGON_MODE_FILL) 128 return TRUE; 129 130 /* polygon offset */ 131 if (rasterizer->offset_point || 132 rasterizer->offset_line || 133 rasterizer->offset_tri) 134 return TRUE; 135 136 /* two-side lighting */ 137 if (rasterizer->light_twoside) 138 return TRUE; 139 } 140 141 /* polygon cull - this is difficult - hardware can cull just fine 142 * most of the time (though sometimes CULL_NEITHER is unsupported. 143 * 144 * Generally this isn't a reason to require the pipeline, though. 145 * 146 if (rasterizer->cull_mode) 147 return TRUE; 148 */ 149 150 return FALSE; 151 } 152 153 154 155 /** 156 * Rebuild the rendering pipeline. 157 */ 158 static struct draw_stage *validate_pipeline( struct draw_stage *stage ) 159 { 160 struct draw_context *draw = stage->draw; 161 struct draw_stage *next = draw->pipeline.rasterize; 162 boolean need_det = FALSE; 163 boolean precalc_flat = FALSE; 164 boolean wide_lines, wide_points; 165 const struct pipe_rasterizer_state *rast = draw->rasterizer; 166 167 /* Set the validate's next stage to the rasterize stage, so that it 168 * can be found later if needed for flushing. 169 */ 170 stage->next = next; 171 172 /* drawing wide lines? */ 173 wide_lines = (roundf(rast->line_width) > draw->pipeline.wide_line_threshold 174 && !rast->line_smooth); 175 176 /* drawing large/sprite points (but not AA points)? */ 177 if (rast->sprite_coord_enable && draw->pipeline.point_sprite) 178 wide_points = TRUE; 179 else if (rast->point_smooth && draw->pipeline.aapoint) 180 wide_points = FALSE; 181 else if (rast->point_size > draw->pipeline.wide_point_threshold) 182 wide_points = TRUE; 183 else if (rast->point_quad_rasterization && draw->pipeline.wide_point_sprites) 184 wide_points = TRUE; 185 else 186 wide_points = FALSE; 187 188 /* 189 * NOTE: we build up the pipeline in end-to-start order. 190 * 191 * TODO: make the current primitive part of the state and build 192 * shorter pipelines for lines & points. 193 */ 194 195 if (rast->line_smooth && draw->pipeline.aaline) { 196 draw->pipeline.aaline->next = next; 197 next = draw->pipeline.aaline; 198 precalc_flat = TRUE; 199 } 200 201 if (rast->point_smooth && draw->pipeline.aapoint) { 202 draw->pipeline.aapoint->next = next; 203 next = draw->pipeline.aapoint; 204 } 205 206 if (wide_lines) { 207 draw->pipeline.wide_line->next = next; 208 next = draw->pipeline.wide_line; 209 precalc_flat = TRUE; 210 } 211 212 if (wide_points) { 213 draw->pipeline.wide_point->next = next; 214 next = draw->pipeline.wide_point; 215 } 216 217 if (rast->line_stipple_enable && draw->pipeline.line_stipple) { 218 draw->pipeline.stipple->next = next; 219 next = draw->pipeline.stipple; 220 precalc_flat = TRUE; /* only needed for lines really */ 221 } 222 223 if (rast->poly_stipple_enable 224 && draw->pipeline.pstipple) { 225 draw->pipeline.pstipple->next = next; 226 next = draw->pipeline.pstipple; 227 } 228 229 if (rast->fill_front != PIPE_POLYGON_MODE_FILL || 230 rast->fill_back != PIPE_POLYGON_MODE_FILL) { 231 draw->pipeline.unfilled->next = next; 232 next = draw->pipeline.unfilled; 233 precalc_flat = TRUE; /* only needed for triangles really */ 234 need_det = TRUE; 235 } 236 237 if (rast->flatshade && precalc_flat) { 238 draw->pipeline.flatshade->next = next; 239 next = draw->pipeline.flatshade; 240 } 241 242 if (rast->offset_point || 243 rast->offset_line || 244 rast->offset_tri) { 245 draw->pipeline.offset->next = next; 246 next = draw->pipeline.offset; 247 need_det = TRUE; 248 } 249 250 if (rast->light_twoside) { 251 draw->pipeline.twoside->next = next; 252 next = draw->pipeline.twoside; 253 need_det = TRUE; 254 } 255 256 /* Always run the cull stage as we calculate determinant there 257 * also. 258 * 259 * This can actually be a win as culling out the triangles can lead 260 * to less work emitting vertices, smaller vertex buffers, etc. 261 * It's difficult to say whether this will be true in general. 262 */ 263 if (need_det || rast->cull_face != PIPE_FACE_NONE) { 264 draw->pipeline.cull->next = next; 265 next = draw->pipeline.cull; 266 } 267 268 /* Clip stage 269 */ 270 if (draw->clip_xy || draw->clip_z || draw->clip_user) 271 { 272 draw->pipeline.clip->next = next; 273 next = draw->pipeline.clip; 274 } 275 276 277 draw->pipeline.first = next; 278 279 if (0) { 280 debug_printf("draw pipeline:\n"); 281 for (next = draw->pipeline.first; next ; next = next->next ) 282 debug_printf(" %s\n", next->name); 283 debug_printf("\n"); 284 } 285 286 return draw->pipeline.first; 287 } 288 289 static void validate_tri( struct draw_stage *stage, 290 struct prim_header *header ) 291 { 292 struct draw_stage *pipeline = validate_pipeline( stage ); 293 pipeline->tri( pipeline, header ); 294 } 295 296 static void validate_line( struct draw_stage *stage, 297 struct prim_header *header ) 298 { 299 struct draw_stage *pipeline = validate_pipeline( stage ); 300 pipeline->line( pipeline, header ); 301 } 302 303 static void validate_point( struct draw_stage *stage, 304 struct prim_header *header ) 305 { 306 struct draw_stage *pipeline = validate_pipeline( stage ); 307 pipeline->point( pipeline, header ); 308 } 309 310 static void validate_reset_stipple_counter( struct draw_stage *stage ) 311 { 312 struct draw_stage *pipeline = validate_pipeline( stage ); 313 pipeline->reset_stipple_counter( pipeline ); 314 } 315 316 static void validate_flush( struct draw_stage *stage, 317 unsigned flags ) 318 { 319 /* May need to pass a backend flush on to the rasterize stage. 320 */ 321 if (stage->next) 322 stage->next->flush( stage->next, flags ); 323 } 324 325 326 static void validate_destroy( struct draw_stage *stage ) 327 { 328 FREE( stage ); 329 } 330 331 332 /** 333 * Create validate pipeline stage. 334 */ 335 struct draw_stage *draw_validate_stage( struct draw_context *draw ) 336 { 337 struct draw_stage *stage = CALLOC_STRUCT(draw_stage); 338 if (stage == NULL) 339 return NULL; 340 341 stage->draw = draw; 342 stage->name = "validate"; 343 stage->next = NULL; 344 stage->point = validate_point; 345 stage->line = validate_line; 346 stage->tri = validate_tri; 347 stage->flush = validate_flush; 348 stage->reset_stipple_counter = validate_reset_stipple_counter; 349 stage->destroy = validate_destroy; 350 351 return stage; 352 } 353