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