Subversion Repositories Kolibri OS

Rev

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