home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / tnl / t_vb_program.cpp < prev    next >
C/C++ Source or Header  |  2002-10-31  |  17KB  |  478 lines

  1. /* $Id: t_vb_program.c,v 1.16 2002/10/31 17:14:16 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  5.0
  6.  *
  7.  * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
  8.  *
  9.  * Permission is hereby granted, free of charge, to any person obtaining a
  10.  * copy of this software and associated documentation files (the "Software"),
  11.  * to deal in the Software without restriction, including without limitation
  12.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  13.  * and/or sell copies of the Software, and to permit persons to whom the
  14.  * Software is furnished to do so, subject to the following conditions:
  15.  *
  16.  * The above copyright notice and this permission notice shall be included
  17.  * in all copies or substantial portions of the Software.
  18.  *
  19.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  20.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  22.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  23.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  24.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  */
  26.  
  27. /*
  28.  * -------- Regarding NV_vertex_program --------
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions are met:
  31.  * 
  32.  * o Redistribution of the source code must contain a copyright notice
  33.  *   and this list of conditions;
  34.  * 
  35.  * o Redistribution in binary and source code form must contain the
  36.  *   following Notice in the software and any documentation and/or other
  37.  *   materials provided with the distribution; and
  38.  * 
  39.  * o The name of Nvidia may not be used to promote or endorse software
  40.  *   derived from the software.
  41.  * 
  42.  * NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
  43.  * royalty free patent license under patent claims that are licensable by
  44.  * Nvidia and which are necessarily required and for which no commercially
  45.  * viable non infringing alternative exists to make, use, sell, offer to sell,
  46.  * import and otherwise transfer the vertex extension for the Mesa 3D Graphics
  47.  * Library as distributed in source code and object code form.  No hardware or
  48.  * hardware implementation (including a semiconductor implementation and chips)
  49.  * are licensed hereunder. If a recipient makes a patent claim or institutes
  50.  * patent litigation against Nvidia or Nvidia's customers for use or sale of
  51.  * Nvidia products, then this license grant as to such recipient shall
  52.  * immediately terminate and recipient immediately agrees to cease use and
  53.  * distribution of the Mesa Program and derivatives thereof. 
  54.  * 
  55.  * THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
  56.  * WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
  57.  * WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
  58.  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  59.  * 
  60.  * NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  61.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
  62.  * LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  63.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  64.  * ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
  65.  * LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
  66.  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  67.  * 
  68.  * If you do not comply with this agreement, then Nvidia may cancel the license
  69.  * and rights granted herein.
  70.  * ---------------------------------------------
  71.  */
  72.  
  73. /**
  74.  * \file tnl/t_vb_program.c
  75.  * \brief Pipeline stage for executing vertex programs
  76.  * \author Brian Paul,  Keith Whitwell
  77.  */
  78.  
  79.  
  80. #include "glheader.h"
  81. #include "api_noop.h"
  82. #include "colormac.h"
  83. #include "context.h"
  84. #include "dlist.h"
  85. #include "hash.h"
  86. #include "light.h"
  87. #include "macros.h"
  88. #include "imports.h"
  89. #include "mmath.h"
  90. #include "simple_list.h"
  91. #include "mtypes.h"
  92. #include "vpexec.h"
  93.  
  94. #include "math/m_translate.h"
  95.  
  96. #include "t_context.h"
  97. #include "t_pipeline.h"
  98. #include "t_imm_api.h"
  99. #include "t_imm_exec.h"
  100.  
  101.  
  102. /**
  103.  * \warning These values _MUST_ match the values in the OutputRegisters[]
  104.  * array in vpparse.c!!!
  105.  */
  106. #define VERT_RESULT_HPOS 0
  107. #define VERT_RESULT_COL0 1
  108. #define VERT_RESULT_COL1 2
  109. #define VERT_RESULT_BFC0 3
  110. #define VERT_RESULT_BFC1 4
  111. #define VERT_RESULT_FOGC 5
  112. #define VERT_RESULT_PSIZ 6
  113. #define VERT_RESULT_TEX0 7
  114. #define VERT_RESULT_TEX1 8
  115. #define VERT_RESULT_TEX2 9
  116. #define VERT_RESULT_TEX3 10
  117. #define VERT_RESULT_TEX4 11
  118. #define VERT_RESULT_TEX5 12
  119. #define VERT_RESULT_TEX6 13
  120. #define VERT_RESULT_TEX7 14
  121.  
  122.  
  123. /*!
  124.  * Private storage for the vertex program pipeline stage.
  125.  */
  126. struct vp_stage_data {
  127.    /** The results of running the vertex program go into these arrays. */
  128.    GLvector4f attribs[15];
  129.  
  130.    /* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */
  131.    struct gl_client_array color0[2];  /**< diffuse front and back */
  132.    struct gl_client_array color1[2];  /**< specular front and back */
  133.  
  134.    GLvector4f ndcCoords;              /**< normalized device coords */
  135.    GLubyte *clipmask;                 /**< clip flags */
  136.    GLubyte ormask, andmask;           /**< for clipping */
  137. };
  138.  
  139.  
  140. #define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
  141.  
  142.  
  143. /**
  144.  * This function executes vertex programs
  145.  */
  146. static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
  147. {
  148.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  149.    struct vp_stage_data *store = VP_STAGE_DATA(stage);
  150.    struct vertex_buffer *VB = &tnl->vb;
  151.    struct vp_machine *machine = &(ctx->VertexProgram.Machine);
  152.    struct vp_program *program = ctx->VertexProgram.Current;
  153.    GLuint i;
  154.  
  155.    _mesa_init_tracked_matrices(ctx); /* load registers with matrices */
  156.    _mesa_init_vp_registers(ctx);     /* init temp and result regs */
  157.  
  158.    for (i = 0; i < VB->Count; i++) {
  159.       GLuint attr;
  160.  
  161. #if 0
  162.       printf("Input  %d: %f, %f, %f, %f\n", i,
  163.              VB->AttribPtr[0]->data[i][0],
  164.              VB->AttribPtr[0]->data[i][1],
  165.              VB->AttribPtr[0]->data[i][2],
  166.              VB->AttribPtr[0]->data[i][3]);
  167.       printf("   color: %f, %f, %f, %f\n",
  168.              VB->AttribPtr[3]->data[i][0],
  169.              VB->AttribPtr[3]->data[i][1],
  170.              VB->AttribPtr[3]->data[i][2],
  171.              VB->AttribPtr[3]->data[i][3]);
  172.       printf("  normal: %f, %f, %f, %f\n",
  173.              VB->AttribPtr[2]->data[i][0],
  174.              VB->AttribPtr[2]->data[i][1],
  175.              VB->AttribPtr[2]->data[i][2],
  176.              VB->AttribPtr[2]->data[i][3]);
  177. #endif
  178.  
  179.       /* load the input attribute registers */
  180.       if (VB->Flag) {
  181.          /* the traditional glBegin/glVertex/glEnd case */
  182.          for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
  183.             if (attr == 0 || (VB->Flag[i] & (1 << attr))) {
  184.                COPY_4V(machine->Registers[VP_INPUT_REG_START + attr],
  185.                        VB->AttribPtr[attr]->data[i]);
  186.             }
  187.          }
  188.       }
  189.       else {
  190.          /* the vertex array case */
  191.          for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
  192.             if (program->InputsRead & (1 << attr)) {
  193.                const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
  194.                const GLuint stride = VB->AttribPtr[attr]->stride;
  195.                const GLfloat *data = (GLfloat *) (ptr + stride * i);
  196.                COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], data);
  197.                /*ASSERT(VB->AttribPtr[attr]->size == 4);*/
  198.                ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0);
  199.             }
  200.          }
  201.       }
  202.  
  203.       /* execute the program */
  204.       ASSERT(program);
  205.       _mesa_exec_program(ctx, program);
  206.  
  207. #if 0
  208.       printf("Output %d: %f, %f, %f, %f\n", i,
  209.              machine->Registers[VP_OUTPUT_REG_START + 0][0],
  210.              machine->Registers[VP_OUTPUT_REG_START + 0][1],
  211.              machine->Registers[VP_OUTPUT_REG_START + 0][2],
  212.              machine->Registers[VP_OUTPUT_REG_START + 0][3]);
  213.       printf("   color: %f, %f, %f, %f\n",
  214.              machine->Registers[VP_OUTPUT_REG_START +_1][0],
  215.              machine->Registers[VP_OUTPUT_REG_START + 1][1],
  216.              machine->Registers[VP_OUTPUT_REG_START + 1][2],
  217.              machine->Registers[VP_OUTPUT_REG_START + 1][3]);
  218.       printf("PointSize[%d]: %g\n", i,
  219.              machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]);
  220. #endif
  221.  
  222.       /* Fixup fog an point size results if needed */
  223.       if (ctx->Fog.Enabled &&
  224.           (program->OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) {
  225.          machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_FOGC][0] = 1.0;
  226.       }
  227.  
  228.       if (ctx->VertexProgram.PointSizeEnabled &&
  229.           (program->OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) {
  230.          machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]
  231.             = ctx->Point.Size;
  232.       }
  233.  
  234.       /* copy the output registers into the VB->attribs arrays */
  235.       /* XXX (optimize) could use a conditional and smaller loop limit here */
  236.       for (attr = 0; attr < 15; attr++) {
  237.          COPY_4V( store->attribs[attr].data[i],
  238.                   machine->Registers[VP_OUTPUT_REG_START + attr] );
  239.       }
  240.    }
  241.  
  242.    /* Setup the VB pointers so that the next pipeline stages get
  243.     * their data from the right place (the program output arrays).
  244.     */
  245.    VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
  246.    VB->ClipPtr->size = 4;
  247.    VB->ClipPtr->count = VB->Count;
  248.    VB->ColorPtr[0] = &store->color0[0];
  249.    VB->ColorPtr[1] = &store->color0[1];
  250.    VB->SecondaryColorPtr[0] = &store->color1[0];
  251.    VB->SecondaryColorPtr[1] = &store->color1[1];
  252.    VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
  253.    VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ];
  254.    for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
  255.       VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i];
  256.  
  257.    /* Cliptest and perspective divide.  Clip functions must clear
  258.     * the clipmask.
  259.     */
  260.    store->ormask = 0;
  261.    store->andmask = CLIP_ALL_BITS;
  262.  
  263.    if (tnl->NeedNdcCoords) {
  264.       VB->NdcPtr =
  265.          _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
  266.                                             &store->ndcCoords,
  267.                                             store->clipmask,
  268.                                             &store->ormask,
  269.                                             &store->andmask );
  270.    }
  271.    else {
  272.       VB->NdcPtr = 0;
  273.       _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
  274.                                             0,
  275.                                             store->clipmask,
  276.                                             &store->ormask,
  277.                                             &store->andmask );
  278.    }
  279.  
  280.    if (store->andmask)  /* All vertices are outside the frustum */
  281.       return GL_FALSE;
  282.  
  283.  
  284.    /* This is where we'd do clip testing against the user-defined
  285.     * clipping planes, but they're not supported by vertex programs.
  286.     */
  287.  
  288.    VB->ClipOrMask = store->ormask;
  289.    VB->ClipMask = store->clipmask;
  290.  
  291.    /* XXXX what's this?
  292.    if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
  293.       VB->importable_data |= VERT_BIT_CLIP;
  294.    */
  295.  
  296.    return GL_TRUE;
  297. }
  298.  
  299.  
  300. /**
  301.  * This function validates stuff.
  302.  */
  303. static GLboolean run_validate_program( GLcontext *ctx,
  304.                     struct gl_pipeline_stage *stage )
  305. {
  306. #if 000
  307.    /* XXX do we need any validation for vertex programs? */
  308.    GLuint ind = 0;
  309.    light_func *tab;
  310.  
  311.    if (ctx->Visual.rgbMode) {
  312.       if (ctx->Light._NeedVertices) {
  313.      if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  314.         tab = _tnl_light_spec_tab;
  315.      else
  316.         tab = _tnl_light_tab;
  317.       }
  318.       else {
  319.      if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
  320.         tab = _tnl_light_fast_single_tab;
  321.      else
  322.         tab = _tnl_light_fast_tab;
  323.       }
  324.    }
  325.    else
  326.       tab = _tnl_light_ci_tab;
  327.  
  328.    if (ctx->Light.ColorMaterialEnabled)
  329.       ind |= LIGHT_COLORMATERIAL;
  330.  
  331.    if (ctx->Light.Model.TwoSide)
  332.       ind |= LIGHT_TWOSIDE;
  333.  
  334.    VP_STAGE_DATA(stage)->light_func_tab = &tab[ind];
  335.  
  336.    /* This and the above should only be done on _NEW_LIGHT:
  337.     */
  338.    _mesa_validate_all_lighting_tables( ctx );
  339. #endif
  340.  
  341.    /* Now run the stage...
  342.     */
  343.    stage->run = run_vp;
  344.    return stage->run( ctx, stage );
  345. }
  346.  
  347.  
  348. /**
  349.  * Initialize a gl_client_array to point into a GLvector4f color vector.
  350.  */
  351. static void init_color_array( struct gl_client_array *a, GLvector4f *vec )
  352. {
  353.    a->Ptr = vec->data;
  354.    a->Size = 4;
  355.    a->Type = GL_FLOAT;
  356.    a->Stride = 0;
  357.    a->StrideB = sizeof(GLfloat) * 4;
  358.    a->Enabled = 0;
  359.    a->Flags = 0;
  360. }
  361.  
  362.  
  363. /**
  364.  * Called the first time stage->run is called.  In effect, don't
  365.  * allocate data until the first time the stage is run.
  366.  */
  367. static GLboolean run_init_vp( GLcontext *ctx,
  368.                               struct gl_pipeline_stage *stage )
  369. {
  370.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  371.    struct vertex_buffer *VB = &(tnl->vb);
  372.    struct vp_stage_data *store;
  373.    const GLuint size = VB->Size;
  374.    GLuint i;
  375.  
  376.    stage->privatePtr = MALLOC(sizeof(*store));
  377.    store = VP_STAGE_DATA(stage);
  378.    if (!store)
  379.       return GL_FALSE;
  380.  
  381.    /* Allocate arrays of vertex output values */
  382.    for (i = 0; i < 15; i++)
  383.       _mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 );
  384.  
  385.    /* Make the color0[] and color1[] arrays point into the attribs[] arrays */
  386.    init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] );
  387.    init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] );
  388.    init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] );
  389.    init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] );
  390.  
  391.    /* a few other misc allocations */
  392.    _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
  393.    store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
  394.  
  395.    /* Now validate the stage derived data...
  396.     */
  397.    stage->run = run_validate_program;
  398.    return stage->run( ctx, stage );
  399. }
  400.  
  401.  
  402.  
  403. /**
  404.  * Check if vertex program mode is enabled. 
  405.  * If so, configure the pipeline stage's type, inputs, and outputs.
  406.  */
  407. static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
  408. {
  409.    stage->active = ctx->VertexProgram.Enabled;
  410.  
  411.    if (stage->active) {
  412.       /* I believe this is right - Keith?
  413.        * Set stage->inputs equal to the bitmask of vertex attributes
  414.        * which the program needs for inputs.
  415.        */
  416.  
  417.       stage->inputs = ctx->VertexProgram.Current->InputsRead;
  418.  
  419. #if 000
  420.       if (stage->privatePtr)
  421.      stage->run = run_validate_program;
  422.       stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
  423.       if (ctx->Light._NeedVertices)
  424.      stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
  425.       if (ctx->Light.ColorMaterialEnabled)
  426.      stage->inputs |= VERT_BIT_COLOR0;
  427.  
  428.       stage->outputs = VERT_BIT_COLOR0;
  429.       if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  430.      stage->outputs |= VERT_BIT_COLOR1;
  431. #endif
  432.    }
  433. }
  434.  
  435.  
  436. /**
  437.  * Destructor for this pipeline stage.
  438.  */
  439. static void dtr( struct gl_pipeline_stage *stage )
  440. {
  441.    struct vp_stage_data *store = VP_STAGE_DATA(stage);
  442.  
  443.    if (store) {
  444.       GLuint i;
  445.  
  446.       /* free the vertex program result arrays */
  447.       for (i = 0; i < 15; i++)
  448.          _mesa_vector4f_free( &store->attribs[i] );
  449.  
  450.       /* free misc arrays */
  451.       _mesa_vector4f_free( &store->ndcCoords );
  452.       ALIGN_FREE( store->clipmask );
  453.  
  454.       FREE( store );
  455.       stage->privatePtr = 0;
  456.    }
  457. }
  458.  
  459. /**
  460.  * Public description of this pipeline stage.
  461.  */
  462. const struct gl_pipeline_stage _tnl_vertex_program_stage =
  463. {
  464.    "vertex-program",
  465.    _NEW_ALL,    /*XXX FIX */    /* recheck */
  466.    _NEW_ALL,    /*XXX FIX */    /* recalc -- modelview dependency
  467.                  * otherwise not captured by inputs
  468.                  * (which may be VERT_BIT_POS) */
  469.    GL_FALSE,            /* active */
  470.    /*0*/ VERT_BIT_POS,                /* inputs  XXX OK? */
  471.    VERT_BIT_CLIP | VERT_BIT_COLOR0,            /* outputs XXX OK? */
  472.    0,                /* changed_inputs */
  473.    NULL,            /* private_data */
  474.    dtr,                /* destroy */
  475.    check_vp,            /* check */
  476.    run_init_vp            /* run -- initially set to ctr */
  477. };
  478.