Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Mesa 3-D graphics library
  3.  * Version:  7.6
  4.  *
  5.  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
  6.  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
  7.  *
  8.  * Permission is hereby granted, free of charge, to any person obtaining a
  9.  * copy of this software and associated documentation files (the "Software"),
  10.  * to deal in the Software without restriction, including without limitation
  11.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12.  * and/or sell copies of the Software, and to permit persons to whom the
  13.  * Software is furnished to do so, subject to the following conditions:
  14.  *
  15.  * The above copyright notice and this permission notice shall be included
  16.  * in all copies or substantial portions 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 MERCHANTABILITY,
  20.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  21.  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  22.  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  23.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24.  */
  25.  
  26.  
  27. /**
  28.  * \file tnl/t_vb_program.c
  29.  * \brief Pipeline stage for executing vertex programs.
  30.  * \author Brian Paul,  Keith Whitwell
  31.  */
  32.  
  33.  
  34. #include "main/glheader.h"
  35. #include "main/colormac.h"
  36. #include "main/macros.h"
  37. #include "main/imports.h"
  38. #include "math/m_xform.h"
  39. #include "program/prog_instruction.h"
  40. #include "program/prog_statevars.h"
  41. #include "program/prog_execute.h"
  42. #include "swrast/s_context.h"
  43.  
  44. #include "tnl/tnl.h"
  45. #include "tnl/t_context.h"
  46. #include "tnl/t_pipeline.h"
  47.  
  48.  
  49. #ifdef NAN_CHECK
  50. /** Check for NaNs and very large values */
  51. static INLINE void
  52. check_float(float x)
  53. {
  54.    assert(!IS_INF_OR_NAN(x));
  55.    assert(1.0e-15 <= x && x <= 1.0e15);
  56. }
  57. #endif
  58.  
  59.  
  60. /*!
  61.  * Private storage for the vertex program pipeline stage.
  62.  */
  63. struct vp_stage_data {
  64.    /** The results of running the vertex program go into these arrays. */
  65.    GLvector4f results[VERT_RESULT_MAX];
  66.  
  67.    GLvector4f ndcCoords;              /**< normalized device coords */
  68.    GLubyte *clipmask;                 /**< clip flags */
  69.    GLubyte ormask, andmask;           /**< for clipping */
  70.  
  71.    struct gl_program_machine machine;
  72. };
  73.  
  74.  
  75. #define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
  76.  
  77.  
  78. static void
  79. userclip( struct gl_context *ctx,
  80.           GLvector4f *clip,
  81.           GLubyte *clipmask,
  82.           GLubyte *clipormask,
  83.           GLubyte *clipandmask )
  84. {
  85.    GLuint p;
  86.  
  87.    for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
  88.       if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
  89.          GLuint nr, i;
  90.          const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
  91.          const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
  92.          const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
  93.          const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
  94.          GLfloat *coord = (GLfloat *)clip->data;
  95.          GLuint stride = clip->stride;
  96.          GLuint count = clip->count;
  97.  
  98.          for (nr = 0, i = 0 ; i < count ; i++) {
  99.             GLfloat dp = (coord[0] * a +
  100.                           coord[1] * b +
  101.                           coord[2] * c +
  102.                           coord[3] * d);
  103.  
  104.             if (dp < 0) {
  105.                nr++;
  106.                clipmask[i] |= CLIP_USER_BIT;
  107.             }
  108.  
  109.             STRIDE_F(coord, stride);
  110.          }
  111.  
  112.          if (nr > 0) {
  113.             *clipormask |= CLIP_USER_BIT;
  114.             if (nr == count) {
  115.                *clipandmask |= CLIP_USER_BIT;
  116.                return;
  117.             }
  118.          }
  119.       }
  120.    }
  121. }
  122.  
  123.  
  124. static GLboolean
  125. do_ndc_cliptest(struct gl_context *ctx, struct vp_stage_data *store)
  126. {
  127.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  128.    struct vertex_buffer *VB = &tnl->vb;
  129.    /* Cliptest and perspective divide.  Clip functions must clear
  130.     * the clipmask.
  131.     */
  132.    store->ormask = 0;
  133.    store->andmask = CLIP_FRUSTUM_BITS;
  134.  
  135.    tnl_clip_prepare(ctx);
  136.  
  137.    if (tnl->NeedNdcCoords) {
  138.       VB->NdcPtr =
  139.          _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
  140.                                             &store->ndcCoords,
  141.                                             store->clipmask,
  142.                                             &store->ormask,
  143.                                             &store->andmask,
  144.                                             !ctx->Transform.DepthClamp );
  145.    }
  146.    else {
  147.       VB->NdcPtr = NULL;
  148.       _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
  149.                                             NULL,
  150.                                             store->clipmask,
  151.                                             &store->ormask,
  152.                                             &store->andmask,
  153.                                             !ctx->Transform.DepthClamp );
  154.    }
  155.  
  156.    if (store->andmask) {
  157.       /* All vertices are outside the frustum */
  158.       return GL_FALSE;
  159.    }
  160.  
  161.    /* Test userclip planes.  This contributes to VB->ClipMask.
  162.     */
  163.    /** XXX NEW_SLANG _Enabled ??? */
  164.    if (ctx->Transform.ClipPlanesEnabled && (!ctx->VertexProgram._Enabled ||
  165.       ctx->VertexProgram.Current->IsPositionInvariant)) {
  166.       userclip( ctx,
  167.                 VB->ClipPtr,
  168.                 store->clipmask,
  169.                 &store->ormask,
  170.                 &store->andmask );
  171.  
  172.       if (store->andmask) {
  173.          return GL_FALSE;
  174.       }
  175.    }
  176.  
  177.    VB->ClipAndMask = store->andmask;
  178.    VB->ClipOrMask = store->ormask;
  179.    VB->ClipMask = store->clipmask;
  180.  
  181.    return GL_TRUE;
  182. }
  183.  
  184.  
  185. /**
  186.  * XXX the texture sampling code in this module is a bit of a hack.
  187.  * The texture sampling code is in swrast, though it doesn't have any
  188.  * real dependencies on the rest of swrast.  It should probably be
  189.  * moved into main/ someday.
  190.  */
  191. static void
  192. vp_fetch_texel(struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
  193.                GLuint unit, GLfloat color[4])
  194. {
  195.    SWcontext *swrast = SWRAST_CONTEXT(ctx);
  196.  
  197.    /* XXX use a float-valued TextureSample routine here!!! */
  198.    swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
  199.                                1, (const GLfloat (*)[4]) texcoord,
  200.                                &lambda,  (GLfloat (*)[4]) color);
  201. }
  202.  
  203.  
  204. /**
  205.  * Called via ctx->Driver.ProgramStringNotify() after a new vertex program
  206.  * string has been parsed.
  207.  */
  208. GLboolean
  209. _tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program)
  210. {
  211.    /* No-op.
  212.     * If we had derived anything from the program that was private to this
  213.     * stage we'd recompute/validate it here.
  214.     */
  215.    return GL_TRUE;
  216. }
  217.  
  218.  
  219. /**
  220.  * Initialize virtual machine state prior to executing vertex program.
  221.  */
  222. static void
  223. init_machine(struct gl_context *ctx, struct gl_program_machine *machine)
  224. {
  225.    /* Input registers get initialized from the current vertex attribs */
  226.    memcpy(machine->VertAttribs, ctx->Current.Attrib,
  227.           MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat));
  228.  
  229.    if (ctx->VertexProgram._Current->IsNVProgram) {
  230.       GLuint i;
  231.       /* Output/result regs are initialized to [0,0,0,1] */
  232.       for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
  233.          ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
  234.       }
  235.       /* Temp regs are initialized to [0,0,0,0] */
  236.       for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
  237.          ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
  238.       }
  239.       for (i = 0; i < MAX_VERTEX_PROGRAM_ADDRESS_REGS; i++) {
  240.          ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0);
  241.       }
  242.    }
  243.  
  244.    machine->NumDeriv = 0;
  245.  
  246.    /* init condition codes */
  247.    machine->CondCodes[0] = COND_EQ;
  248.    machine->CondCodes[1] = COND_EQ;
  249.    machine->CondCodes[2] = COND_EQ;
  250.    machine->CondCodes[3] = COND_EQ;
  251.  
  252.    /* init call stack */
  253.    machine->StackDepth = 0;
  254.  
  255.    machine->FetchTexelLod = vp_fetch_texel;
  256.    machine->FetchTexelDeriv = NULL; /* not used by vertex programs */
  257.  
  258.    machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits;
  259. }
  260.  
  261.  
  262. /**
  263.  * Map the texture images which the vertex program will access (if any).
  264.  */
  265. static void
  266. map_textures(struct gl_context *ctx, const struct gl_vertex_program *vp)
  267. {
  268.    GLuint u;
  269.  
  270.    if (!ctx->Driver.MapTexture)
  271.       return;
  272.  
  273.    for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
  274.       if (vp->Base.TexturesUsed[u]) {
  275.          /* Note: _Current *should* correspond to the target indicated
  276.           * in TexturesUsed[u].
  277.           */
  278.          ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[u]._Current);
  279.       }
  280.    }
  281. }
  282.  
  283.  
  284. /**
  285.  * Unmap the texture images which were used by the vertex program (if any).
  286.  */
  287. static void
  288. unmap_textures(struct gl_context *ctx, const struct gl_vertex_program *vp)
  289. {
  290.    GLuint u;
  291.  
  292.    if (!ctx->Driver.MapTexture)
  293.       return;
  294.  
  295.    for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
  296.       if (vp->Base.TexturesUsed[u]) {
  297.          /* Note: _Current *should* correspond to the target indicated
  298.           * in TexturesUsed[u].
  299.           */
  300.          ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[u]._Current);
  301.       }
  302.    }
  303. }
  304.  
  305.  
  306. /**
  307.  * This function executes vertex programs
  308.  */
  309. static GLboolean
  310. run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage )
  311. {
  312.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  313.    struct vp_stage_data *store = VP_STAGE_DATA(stage);
  314.    struct vertex_buffer *VB = &tnl->vb;
  315.    struct gl_vertex_program *program = ctx->VertexProgram._Current;
  316.    struct gl_program_machine *machine = &store->machine;
  317.    GLuint outputs[VERT_RESULT_MAX], numOutputs;
  318.    GLuint i, j;
  319.  
  320.    if (!program)
  321.       return GL_TRUE;
  322.  
  323.    if (program->IsNVProgram) {
  324.       _mesa_load_tracked_matrices(ctx);
  325.    }
  326.    else {
  327.       /* ARB program or vertex shader */
  328.       _mesa_load_state_parameters(ctx, program->Base.Parameters);
  329.    }
  330.  
  331.    /* make list of outputs to save some time below */
  332.    numOutputs = 0;
  333.    for (i = 0; i < VERT_RESULT_MAX; i++) {
  334.       if (program->Base.OutputsWritten & BITFIELD64_BIT(i)) {
  335.          outputs[numOutputs++] = i;
  336.       }
  337.    }
  338.  
  339.    map_textures(ctx, program);
  340.  
  341.    for (i = 0; i < VB->Count; i++) {
  342.       GLuint attr;
  343.  
  344.       init_machine(ctx, machine);
  345.  
  346. #if 0
  347.       printf("Input  %d: %f, %f, %f, %f\n", i,
  348.              VB->AttribPtr[0]->data[i][0],
  349.              VB->AttribPtr[0]->data[i][1],
  350.              VB->AttribPtr[0]->data[i][2],
  351.              VB->AttribPtr[0]->data[i][3]);
  352.       printf("   color: %f, %f, %f, %f\n",
  353.              VB->AttribPtr[3]->data[i][0],
  354.              VB->AttribPtr[3]->data[i][1],
  355.              VB->AttribPtr[3]->data[i][2],
  356.              VB->AttribPtr[3]->data[i][3]);
  357.       printf("  normal: %f, %f, %f, %f\n",
  358.              VB->AttribPtr[2]->data[i][0],
  359.              VB->AttribPtr[2]->data[i][1],
  360.              VB->AttribPtr[2]->data[i][2],
  361.              VB->AttribPtr[2]->data[i][3]);
  362. #endif
  363.  
  364.       /* the vertex array case */
  365.       for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
  366.          if (program->Base.InputsRead & (1 << attr)) {
  367.             const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
  368.             const GLuint size = VB->AttribPtr[attr]->size;
  369.             const GLuint stride = VB->AttribPtr[attr]->stride;
  370.             const GLfloat *data = (GLfloat *) (ptr + stride * i);
  371. #ifdef NAN_CHECK
  372.             check_float(data[0]);
  373.             check_float(data[1]);
  374.             check_float(data[2]);
  375.             check_float(data[3]);
  376. #endif
  377.             COPY_CLEAN_4V(machine->VertAttribs[attr], size, data);
  378.          }
  379.       }
  380.  
  381.       /* execute the program */
  382.       _mesa_execute_program(ctx, &program->Base, machine);
  383.  
  384.       /* copy the output registers into the VB->attribs arrays */
  385.       for (j = 0; j < numOutputs; j++) {
  386.          const GLuint attr = outputs[j];
  387. #ifdef NAN_CHECK
  388.          check_float(machine->Outputs[attr][0]);
  389.          check_float(machine->Outputs[attr][1]);
  390.          check_float(machine->Outputs[attr][2]);
  391.          check_float(machine->Outputs[attr][3]);
  392. #endif
  393.          COPY_4V(store->results[attr].data[i], machine->Outputs[attr]);
  394.       }
  395.  
  396.       /* FOGC is a special case.  Fragment shader expects (f,0,0,1) */
  397.       if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) {
  398.          store->results[VERT_RESULT_FOGC].data[i][1] = 0.0;
  399.          store->results[VERT_RESULT_FOGC].data[i][2] = 0.0;
  400.          store->results[VERT_RESULT_FOGC].data[i][3] = 1.0;
  401.       }
  402. #ifdef NAN_CHECK
  403.       ASSERT(machine->Outputs[0][3] != 0.0F);
  404. #endif
  405. #if 0
  406.       printf("HPOS: %f %f %f %f\n",
  407.              machine->Outputs[0][0],
  408.              machine->Outputs[0][1],
  409.              machine->Outputs[0][2],
  410.              machine->Outputs[0][3]);
  411. #endif
  412.    }
  413.  
  414.    unmap_textures(ctx, program);
  415.  
  416.    /* Fixup fog and point size results if needed */
  417.    if (program->IsNVProgram) {
  418.       if (ctx->Fog.Enabled &&
  419.           (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) == 0) {
  420.          for (i = 0; i < VB->Count; i++) {
  421.             store->results[VERT_RESULT_FOGC].data[i][0] = 1.0;
  422.          }
  423.       }
  424.  
  425.       if (ctx->VertexProgram.PointSizeEnabled &&
  426.           (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) == 0) {
  427.          for (i = 0; i < VB->Count; i++) {
  428.             store->results[VERT_RESULT_PSIZ].data[i][0] = ctx->Point.Size;
  429.          }
  430.       }
  431.    }
  432.  
  433.    if (program->IsPositionInvariant) {
  434.       /* We need the exact same transform as in the fixed function path here
  435.        * to guarantee invariance, depending on compiler optimization flags
  436.        * results could be different otherwise.
  437.        */
  438.       VB->ClipPtr = TransformRaw( &store->results[0],
  439.                                   &ctx->_ModelProjectMatrix,
  440.                                   VB->AttribPtr[0] );
  441.  
  442.       /* Drivers expect this to be clean to element 4...
  443.        */
  444.       switch (VB->ClipPtr->size) {
  445.       case 1:
  446.          /* impossible */
  447.       case 2:
  448.          _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
  449.          /* fall-through */
  450.       case 3:
  451.          _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
  452.          /* fall-through */
  453.       case 4:
  454.          break;
  455.       }
  456.    }
  457.    else {
  458.       /* Setup the VB pointers so that the next pipeline stages get
  459.        * their data from the right place (the program output arrays).
  460.        */
  461.       VB->ClipPtr = &store->results[VERT_RESULT_HPOS];
  462.       VB->ClipPtr->size = 4;
  463.       VB->ClipPtr->count = VB->Count;
  464.    }
  465.  
  466.    VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VERT_RESULT_COL0];
  467.    VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VERT_RESULT_COL1];
  468.    VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VERT_RESULT_FOGC];
  469.    VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VERT_RESULT_PSIZ];
  470.    VB->BackfaceColorPtr = &store->results[VERT_RESULT_BFC0];
  471.    VB->BackfaceSecondaryColorPtr = &store->results[VERT_RESULT_BFC1];
  472.  
  473.    for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
  474.       VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]
  475.          = &store->results[VERT_RESULT_TEX0 + i];
  476.    }
  477.  
  478.    for (i = 0; i < ctx->Const.MaxVarying; i++) {
  479.       if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) {
  480.          /* Note: varying results get put into the generic attributes */
  481.          VB->AttribPtr[VERT_ATTRIB_GENERIC0+i]
  482.             = &store->results[VERT_RESULT_VAR0 + i];
  483.       }
  484.    }
  485.  
  486.  
  487.    /* Perform NDC and cliptest operations:
  488.     */
  489.    return do_ndc_cliptest(ctx, store);
  490. }
  491.  
  492.  
  493. /**
  494.  * Called the first time stage->run is called.  In effect, don't
  495.  * allocate data until the first time the stage is run.
  496.  */
  497. static GLboolean
  498. init_vp(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
  499. {
  500.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  501.    struct vertex_buffer *VB = &(tnl->vb);
  502.    struct vp_stage_data *store;
  503.    const GLuint size = VB->Size;
  504.    GLuint i;
  505.  
  506.    stage->privatePtr = CALLOC(sizeof(*store));
  507.    store = VP_STAGE_DATA(stage);
  508.    if (!store)
  509.       return GL_FALSE;
  510.  
  511.    /* Allocate arrays of vertex output values */
  512.    for (i = 0; i < VERT_RESULT_MAX; i++) {
  513.       _mesa_vector4f_alloc( &store->results[i], 0, size, 32 );
  514.       store->results[i].size = 4;
  515.    }
  516.  
  517.    /* a few other misc allocations */
  518.    _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
  519.    store->clipmask = (GLubyte *) _mesa_align_malloc(sizeof(GLubyte)*size, 32 );
  520.  
  521.    return GL_TRUE;
  522. }
  523.  
  524.  
  525. /**
  526.  * Destructor for this pipeline stage.
  527.  */
  528. static void
  529. dtr(struct tnl_pipeline_stage *stage)
  530. {
  531.    struct vp_stage_data *store = VP_STAGE_DATA(stage);
  532.  
  533.    if (store) {
  534.       GLuint i;
  535.  
  536.       /* free the vertex program result arrays */
  537.       for (i = 0; i < VERT_RESULT_MAX; i++)
  538.          _mesa_vector4f_free( &store->results[i] );
  539.  
  540.       /* free misc arrays */
  541.       _mesa_vector4f_free( &store->ndcCoords );
  542.       _mesa_align_free( store->clipmask );
  543.  
  544.       FREE( store );
  545.       stage->privatePtr = NULL;
  546.    }
  547. }
  548.  
  549.  
  550. static void
  551. validate_vp_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
  552. {
  553.    if (ctx->VertexProgram._Current) {
  554.       _swrast_update_texture_samplers(ctx);
  555.    }
  556. }
  557.  
  558.  
  559.  
  560. /**
  561.  * Public description of this pipeline stage.
  562.  */
  563. const struct tnl_pipeline_stage _tnl_vertex_program_stage =
  564. {
  565.    "vertex-program",
  566.    NULL,                        /* private_data */
  567.    init_vp,                     /* create */
  568.    dtr,                         /* destroy */
  569.    validate_vp_stage,           /* validate */
  570.    run_vp                       /* run -- initially set to ctr */
  571. };
  572.