Subversion Repositories Kolibri OS

Rev

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

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