Home | History | Annotate | Download | only in tnl
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5.3
      4  *
      5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     21  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Authors:
     25  *    Keith Whitwell <keith (at) tungstengraphics.com>
     26  */
     27 
     28 #include "main/glheader.h"
     29 #include "main/context.h"
     30 #include "main/imports.h"
     31 #include "main/mtypes.h"
     32 
     33 #include "t_context.h"
     34 #include "t_pipeline.h"
     35 #include "t_vp_build.h"
     36 #include "t_vertex.h"
     37 
     38 void _tnl_install_pipeline( struct gl_context *ctx,
     39 			    const struct tnl_pipeline_stage **stages )
     40 {
     41    TNLcontext *tnl = TNL_CONTEXT(ctx);
     42    GLuint i;
     43 
     44    tnl->pipeline.new_state = ~0;
     45 
     46    /* Create a writeable copy of each stage.
     47     */
     48    for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
     49       struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
     50       memcpy(s, stages[i], sizeof(*s));
     51       if (s->create)
     52 	 s->create(ctx, s);
     53    }
     54 
     55    tnl->pipeline.nr_stages = i;
     56 }
     57 
     58 void _tnl_destroy_pipeline( struct gl_context *ctx )
     59 {
     60    TNLcontext *tnl = TNL_CONTEXT(ctx);
     61    GLuint i;
     62 
     63    for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
     64       struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
     65       if (s->destroy)
     66 	 s->destroy(s);
     67    }
     68 
     69    tnl->pipeline.nr_stages = 0;
     70 }
     71 
     72 
     73 
     74 static GLuint check_input_changes( struct gl_context *ctx )
     75 {
     76    TNLcontext *tnl = TNL_CONTEXT(ctx);
     77    GLuint i;
     78 
     79    for (i = 0; i <= _TNL_LAST_MAT; i++) {
     80       if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
     81 	  tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
     82 	 tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
     83 	 tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
     84 	 tnl->pipeline.input_changes |= 1<<i;
     85       }
     86    }
     87 
     88    return tnl->pipeline.input_changes;
     89 }
     90 
     91 
     92 static GLuint check_output_changes( struct gl_context *ctx )
     93 {
     94 #if 0
     95    TNLcontext *tnl = TNL_CONTEXT(ctx);
     96 
     97    for (i = 0; i < VERT_RESULT_MAX; i++) {
     98       if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
     99 	  tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
    100 	 tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
    101 	 tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
    102 	 tnl->pipeline.output_changes |= 1<<i;
    103       }
    104    }
    105 
    106    if (tnl->pipeline.output_changes)
    107       tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
    108 
    109    return tnl->pipeline.output_changes;
    110 #else
    111    return ~0;
    112 #endif
    113 }
    114 
    115 
    116 void _tnl_run_pipeline( struct gl_context *ctx )
    117 {
    118    TNLcontext *tnl = TNL_CONTEXT(ctx);
    119    unsigned short __tmp;
    120    GLuint i;
    121 
    122    if (!tnl->vb.Count)
    123       return;
    124 
    125    /* Check for changed input sizes or change in stride to/from zero
    126     * (ie const or non-const).
    127     */
    128    if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
    129       if (ctx->VertexProgram._MaintainTnlProgram)
    130 	 _tnl_UpdateFixedFunctionProgram( ctx );
    131 
    132       for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
    133 	 struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
    134 	 if (s->validate)
    135 	    s->validate( ctx, s );
    136       }
    137 
    138       tnl->pipeline.new_state = 0;
    139       tnl->pipeline.input_changes = 0;
    140 
    141       /* Pipeline can only change its output in response to either a
    142        * statechange or an input size/stride change.  No other changes
    143        * are allowed.
    144        */
    145       if (check_output_changes( ctx ))
    146 	 _tnl_notify_pipeline_output_change( ctx );
    147    }
    148 
    149 #ifndef _OPENMP
    150    /* Don't adjust FPU precision mode in case multiple threads are to be used.
    151     * This would require that the additional threads also changed the FPU mode
    152     * which is quite a mess as this had to be done in all parallelized sections;
    153     * otherwise the master thread and all other threads are running in different
    154     * modes, producing inconsistent results.
    155     * Note that all x64 implementations don't define/use START_FAST_MATH, so
    156     * this is "hack" is only used in i386 mode
    157     */
    158    START_FAST_MATH(__tmp);
    159 #endif
    160 
    161    for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
    162       struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
    163       if (!s->run( ctx, s ))
    164 	 break;
    165    }
    166 
    167 #ifndef _OPENMP
    168    END_FAST_MATH(__tmp);
    169 #endif
    170 }
    171 
    172 
    173 
    174 /* The default pipeline.  This is useful for software rasterizers, and
    175  * simple hardware rasterizers.  For customization, I don't recommend
    176  * tampering with the internals of these stages in the way that
    177  * drivers did in Mesa 3.4.  These stages are basically black boxes,
    178  * and should be left intact.
    179  *
    180  * To customize the pipeline, consider:
    181  *
    182  * - removing redundant stages (making sure that the software rasterizer
    183  *   can cope with this on fallback paths).  An example is fog
    184  *   coordinate generation, which is not required in the FX driver.
    185  *
    186  * - replacing general-purpose machine-independent stages with
    187  *   general-purpose machine-specific stages.  There is no example of
    188  *   this to date, though it must be borne in mind that all subsequent
    189  *   stages that reference the output of the new stage must cope with
    190  *   any machine-specific data introduced.  This may not be easy
    191  *   unless there are no such stages (ie the new stage is the last in
    192  *   the pipe).
    193  *
    194  * - inserting optimized (but specialized) stages ahead of the
    195  *   general-purpose fallback implementation.  For example, the old
    196  *   fastpath mechanism, which only works when the VB->Elts input is
    197  *   available, can be duplicated by placing the fastpath stage at the
    198  *   head of this pipeline.  Such specialized stages are currently
    199  *   constrained to have no outputs (ie. they must either finish the *
    200  *   pipeline by returning GL_FALSE from run(), or do nothing).
    201  *
    202  * Some work can be done to lift some of the restrictions in the final
    203  * case, if it becomes necessary to do so.
    204  */
    205 const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
    206    &_tnl_vertex_transform_stage,
    207    &_tnl_normal_transform_stage,
    208    &_tnl_lighting_stage,
    209    &_tnl_texgen_stage,
    210    &_tnl_texture_transform_stage,
    211    &_tnl_point_attenuation_stage,
    212    &_tnl_vertex_program_stage,
    213    &_tnl_fog_coordinate_stage,
    214    &_tnl_render_stage,
    215    NULL
    216 };
    217 
    218 const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = {
    219    &_tnl_vertex_program_stage,
    220    &_tnl_render_stage,
    221    NULL
    222 };
    223