draw_pipe_validate.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 /* Authors:  Keith Whitwell <keith@tungstengraphics.com>
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    /* If the driver has overridden this, use that version: 
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    /* Don't have to worry about triangles turning into lines/points
00079     * and triggering the pipeline, because we have to trigger the
00080     * pipeline *anyway* if unfilled mode is active.
00081     */
00082    if (lines(prim)) 
00083    {
00084       /* line stipple */
00085       if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple)
00086          return TRUE;
00087 
00088       /* wide lines */
00089       if (rasterizer->line_width > draw->pipeline.wide_line_threshold)
00090          return TRUE;
00091 
00092       /* AA lines */
00093       if (rasterizer->line_smooth && draw->pipeline.aaline)
00094          return TRUE;
00095    }
00096 
00097    if (points(prim))
00098    {
00099       /* large points */
00100       if (rasterizer->point_size > draw->pipeline.wide_point_threshold)
00101          return TRUE;
00102 
00103       /* AA points */
00104       if (rasterizer->point_smooth && draw->pipeline.aapoint)
00105          return TRUE;
00106 
00107       /* point sprites */
00108       if (rasterizer->point_sprite && draw->pipeline.point_sprite)
00109          return TRUE;
00110    }
00111 
00112 
00113    if (triangles(prim)) 
00114    {
00115       /* polygon stipple */
00116       if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
00117          return TRUE;
00118 
00119       /* unfilled polygons */
00120       if (rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
00121           rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL)
00122          return TRUE;
00123       
00124       /* polygon offset */
00125       if (rasterizer->offset_cw || rasterizer->offset_ccw)
00126          return TRUE;
00127 
00128       /* two-side lighting */
00129       if (rasterizer->light_twoside)
00130          return TRUE;
00131    }
00132 
00133    /* polygon cull - this is difficult - hardware can cull just fine
00134     * most of the time (though sometimes CULL_NEITHER is unsupported.
00135     * 
00136     * Generally this isn't a reason to require the pipeline, though.
00137     *
00138    if (rasterizer->cull_mode)
00139       return TRUE;
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    /* Set the validate's next stage to the rasterize stage, so that it
00159     * can be found later if needed for flushing.
00160     */
00161    stage->next = next;
00162 
00163    /* drawing wide lines? */
00164    wide_lines = (draw->rasterizer->line_width > draw->pipeline.wide_line_threshold
00165                  && !draw->rasterizer->line_smooth);
00166 
00167    /* drawing large points? */
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     * NOTE: we build up the pipeline in end-to-start order.
00179     *
00180     * TODO: make the current primitive part of the state and build
00181     * shorter pipelines for lines & points.
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;         /* only needed for lines really */
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;         /* only needed for triangles really */
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    /* Always run the cull stage as we calculate determinant there
00244     * also.  
00245     *
00246     * This can actually be a win as culling out the triangles can lead
00247     * to less work emitting vertices, smaller vertex buffers, etc.
00248     * It's difficult to say whether this will be true in general.
00249     */
00250    if (need_det || draw->rasterizer->cull_mode) {
00251       draw->pipeline.cull->next = next;
00252       next = draw->pipeline.cull;
00253    }
00254 
00255    /* Clip stage
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    /* May need to pass a backend flush on to the rasterize stage.
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 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4