home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / tnl / t_imm_exec.cpp < prev    next >
C/C++ Source or Header  |  2002-10-24  |  18KB  |  599 lines

  1. /* $Id: t_imm_exec.c,v 1.43 2002/10/24 23:57:25 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  4.1
  6.  *
  7.  * Copyright (C) 1999-2002  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.  * \file tnl/t_imm_exec.c
  29.  * \brief Setup to execute immediate-mode vertex data.
  30.  * \author Keith Whitwell
  31.  */
  32.  
  33. #include "glheader.h"
  34. #include "colormac.h"
  35. #include "context.h"
  36. #include "enums.h"
  37. #include "dlist.h"
  38. #include "macros.h"
  39. #include "imports.h"
  40. #include "mmath.h"
  41. #include "light.h"
  42. #include "state.h"
  43. #include "mtypes.h"
  44.  
  45. #include "math/m_matrix.h"
  46. #include "math/m_xform.h"
  47.  
  48. #include "t_context.h"
  49. #include "t_array_import.h"
  50. #include "t_imm_alloc.h"
  51. #include "t_imm_api.h"
  52. #include "t_imm_debug.h"
  53. #include "t_imm_dlist.h"
  54. #include "t_imm_eval.h"
  55. #include "t_imm_elt.h"
  56. #include "t_imm_exec.h"
  57. #include "t_imm_fixup.h"
  58. #include "t_pipeline.h"
  59.  
  60.  
  61.  
  62. static void reset_input( GLcontext *ctx,
  63.              GLuint start,
  64.              GLuint beginstate,
  65.              GLuint savedbeginstate )
  66. {
  67.    struct immediate *IM = TNL_CURRENT_IM(ctx);
  68.  
  69.    /* Clear the dirty part of the flag array.
  70.     */
  71.    if (start < IM->Count+2)
  72.       MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
  73.  
  74.    if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
  75.       _mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, beginstate);
  76.  
  77.    IM->Start = start;
  78.    IM->Count = start;
  79.    IM->LastMaterial = start;
  80.    IM->BeginState = beginstate;
  81.    IM->SavedBeginState = savedbeginstate;
  82.    IM->TexSize = 0;
  83.    IM->MaterialOrMask = 0;
  84.  
  85.    if (IM->MaterialMask) 
  86.       IM->MaterialMask[IM->Start] = 0;
  87.  
  88.    IM->ArrayEltFlags = ~ctx->Array._Enabled;
  89.    IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
  90.    IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER;
  91. }
  92.   
  93. void _tnl_reset_exec_input( GLcontext *ctx,
  94.                 GLuint start,
  95.                 GLuint beginstate,
  96.                 GLuint savedbeginstate )
  97. {
  98.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  99.    struct immediate *IM = TNL_CURRENT_IM(ctx);
  100.  
  101.    reset_input( ctx, start, beginstate, savedbeginstate );
  102.  
  103.    IM->CopyStart = start - tnl->ExecCopyCount;
  104.  
  105.    IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
  106.    if (tnl->ExecParity)
  107.       IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
  108.  
  109.    IM->LastPrimitive = IM->CopyStart;
  110. }
  111.  
  112.  
  113. void _tnl_reset_compile_input( GLcontext *ctx,
  114.                 GLuint start,
  115.                 GLuint beginstate,
  116.                 GLuint savedbeginstate )
  117. {
  118.    struct immediate *IM = TNL_CURRENT_IM(ctx);
  119.  
  120.    reset_input( ctx, start, beginstate, savedbeginstate );
  121.    IM->CopyStart = start;
  122.    IM->LastPrimitive = IM->Start;
  123. }
  124.   
  125.  
  126. /**
  127.  * Copy the last specified normal, color, texcoord, edge flag, etc
  128.  * from the immediate struct into the ctx->Current attribute group.
  129.  */
  130. void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
  131.                GLuint flag, GLuint count )
  132. {
  133.    if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
  134.       _tnl_print_vert_flags("copy to current", flag);
  135.  
  136.    /* XXX should be able to replace these conditions with a loop over
  137.     * the 16 vertex attributes.
  138.     */
  139.    if (flag & VERT_BIT_NORMAL)
  140.       COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL],
  141.                 IM->Attrib[VERT_ATTRIB_NORMAL][count]);
  142.  
  143.    if (flag & VERT_BIT_INDEX)
  144.       ctx->Current.Index = IM->Index[count];
  145.  
  146.    if (flag & VERT_BIT_EDGEFLAG)
  147.       ctx->Current.EdgeFlag = IM->EdgeFlag[count];
  148.  
  149.    if (flag & VERT_BIT_COLOR0) {
  150.       COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
  151.                IM->Attrib[VERT_ATTRIB_COLOR0][count]);
  152.       if (ctx->Light.ColorMaterialEnabled) {
  153.      _mesa_update_color_material( ctx,
  154.                                    ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
  155.       TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  156.       }
  157.    }
  158.  
  159.    if (flag & VERT_BIT_COLOR1)
  160.       COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR1],
  161.                IM->Attrib[VERT_ATTRIB_COLOR1][count]);
  162.  
  163.    if (flag & VERT_BIT_FOG)
  164.       ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = IM->Attrib[VERT_ATTRIB_FOG][count][0];
  165.  
  166.    if (flag & VERT_BITS_TEX_ANY) {
  167.       GLuint i;
  168.       for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
  169.      if (flag & VERT_BIT_TEX(i)) {
  170.         COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i],
  171.                       IM->Attrib[VERT_ATTRIB_TEX0 + i][count]);
  172.      }
  173.       }
  174.    }
  175.  
  176.    if (flag & VERT_BIT_MATERIAL) {
  177.       _mesa_update_material( ctx,
  178.               IM->Material[IM->LastMaterial],
  179.               IM->MaterialOrMask );
  180.  
  181.       TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
  182.    }
  183. }
  184.  
  185.  
  186.  
  187. void _tnl_compute_orflag( struct immediate *IM, GLuint start )
  188. {
  189.    GLuint count = IM->Count;
  190.    GLuint orflag = 0;
  191.    GLuint andflag = ~0U;
  192.    GLuint i;
  193.  
  194.    IM->LastData = count-1;
  195.  
  196.  
  197.    /* Compute the flags for the whole buffer.
  198.     */
  199.    for (i = start ; i < count ; i++) {
  200.       andflag &= IM->Flag[i];
  201.       orflag |= IM->Flag[i];
  202.    }
  203.  
  204.    /* It is possible there will be data in the buffer arising from
  205.     * calls like 'glNormal', 'glMaterial' that occur after the final
  206.     * glVertex, glEval, etc.  Additionally, a buffer can consist of
  207.     * eg. a single glMaterial call, in which case IM->Start ==
  208.     * IM->Count, but the buffer is definitely not empty.
  209.     */
  210.    if (IM->Flag[i] & VERT_BITS_DATA) {
  211.       IM->LastData++;
  212.       orflag |= IM->Flag[i];
  213.    }
  214.  
  215.    IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB;
  216.    IM->CopyAndFlag = IM->AndFlag = andflag;
  217.    IM->OrFlag = orflag;
  218.    IM->CopyOrFlag = orflag;
  219.    IM->Evaluated = 0;
  220. }
  221.  
  222.  
  223. /**
  224.  * This is where the vertex data is transfered from the 'struct immediate
  225.  * into the 'struct vertex_buffer'.
  226.  *
  227.  * Note: The 'start' member of the GLvector structs is now redundant
  228.  * because we always re-transform copied vertices, and the vectors
  229.  * below are set up so that the first copied vertex (if any) appears
  230.  * at position zero.
  231.  */
  232. static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
  233. {
  234.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  235.    struct vertex_buffer *VB = &tnl->vb;
  236.    struct vertex_arrays *tmp = &tnl->imm_inputs;
  237.    GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
  238.    const GLuint start = IM->CopyStart;
  239.    const GLuint count = IM->Count - start;
  240.  
  241.    /* TODO: optimize the case where nothing has changed.  (Just bind
  242.     * tmp to vb).
  243.     */
  244.  
  245.    /* Setup constant data in the VB.
  246.     */
  247.    VB->Count = count;
  248.    VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
  249.    VB->import_data = NULL;
  250.    VB->importable_data = 0;
  251.  
  252.    /* Need an IM->FirstPrimitive?
  253.     */
  254.    VB->Primitive = IM->Primitive + IM->CopyStart;
  255.    VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
  256.    VB->FirstPrimitive = 0;
  257.  
  258.    VB->Flag = IM->Flag + start;
  259.  
  260.    /* TexCoordPtr's are zeroed in loop below.
  261.     */
  262.    VB->NormalPtr = NULL;
  263.    VB->NormalLengthPtr = NULL;
  264.    VB->EdgeFlag = NULL;
  265.    VB->IndexPtr[0] = NULL;
  266.    VB->IndexPtr[1] = NULL;
  267.    VB->ColorPtr[0] = NULL;
  268.    VB->ColorPtr[1] = NULL;
  269.    VB->SecondaryColorPtr[0] = NULL;
  270.    VB->SecondaryColorPtr[1] = NULL;
  271.    VB->Elts = NULL;
  272.    VB->MaterialMask = NULL;
  273.    VB->Material = NULL;
  274.  
  275. /*     _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
  276. /*     _tnl_print_vert_flags("orflag", IM->OrFlag); */
  277. /*     _tnl_print_vert_flags("inputs", inputs); */
  278.  
  279.    /* Setup the initial values of array pointers in the vb.
  280.     */
  281.    if (inputs & VERT_BIT_POS) {
  282.       tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start;
  283.       tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start);
  284.       tmp->Obj.count = count;
  285.       VB->ObjPtr = &tmp->Obj;
  286.       if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234)
  287.      tmp->Obj.size = 4;
  288.       else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23)
  289.      tmp->Obj.size = 3;
  290.       else
  291.      tmp->Obj.size = 2;
  292.    }
  293.  
  294.    if (inputs & VERT_BIT_NORMAL) {
  295.       tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start;
  296.       tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start);
  297.       tmp->Normal.count = count;
  298.       tmp->Normal.size = 3; /* just to be safe */
  299.       VB->NormalPtr = &tmp->Normal;
  300.       if (IM->NormalLengthPtr)
  301.      VB->NormalLengthPtr = IM->NormalLengthPtr + start;
  302.    }
  303.  
  304.    if (inputs & VERT_BIT_INDEX) {
  305.       tmp->Index.count = count;
  306.       tmp->Index.data = IM->Index + start;
  307.       tmp->Index.start = IM->Index + start;
  308.       VB->IndexPtr[0] = &tmp->Index;
  309.    }
  310.  
  311.    if (inputs & VERT_BIT_FOG) {
  312.       tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start;
  313.       tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start);
  314.       tmp->FogCoord.count = count;
  315.       VB->FogCoordPtr = &tmp->FogCoord;
  316.    }
  317.  
  318.    if (inputs & VERT_BIT_COLOR1) {
  319.       tmp->SecondaryColor.Ptr = IM->Attrib[VERT_ATTRIB_COLOR1] + start;
  320.       VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
  321.    }
  322.  
  323.    if (inputs & VERT_BIT_EDGEFLAG) {
  324.       VB->EdgeFlag = IM->EdgeFlag + start;
  325.    }
  326.  
  327.    if (inputs & VERT_BIT_COLOR0) {
  328.       if (IM->CopyOrFlag & VERT_BIT_COLOR0) {
  329.      tmp->Color.Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
  330.      tmp->Color.StrideB = 4 * sizeof(GLfloat);
  331.      tmp->Color.Flags = 0;
  332.       }
  333.       else {
  334.      tmp->Color.Ptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
  335.      tmp->Color.StrideB = 0;
  336.      tmp->Color.Flags = CA_CLIENT_DATA; /* hack */
  337.      VB->import_source = IM;
  338.      VB->importable_data |= VERT_BIT_COLOR0;
  339.      VB->import_data = _tnl_upgrade_current_data;
  340.       }
  341.       VB->ColorPtr[0] = &tmp->Color;
  342.    }
  343.  
  344.    if (inputs & VERT_BITS_TEX_ANY) {
  345.       GLuint i;
  346.       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
  347.      VB->TexCoordPtr[i] = NULL;
  348.      if (inputs & VERT_BIT_TEX(i)) {
  349.         tmp->TexCoord[i].count = count;
  350.         tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start;
  351.         tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start);
  352.         tmp->TexCoord[i].size = 2;
  353.         if (IM->TexSize & TEX_SIZE_3(i)) {
  354.            tmp->TexCoord[i].size = 3;
  355.            if (IM->TexSize & TEX_SIZE_4(i))
  356.           tmp->TexCoord[i].size = 4;
  357.         }
  358.         VB->TexCoordPtr[i] = &tmp->TexCoord[i];
  359.      }
  360.       }
  361.    }
  362.  
  363.    if ((inputs & IM->OrFlag & VERT_BIT_MATERIAL) && IM->Material) {
  364.       VB->MaterialMask = IM->MaterialMask + start;
  365.       VB->Material = IM->Material + start;
  366.    }
  367.  
  368.    /* GL_NV_vertex_program */
  369.    if (ctx->VertexProgram.Enabled) {
  370.       GLuint attr;
  371.       for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
  372.          tmp->Attribs[attr].count = count;
  373.          tmp->Attribs[attr].data = IM->Attrib[attr] + start;
  374.          tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start);
  375.          tmp->Attribs[attr].size = 4;
  376.          VB->AttribPtr[attr] = &(tmp->Attribs[attr]);
  377.       }
  378.    }
  379. }
  380.  
  381.  
  382.  
  383.  
  384. /**
  385.  * Called by exec_vert_cassette, execute_compiled_cassette, but not
  386.  * exec_elt_cassette.
  387.  */
  388. void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
  389. {
  390.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  391.  
  392.    _tnl_vb_bind_immediate( ctx, IM );
  393.  
  394.    if (IM->OrFlag & VERT_BITS_EVAL_ANY)
  395.       _tnl_eval_immediate( ctx, IM );
  396.  
  397.    /* Invalidate all stored data before and after run:
  398.     */
  399.    tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
  400.    tnl->Driver.RunPipeline( ctx );
  401.    tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
  402.  
  403.    _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
  404. }
  405.  
  406.  
  407. /**
  408.  * Called for regular vertex cassettes.
  409.  */
  410. static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
  411. {
  412.    if (IM->FlushElt) {
  413.       /* Orflag is computed twice, but only reach this code if app is
  414.        * using a mixture of glArrayElement() and glVertex() while
  415.        * arrays are locked (else would be in exec_elt_cassette now).
  416.        */
  417.       ASSERT(ctx->Array.LockCount);
  418.       ASSERT(IM->FlushElt == FLUSH_ELT_LAZY);
  419.       _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count );
  420.       _tnl_compute_orflag( IM, IM->CopyStart ); 
  421.    }
  422.  
  423.    _tnl_fixup_input( ctx, IM );
  424. /*     _tnl_print_cassette( IM ); */
  425.    _tnl_run_cassette( ctx, IM );
  426. }
  427.  
  428.  
  429. /* Called for pure, locked VERT_BIT_ELT cassettes instead of
  430.  * _tnl_run_cassette.
  431.  */
  432. static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
  433. {
  434.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  435.    struct vertex_buffer *VB = &tnl->vb;
  436.  
  437.    _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
  438.  
  439.    /* Take only elements and primitive information from the immediate:
  440.     */
  441.    VB->Elts = IM->Elt + IM->CopyStart;
  442.    VB->Primitive = IM->Primitive + IM->CopyStart;
  443.    VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
  444.    VB->FirstPrimitive = 0;
  445.  
  446.    /* Run the pipeline.  No input changes as a result of this action.
  447.     */
  448.    tnl->Driver.RunPipeline( ctx );
  449.  
  450.    /* Still need to update current values:  
  451.     */
  452.    if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
  453.       _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
  454.       _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData );
  455.    }
  456. }
  457.  
  458.  
  459. static void
  460. exec_empty_cassette( GLcontext *ctx, struct immediate *IM )
  461. {
  462.    if (IM->FlushElt)
  463.       _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
  464.  
  465.    _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
  466. }
  467.  
  468.  
  469.  
  470. /**
  471.  * Called for all cassettes when not compiling or playing a display
  472.  * list.
  473.  */
  474. void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
  475. {
  476.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  477.  
  478.    _tnl_compute_orflag( IM, IM->Start );
  479.    _tnl_copy_immediate_vertices( ctx, IM ); 
  480.    _tnl_get_exec_copy_verts( ctx, IM );
  481.  
  482.    if (tnl->pipeline.build_state_changes)
  483.       _tnl_validate_pipeline( ctx );
  484.  
  485.    if (IM->CopyStart == IM->Count) {
  486.       exec_empty_cassette( ctx, IM );
  487.    }
  488.    else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
  489.         ctx->Array.LockCount &&
  490.         ctx->Array.Vertex.Enabled) {
  491.       exec_elt_cassette( ctx, IM );
  492.    }
  493.    else {
  494.       exec_vert_cassette( ctx, IM );
  495.    }
  496.  
  497.    /* Only reuse the immediate if there are no copied vertices living
  498.     * inside it:
  499.     */
  500.    { 
  501.       GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
  502.       GLuint saved_begin_state = IM->SavedBeginState;
  503.  
  504.       if (--IM->ref_count != 0) {
  505.      IM = _tnl_alloc_immediate( ctx );
  506.      SET_IMMEDIATE( ctx, IM );
  507.       }
  508.  
  509.       IM->ref_count++;
  510.      
  511.       _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 
  512.                  begin_state, saved_begin_state );
  513.    }
  514.  
  515.    if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
  516.       ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
  517. }
  518.  
  519.  
  520.  
  521.  
  522. /**
  523.  * Setup vector pointers that will be used to bind immediates to VB's.
  524.  */
  525. void _tnl_imm_init( GLcontext *ctx )
  526. {
  527.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  528.    struct vertex_arrays *tmp = &tnl->imm_inputs;
  529.    GLuint i;
  530.    static int firsttime = 1;
  531.  
  532.    if (firsttime) {
  533.       firsttime = 0;
  534.       _tnl_imm_elt_init();
  535.    }
  536.  
  537.    ctx->swtnl_im = _tnl_alloc_immediate( ctx );
  538.    TNL_CURRENT_IM(ctx)->ref_count++;
  539.  
  540.    tnl->ExecCopyTexSize = 0;
  541.    tnl->ExecCopyCount = 0;
  542.    tnl->ExecCopySource = 0;
  543.  
  544.    TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
  545.  
  546.    _mesa_vector4f_init( &tmp->Obj, 0, 0 );
  547.    _mesa_vector4f_init( &tmp->Normal, 0, 0 );
  548.  
  549.    tmp->Color.Ptr = NULL;
  550.    tmp->Color.Type = GL_FLOAT;
  551.    tmp->Color.Size = 4;
  552.    tmp->Color.Stride = 0;
  553.    tmp->Color.StrideB = 4 * sizeof(GLfloat);
  554.    tmp->Color.Flags = 0;
  555.  
  556.    tmp->SecondaryColor.Ptr = NULL;
  557.    tmp->SecondaryColor.Type = GL_FLOAT;
  558.    tmp->SecondaryColor.Size = 4;
  559.    tmp->SecondaryColor.Stride = 0;
  560.    tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat);
  561.    tmp->SecondaryColor.Flags = 0;
  562.  
  563.    _mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
  564.    _mesa_vector1ui_init( &tmp->Index, 0, 0 );
  565.    _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
  566.  
  567.    for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
  568.       _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
  569.  
  570.    /* Install the first immediate.  Intially outside begin/end.
  571.     */
  572.    _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
  573.    tnl->ReplayHardBeginEnd = 0;
  574.  
  575.    _tnl_imm_vtxfmt_init( ctx );
  576. }
  577.  
  578.  
  579. /**
  580.  * Deallocate the immediate-mode buffer for the given context, if
  581.  * its reference count goes to zero.
  582.  */
  583. void _tnl_imm_destroy( GLcontext *ctx )
  584. {
  585.    if (TNL_CURRENT_IM(ctx)) {
  586.       TNL_CURRENT_IM(ctx)->ref_count--;
  587.       if (TNL_CURRENT_IM(ctx)->ref_count == 0)
  588.      _tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
  589.       /* 
  590.        * Don't use SET_IMMEDIATE here, or else we'll whack the
  591.        * _tnl_CurrentInput pointer - not good when another 
  592.        * context has already been made current.
  593.        * So we just set the context's own tnl immediate pointer
  594.        * to 0.
  595.        */
  596.       ctx->swtnl_im = NULL;
  597.    }
  598. }
  599.