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

  1. /* $Id: vbxform.c,v 1.18.2.2 1999/12/12 18:30:14 keithw 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.  
  28.  
  29. #ifdef PC_HEADER
  30. #include "all.h"
  31. #else
  32. #ifndef XFree86Server
  33. #include <math.h>
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #else
  37. #include "GL/xf86glx.h"
  38. #endif
  39. #include "context.h"
  40. #include "cva.h"
  41. #include "clip.h"
  42. #include "eval.h"
  43. #include "enums.h"
  44. #include "dlist.h"
  45. #include "fog.h"
  46. #include "light.h"
  47. #include "macros.h"
  48. #include "matrix.h"
  49. #include "mmath.h"
  50. #include "pipeline.h"
  51. #include "shade.h"
  52. #include "texture.h"
  53. #include "types.h"
  54. #include "varray.h"
  55. #include "vb.h"
  56. #include "vbcull.h"
  57. #include "vbfill.h"
  58. #include "vbrender.h"
  59. #include "vbxform.h"
  60. #include "xform.h"
  61. #endif
  62.  
  63.  
  64. void gl_maybe_transform_vb( struct immediate *IM )
  65. {
  66.    GLcontext *ctx = IM->backref;
  67.  
  68.    if (ctx->NewState)
  69.       gl_update_state(ctx);
  70.  
  71.    if (IM->FlushElt) {
  72.       gl_exec_array_elements( ctx, IM, IM->LastPrimitive, IM->Count );
  73.       IM->FlushElt = 0;
  74.    }
  75.  
  76.    gl_compute_orflag( IM );
  77.  
  78.    if (ctx->ExecuteFlag) 
  79.       gl_cva_compile_cassette( ctx, IM );
  80.    else
  81.       gl_fixup_input( ctx, IM );
  82.    
  83.    if (ctx->CompileFlag) 
  84.       gl_compile_cassette( ctx );
  85.    else
  86.       gl_reset_input( ctx );
  87. }
  88.  
  89.  
  90. void gl_flush_vb( GLcontext *ctx, const char *where )
  91. {
  92.    struct immediate *IM = ctx->input;
  93.  
  94.    if (MESA_VERBOSE&VERBOSE_PIPELINE)
  95.       fprintf(stderr, "gl_flush_vb: %s\n", where);
  96.  
  97.    gl_maybe_transform_vb( IM );
  98. }
  99.  
  100. /* Drivers can call this inside their swapbuffers routines:
  101.  */
  102. void gl_internal_flush( GLcontext *ctx )
  103. {
  104.    FLUSH_VB( ctx, "internal flush" );
  105. }
  106.  
  107.  
  108. #define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)  
  109.  
  110. /* 
  111.  *
  112.  */
  113. void gl_reset_vb( struct vertex_buffer *VB )
  114. {
  115.    GLuint copy;
  116.    GLuint dst;
  117.    GLuint start;
  118.    struct immediate *IM = VB->IM;
  119.    GLubyte clipor = VB->ClipOrMask;
  120.  
  121.    if (!VB->CullDone)
  122.       gl_fast_copy_vb( VB );
  123.       
  124.    copy = VB->CopyCount;
  125.    start = 3-copy;
  126.  
  127.    VB->CopyStart = start;
  128.    VB->ClipOrMask = 0;
  129.    VB->ClipAndMask = CLIP_ALL_BITS;
  130.  
  131.    if (IM) 
  132.    {
  133.       if (VB->Count != IM->Count && 0) {
  134.      fprintf(stderr, "Trying to copy vertices in the middle of an IM (%d/%d)!!\n",
  135.          VB->Count, IM->Count);
  136.       }
  137.       else if (VB->pipeline->copy_transformed_data) {
  138.  
  139.      for (dst = start ; dst < VB_START ; dst++) 
  140.      {
  141.         GLuint src = VB->Copy[dst];
  142.         
  143.         if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  144.            fprintf(stderr, "copying vertex %u to %u\n", src, dst);
  145.         
  146.         COPY_4FV( VB->Clip.data[dst], VEC_ELT(VB->ClipPtr, GLfloat, src) ); 
  147.         COPY_4FV( VB->Win.data[dst], VB->Win.data[src] ); 
  148.         
  149.         VB->UserClipMask[dst] = VB->UserClipMask[src];
  150.         VB->ClipMask[dst] = (GLubyte) (VB->ClipMask[src] & ~CLIP_CULLED_BIT);
  151.         VB->ClipAndMask &= VB->ClipMask[dst];
  152.         VB->ClipOrMask  |= VB->ClipMask[dst];
  153.         VB->ClipMask[src] = 0;    /* hack for bounds_cull_vb */
  154.  
  155.         COPY_4UBV( IM->Color[dst], IM->Color[src] );
  156.         COPY_4UBV( VB->Spec[0][dst], VB->Spec[0][src] );
  157.         COPY_4UBV( VB->Spec[1][dst], VB->Spec[1][src] );
  158.         COPY_4UBV( VB->BColor.data[dst], VB->BColor.data[src] );
  159.         IM->Index[dst] = IM->Index[src];
  160.         VB->BIndex.data[dst] = VB->BIndex.data[src];
  161.  
  162.         if (VB->TexCoordPtr[0] == &IM->v.TexCoord[0])
  163.            COPY_4FV( IM->TexCoord[0][dst], IM->TexCoord[0][src] );
  164.         
  165.         if (VB->TexCoordPtr[1] == &IM->v.TexCoord[1])
  166.            COPY_4FV( IM->TexCoord[1][dst], IM->TexCoord[1][src] );
  167.  
  168.         IM->Elt[dst] = IM->Elt[src];
  169.         VB->SavedOrFlag |= IM->Flag[src];
  170.      } 
  171.       }
  172.       
  173.       VB->CullDone = 0;
  174.    }
  175.  
  176.    if (clipor & CLIP_USER_BIT) 
  177.       MEMSET(VB->UserClipMask + VB->Start, 0, VB->Count);
  178.  
  179.    VB->NormCullStart = 0;
  180.    VB->Parity = (VB->LastPrimitive^VB->Count)&1;
  181.    VB->PurgeFlags = 0;
  182.    VB->EarlyCull = 1;
  183.    VB->Culled = 0;
  184.    VB->BoundsPtr = 0;
  185.    VB->NormalLengthPtr = 0;  
  186.    VB->Indirect = 0;
  187.    VB->Culled = 0;
  188. }
  189.  
  190.  
  191.  
  192.  
  193. /* Copy the untransformed parts of the overlapping vertices from one
  194.  * immediate struct to another (or possibly the same one).  
  195.  *
  196.  * Only copy those elements which are genuinely untransformed.  Others
  197.  * are done in gl_reset_vb.
  198.  */
  199. void gl_copy_prev_vertices( struct vertex_buffer *VB,
  200.                 struct immediate *prev,
  201.                 struct immediate *next )
  202. {
  203.    GLuint dst;
  204.    GLuint flags = VB->pipeline->inputs;
  205.  
  206.    if (MESA_VERBOSE&VERBOSE_CULL)
  207.       fprintf(stderr, "copy prev vertices im: prev %d next %d copystart %d\n", 
  208.           prev->id, next->id, VB->CopyStart);
  209.  
  210.    /* VB_START is correct as vertex copying is only required when an
  211.     * IM wraps, which means that the next VB must start at VB_START.
  212.     */
  213.    for (dst = VB->CopyStart ; dst < VB_START ; dst++) 
  214.    {
  215.       GLuint src = VB->Copy[dst];
  216.  
  217.       if (MESA_VERBOSE&VERBOSE_CULL)
  218.      fprintf(stderr, "copy_prev: copy %d to %d\n", src, dst );
  219.  
  220.       COPY_4FV( next->Obj[dst], prev->Obj[src] );
  221.  
  222.       if ((flags&VERT_TEX0_ANY) && VB->TexCoordPtr[0] == &prev->v.TexCoord[0])
  223.      COPY_4FV( next->TexCoord[0][dst], prev->TexCoord[0][src] );
  224.         
  225.       if ((flags&VERT_TEX1_ANY) && VB->TexCoordPtr[1] == &prev->v.TexCoord[1])
  226.      COPY_4FV( next->TexCoord[1][dst], prev->TexCoord[1][src] );
  227.  
  228.       COPY_4UBV( next->Color[dst], prev->Color[src] );
  229.       next->Index[dst] = prev->Index[src];
  230.       next->EdgeFlag[dst] = prev->EdgeFlag[src];
  231.  
  232.       next->Elt[dst] = prev->Elt[src];
  233.       VB->SavedOrFlag |= prev->Flag[src];
  234.    }
  235. }
  236.  
  237.  
  238.  
  239. void RESET_IMMEDIATE( GLcontext *ctx ) 
  240. {
  241.    if (ctx->VB->prev_buffer != ctx->VB->IM) {
  242.       /* Should only get here if we are trying to use the internal
  243.        * interfaces, eg gl_Vertex3f(), gl_Begin() from inside a
  244.        * display list.  In this case, it is necessary to pull the
  245.        * current values into the ctx->VB.store buffer, because this
  246.        * may not have been done.
  247.        */
  248.       FLUSH_VB( ctx, "RESET_IMMEDIATE" );
  249.       gl_reset_input( ctx );
  250.    }
  251. }
  252.  
  253.  
  254. /* Called to initialize new buffers, and to recycle old ones.
  255.  */
  256. void gl_reset_input( GLcontext *ctx )
  257. {
  258.    struct immediate *IM = ctx->input;
  259.  
  260.    MEMSET(IM->Flag, 0, sizeof(GLuint) * (IM->Count+2));
  261.    IM->Start = VB_START;
  262.    IM->Count = VB_START;
  263.    
  264.    IM->Primitive[IM->Start] = ctx->Current.Primitive;
  265.    IM->LastPrimitive = IM->Start;
  266.    IM->BeginState = VERT_BEGIN_0;         
  267.    IM->OrFlag = 0;
  268.    IM->AndFlag = ~0U;
  269.  
  270.    if (0)
  271.       fprintf(stderr, 
  272.        "in reset_input(IM %d), BeginState is %x, setting prim[%d] to %s\n", 
  273.        IM->id,
  274.        VERT_BEGIN_0,
  275.        IM->Start, gl_lookup_enum_by_nr(ctx->Current.Primitive));
  276.  
  277.    IM->ArrayAndFlags = ~ctx->Array.Flags;
  278.    IM->ArrayIncr = ctx->Array.Vertex.Enabled;
  279.    IM->ArrayEltFlush = !(ctx->CompileCVAFlag);
  280. }
  281.  
  282.  
  283. /* Preserves size information as well.
  284.  */
  285. static void 
  286. fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
  287. {
  288.    GLuint i = start;
  289.  
  290.    for (;;) {
  291.       if ((flag[++i] & match) == 0) {
  292.      COPY_4FV(data[i], data[i-1]);
  293.      flag[i] |= (flag[i-1] & match);
  294.      if (flag[i] & VERT_END_VB) break;
  295.       } 
  296.    }
  297. }
  298.  
  299.  
  300.  
  301. /* Only needed for buffers with eval coords.
  302.  */
  303. static void
  304. fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
  305. {
  306.    GLuint i = start;
  307.  
  308.    for (;;) {
  309.       if ((flag[++i] & match) == 0) {
  310.      COPY_3V(data[i], data[i-1]);
  311.      flag[i] |= match;
  312.      if (flag[i] & VERT_END_VB) break;
  313.       } 
  314.    }
  315. }
  316.  
  317.  
  318. static void
  319. fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
  320. {
  321.    GLuint i = start;
  322.  
  323.    for (;;) {
  324.       if ((flag[++i] & match) == 0) {
  325.      data[i] = data[i-1];
  326.      if (flag[i] & VERT_END_VB) break;
  327.       } 
  328.    }
  329.    flag[i] |= match;
  330. }
  331.  
  332. static void
  333. fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
  334. {
  335.    GLuint i = start;
  336.  
  337.    for (;;) {
  338.       if ((flag[++i] & match) == 0) {
  339.      data[i] = data[i-1];
  340.      if (flag[i] & VERT_END_VB) break;
  341.       } 
  342.    }
  343.    flag[i] |= match;
  344. }
  345.  
  346.  
  347. static void
  348. fixup_4ub( GLubyte data[][4], GLuint flag[], GLuint start, GLuint match )
  349. {
  350.    GLuint i = start;
  351.  
  352.    for (;;) {
  353.       if ((flag[++i] & match) == 0) {
  354.      COPY_4UBV(data[i], data[i-1]);
  355.      if (flag[i] & VERT_END_VB) break;
  356.       } 
  357.    }
  358.    flag[i] |= match;
  359. }
  360.  
  361.  
  362. /* Do this instead of fixup for shared normals.
  363.  */
  364. static void
  365. find_last_3f( float data[][3], GLuint flag[], GLuint match, GLuint count )
  366. {
  367.    GLuint i = count;
  368.  
  369.    for (;;) 
  370.       if ((flag[--i] & match) != 0) {
  371.      COPY_3V(data[count], data[i]);     
  372.      return;      
  373.       }
  374. }
  375.  
  376. static void
  377. fixup_first_4v( GLfloat data[][4], GLuint flag[], GLuint match, 
  378.         GLuint start, GLfloat *dflt )
  379. {
  380.    GLuint i = start-1;
  381.    match |= VERT_END_VB;
  382.  
  383.    while ((flag[++i]&match) == 0)
  384.       COPY_4FV(data[i], dflt);
  385. }
  386.  
  387.  
  388. static void
  389. fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
  390.          GLuint start, GLuint dflt )
  391. {
  392.    GLuint i = start-1;
  393.    match |= VERT_END_VB;
  394.  
  395.    while ((flag[++i]&match) == 0)
  396.       data[i] = dflt;
  397. }
  398.  
  399.  
  400. static void
  401. fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
  402.          GLuint start, GLubyte dflt )
  403. {
  404.    GLuint i = start-1;
  405.    match |= VERT_END_VB;
  406.  
  407.    while ((flag[++i]&match) == 0)
  408.       data[i] = dflt;
  409. }
  410.  
  411.  
  412. static void
  413. fixup_first_4ub( GLubyte data[][4], GLuint flag[], GLuint match,
  414.          GLuint start, GLubyte dflt[4] )
  415. {
  416.    GLuint i = start-1;
  417.    match |= VERT_END_VB;
  418.  
  419.    while ((flag[++i]&match) == 0)
  420.       COPY_4UBV(data[i], dflt);
  421. }
  422.  
  423.  
  424.  
  425.  
  426. static GLuint vertex_sizes[16] = { 0, 
  427.                    1, 
  428.                    2, 2, 
  429.                    3, 3, 3, 3, 
  430.                    4, 4, 4, 4, 4, 4, 4, 4 };
  431.  
  432.  
  433.  
  434. GLuint gl_texcoord_size( GLuint flag, GLuint unit )
  435. {
  436.    flag >>= VERT_TEX0_SHIFT + unit * NR_TEXSIZE_BITS;
  437.    return vertex_sizes[flag & 0xf];
  438. }
  439.  
  440.  
  441. static void set_vec_sizes( struct immediate *IM, GLuint orflag )
  442. {
  443.    GLuint i;
  444.  
  445.    if (orflag & VERT_OBJ_ANY) {
  446.       GLuint szflag = orflag & VERT_OBJ_234;
  447.       IM->v.Obj.size = vertex_sizes[szflag<<1];
  448.    }
  449.  
  450.    for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) {
  451.       if (orflag & VERT_TEX_ANY(i)) {
  452.      GLuint szflag = ((orflag>>(VERT_TEX0_SHIFT+i*NR_TEXSIZE_BITS))
  453.               & 0xf);
  454.      IM->v.TexCoord[i].size = vertex_sizes[szflag];
  455.       }
  456.    }
  457. }
  458.  
  459.  
  460. void gl_compute_orflag( struct immediate *IM )
  461. {
  462.    GLuint count = IM->Count;
  463.    GLuint orflag = 0;
  464.    GLuint andflag = ~0U;
  465.    GLuint i;
  466.  
  467.    IM->LastData = count-1;
  468.  
  469.    /* Compute the flags for the whole buffer, even if 
  470.     */
  471.    for (i = IM->Start ; i < count ; i++) {
  472.       andflag &= IM->Flag[i];
  473.       orflag |= IM->Flag[i];
  474.    }
  475.  
  476.    if (IM->Flag[i] & VERT_DATA) {
  477.       IM->LastData++;
  478. /*        andflag &= IM->Flag[i]; */    /* possibly incorrect (norm_bug.c) */
  479.       orflag |= IM->Flag[i];
  480.    }      
  481.  
  482.    IM->Flag[IM->LastData+1] |= VERT_END_VB;
  483.    IM->AndFlag = andflag;
  484.    IM->OrFlag = orflag;
  485. }
  486.  
  487. void gl_fixup_input( GLcontext *ctx, struct immediate *IM )
  488. {
  489.    GLuint count = IM->Count;
  490.    GLuint start = IM->Start;
  491.    GLuint fixup, diff;
  492.    GLuint andflag = IM->AndFlag;
  493.    GLuint orflag = IM->OrFlag;
  494.  
  495.    IM->Primitive[count] = IM->Primitive[IM->LastPrimitive];
  496.    IM->NextPrimitive[IM->LastPrimitive] = count;
  497.    IM->NextPrimitive[count] = count+1;
  498.  
  499.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE) 
  500.    {
  501.       fprintf(stderr, "Start: %u Count: %u LastData: %u\n", 
  502.           IM->Start, IM->Count, IM->LastData);
  503.       gl_print_vert_flags("Orflag", orflag);
  504.       gl_print_vert_flags("Andflag", andflag);
  505.    }
  506.  
  507.    /* Array elements modify the current state - must do this before
  508.     * fixup.
  509.     */
  510.    if (ctx->CompileCVAFlag && !(andflag & VERT_ELT)) 
  511.       gl_rescue_cva( ctx, IM );
  512.  
  513.    if (orflag & VERT_ELT) 
  514.    {
  515.       orflag = IM->OrFlag;
  516.       andflag = IM->AndFlag;
  517.       start = IM->Start;
  518.    }
  519.    
  520.    fixup = ~andflag & VERT_FIXUP;
  521.  
  522.    if (!ctx->CompileFlag) 
  523.       fixup &= ctx->CVA.elt.inputs; 
  524.    
  525.    if (!ctx->ExecuteFlag)
  526.       fixup &= orflag;
  527.  
  528.    if (ctx->CompileCVAFlag)
  529.       fixup &= ~ctx->CVA.pre.outputs;
  530.  
  531.    if ((orflag & (VERT_OBJ_ANY|VERT_EVAL_ANY)) == 0)
  532.       fixup = 0;
  533.  
  534.    if (fixup) 
  535.    {
  536.  
  537.       if (ctx->ExecuteFlag && (fixup & ~IM->Flag[start])) {
  538.      GLuint copy = fixup & ~IM->Flag[start];
  539.  
  540.      if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  541.         gl_print_vert_flags("copy from current", copy);
  542.      
  543.      if (copy & VERT_NORM) 
  544.         COPY_3V( IM->Normal[start], ctx->Current.Normal );
  545.      
  546.      if (copy & VERT_RGBA)
  547.         COPY_4UBV( IM->Color[start], ctx->Current.ByteColor);
  548.       
  549.      if (copy & VERT_INDEX)
  550.         IM->Index[start] = ctx->Current.Index;
  551.      
  552.      if (copy & VERT_EDGE)
  553.         IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
  554.  
  555.      if (copy & VERT_TEX0_ANY)
  556.         COPY_4FV( IM->TexCoord[0][start], ctx->Current.Texcoord[0] ); 
  557.      
  558.      if (copy & VERT_TEX1_ANY)
  559.         COPY_4FV( IM->TexCoord[1][start], ctx->Current.Texcoord[1] ); 
  560.       }
  561.  
  562.  
  563.       if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  564.      gl_print_vert_flags("fixup", fixup);
  565.       
  566.       if (fixup & VERT_TEX0_ANY) {
  567.      if (orflag & VERT_TEX0_ANY)
  568.         fixup_4f( IM->TexCoord[0], IM->Flag, start, VERT_TEX0_1234 );
  569.      else 
  570.         fixup_first_4v( IM->TexCoord[0], IM->Flag, 0, start, 
  571.                 IM->TexCoord[0][start]);
  572.       }
  573.  
  574.       if (fixup & VERT_TEX1_ANY) {
  575.      if (orflag & VERT_TEX1_ANY)
  576.         fixup_4f( IM->TexCoord[1], IM->Flag, start, VERT_TEX1_1234 );
  577.      else 
  578.         fixup_first_4v( IM->TexCoord[1], IM->Flag, 0, start, 
  579.                 IM->TexCoord[1][start] );
  580.       }
  581.  
  582.       if (fixup & VERT_EDGE) {
  583.      if (orflag & VERT_EDGE)
  584.         fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
  585.      else 
  586.         fixup_first_1ub( IM->EdgeFlag, IM->Flag, 0, start, 
  587.                  IM->EdgeFlag[start] );
  588.       }
  589.  
  590.       if (fixup & VERT_INDEX) {
  591.      if (orflag & VERT_INDEX)
  592.         fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
  593.      else 
  594.         fixup_first_1ui( IM->Index, IM->Flag, 0, start, IM->Index[start] );
  595.       }
  596.  
  597.       if (fixup & VERT_RGBA) {
  598.      if (orflag & VERT_RGBA) 
  599.         fixup_4ub( IM->Color, IM->Flag, start, VERT_RGBA );      
  600.      else 
  601.         fixup_first_4ub( IM->Color, IM->Flag, 0, start, IM->Color[start] );
  602.       }
  603.  
  604.       if (fixup & VERT_NORM) {
  605.      /* Only eval cannot use the Flag member to find valid normals:
  606.       */
  607.      if (IM->OrFlag & VERT_EVAL_ANY)
  608.         fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
  609.      else {
  610.         /* Copy-to-current requires a valid normal in the last slot:
  611.          */
  612.         if ((IM->OrFlag & VERT_NORM) &&
  613.         !(IM->Flag[IM->LastData] & VERT_NORM)) 
  614.            find_last_3f( IM->Normal, IM->Flag, VERT_NORM, IM->LastData );
  615.      }
  616.       }
  617.    }
  618.  
  619.    diff = count - start;
  620.    IM->v.Obj.count = diff;
  621.    IM->v.Normal.count = diff;
  622.    IM->v.TexCoord[0].count = diff;
  623.    IM->v.TexCoord[1].count = diff;
  624.    IM->v.EdgeFlag.count = diff;
  625.    IM->v.Color.count = diff;
  626.    IM->v.Index.count = diff;
  627.  
  628.    /* Prune possible half-filled slot.
  629.     */
  630.    IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
  631.    IM->Flag[IM->Count] |= VERT_END_VB;
  632. }
  633.  
  634.  
  635. static void calc_normal_lengths( GLfloat *dest, 
  636.                  CONST GLfloat (*data)[3],
  637.                  const GLuint *flags,
  638.                  GLuint count )
  639. {
  640.    GLuint i;
  641.  
  642.    for (i = 0 ; i < count ; i++ )
  643.       if (flags[i] & VERT_NORM) {
  644.      GLfloat tmp = (GLfloat) LEN_3FV( data[i] );
  645.      dest[i] = 0;
  646.      if (tmp > 0)
  647.         dest[i] = 1.0F / tmp;
  648.       }      
  649. }
  650.  
  651.  
  652. /* Revive a compiled immediate struct - propogate new 'Current'
  653.  * values.  Often this is redundant because the current values were
  654.  * known and fixed up at compile time.
  655.  */
  656. void gl_fixup_cassette( GLcontext *ctx, struct immediate *IM )
  657. {
  658.    GLuint fixup;
  659.    GLuint count = IM->Count;
  660.    GLuint start = IM->Start;
  661.    
  662.    if (count == start) 
  663.       return;
  664.  
  665.    if (ctx->NewState)
  666.       gl_update_state( ctx );
  667.  
  668.  
  669.    if (ctx->Transform.Normalize && IM->LastCalcedLength < IM->Count) {
  670.       GLuint start = IM->LastCalcedLength;
  671.  
  672.       if (!IM->NormalLengths)
  673.      IM->NormalLengths = (GLfloat *)MALLOC(sizeof(GLfloat) * VB_SIZE);
  674.  
  675.       calc_normal_lengths( IM->NormalLengths + start, 
  676.                (const GLfloat (*)[3])(IM->Normal + start), 
  677.                IM->Flag + start, 
  678.                IM->Count - start);
  679.       
  680.       IM->LastCalcedLength = IM->Count;
  681.    }
  682.  
  683.    fixup = ctx->CVA.elt.inputs & ~IM->AndFlag & VERT_FIXUP;
  684.  
  685.    if (fixup) {
  686.  
  687.       if (MESA_VERBOSE & VERBOSE_IMMEDIATE) {
  688.      fprintf(stderr, "start: %d count: %d\n", start, count);
  689.      gl_print_vert_flags("fixup_cassette", fixup);
  690.       }
  691.  
  692.       if (fixup & VERT_TEX0_ANY) 
  693.      fixup_first_4v( IM->TexCoord[0], IM->Flag, VERT_TEX0_ANY, start,
  694.              ctx->Current.Texcoord[0] );
  695.  
  696.       if (fixup & VERT_TEX1_ANY) 
  697.      fixup_first_4v( IM->TexCoord[1], IM->Flag, VERT_TEX1_ANY, start,
  698.              ctx->Current.Texcoord[1] );
  699.  
  700.       if (fixup & VERT_EDGE)
  701.      fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGE, start,
  702.              ctx->Current.EdgeFlag );
  703.  
  704.       if (fixup & VERT_INDEX)
  705.      fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
  706.              ctx->Current.Index );
  707.    
  708.       if (fixup & VERT_RGBA) 
  709.      fixup_first_4ub(IM->Color, IM->Flag, VERT_RGBA, start,
  710.              ctx->Current.ByteColor );      
  711.  
  712.       if ((fixup & VERT_NORM) && !(IM->Flag[start] & VERT_NORM)) {
  713.      COPY_3V(IM->Normal[start], ctx->Current.Normal);
  714.      if (ctx->Transform.Normalize)
  715.         IM->NormalLengths[start] = 1.0F / (GLfloat) LEN_3FV(ctx->Current.Normal);
  716.       }
  717.    }  
  718. }
  719.  
  720.  
  721.  
  722. static void fixup_primitives( struct vertex_buffer *VB, struct immediate *IM )
  723. {
  724.    static GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
  725.    static GLuint intro[GL_POLYGON+2]     = { 0,0,2,2,0,2,2,0,2,2,0 };
  726.    GLcontext *ctx = VB->ctx;
  727.    const GLuint *flags = IM->Flag;
  728.    const GLuint *in_prim = IM->Primitive;
  729.    const GLuint *in_nextprim = IM->NextPrimitive;
  730.    GLuint *out_prim = VB->IM->Primitive;
  731.    GLuint *out_nextprim = VB->IM->NextPrimitive;
  732.    GLuint count = VB->Count;
  733.    GLuint start = VB->Start;
  734.    GLuint in, out, last;
  735.    GLuint incr, prim;   
  736.    GLuint transition;
  737.    GLuint interesting;
  738.    GLuint err;
  739.    
  740. /*     printf("IM: %d VB->Count %d VB->Start %d current prim: %d\n", IM->id, VB->Count, VB->Start, ctx->Current.Primitive);  */
  741.  
  742.    if (ctx->Current.Primitive == GL_POLYGON+1) {
  743.       transition = VERT_BEGIN;
  744.       err = IM->BeginState & VERT_ERROR_1;
  745.    } else {
  746.       transition = VERT_END;
  747.       err = IM->BeginState & VERT_ERROR_0;
  748.    }
  749.  
  750.    if (err) {
  751.       /* Occurred somewhere inside the vb.  Don't know/care where/why.
  752.        */
  753.       gl_error( ctx, GL_INVALID_OPERATION, "begin/end");
  754.    }
  755.  
  756.    interesting = transition | VERT_END_VB;
  757.  
  758.  
  759.    for (in = start ; in <= count ; in = in_nextprim[in]) 
  760.       if (flags[in] & interesting) 
  761.      break;
  762.  
  763.    out = VB->CopyStart;
  764.  
  765.    if (in == out) {
  766.       out_nextprim[out] = in_nextprim[in];
  767.       out_prim[out] = in_prim[in];
  768.       last = IM->LastPrimitive;
  769.    } else if (flags[in] & transition) {
  770.       out_nextprim[out] = in;
  771.       out_prim[out] = ctx->Current.Primitive;
  772.       out = in;
  773.       last = IM->LastPrimitive;
  774.    } else {
  775.       out_nextprim[out] = in;
  776.       out_prim[out] = ctx->Current.Primitive;
  777.       in++;
  778.       last = out;
  779.    }
  780.  
  781.    for ( ; in <= count ; in = in_nextprim[in] ) {
  782.       out_prim[in] = in_prim[in];
  783.       out_nextprim[in] = in_nextprim[in];
  784.    }
  785.       
  786.  
  787.    VB->Primitive = out_prim;
  788.    VB->NextPrimitive = out_nextprim;
  789.    VB->LastPrimitive = last;
  790.    prim = ctx->Current.Primitive = (GLenum) out_prim[last];
  791.  
  792.  
  793.    /* Calculate whether the primitive finished on a 'good number' of
  794.     * vertices, or whether there are overflowing vertices we have to
  795.     * copy to the next buffer (in addition to the normal ones required
  796.     * by a continuing primitive).
  797.     *
  798.     * Note that GL_POLYGON+1, ie outside begin/end, has increment 1.
  799.     */
  800.  
  801.    incr = increment[prim];
  802.   
  803.    if (incr != 1 && (count - last - intro[prim])) 
  804.       VB->Ovf = (count - last - intro[prim]) % incr; 
  805.    else
  806.       VB->Ovf = 0;
  807.  
  808.    if (0) 
  809.       fprintf(stderr, "prim: %s count %u last %u incr %u ovf: %u\n",
  810.           gl_prim_name[prim], count, last, incr, VB->Ovf);
  811. }
  812.  
  813.  
  814. void gl_copy_to_current( GLcontext *ctx, struct immediate *IM )
  815. {
  816.    GLuint count = IM->LastData;
  817.    GLuint flag = IM->OrFlag;
  818.    GLuint mask = 0;
  819.  
  820.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  821.       gl_print_vert_flags("copy to current", flag);
  822.  
  823.    if (flag & VERT_NORM) 
  824.       COPY_3FV( ctx->Current.Normal, IM->Normal[count]);   
  825.    
  826.    if (flag & VERT_INDEX)
  827.       ctx->Current.Index = IM->Index[count];
  828.  
  829.    if (flag & VERT_EDGE)
  830.       ctx->Current.EdgeFlag = IM->EdgeFlag[count];
  831.  
  832.    if (flag & VERT_RGBA) 
  833.       COPY_4UBV(ctx->Current.ByteColor, IM->Color[count]);
  834.  
  835.    if (flag & VERT_TEX0_ANY) {
  836.       mask |= VERT_TEX0_1234;
  837.       COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]);
  838.    }
  839.       
  840.    if (flag & VERT_TEX1_ANY) {
  841.       mask |= VERT_TEX1_1234;
  842.       COPY_4FV( ctx->Current.Texcoord[1], IM->TexCoord[1][count]);
  843.    }
  844.  
  845.    /* Save the texcoord size information as well.
  846.     */
  847.    ctx->Current.Flag &= ~mask;
  848.    ctx->Current.Flag |= IM->Flag[count] & mask;
  849. }
  850.  
  851.  
  852. void gl_execute_cassette( GLcontext *ctx, struct immediate *IM )
  853. {
  854.    struct vertex_buffer *VB = ctx->VB;
  855.    struct immediate *prev = VB->prev_buffer;
  856.    GLuint vec_start, diff;
  857.  
  858.    IM->ref_count++;
  859.  
  860.    if (prev != IM || IM != VB->IM) {
  861.       gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
  862.    }
  863.  
  864.    if (! --prev->ref_count ) 
  865.       gl_immediate_free( prev );
  866.  
  867.    VB->prev_buffer = IM;
  868.    VB->Start = IM->Start;
  869.    VB->Count = IM->Count;
  870.    VB->Flag = IM->Flag;
  871.    VB->OrFlag = IM->OrFlag | VB->SavedOrFlag;
  872.    VB->EltPtr = &IM->v.Elt;
  873.    VB->MaterialMask = IM->MaterialMask;
  874.    VB->Material = IM->Material;
  875.    VB->CullMode = (GLubyte) ((IM->AndFlag & VERT_NORM) ? 0 : COMPACTED_NORMALS);
  876.    VB->ObjPtr = &IM->v.Obj;
  877.    VB->NormalPtr = &IM->v.Normal;
  878.    VB->ColorPtr = &IM->v.Color;
  879.    VB->Color[0] = VB->Color[1] = VB->ColorPtr;
  880.    VB->IndexPtr = &IM->v.Index;
  881.    VB->EdgeFlagPtr = &IM->v.EdgeFlag;
  882.    VB->TexCoordPtr[0] = &IM->v.TexCoord[0];
  883.    VB->TexCoordPtr[1] = &IM->v.TexCoord[1];
  884. /*     VB->BoundsPtr = IM->Bounds; */
  885.    VB->NormalLengthPtr = IM->NormalLengths;
  886.    VB->IndirectCount = VB->Count;
  887.    VB->SavedOrFlag = 0;
  888.  
  889.    if (IM->Start != VB_START)
  890.       VB->CopyStart = IM->Start;
  891.  
  892.    vec_start = IM->Start;
  893.    if (vec_start == VB_START && VB->pipeline->replay_copied_vertices)
  894.       vec_start = VB->CopyStart;
  895.  
  896.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  897.       fprintf(stderr, "reseting vectors to %d/%d .. %d\n", vec_start, IM->Start, IM->Count);
  898.  
  899.    VB->LastPrimitive = IM->Start; 
  900.  
  901.    diff = IM->Count - vec_start;
  902.  
  903.    RESET_VEC(IM->v.Obj, (GLfloat *), vec_start, diff);
  904.    RESET_VEC(IM->v.Normal, (GLfloat *), vec_start, diff);
  905.    RESET_VEC(IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
  906.    RESET_VEC(IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
  907.    RESET_VEC(IM->v.Index, &, vec_start, diff);
  908.    RESET_VEC(IM->v.Elt, &, vec_start, diff);
  909.    RESET_VEC(IM->v.EdgeFlag, &, vec_start, diff);
  910.    RESET_VEC(IM->v.Color, (GLubyte *), vec_start, diff);
  911.    RESET_VEC(VB->Clip, (GLfloat *), vec_start, diff);
  912.    RESET_VEC(VB->Eye, (GLfloat *), vec_start, diff);
  913.    RESET_VEC(VB->Win, (GLfloat *), vec_start, diff);
  914.    RESET_VEC(VB->BColor, (GLubyte *), vec_start, diff); 
  915.    RESET_VEC(VB->BIndex, &, vec_start, diff);
  916.  
  917.    if (IM != VB->IM) {
  918.       RESET_VEC(VB->IM->v.Obj, (GLfloat *), vec_start, diff);
  919.       RESET_VEC(VB->IM->v.Normal, (GLfloat *), vec_start, diff);
  920.       RESET_VEC(VB->IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
  921.       RESET_VEC(VB->IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
  922.       RESET_VEC(VB->IM->v.Index, &, vec_start, diff);
  923.       RESET_VEC(VB->IM->v.Elt, &, vec_start, diff);
  924.       RESET_VEC(VB->IM->v.EdgeFlag, &, vec_start, diff);
  925.       RESET_VEC(VB->IM->v.Color, (GLubyte *), vec_start, diff);
  926.    }
  927.  
  928.    gl_copy_to_current( ctx, IM );
  929.  
  930.    set_vec_sizes( IM, VB->OrFlag );
  931.  
  932.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE) 
  933.       fprintf(stderr,
  934.           "executing cassette, rows %u tc0->size == %u tc1->size == %u\n",
  935.           VB->Count,
  936.           VB->TexCoordPtr[0]->size,
  937.           VB->TexCoordPtr[1]->size);
  938.  
  939.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE) 
  940.       gl_print_cassette( IM );
  941.  
  942.    
  943.    if (IM->OrFlag & VERT_EVAL_ANY) 
  944.       gl_eval_vb( VB );
  945.  
  946.    if (IM->Count > IM->Start || (IM->Flag[IM->Start] & (VERT_END|VERT_BEGIN)))
  947.       fixup_primitives( VB, IM );
  948.  
  949.    if (VB->IndirectCount > IM->Start) 
  950.       gl_run_pipeline( VB );      
  951.    else 
  952.       gl_update_materials( VB );
  953.  
  954.    /* This is unfortunate:
  955.     */
  956.    if (VB->pipeline->replay_copied_vertices) {
  957.       if (!VB->CullDone)
  958.      gl_fast_copy_vb( VB );
  959.  
  960.       gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
  961.    }
  962.  
  963.    gl_reset_vb( VB );
  964. }
  965.  
  966. void gl_print_cassette( struct immediate *IM )
  967. {
  968.    gl_print_cassette_flags( IM, IM->Flag );
  969. }
  970.  
  971. void gl_print_cassette_flags( struct immediate *IM, GLuint *flags ) 
  972. {
  973.    GLuint i;
  974.    GLuint andflag = IM->AndFlag;
  975.    GLuint orflag = IM->OrFlag;
  976.    GLuint state = IM->BeginState;
  977.    GLuint req = ~0;
  978.    static const char *tplate[5] = { "%s ", 
  979.                     "%s: %f ",
  980.                     "%s: %f %f ",
  981.                     "%s: %f %f %f ",
  982.                     "%s: %f %f %f %f " };
  983.  
  984.    fprintf(stderr, "Cassette id %d, %u rows.\n", IM->id, IM->Count - IM->Start);
  985.  
  986.    gl_print_vert_flags("Contains at least one", orflag);
  987.  
  988.    if (IM->Count != IM->Start) 
  989.    {
  990.       gl_print_vert_flags("Contains a full complement of", andflag);
  991.    
  992.       fprintf(stderr, "Final begin/end state %s/%s, errors %s/%s\n",
  993.          (state & VERT_BEGIN_0) ? "in" : "out", 
  994.          (state & VERT_BEGIN_1) ? "in" : "out", 
  995.          (state & VERT_ERROR_0) ? "y" : "n", 
  996.          (state & VERT_ERROR_1) ? "y" : "n");
  997.  
  998.       fprintf(stderr, "Obj size: %u, TexCoord0 size: %u, TexCoord1 size: %u\n",
  999.          IM->v.Obj.size,
  1000.          IM->v.TexCoord[0].size,
  1001.          IM->v.TexCoord[1].size);
  1002.    }
  1003.  
  1004.    for (i = IM->Start ; i <= IM->Count ; i++) {
  1005.       fprintf(stderr, "%u: ", i);
  1006.       if (req & VERT_OBJ_ANY) {
  1007.      if (flags[i] & VERT_EVAL_C1) 
  1008.         fprintf(stderr, "EvalCoord %f ", IM->Obj[i][0]);
  1009.      else if (flags[i] & VERT_EVAL_P1) 
  1010.         fprintf(stderr, "EvalPoint %.0f ", IM->Obj[i][0]);
  1011.      else if (flags[i] & VERT_EVAL_C2) 
  1012.         fprintf(stderr, "EvalCoord %f %f ", IM->Obj[i][0], IM->Obj[i][1]);
  1013.      else if (flags[i] & VERT_EVAL_P2) 
  1014.         fprintf(stderr, "EvalPoint %.0f %.0f ", IM->Obj[i][0], IM->Obj[i][1]);
  1015.      else if (i < IM->Count && (flags[i]&VERT_OBJ_234)) {
  1016.         fprintf(stderr, "(%x) ", flags[i] & VERT_OBJ_234);
  1017.         fprintf(stderr, tplate[vertex_sizes[(flags[i]&VERT_OBJ_234)<<1]],
  1018.            "Obj",
  1019.            IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2], IM->Obj[i][3]);
  1020.       }
  1021.       }
  1022.  
  1023.       if (req & flags[i] & VERT_ELT) 
  1024.      fprintf(stderr, " Elt %u\t", IM->Elt[i]);
  1025.  
  1026.       if (req & flags[i] & VERT_NORM)
  1027.      fprintf(stderr, " Norm %f %f %f ", 
  1028.         IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]);
  1029.  
  1030.       if (req & flags[i] & VERT_TEX0_ANY)
  1031.      fprintf(stderr, tplate[vertex_sizes[(flags[i]>>VERT_TEX0_SHIFT)&7]], 
  1032.         "TC0",
  1033.         IM->TexCoord[0][i][0], IM->TexCoord[0][i][1], 
  1034.         IM->TexCoord[0][i][2], IM->TexCoord[0][i][2]);
  1035.  
  1036.  
  1037.       if (req & flags[i] & VERT_TEX1_ANY)
  1038.      fprintf(stderr, tplate[vertex_sizes[(flags[i]>>(VERT_TEX0_SHIFT+4))&7]], 
  1039.         "TC1",
  1040.         IM->TexCoord[1][i][0], IM->TexCoord[1][i][1], 
  1041.         IM->TexCoord[1][i][2], IM->TexCoord[1][i][2]);
  1042.  
  1043.       if (req & flags[i] & VERT_RGBA)
  1044.      fprintf(stderr, " Rgba %d %d %d %d ", 
  1045.         IM->Color[i][0], IM->Color[i][1], 
  1046.         IM->Color[i][2], IM->Color[i][3]);
  1047.  
  1048.       if (req & flags[i] & VERT_INDEX)
  1049.      fprintf(stderr, " Index %u ", IM->Index[i]);
  1050.       
  1051.       if (req & flags[i] & VERT_EDGE)
  1052.      fprintf(stderr, " Edgeflag %d ", IM->EdgeFlag[i]);
  1053.  
  1054.       if (req & flags[i] & VERT_MATERIAL)
  1055.      fprintf(stderr, " Material ");
  1056.      
  1057.  
  1058.       /* The order of these two is not easily knowable, but this is
  1059.        * the usually correct way to look at them.
  1060.        */
  1061.       if (req & flags[i] & VERT_END) 
  1062.      fprintf(stderr, " END ");
  1063.  
  1064.       if (req & flags[i] & VERT_BEGIN) 
  1065.      fprintf(stderr, " BEGIN(%s) ", gl_prim_name[IM->Primitive[i]]);
  1066.  
  1067.       fprintf(stderr, "\n");  
  1068.    }      
  1069. }
  1070.  
  1071.  
  1072.  
  1073.  
  1074.  
  1075.  
  1076.  
  1077.  
  1078.  
  1079.  
  1080.  
  1081.  
  1082.  
  1083.