home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / System / Mesa-3.1 / src / cva.c < prev    next >
C/C++ Source or Header  |  2000-01-07  |  21KB  |  781 lines

  1. /* $Id: cva.c,v 1.11 1999/11/08 07:36:43 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.1
  6.  * 
  7.  * Copyright (C) 1999  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. /* Mesa CVA implementation.  
  28.  * Copyright (C) 1999 Keith Whitwell
  29.  */
  30.  
  31. #ifndef XFree86Server
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #else
  35. #include "GL/xf86glx.h"
  36. #endif
  37. #include "api.h"
  38. #include "types.h"
  39. #include "cva.h"
  40. #include "context.h"
  41. #include "macros.h"
  42. #include "pipeline.h"
  43. #include "varray.h"
  44. #include "vbcull.h"
  45. #include "vbrender.h"
  46. #include "vbxform.h"
  47. #include "vector.h"
  48.  
  49. /* Mesa CVA implementation.  
  50.  * Copyright (C) 1999 Keith Whitwell
  51.  */
  52.  
  53.  
  54.  
  55. static void copy_clipmask( GLubyte *dest, GLubyte *ormask, GLubyte *andmask,
  56.                const GLubyte *src, 
  57.                const GLuint *elt, GLuint nr )
  58. {
  59.    GLuint i;
  60.    GLubyte o = *ormask;
  61.    GLubyte a = *andmask;
  62.  
  63.    for (i = 0 ; i < nr ; i++) {
  64.       GLubyte t = src[elt[i]];
  65.       dest[i] = t;
  66.       o |= t;
  67.       a &= t;
  68.    }  
  69.  
  70.    *ormask = o;
  71.    *andmask = a;
  72. }
  73.  
  74. static void translate_4f( GLvector4f *dest, 
  75.               CONST GLvector4f *src, 
  76.               CONST GLuint elt[], 
  77.               GLuint nr )
  78. {
  79.    GLuint i;
  80.    GLfloat (*from)[4] = (GLfloat (*)[4])src->start;
  81.    GLfloat (*to)[4] = (GLfloat (*)[4])dest->start;
  82.    GLuint stride = src->stride;
  83.    
  84.    if (stride == 4 * sizeof(GLfloat)) {
  85.       for (i = 0 ; i < nr ; i++) 
  86.      COPY_4FV( to[i], from[elt[i]] );
  87.    } else {
  88.       for (i = 0 ; i < nr ; i++) {
  89.      CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
  90.      COPY_4FV( to[i], (GLfloat *)f );
  91.       }
  92.    }      
  93.  
  94.    dest->size = src->size;
  95.    dest->flags |= (src->flags & VEC_SIZE_4);
  96.    dest->count = nr;
  97. }
  98.  
  99. static void translate_3f( GLvector3f *dest, 
  100.               CONST GLvector3f *src, 
  101.               CONST GLuint elt[], 
  102.               GLuint nr )
  103. {
  104.    GLuint i;
  105.    GLfloat (*from)[3] = (GLfloat (*)[3])src->start;
  106.    GLfloat (*to)[3] = (GLfloat (*)[3])dest->start;
  107.    GLuint stride = src->stride;
  108.  
  109.    if (stride == 3 * sizeof(GLfloat)) {
  110.       for (i = 0 ; i < nr ; i++) 
  111.      COPY_3FV( to[i], from[elt[i]] );
  112.    } else {
  113.       for (i = 0 ; i < nr ; i++) {
  114.      CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
  115.      COPY_3FV( to[i], (GLfloat *)f );
  116.       }
  117.    }
  118.  
  119.    dest->count = nr;
  120. }
  121.  
  122. static void translate_4ub( GLvector4ub *dest, 
  123.                CONST GLvector4ub *src,
  124.                GLuint elt[], 
  125.                GLuint nr )
  126. {
  127.    GLuint i;
  128.    GLubyte (*from)[4] = (GLubyte (*)[4])src->start;
  129.    GLubyte (*to)[4] = (GLubyte (*)[4])dest->start;
  130.    GLuint stride = src->stride;
  131.  
  132.    if (stride == 4 * sizeof(GLubyte)) {
  133.       for (i = 0 ; i < nr ; i++)
  134.      COPY_4UBV( to[i], from[elt[i]]);
  135.    } else {
  136.       for (i = 0 ; i < nr ; i++) {
  137.      CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
  138.      COPY_4UBV( to[i], f );
  139.       }
  140.    }
  141.  
  142.    dest->count = nr;
  143. }
  144.  
  145. static void translate_1ui( GLvector1ui *dest, 
  146.                GLvector1ui *src, 
  147.                GLuint elt[], 
  148.                GLuint nr )
  149. {
  150.    GLuint i;
  151.    GLuint *from = src->start;
  152.    GLuint *to = dest->start;
  153.    GLuint stride = src->stride;
  154.  
  155.    if (stride == sizeof(GLuint)) {
  156.       for (i = 0 ; i < nr ; i++)
  157.      to[i] = from[elt[i]];
  158.    } else {
  159.       for (i = 0 ; i < nr ; i++) {
  160.      CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
  161.      to[i] = *(GLuint *)f;
  162.       }
  163.    }
  164.  
  165.    dest->count = nr;
  166. }
  167.  
  168. static void translate_1ub( GLvector1ub *dest, 
  169.                GLvector1ub *src, 
  170.                GLuint elt[], 
  171.                GLuint nr )
  172. {
  173.    GLuint i;
  174.    GLubyte *from = src->start;
  175.    GLubyte *to = dest->start;
  176.    GLuint stride = src->stride;
  177.  
  178.    if (stride == sizeof(GLubyte)) {
  179.       for (i = 0 ; i < nr ; i++)
  180.      to[i] = from[elt[i]];
  181.    } else {
  182.       for (i = 0 ; i < nr ; i++) {
  183.      CONST GLubyte *f = from + elt[i] * stride;
  184.      to[i] = *f;
  185.       }
  186.    }
  187.  
  188.    dest->count = nr;
  189. }
  190.  
  191.  
  192. /* The fallback case for handling the merge of cva and immediate
  193.  * data.  This code back-copies data from cva->immediate to build a
  194.  * normal looking immediate struct, which is then sent off to the
  195.  * old raster setup and render routines.
  196.  *
  197.  * The FX driver implements a replacement for this step which merges
  198.  * the new data into the already prepared GrVertex structs.
  199.  *
  200.  * When there is no data to merge, gl_render_vb_indirect is called
  201.  * instead.
  202.  */
  203. void gl_merge_cva( struct vertex_buffer *VB,
  204.            struct vertex_buffer *cvaVB )
  205. {
  206.    GLcontext *ctx = VB->ctx;
  207.    GLuint *elt = VB->EltPtr->start;
  208.    GLuint count = VB->Count - VB->Start;
  209.    GLuint available = ctx->CVA.pre.outputs | ctx->Array.Summary;
  210.    GLuint required = ctx->CVA.elt.inputs;
  211.    GLuint flags;
  212.  
  213.    /* Should attempt to build an or-flag of reduced (ie rasterization)
  214.     * prims in the VB, so a software points function doesn't screw us
  215.     * when we're doing hardware triangles.
  216.     */
  217.    if ((required & VERT_SETUP_FULL) && 
  218.        (ctx->IndirectTriangles & DD_SW_SETUP))
  219.    {
  220.       if (MESA_VERBOSE & VERBOSE_PIPELINE)
  221.      gl_print_vert_flags("extra flags for setup", 
  222.                  ctx->RenderFlags & available & ~required);
  223.       required |= ctx->RenderFlags;
  224.    }
  225.  
  226.    flags = required & available;
  227.  
  228.    if ((flags & VERT_DATA) == 0)
  229.       return;
  230.    
  231.    if (MESA_VERBOSE&VERBOSE_PIPELINE)
  232.       gl_print_vert_flags("cva merge", flags); 
  233.  
  234.    if (flags & VERT_WIN) {
  235.       VB->ClipPtr = &VB->Clip;
  236.       VB->Projected = &VB->Win;
  237.       VB->CullMode = 0;
  238.    
  239.       if (cvaVB->ClipOrMask) {
  240.  
  241.      /* Copy clipmask back into VB, build a new clipOrMask */
  242.      copy_clipmask( VB->ClipMask + VB->Start, 
  243.             &VB->ClipOrMask, &VB->ClipAndMask,
  244.             cvaVB->ClipMask, 
  245.             elt, 
  246.             VB->Count - VB->Start );
  247.      
  248.      /* overkill if !VB->ClipOrMask - should just copy 'copied' verts */
  249.      translate_4f( VB->ClipPtr, cvaVB->ClipPtr, elt, count);
  250.  
  251.      if (VB->ClipOrMask & CLIP_USER_BIT) {
  252.         GLubyte or = 0, and = ~0;
  253.  
  254.         copy_clipmask( VB->UserClipMask + VB->Start,
  255.                &or, &and,
  256.                cvaVB->UserClipMask,
  257.                elt,
  258.                VB->Count - VB->Start);
  259.         
  260.         if (and) VB->ClipAndMask |= CLIP_USER_BIT;
  261.      }
  262.  
  263.      if (VB->ClipOrMask) 
  264.         VB->CullMode |= CLIP_MASK_ACTIVE;      
  265.  
  266.      if (VB->ClipAndMask) {
  267.         VB->Culled = 1;
  268.         gl_dont_cull_vb( VB );   
  269.         return;
  270.      }
  271.       }
  272.  
  273.       translate_4f( &VB->Win, &cvaVB->Win, elt, count );
  274.  
  275.       /* Can't be precomputed - but may be wasteful to do this now.
  276.        */
  277.       if (ctx->IndirectTriangles & DD_ANY_CULL)
  278.       {
  279.      GLuint cullcount = gl_cull_vb( VB );      
  280.      if (cullcount) VB->CullMode |= CULL_MASK_ACTIVE;
  281.      if (cullcount == VB->Count) { VB->Culled = 2 ; return; }
  282.       }
  283.       else 
  284.      gl_dont_cull_vb( VB );   
  285.    } else {
  286.       VB->ClipPtr = &VB->Clip;
  287.       VB->Projected = &VB->Win;
  288.    }
  289.  
  290.    if (flags & VERT_EYE) 
  291.    {
  292.       VB->Unprojected = VB->EyePtr = &VB->Eye;
  293.       translate_4f( VB->EyePtr, cvaVB->EyePtr, elt, count);
  294.    }
  295.  
  296.    if (flags & VERT_OBJ_ANY) 
  297.    {
  298.       VB->ObjPtr = &VB->IM->v.Obj;
  299.       if (!ctx->NeedEyeCoords) VB->Unprojected = VB->ObjPtr;
  300.       translate_4f( VB->ObjPtr, cvaVB->ObjPtr, elt, count);
  301.    }
  302.  
  303.    if (flags & VERT_NORM) 
  304.    {
  305.       VB->NormalPtr = &VB->IM->v.Normal;      
  306.       translate_3f( VB->NormalPtr, cvaVB->NormalPtr, elt, count );
  307.       VB->CullMode &= ~COMPACTED_NORMALS;
  308.    }
  309.  
  310.    if (flags & VERT_RGBA) 
  311.    {
  312.       VB->ColorPtr = VB->Color[0] = VB->LitColor[0];
  313.       translate_4ub( VB->Color[0], cvaVB->Color[0], elt, count );
  314.  
  315.       if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
  316.      VB->Color[1] = VB->LitColor[1];
  317.      translate_4ub( VB->Color[1], cvaVB->Color[1], elt, count );
  318.       }
  319.    }
  320.    
  321.    if (flags & VERT_INDEX) 
  322.    {
  323.       VB->IndexPtr = VB->Index[0] = VB->LitIndex[0];
  324.       translate_1ui( VB->Index[0], cvaVB->Index[0], elt, count );
  325.  
  326.       if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
  327.      VB->Index[1] = VB->LitIndex[1];
  328.      translate_1ui( VB->Index[1], cvaVB->Index[1], elt, count );
  329.       }
  330.    }
  331.  
  332.    if (flags & VERT_EDGE) 
  333.    {
  334.       VB->EdgeFlagPtr = &VB->IM->v.EdgeFlag;      
  335.       translate_1ub( VB->EdgeFlagPtr, cvaVB->EdgeFlagPtr, elt, count );
  336.    }
  337.  
  338.    if (flags & VERT_TEX0_ANY) 
  339.    {
  340.       VB->TexCoordPtr[0] = &VB->IM->v.TexCoord[0];
  341.       translate_4f( VB->TexCoordPtr[0], cvaVB->TexCoordPtr[0], elt, count);
  342.    }
  343.  
  344.    if (flags & VERT_TEX1_ANY) 
  345.    {
  346.       VB->TexCoordPtr[1] = &VB->IM->v.TexCoord[1];      
  347.       translate_4f( VB->TexCoordPtr[1], cvaVB->TexCoordPtr[1], elt, count);
  348.    }
  349. }
  350.  
  351.  
  352.  
  353.  
  354. /* We don't have a good mechanism for dealing with the situation where
  355.  * cva is 'abandoned' midway through a vertex buffer, or indeed any mixing
  356.  * of cva & standard data in a single immediate struct.
  357.  *
  358.  * Basically just abandon CVA even though the precalced data
  359.  * is already there.
  360.  */
  361. void gl_rescue_cva( GLcontext *ctx, struct immediate *IM )
  362. {
  363.    struct vertex_buffer *VB = ctx->VB;
  364.  
  365.    IM->Start = VB->CopyStart;
  366.  
  367.    ctx->CompileCVAFlag = 0;
  368.    gl_build_immediate_pipeline( ctx );
  369.    gl_exec_array_elements( ctx, IM, IM->Start, IM->Count );
  370. }
  371.  
  372.  
  373.  
  374.  
  375.  
  376. /* Transform the array components now, upto the setup call.  When
  377.  * actual draw commands arrive, the data will be merged prior to
  378.  * calling render_vb.  
  379.  */
  380. void GLAPIENTRY glLockArraysEXT(CTX_ARG GLint first, GLsizei count )
  381. {
  382.    GLcontext *ctx;
  383.    GET_CONTEXT;
  384.    CHECK_CONTEXT;
  385.    ctx = CC;
  386.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "unlock arrays" );
  387.  
  388.    if (MESA_VERBOSE & VERBOSE_API)
  389.       fprintf(stderr, "glLockArrays %d %d\n", first, count);
  390.  
  391.    /* Can't mix locked & unlocked - if count is too large, just
  392.     * unlock.  
  393.     */
  394.    if (first == 0 && 
  395.        count > 0 && 
  396.        count <= ctx->Const.MaxArrayLockSize)
  397.    {   
  398.       struct gl_cva *cva = &ctx->CVA;
  399.  
  400.       if (!ctx->Array.LockCount) {
  401.      ctx->Array.NewArrayState = ~0;
  402.      ctx->CVA.lock_changed ^= 1;
  403.      ctx->NewState |= NEW_CLIENT_STATE;
  404.       }
  405.  
  406.       ctx->Array.LockFirst = first;
  407.       ctx->Array.LockCount = count;     
  408.       ctx->CompileCVAFlag = !ctx->CompileFlag;
  409.  
  410.       if (!cva->VB) {
  411.      cva->VB = gl_vb_create_for_cva( ctx, ctx->Const.MaxArrayLockSize );
  412.      gl_alloc_cva_store( cva, cva->VB->Size );
  413.      gl_reset_cva_vb( cva->VB, ~0 );
  414.       }
  415.    } 
  416.    else
  417.    {
  418.       if (ctx->Array.LockCount) {
  419.      ctx->CVA.lock_changed ^= 1;
  420.      ctx->NewState |= NEW_CLIENT_STATE;
  421.       }
  422.  
  423.  
  424.       ctx->Array.LockFirst = 0;
  425.       ctx->Array.LockCount = 0;
  426.       ctx->CompileCVAFlag = 0;
  427.    }
  428. }
  429.  
  430.  
  431.  
  432.  
  433. void GLAPIENTRY glUnlockArraysEXT(CTX_VOID )
  434. {
  435.    GLcontext *ctx;
  436.    GET_CONTEXT;
  437.    CHECK_CONTEXT;
  438.    ctx = CC;
  439.    ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "unlock arrays" );
  440.  
  441.    if (MESA_VERBOSE & VERBOSE_API)
  442.       fprintf(stderr, "glUnlockArrays\n");
  443.  
  444.    if (ctx->Array.LockCount) {
  445.       ctx->CVA.lock_changed ^= 1;
  446.       ctx->NewState |= NEW_CLIENT_STATE;
  447.    }
  448.  
  449.    ctx->Array.LockFirst = 0;
  450.    ctx->Array.LockCount = 0;
  451.    ctx->CompileCVAFlag = 0;
  452. }
  453.  
  454.  
  455. /* This storage used to hold translated client data if type or stride
  456.  * need to be fixed.
  457.  */
  458. void gl_alloc_cva_store( struct gl_cva *cva, GLuint size )
  459. {
  460.    cva->store.Obj = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size );
  461.    cva->store.Normal = (GLfloat (*)[3])MALLOC( sizeof(GLfloat) * 3 * size );
  462.    cva->store.Color = (GLubyte (*)[4])MALLOC( sizeof(GLubyte) * 4 * size );
  463.    cva->store.EdgeFlag = (GLubyte *)MALLOC( sizeof(GLubyte) * size );
  464.    cva->store.Index = (GLuint *)MALLOC( sizeof(GLuint) * size );
  465.    cva->store.TexCoord[0] = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size);
  466.    cva->store.TexCoord[1] = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size);
  467.    cva->store.Elt = (GLuint *)MALLOC( sizeof(GLuint) * size );
  468.    cva->elt_size = size;
  469. }
  470.  
  471. void gl_free_cva_store( struct gl_cva *cva )
  472. {
  473.    FREE( cva->store.Obj );
  474.    FREE( cva->store.Normal );
  475.    FREE( cva->store.Color );
  476.    FREE( cva->store.EdgeFlag );
  477.    FREE( cva->store.Index );
  478.    FREE( cva->store.TexCoord[0] );
  479.    FREE( cva->store.TexCoord[1] );
  480.    FREE( cva->store.Elt );
  481. }
  482.  
  483.  
  484. void gl_prepare_arrays_cva( struct vertex_buffer *VB )
  485. {
  486.    GLcontext *ctx = VB->ctx;
  487.    struct gl_cva *cva = &ctx->CVA;
  488.    GLuint start = ctx->Array.LockFirst;
  489.    GLuint n = ctx->Array.LockCount;
  490.    GLuint enable = ((ctx->Array.NewArrayState & ctx->Array.Summary) |
  491.             VB->pipeline->fallback);
  492.    GLuint disable = ctx->Array.NewArrayState & ~enable;
  493.    GLuint i;
  494.  
  495.    if (MESA_VERBOSE&VERBOSE_PIPELINE) {
  496.       gl_print_vert_flags("*** ENABLE", enable);
  497.       gl_print_vert_flags("*** DISABLE", disable);
  498.    }
  499.  
  500.    if (enable) 
  501.    {
  502.       struct gl_client_array *client_data;
  503.       GLuint fallback = VB->pipeline->fallback;
  504.    
  505.       if (enable & VERT_ELT) 
  506.       {
  507.      GLvector1ui *elt = VB->EltPtr = &cva->v.Elt;
  508.  
  509.      if (cva->Elt.Type == GL_UNSIGNED_INT)
  510.      {
  511.         elt->data = (GLuint *) cva->Elt.Ptr;
  512.         elt->stride = sizeof(GLuint);
  513.         elt->flags = 0;
  514.      } else {
  515.         elt->data = cva->store.Elt;
  516.         elt->stride = sizeof(GLuint);
  517.  
  518.         if (cva->elt_count > cva->elt_size) 
  519.         {
  520.            while (cva->elt_count > (cva->elt_size *= 2)) {};
  521.            FREE(cva->store.Elt);
  522.            cva->store.Elt = (GLuint *) MALLOC(cva->elt_size * 
  523.                           sizeof(GLuint));
  524.         }
  525.         cva->EltFunc( elt->data, &cva->Elt, 0, cva->elt_count );
  526.      }    
  527.      elt->start = VEC_ELT(elt, GLuint, 0); 
  528.      elt->count = cva->elt_count;
  529.  
  530.      fallback |= (cva->pre.new_inputs & ~ctx->Array.Summary);
  531.      enable |= fallback;
  532.      disable &= ~fallback;
  533.      if (MESA_VERBOSE&VERBOSE_PIPELINE) {
  534.         gl_print_vert_flags("*** NEW INPUTS", cva->pre.new_inputs);
  535.         gl_print_vert_flags("*** FALLBACK", fallback);
  536.      }
  537.       }
  538.  
  539.       if (enable & VERT_RGBA) 
  540.       {
  541.      GLvector4ub *col = &cva->v.Color;
  542.  
  543.      client_data = &ctx->Array.Color;
  544.      if (fallback & VERT_RGBA) client_data = &ctx->Fallback.Color;
  545.  
  546.      VB->Color[0] = VB->Color[1] = VB->ColorPtr = &cva->v.Color;
  547.       
  548.      if (client_data->Type != GL_UNSIGNED_BYTE ||
  549.          client_data->Size != 4)
  550.      {
  551.         col->data = cva->store.Color;
  552.         col->stride = 4 * sizeof(GLubyte);
  553.         ctx->Array.ColorFunc( col->data, client_data, start, n );
  554.         col->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
  555.      } else {
  556.         col->data = (GLubyte (*)[4]) client_data->Ptr;
  557.         col->stride = client_data->StrideB;
  558.         col->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
  559.         if (client_data->StrideB != 4 * sizeof(GLubyte)) 
  560.            col->flags ^= VEC_STRIDE_FLAGS;
  561.      }    
  562.      col->start = VEC_ELT(col, GLubyte, start); 
  563.      col->count = n;
  564.       }
  565.    
  566.       if (enable & VERT_INDEX) 
  567.       {
  568.      GLvector1ui *index = VB->IndexPtr = &cva->v.Index; 
  569.      VB->Index[0] = VB->Index[1] = VB->IndexPtr;
  570.  
  571.      client_data = &ctx->Array.Index;
  572.      if (fallback & VERT_INDEX) client_data = &ctx->Fallback.Index;
  573.  
  574.      if (client_data->Type != GL_UNSIGNED_INT)
  575.      {
  576.         index->data = cva->store.Index;
  577.         index->stride = sizeof(GLuint);
  578.         ctx->Array.IndexFunc( index->data, client_data, start, n );
  579.         index->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
  580.      } else {
  581.         index->data = (GLuint *) client_data->Ptr;
  582.         index->stride = client_data->StrideB;
  583.         index->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE; 
  584.         if (index->stride != sizeof(GLuint))
  585.            index->flags ^= VEC_STRIDE_FLAGS;
  586.      }    
  587.      index->count = n;
  588.      index->start = VEC_ELT(index, GLuint, start); 
  589.       }
  590.  
  591.       for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
  592.      if (enable & PIPE_TEX(i)) {
  593.         GLvector4f *tc = VB->TexCoordPtr[i] = &cva->v.TexCoord[i];
  594.  
  595.         client_data = &ctx->Array.TexCoord[i];
  596.  
  597.         if (fallback & PIPE_TEX(i)) {
  598.            client_data = &ctx->Fallback.TexCoord[i];
  599.            client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
  600.         }
  601.  
  602.         /* Writeability and stride handled lazily by
  603.          * gl_import_client_data(). 
  604.          */
  605.         if (client_data->Type == GL_FLOAT)
  606.         {
  607.            tc->data = (GLfloat (*)[4]) client_data->Ptr;
  608.            tc->stride = client_data->StrideB;
  609.            tc->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
  610.            if (tc->stride != 4 * sizeof(GLfloat)) 
  611.           tc->flags ^= VEC_STRIDE_FLAGS;
  612.         } else {
  613.            tc->data = cva->store.TexCoord[i];
  614.            tc->stride = 4 * sizeof(GLfloat);
  615.            ctx->Array.TexCoordFunc[i]( tc->data, client_data, start, n );
  616.            tc->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
  617.         }         
  618.         tc->count = n;
  619.         tc->start = VEC_ELT(tc, GLfloat, start); 
  620.         tc->size = client_data->Size;
  621.      }
  622.       
  623.       if (enable & VERT_OBJ_ANY) 
  624.       {
  625.      GLvector4f *obj = VB->ObjPtr = &cva->v.Obj;
  626.  
  627.      if (ctx->Array.Vertex.Type == GL_FLOAT)
  628.      {
  629.         obj->data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr;
  630.         obj->stride = ctx->Array.Vertex.StrideB;
  631.         obj->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
  632.         if (obj->stride != 4 * sizeof(GLfloat)) 
  633.            obj->flags ^= VEC_STRIDE_FLAGS;
  634.      } else {
  635.         obj->data = cva->store.Obj;
  636.         obj->stride = 4 * sizeof(GLfloat);
  637.         ctx->Array.VertexFunc( obj->data, &ctx->Array.Vertex, start, n );
  638.         obj->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
  639.      }
  640.      obj->count = n;
  641.      obj->start = VEC_ELT(obj, GLfloat, start);
  642.      obj->size = ctx->Array.Vertex.Size;
  643.       }
  644.  
  645.       if (enable & VERT_NORM) 
  646.       {
  647.      GLvector3f *norm = VB->NormalPtr = &cva->v.Normal;
  648.  
  649.      client_data = &ctx->Array.Normal;
  650.  
  651.      if (fallback & VERT_NORM) 
  652.         client_data = &ctx->Fallback.Normal;
  653.  
  654.      /* Never need to write to normals, and we can always cope with stride.
  655.       */
  656.      if (client_data->Type == GL_FLOAT) {
  657.         norm->data = (GLfloat (*)[3]) client_data->Ptr;
  658.         norm->stride = client_data->StrideB;
  659.      } else {
  660.         norm->data = cva->store.Normal;
  661.         norm->stride = 3 * sizeof(GLfloat);
  662.         ctx->Array.NormalFunc( norm->data, client_data, start, n );
  663.      }
  664.      norm->flags = 0;
  665.      norm->count = n;
  666.      norm->start = VEC_ELT(norm, GLfloat, start);
  667.       }
  668.  
  669.       if (enable & VERT_EDGE) 
  670.       {
  671.      GLvector1ub *edge = VB->EdgeFlagPtr = &cva->v.EdgeFlag;
  672.  
  673.      client_data = &ctx->Array.EdgeFlag;
  674.  
  675.      if (fallback & VERT_EDGE) 
  676.         client_data = &ctx->Fallback.EdgeFlag;
  677.  
  678.      edge->data = (GLboolean *) client_data->Ptr;
  679.      edge->stride = client_data->StrideB;
  680.      edge->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
  681.      if (edge->stride != sizeof(GLubyte))
  682.         edge->flags ^= VEC_STRIDE_FLAGS;
  683.  
  684.      edge->count = n;
  685.      edge->start = VEC_ELT(edge, GLubyte, start);
  686.       }
  687.    }
  688.  
  689.    if (disable) {
  690.       if (disable & VERT_RGBA) cva->v.Color = *VB->LitColor[0];
  691.       if (disable & VERT_INDEX) cva->v.Index = *VB->LitIndex[0];
  692.       if (disable & VERT_NORM) cva->v.Normal = *VB->store.Normal;
  693.       if (disable & VERT_OBJ_ANY) cva->v.Obj = *VB->store.Obj;
  694.       if (disable & VERT_TEX0_ANY) cva->v.TexCoord[0]= *(VB->store.TexCoord[0]);
  695.       if (disable & VERT_TEX0_ANY) cva->v.TexCoord[1]= *(VB->store.TexCoord[1]);
  696.       if (disable & VERT_EDGE) cva->v.EdgeFlag = *VB->store.EdgeFlag;
  697.    }
  698.       
  699.    VB->Flag[VB->Count] &= ~VERT_END_VB;
  700.    VB->Count = n;
  701.            
  702.    if (ctx->Enabled & ENABLE_LIGHT) 
  703.    {
  704.       if (ctx->Array.Flags != VB->Flag[0])
  705.      VB->FlagMax = 0;
  706.       
  707.       if (VB->FlagMax < n) {
  708.      for (i = VB->FlagMax ; i < n ; i++) 
  709.         VB->Flag[i] = ctx->Array.Flags;
  710.      VB->Flag[i] = 0;
  711.      VB->FlagMax = n;
  712.       }
  713.  
  714.       VB->Flag[n] |= VERT_END_VB;
  715.    }
  716. }
  717.  
  718. void gl_cva_force_precalc( GLcontext *ctx )
  719. {
  720.    struct gl_cva *cva = &ctx->CVA;
  721.  
  722.    if (cva->pre.changed_ops) 
  723.       gl_reset_cva_vb( cva->VB, cva->pre.changed_ops );
  724.  
  725.    gl_run_pipeline( cva->VB );
  726.  
  727.    ctx->Array.NewArrayState = 0;
  728. }
  729.  
  730.  
  731. /* Simplified: just make sure the pipelines are valid.
  732.  */
  733. void gl_cva_compile_cassette( GLcontext *ctx, struct immediate *IM )
  734. {
  735.    struct gl_cva *cva = &ctx->CVA;
  736.    cva->orflag |= IM->OrFlag;
  737.  
  738.    /* Allow pipeline recalculation based on inputs received from client.
  739.     */
  740.    if (IM->OrFlag & (cva->pre.forbidden_inputs|cva->elt.forbidden_inputs)) 
  741.    {
  742.       if (IM->OrFlag & cva->pre.forbidden_inputs) 
  743.       {
  744.      cva->pre.pipeline_valid = 0;
  745.      cva->pre.data_valid = 0;
  746.      cva->pre.forbidden_inputs = 0;
  747.       }
  748.  
  749.       if ((IM->OrFlag & cva->elt.forbidden_inputs))
  750.       {
  751.      cva->elt.forbidden_inputs = 0;
  752.       }
  753.  
  754.       cva->elt.pipeline_valid = 0;
  755.    }
  756.  
  757.    /* Recalculate CVA data if necessary.
  758.     */
  759.    if (ctx->CompileCVAFlag && !cva->pre.data_valid) 
  760.    {
  761.       if (!cva->pre.pipeline_valid) 
  762.      gl_build_precalc_pipeline( ctx );
  763.    
  764.       gl_cva_force_precalc( ctx );
  765.    }
  766.  
  767.    /* Build immediate pipeline if necessary.
  768.     */
  769.    if (!cva->elt.pipeline_valid)
  770.       gl_build_immediate_pipeline( ctx );
  771.  
  772.    gl_fixup_input( ctx, IM );
  773.    gl_execute_cassette( ctx, IM );      
  774. }
  775.  
  776.  
  777. void gl_cva_init( GLcontext *ctx )
  778. {
  779.    (void) ctx;
  780. }
  781.