00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "util/u_memory.h"
00032 #include "pipe/p_defines.h"
00033 #include "draw_private.h"
00034 #include "draw_pipe.h"
00035 #include "draw_context.h"
00036 #include "draw_vbuf.h"
00037
00038 static boolean points( unsigned prim )
00039 {
00040 return (prim == PIPE_PRIM_POINTS);
00041 }
00042
00043 static boolean lines( unsigned prim )
00044 {
00045 return (prim == PIPE_PRIM_LINES ||
00046 prim == PIPE_PRIM_LINE_STRIP ||
00047 prim == PIPE_PRIM_LINE_LOOP);
00048 }
00049
00050 static boolean triangles( unsigned prim )
00051 {
00052 return prim >= PIPE_PRIM_TRIANGLES;
00053 }
00054
00063 boolean
00064 draw_need_pipeline(const struct draw_context *draw,
00065 const struct pipe_rasterizer_state *rasterizer,
00066 unsigned int prim )
00067 {
00068
00069
00070 if (draw->render &&
00071 draw->render->need_pipeline)
00072 {
00073 return draw->render->need_pipeline( draw->render,
00074 rasterizer,
00075 prim );
00076 }
00077
00078
00079
00080
00081
00082 if (lines(prim))
00083 {
00084
00085 if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple)
00086 return TRUE;
00087
00088
00089 if (rasterizer->line_width > draw->pipeline.wide_line_threshold)
00090 return TRUE;
00091
00092
00093 if (rasterizer->line_smooth && draw->pipeline.aaline)
00094 return TRUE;
00095 }
00096
00097 if (points(prim))
00098 {
00099
00100 if (rasterizer->point_size > draw->pipeline.wide_point_threshold)
00101 return TRUE;
00102
00103
00104 if (rasterizer->point_smooth && draw->pipeline.aapoint)
00105 return TRUE;
00106
00107
00108 if (rasterizer->point_sprite && draw->pipeline.point_sprite)
00109 return TRUE;
00110 }
00111
00112
00113 if (triangles(prim))
00114 {
00115
00116 if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
00117 return TRUE;
00118
00119
00120 if (rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
00121 rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL)
00122 return TRUE;
00123
00124
00125 if (rasterizer->offset_cw || rasterizer->offset_ccw)
00126 return TRUE;
00127
00128
00129 if (rasterizer->light_twoside)
00130 return TRUE;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 return FALSE;
00143 }
00144
00145
00146
00150 static struct draw_stage *validate_pipeline( struct draw_stage *stage )
00151 {
00152 struct draw_context *draw = stage->draw;
00153 struct draw_stage *next = draw->pipeline.rasterize;
00154 int need_det = 0;
00155 int precalc_flat = 0;
00156 boolean wide_lines, wide_points;
00157
00158
00159
00160
00161 stage->next = next;
00162
00163
00164 wide_lines = (draw->rasterizer->line_width > draw->pipeline.wide_line_threshold
00165 && !draw->rasterizer->line_smooth);
00166
00167
00168 if (draw->rasterizer->point_sprite && draw->pipeline.point_sprite)
00169 wide_points = TRUE;
00170 else if (draw->rasterizer->point_smooth && draw->pipeline.aapoint)
00171 wide_points = FALSE;
00172 else if (draw->rasterizer->point_size > draw->pipeline.wide_point_threshold)
00173 wide_points = TRUE;
00174 else
00175 wide_points = FALSE;
00176
00177
00178
00179
00180
00181
00182
00183
00184 if (draw->rasterizer->line_smooth && draw->pipeline.aaline) {
00185 draw->pipeline.aaline->next = next;
00186 next = draw->pipeline.aaline;
00187 }
00188
00189 if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) {
00190 draw->pipeline.aapoint->next = next;
00191 next = draw->pipeline.aapoint;
00192 }
00193
00194 if (wide_lines) {
00195 draw->pipeline.wide_line->next = next;
00196 next = draw->pipeline.wide_line;
00197 precalc_flat = 1;
00198 }
00199
00200 if (wide_points || draw->rasterizer->point_sprite) {
00201 draw->pipeline.wide_point->next = next;
00202 next = draw->pipeline.wide_point;
00203 }
00204
00205 if (draw->rasterizer->line_stipple_enable && draw->pipeline.line_stipple) {
00206 draw->pipeline.stipple->next = next;
00207 next = draw->pipeline.stipple;
00208 precalc_flat = 1;
00209 }
00210
00211 if (draw->rasterizer->poly_stipple_enable
00212 && draw->pipeline.pstipple) {
00213 draw->pipeline.pstipple->next = next;
00214 next = draw->pipeline.pstipple;
00215 }
00216
00217 if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
00218 draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL) {
00219 draw->pipeline.unfilled->next = next;
00220 next = draw->pipeline.unfilled;
00221 precalc_flat = 1;
00222 need_det = 1;
00223 }
00224
00225 if (draw->rasterizer->flatshade && precalc_flat) {
00226 draw->pipeline.flatshade->next = next;
00227 next = draw->pipeline.flatshade;
00228 }
00229
00230 if (draw->rasterizer->offset_cw ||
00231 draw->rasterizer->offset_ccw) {
00232 draw->pipeline.offset->next = next;
00233 next = draw->pipeline.offset;
00234 need_det = 1;
00235 }
00236
00237 if (draw->rasterizer->light_twoside) {
00238 draw->pipeline.twoside->next = next;
00239 next = draw->pipeline.twoside;
00240 need_det = 1;
00241 }
00242
00243
00244
00245
00246
00247
00248
00249
00250 if (need_det || draw->rasterizer->cull_mode) {
00251 draw->pipeline.cull->next = next;
00252 next = draw->pipeline.cull;
00253 }
00254
00255
00256
00257 if (!draw->bypass_clipping)
00258 {
00259 draw->pipeline.clip->next = next;
00260 next = draw->pipeline.clip;
00261 }
00262
00263
00264 draw->pipeline.first = next;
00265 return next;
00266 }
00267
00268 static void validate_tri( struct draw_stage *stage,
00269 struct prim_header *header )
00270 {
00271 struct draw_stage *pipeline = validate_pipeline( stage );
00272 pipeline->tri( pipeline, header );
00273 }
00274
00275 static void validate_line( struct draw_stage *stage,
00276 struct prim_header *header )
00277 {
00278 struct draw_stage *pipeline = validate_pipeline( stage );
00279 pipeline->line( pipeline, header );
00280 }
00281
00282 static void validate_point( struct draw_stage *stage,
00283 struct prim_header *header )
00284 {
00285 struct draw_stage *pipeline = validate_pipeline( stage );
00286 pipeline->point( pipeline, header );
00287 }
00288
00289 static void validate_reset_stipple_counter( struct draw_stage *stage )
00290 {
00291 struct draw_stage *pipeline = validate_pipeline( stage );
00292 pipeline->reset_stipple_counter( pipeline );
00293 }
00294
00295 static void validate_flush( struct draw_stage *stage,
00296 unsigned flags )
00297 {
00298
00299
00300 if (stage->next)
00301 stage->next->flush( stage->next, flags );
00302 }
00303
00304
00305 static void validate_destroy( struct draw_stage *stage )
00306 {
00307 FREE( stage );
00308 }
00309
00310
00314 struct draw_stage *draw_validate_stage( struct draw_context *draw )
00315 {
00316 struct draw_stage *stage = CALLOC_STRUCT(draw_stage);
00317 if (stage == NULL)
00318 return NULL;
00319
00320 stage->draw = draw;
00321 stage->next = NULL;
00322 stage->point = validate_point;
00323 stage->line = validate_line;
00324 stage->tri = validate_tri;
00325 stage->flush = validate_flush;
00326 stage->reset_stipple_counter = validate_reset_stipple_counter;
00327 stage->destroy = validate_destroy;
00328
00329 return stage;
00330 }