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