1 /************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 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 VMWARE 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 <keithw (at) vmware.com> 29 */ 30 31 #include "util/u_memory.h" 32 #include "util/u_math.h" 33 #include "util/u_prim.h" 34 #include "pipe/p_defines.h" 35 #include "draw_private.h" 36 #include "draw_pipe.h" 37 #include "draw_context.h" 38 #include "draw_vbuf.h" 39 40 41 /** 42 * Default version of a function to check if we need any special 43 * pipeline stages, or whether prims/verts can go through untouched. 44 * Don't test for bypass clipping or vs modes, this function is just 45 * about the primitive pipeline stages. 46 * 47 * This can be overridden by the driver. 48 */ 49 boolean 50 draw_need_pipeline(const struct draw_context *draw, 51 const struct pipe_rasterizer_state *rasterizer, 52 unsigned int prim ) 53 { 54 unsigned reduced_prim = u_reduced_prim(prim); 55 56 /* If the driver has overridden this, use that version: 57 */ 58 if (draw->render && 59 draw->render->need_pipeline) 60 { 61 return draw->render->need_pipeline( draw->render, 62 rasterizer, 63 prim ); 64 } 65 66 /* Don't have to worry about triangles turning into lines/points 67 * and triggering the pipeline, because we have to trigger the 68 * pipeline *anyway* if unfilled mode is active. 69 */ 70 if (reduced_prim == PIPE_PRIM_LINES) { 71 /* line stipple */ 72 if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple) 73 return TRUE; 74 75 /* wide lines */ 76 if (roundf(rasterizer->line_width) > draw->pipeline.wide_line_threshold) 77 return TRUE; 78 79 /* AA lines */ 80 if (rasterizer->line_smooth && draw->pipeline.aaline) 81 return TRUE; 82 83 if (draw_current_shader_num_written_culldistances(draw)) 84 return TRUE; 85 } 86 else if (reduced_prim == PIPE_PRIM_POINTS) { 87 /* large points */ 88 if (rasterizer->point_size > draw->pipeline.wide_point_threshold) 89 return TRUE; 90 91 /* sprite points */ 92 if (rasterizer->point_quad_rasterization 93 && draw->pipeline.wide_point_sprites) 94 return TRUE; 95 96 /* AA points */ 97 if (rasterizer->point_smooth && draw->pipeline.aapoint) 98 return TRUE; 99 100 /* point sprites */ 101 if (rasterizer->sprite_coord_enable && draw->pipeline.point_sprite) 102 return TRUE; 103 } 104 else if (reduced_prim == PIPE_PRIM_TRIANGLES) { 105 /* polygon stipple */ 106 if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple) 107 return TRUE; 108 109 /* unfilled polygons */ 110 if (rasterizer->fill_front != PIPE_POLYGON_MODE_FILL || 111 rasterizer->fill_back != PIPE_POLYGON_MODE_FILL) 112 return TRUE; 113 114 /* polygon offset */ 115 if (rasterizer->offset_point || 116 rasterizer->offset_line || 117 rasterizer->offset_tri) 118 return TRUE; 119 120 /* two-side lighting */ 121 if (rasterizer->light_twoside) 122 return TRUE; 123 124 if (draw_current_shader_num_written_culldistances(draw)) 125 return TRUE; 126 } 127 128 /* polygon cull - this is difficult - hardware can cull just fine 129 * most of the time (though sometimes CULL_NEITHER is unsupported. 130 * 131 * Generally this isn't a reason to require the pipeline, though. 132 * 133 if (rasterizer->cull_mode) 134 return TRUE; 135 */ 136 137 return FALSE; 138 } 139 140 141 142 /** 143 * Rebuild the rendering pipeline. 144 */ 145 static struct draw_stage *validate_pipeline( struct draw_stage *stage ) 146 { 147 struct draw_context *draw = stage->draw; 148 struct draw_stage *next = draw->pipeline.rasterize; 149 boolean need_det = FALSE; 150 boolean precalc_flat = FALSE; 151 boolean wide_lines, wide_points; 152 const struct pipe_rasterizer_state *rast = draw->rasterizer; 153 154 /* Set the validate's next stage to the rasterize stage, so that it 155 * can be found later if needed for flushing. 156 */ 157 stage->next = next; 158 159 /* drawing wide, non-AA lines? */ 160 wide_lines = rast->line_width != 1.0f && 161 roundf(rast->line_width) > draw->pipeline.wide_line_threshold && 162 !rast->line_smooth; 163 164 /* drawing large/sprite points (but not AA points)? */ 165 if (rast->sprite_coord_enable && draw->pipeline.point_sprite) 166 wide_points = TRUE; 167 else if (rast->point_smooth && draw->pipeline.aapoint) 168 wide_points = FALSE; 169 else if (rast->point_size > draw->pipeline.wide_point_threshold) 170 wide_points = TRUE; 171 else if (rast->point_quad_rasterization && draw->pipeline.wide_point_sprites) 172 wide_points = TRUE; 173 else 174 wide_points = FALSE; 175 176 /* 177 * NOTE: we build up the pipeline in end-to-start order. 178 * 179 * TODO: make the current primitive part of the state and build 180 * shorter pipelines for lines & points. 181 */ 182 183 if (rast->line_smooth && draw->pipeline.aaline) { 184 draw->pipeline.aaline->next = next; 185 next = draw->pipeline.aaline; 186 precalc_flat = TRUE; 187 } 188 189 if (rast->point_smooth && draw->pipeline.aapoint) { 190 draw->pipeline.aapoint->next = next; 191 next = draw->pipeline.aapoint; 192 } 193 194 if (wide_lines) { 195 draw->pipeline.wide_line->next = next; 196 next = draw->pipeline.wide_line; 197 precalc_flat = TRUE; 198 } 199 200 if (wide_points) { 201 draw->pipeline.wide_point->next = next; 202 next = draw->pipeline.wide_point; 203 } 204 205 if (rast->line_stipple_enable && draw->pipeline.line_stipple) { 206 draw->pipeline.stipple->next = next; 207 next = draw->pipeline.stipple; 208 precalc_flat = TRUE; /* only needed for lines really */ 209 } 210 211 if (rast->poly_stipple_enable 212 && draw->pipeline.pstipple) { 213 draw->pipeline.pstipple->next = next; 214 next = draw->pipeline.pstipple; 215 } 216 217 if (rast->fill_front != PIPE_POLYGON_MODE_FILL || 218 rast->fill_back != PIPE_POLYGON_MODE_FILL) { 219 draw->pipeline.unfilled->next = next; 220 next = draw->pipeline.unfilled; 221 precalc_flat = TRUE; /* only needed for triangles really */ 222 need_det = TRUE; 223 } 224 225 if (precalc_flat) { 226 /* 227 * could only run the stage if either rast->flatshade is true 228 * or there's constant interpolated values. 229 */ 230 draw->pipeline.flatshade->next = next; 231 next = draw->pipeline.flatshade; 232 } 233 234 if (rast->offset_point || 235 rast->offset_line || 236 rast->offset_tri) { 237 draw->pipeline.offset->next = next; 238 next = draw->pipeline.offset; 239 need_det = TRUE; 240 } 241 242 if (rast->light_twoside) { 243 draw->pipeline.twoside->next = next; 244 next = draw->pipeline.twoside; 245 need_det = TRUE; 246 } 247 248 /* Always run the cull stage as we calculate determinant there 249 * also. 250 * 251 * This can actually be a win as culling out the triangles can lead 252 * to less work emitting vertices, smaller vertex buffers, etc. 253 * It's difficult to say whether this will be true in general. 254 */ 255 if (need_det || rast->cull_face != PIPE_FACE_NONE || 256 draw_current_shader_num_written_culldistances(draw)) { 257 draw->pipeline.cull->next = next; 258 next = draw->pipeline.cull; 259 } 260 261 /* Clip stage 262 */ 263 if (draw->clip_xy || draw->clip_z || draw->clip_user) 264 { 265 draw->pipeline.clip->next = next; 266 next = draw->pipeline.clip; 267 } 268 269 draw->pipeline.first = next; 270 271 if (0) { 272 debug_printf("draw pipeline:\n"); 273 for (next = draw->pipeline.first; next ; next = next->next ) 274 debug_printf(" %s\n", next->name); 275 debug_printf("\n"); 276 } 277 278 return draw->pipeline.first; 279 } 280 281 static void validate_tri( struct draw_stage *stage, 282 struct prim_header *header ) 283 { 284 struct draw_stage *pipeline = validate_pipeline( stage ); 285 pipeline->tri( pipeline, header ); 286 } 287 288 static void validate_line( struct draw_stage *stage, 289 struct prim_header *header ) 290 { 291 struct draw_stage *pipeline = validate_pipeline( stage ); 292 pipeline->line( pipeline, header ); 293 } 294 295 static void validate_point( struct draw_stage *stage, 296 struct prim_header *header ) 297 { 298 struct draw_stage *pipeline = validate_pipeline( stage ); 299 pipeline->point( pipeline, header ); 300 } 301 302 static void validate_reset_stipple_counter( struct draw_stage *stage ) 303 { 304 struct draw_stage *pipeline = validate_pipeline( stage ); 305 pipeline->reset_stipple_counter( pipeline ); 306 } 307 308 static void validate_flush( struct draw_stage *stage, 309 unsigned flags ) 310 { 311 /* May need to pass a backend flush on to the rasterize stage. 312 */ 313 if (stage->next) 314 stage->next->flush( stage->next, flags ); 315 } 316 317 318 static void validate_destroy( struct draw_stage *stage ) 319 { 320 FREE( stage ); 321 } 322 323 324 /** 325 * Create validate pipeline stage. 326 */ 327 struct draw_stage *draw_validate_stage( struct draw_context *draw ) 328 { 329 struct draw_stage *stage = CALLOC_STRUCT(draw_stage); 330 if (!stage) 331 return NULL; 332 333 stage->draw = draw; 334 stage->name = "validate"; 335 stage->next = NULL; 336 stage->point = validate_point; 337 stage->line = validate_line; 338 stage->tri = validate_tri; 339 stage->flush = validate_flush; 340 stage->reset_stipple_counter = validate_reset_stipple_counter; 341 stage->destroy = validate_destroy; 342 343 return stage; 344 } 345