home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / tnl / t_imm_dlist.cpp < prev    next >
Text File  |  2002-12-08  |  21KB  |  679 lines

  1. /* $Id: t_imm_dlist.c,v 1.44 2002/10/29 20:29:02 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.5
  6.  *
  7.  * Copyright (C) 1999-2001  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.  * Authors:
  27.  *    Keith Whitwell <keith@tungstengraphics.com>
  28.  */
  29.  
  30.  
  31. #include "glheader.h"
  32. #include "context.h"
  33. #include "dlist.h"
  34. #include "debug.h"
  35. #include "mmath.h"
  36. #include "imports.h"
  37. #include "state.h"
  38.  
  39. #include "t_context.h"
  40. #include "t_imm_api.h"
  41. #include "t_imm_elt.h"
  42. #include "t_imm_alloc.h"
  43. #include "t_imm_dlist.h"
  44. #include "t_imm_debug.h"
  45. #include "t_imm_exec.h"
  46. #include "t_imm_fixup.h"
  47. #include "t_pipeline.h"
  48.  
  49. typedef struct {
  50.    struct immediate *IM;
  51.    GLuint Start;
  52.    GLuint Count;
  53.    GLuint BeginState;
  54.    GLuint SavedBeginState;
  55.    GLuint OrFlag;
  56.    GLuint AndFlag;
  57.    GLuint TexSize;
  58.    GLuint LastData;
  59.    GLuint LastPrimitive;
  60.    GLuint LastMaterial;
  61.    GLuint MaterialOrMask;
  62.    GLuint MaterialAndMask;
  63. } TNLvertexcassette;
  64.  
  65. static void execute_compiled_cassette( GLcontext *ctx, void *data );
  66. static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM );
  67.  
  68.  
  69. static void build_normal_lengths( struct immediate *IM )
  70. {
  71.    GLuint i;
  72.    GLfloat len;
  73.    GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL] + IM->Start;
  74.    GLfloat *dest = IM->NormalLengthPtr;
  75.    GLuint *flags = IM->Flag + IM->Start;
  76.    GLuint count = IM->Count - IM->Start;
  77.  
  78.    if (!dest) {
  79.       dest = IM->NormalLengthPtr = (GLfloat *) ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 );
  80.       if (!dest) return;
  81.    }
  82.    dest += IM->Start;
  83.  
  84.    len = (GLfloat) LEN_3FV( data[0] );
  85.    if (len > 0.0F) len = 1.0F / len;
  86.  
  87.    for (i = 0 ; i < count ; ) {
  88.       dest[i] = len;
  89.       if (flags[++i] & VERT_BIT_NORMAL) {
  90.         len = (GLfloat) LEN_3FV( data[i] );
  91.         if (len > 0.0F) len = 1.0F / len;
  92.       }
  93.    }
  94. }
  95.  
  96. static void fixup_normal_lengths( struct immediate *IM )
  97. {
  98.    GLuint i;
  99.    GLfloat len = 1.0F;  /* just to silence warnings */
  100.    GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL];
  101.    GLfloat *dest = IM->NormalLengthPtr;
  102.    GLuint *flags = IM->Flag;
  103.  
  104.    for (i = IM->CopyStart ; i <= IM->Start ; i++) {
  105.       len = (GLfloat) LEN_3FV( data[i] );
  106.       if (len > 0.0F) len = 1.0F / len;
  107.       dest[i] = len;
  108.    }
  109.  
  110.    if (i < IM->Count) {
  111.       while (!(flags[i] & (VERT_BIT_NORMAL|VERT_BIT_END_VB))) {
  112.         dest[i] = len;
  113.         i++;
  114.       }
  115.    }
  116. }
  117.  
  118.  
  119.  
  120. /* Insert the active immediate struct onto the display list currently
  121.  * being built.
  122.  */
  123. void
  124. _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
  125. {
  126.    struct immediate *im = TNL_CURRENT_IM(ctx);
  127.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  128.    TNLvertexcassette *node;
  129.    GLuint new_beginstate;
  130.  
  131.    if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
  132.       _mesa_debug(ctx, "_tnl_compiled_cassette IM: %d\n", IM->id);
  133.  
  134.    if (IM->FlushElt) {
  135.       ASSERT (IM->FlushElt == FLUSH_ELT_LAZY);
  136.       _tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count );
  137.    }
  138.  
  139.    _tnl_compute_orflag( IM, IM->Start );
  140.  
  141.    /* Need to clear this flag, or fixup gets confused.  (The
  142.     * array-elements have been translated away by now, so it's ok to
  143.     * remove it.)
  144.     */
  145.    IM->OrFlag &= ~VERT_BIT_ELT;
  146.    IM->AndFlag &= ~VERT_BIT_ELT;
  147.  
  148.    _tnl_fixup_input( ctx, IM );
  149.  
  150.    node = (TNLvertexcassette *)
  151.       _mesa_alloc_instruction(ctx,
  152.                              tnl->opcode_vertex_cassette,
  153.                              sizeof(TNLvertexcassette));
  154.    if (!node)
  155.       return;
  156.  
  157.    node->IM = im; im->ref_count++;
  158.    node->Start = im->Start;
  159.    node->Count = im->Count;
  160.    node->BeginState = im->BeginState;
  161.    node->SavedBeginState = im->SavedBeginState;
  162.    node->OrFlag = im->OrFlag;
  163.    node->TexSize = im->TexSize;
  164.    node->AndFlag = im->AndFlag;
  165.    node->LastData = im->LastData;
  166.    node->LastPrimitive = im->LastPrimitive;
  167.    node->LastMaterial = im->LastMaterial;
  168.    node->MaterialOrMask = im->MaterialOrMask;
  169.    node->MaterialAndMask = im->MaterialAndMask;
  170.  
  171.    if (tnl->CalcDListNormalLengths) {
  172.       build_normal_lengths( im );
  173.    }
  174.  
  175.    if (ctx->ExecuteFlag) {
  176.       execute_compiled_cassette( ctx, (void *)node );
  177.    }
  178.  
  179.    /* Discard any errors raised in the last cassette.
  180.     */
  181.    new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
  182.  
  183.    /* Decide whether this immediate struct is full, or can be used for
  184.     * the next batch of vertices as well.
  185.     */
  186.    if (im->Count > IMM_MAXDATA - 16) {
  187.       /* Call it full...
  188.        */
  189.       struct immediate *new_im = _tnl_alloc_immediate(ctx);
  190.       new_im->ref_count++;
  191.       im->ref_count--;          /* remove CURRENT_IM reference */
  192.       ASSERT(im->ref_count > 0); /* it is compiled into a display list */
  193.       SET_IMMEDIATE( ctx, new_im );
  194.       _tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS,
  195.                                new_beginstate, node->SavedBeginState );
  196.    } else {
  197.       /* Still some room in the current immediate.
  198.        */
  199.       _tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS,
  200.                        new_beginstate, node->SavedBeginState);
  201.    }
  202. }
  203.  
  204.  
  205. static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM )
  206. {
  207.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  208.  
  209.    /* Can potentially overwrite primitive details - need to save the
  210.     * first slot:
  211.     */
  212.    tnl->DlistPrimitive = IM->Primitive[IM->Start];
  213.    tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
  214.    tnl->DlistLastPrimitive = IM->LastPrimitive;
  215.  
  216.    /* The first primitive may be different from what was recorded in
  217.     * the immediate struct.  Consider an immediate that starts with a
  218.     * glBegin, compiled in a display list, which is called from within
  219.     * an existing Begin/End object.
  220.     */
  221.    if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
  222.       GLuint i;
  223.  
  224.       if (IM->BeginState & VERT_ERROR_1)
  225.         _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
  226.  
  227.       for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
  228.         if (IM->Flag[i] & (VERT_BIT_BEGIN|VERT_BIT_END_VB))
  229.            break;
  230.  
  231.       /* Would like to just ignore vertices upto this point.  Can't
  232.        * set copystart because it might skip materials?
  233.        */
  234.       ASSERT(IM->Start == IM->CopyStart);
  235.       if (i > IM->CopyStart || !(IM->Flag[IM->Start] & VERT_BIT_BEGIN)) {
  236.         IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
  237.         IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
  238.         if (IM->Flag[i] & VERT_BIT_END_VB) {
  239.            IM->Primitive[IM->CopyStart] |= PRIM_LAST;
  240.            IM->LastPrimitive = IM->CopyStart;
  241.         }
  242.       }
  243.    } else {
  244.       GLuint i;
  245.  
  246.       if (IM->BeginState & VERT_ERROR_0)
  247.         _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
  248.  
  249.       if (IM->CopyStart == IM->Start &&
  250.          IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB))
  251.       {
  252.       }
  253.       else
  254.       {
  255.         IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
  256.         if (tnl->ExecParity)
  257.            IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
  258.  
  259.          /* one of these should be true, else we'll be in an infinite loop
  260.          */
  261.          ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
  262.                 IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB));
  263.  
  264.         for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
  265.            if (IM->Flag[i] & (VERT_BIT_END | VERT_BIT_END_VB)) {
  266.               IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
  267.               if (IM->Flag[i] & VERT_BIT_END_VB) {
  268.                  IM->Primitive[IM->CopyStart] |= PRIM_LAST;
  269.                  IM->LastPrimitive = IM->CopyStart;
  270.               }
  271.               if (IM->Flag[i] & VERT_BIT_END) {
  272.                  IM->Primitive[IM->CopyStart] |= PRIM_END;
  273.               }
  274.               break;
  275.            }
  276.       }
  277.    }
  278. }
  279.  
  280. /* Undo any changes potentially made to the immediate in the range
  281.  * IM->Start..IM->Count above.
  282.  */
  283. static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM )
  284. {
  285.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  286.    IM->Primitive[IM->Start] = tnl->DlistPrimitive;
  287.    IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
  288. }
  289.  
  290.  
  291.  
  292. static void
  293. execute_compiled_cassette( GLcontext *ctx, void *data )
  294. {
  295.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  296.    TNLvertexcassette *node = (TNLvertexcassette *)data;
  297.    struct immediate *IM = node->IM;
  298.  
  299. /*     _mesa_debug("%s\n", __FUNCTION__); */
  300.  
  301.    IM->Start = node->Start;
  302.    IM->CopyStart = node->Start;
  303.    IM->Count = node->Count;
  304.    IM->BeginState = node->BeginState;
  305.    IM->SavedBeginState = node->SavedBeginState;
  306.    IM->OrFlag = node->OrFlag;
  307.    IM->TexSize = node->TexSize;
  308.    IM->AndFlag = node->AndFlag;
  309.    IM->LastData = node->LastData;
  310.    IM->LastPrimitive = node->LastPrimitive;
  311.    IM->LastMaterial = node->LastMaterial;
  312.    IM->MaterialOrMask = node->MaterialOrMask;
  313.    IM->MaterialAndMask = node->MaterialAndMask;
  314.  
  315.    if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) &&
  316.        (MESA_VERBOSE & VERBOSE_IMMEDIATE))
  317.       _tnl_print_cassette( IM );
  318.  
  319.    if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) {
  320.       _mesa_debug(ctx, "Run cassette %d, rows %d..%d, beginstate %x ",
  321.                   IM->id, IM->Start, IM->Count, IM->BeginState);
  322.       _tnl_print_vert_flags("orflag", IM->OrFlag);
  323.    }
  324.  
  325.  
  326.    /* Need to respect 'HardBeginEnd' even if the commands are looped
  327.     * back to a driver tnl module.
  328.     */
  329.    if (IM->SavedBeginState) {
  330.       if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
  331.         tnl->ReplayHardBeginEnd = 1;
  332.       if (!tnl->ReplayHardBeginEnd) {
  333.         /* This is a user error.  Whatever operation (like glRectf)
  334.          * decomposed to this hard begin/end pair is now being run
  335.          * inside a begin/end object -- illegally.  Reject it and
  336.          * raise an error.
  337.          */
  338.         _mesa_error(ctx, GL_INVALID_OPERATION, "hard replay");
  339.         return;
  340.       }
  341.    }
  342.  
  343.    if (tnl->LoopbackDListCassettes) {
  344. /*        (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */
  345.       fixup_compiled_primitives( ctx, IM );
  346.       loopback_compiled_cassette( ctx, IM );
  347.       restore_compiled_primitives( ctx, IM );
  348.    }
  349.    else {
  350.       if (ctx->NewState)
  351.         _mesa_update_state(ctx);
  352.  
  353.       if (tnl->pipeline.build_state_changes)
  354.         _tnl_validate_pipeline( ctx );
  355.  
  356.       _tnl_fixup_compiled_cassette( ctx, IM );
  357.       fixup_compiled_primitives( ctx, IM );
  358.  
  359.       if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
  360.         ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
  361.       else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) ||
  362.               (IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) ==
  363.               PRIM_OUTSIDE_BEGIN_END) {
  364.         ctx->Driver.CurrentExecPrimitive =
  365.            IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
  366.       }
  367.  
  368.       _tnl_get_exec_copy_verts( ctx, IM );
  369.  
  370.       if (IM->NormalLengthPtr)
  371.         fixup_normal_lengths( IM );
  372.  
  373.       if (IM->Count == IM->Start)
  374.         _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
  375.       else {
  376. /*      _tnl_print_cassette( IM ); */
  377.         _tnl_run_cassette( ctx, IM );
  378.       }
  379.  
  380.       restore_compiled_primitives( ctx, IM );
  381.    }
  382.  
  383.    if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
  384.       tnl->ReplayHardBeginEnd = 0;
  385. }
  386.  
  387. static void
  388. destroy_compiled_cassette( GLcontext *ctx, void *data )
  389. {
  390.    TNLvertexcassette *node = (TNLvertexcassette *)data;
  391.  
  392.    if ( --node->IM->ref_count == 0 )
  393.       _tnl_free_immediate( ctx, node->IM );
  394. }
  395.  
  396.  
  397. static void
  398. print_compiled_cassette( GLcontext *ctx, void *data )
  399. {
  400.    TNLvertexcassette *node = (TNLvertexcassette *)data;
  401.    struct immediate *IM = node->IM;
  402.  
  403.    _mesa_debug(ctx, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
  404.                node->IM->id, node->Start, node->Count);
  405.  
  406.    IM->Start = node->Start;
  407.    IM->CopyStart = node->Start;
  408.    IM->Count = node->Count;
  409.    IM->BeginState = node->BeginState;
  410.    IM->OrFlag = node->OrFlag;
  411.    IM->TexSize = node->TexSize;
  412.    IM->AndFlag = node->AndFlag;
  413.    IM->LastData = node->LastData;
  414.    IM->LastPrimitive = node->LastPrimitive;
  415.    IM->LastMaterial = node->LastMaterial;
  416.    IM->MaterialOrMask = node->MaterialOrMask;
  417.    IM->MaterialAndMask = node->MaterialAndMask;
  418.  
  419.    _tnl_print_cassette( node->IM );
  420. }
  421.  
  422. void
  423. _tnl_BeginCallList( GLcontext *ctx, GLuint list )
  424. {
  425.    (void) ctx;
  426.    (void) list;
  427.    FLUSH_CURRENT(ctx, 0);
  428. }
  429.  
  430.  
  431. /* Called at the tail of a CallList.  Make current immediate aware of
  432.  * any new to-be-copied vertices.
  433.  */
  434. void
  435. _tnl_EndCallList( GLcontext *ctx )
  436. {
  437.    GLuint beginstate = 0;
  438.  
  439.    if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
  440.       beginstate = VERT_BEGIN_0|VERT_BEGIN_1;
  441.  
  442.    _tnl_reset_exec_input( ctx, TNL_CURRENT_IM(ctx)->Start, beginstate, 0 );
  443. }
  444.  
  445.  
  446. void
  447. _tnl_EndList( GLcontext *ctx )
  448. {
  449.    struct immediate *IM = TNL_CURRENT_IM(ctx);
  450.  
  451.    ctx->swtnl_im = 0;
  452.    IM->ref_count--;
  453.  
  454.    /* outside begin/end, even in COMPILE_AND_EXEC,
  455.     * so no vertices to copy, right?
  456.     */
  457.    ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
  458.  
  459.    /* If this one isn't free, get a clean one.  (Otherwise we'll be
  460.     * using one that's already half full).
  461.     */
  462.    if (IM->ref_count != 0)
  463.       IM = _tnl_alloc_immediate( ctx );
  464.  
  465.    ASSERT(IM->ref_count == 0);
  466.  
  467.    SET_IMMEDIATE( ctx, IM );
  468.    IM->ref_count++;
  469.  
  470.    _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
  471. }
  472.  
  473.  
  474. void
  475. _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
  476. {
  477.    struct immediate *IM = TNL_CURRENT_IM(ctx);
  478.  
  479.    /* Use the installed immediate struct.  No vertices in the current
  480.     * immediate, no copied vertices in the system.
  481.     */
  482.    ASSERT(TNL_CURRENT_IM(ctx));
  483.    ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS);
  484.    ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count);
  485.    ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
  486.  
  487.    /* Set current Begin/End state to unknown:
  488.     */
  489.    IM->BeginState = VERT_BEGIN_0;
  490.    ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
  491. }
  492.  
  493.  
  494. void
  495. _tnl_dlist_init( GLcontext *ctx )
  496. {
  497.    TNLcontext *tnl = TNL_CONTEXT(ctx);
  498.  
  499.    tnl->opcode_vertex_cassette =
  500.       _mesa_alloc_opcode( ctx,
  501.                          sizeof(TNLvertexcassette),
  502.                          execute_compiled_cassette,
  503.                          destroy_compiled_cassette,
  504.                          print_compiled_cassette );
  505. }
  506.  
  507.  
  508. static void emit_material( struct gl_material *src, GLuint bitmask )
  509. {
  510.    if (bitmask & FRONT_EMISSION_BIT)
  511.       glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission );
  512.  
  513.    if (bitmask & BACK_EMISSION_BIT)
  514.       glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission );
  515.  
  516.    if (bitmask & FRONT_AMBIENT_BIT)
  517.       glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient );
  518.  
  519.    if (bitmask & BACK_AMBIENT_BIT)
  520.       glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient );
  521.  
  522.    if (bitmask & FRONT_DIFFUSE_BIT)
  523.       glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse );
  524.  
  525.    if (bitmask & BACK_DIFFUSE_BIT)
  526.       glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse );
  527.  
  528.    if (bitmask & FRONT_SPECULAR_BIT)
  529.       glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular );
  530.  
  531.    if (bitmask & BACK_SPECULAR_BIT)
  532.       glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular );
  533.  
  534.    if (bitmask & FRONT_SHININESS_BIT)
  535.       glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess );
  536.  
  537.    if (bitmask & BACK_SHININESS_BIT)
  538.       glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess );
  539.  
  540.    if (bitmask & FRONT_INDEXES_BIT) {
  541.       GLfloat ind[3];
  542.       ind[0] = src[0].AmbientIndex;
  543.       ind[1] = src[0].DiffuseIndex;
  544.       ind[2] = src[0].SpecularIndex;
  545.       glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind );
  546.    }
  547.  
  548.    if (bitmask & BACK_INDEXES_BIT) {
  549.       GLfloat ind[3];
  550.       ind[0] = src[1].AmbientIndex;
  551.       ind[1] = src[1].DiffuseIndex;
  552.       ind[2] = src[1].SpecularIndex;
  553.       glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind );
  554.    }
  555. }
  556.  
  557. extern "C" {
  558.  
  559.  void AAAglMultiTexCoord4fvARB(GLenum target, const GLfloat *v);
  560. }
  561.  
  562. extern void    glMultiTexCoord4fvARB(GLenum target, const GLfloat *v);
  563.  
  564. #if defined(__IBMCPP__) || defined(__IBMC__)
  565.  
  566. extern "C" {
  567. typedef   void (GLAPIENTRY FUNtexcoordfv)( GLenum aa, const GLfloat *bb );
  568. typedef  FUNtexcoordfv * pFUNtexcoordfv;
  569. }
  570. #endif
  571.  
  572. /* Low-performance helper function to allow driver-supplied tnl
  573.  * modules to process tnl display lists.  This is primarily supplied
  574.  * to avoid fallbacks if CallList is invoked inside a Begin/End pair.
  575.  * For higher performance, drivers should fallback to tnl (if outside
  576.  * begin/end), or (for tnl hardware) implement their own display list
  577.  * mechanism.
  578.  */
  579. static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM )
  580. {
  581.    GLuint i;
  582.    GLuint *flags = IM->Flag;
  583.    GLuint orflag = IM->OrFlag;
  584.    GLuint j;
  585.    void (GLAPIENTRY *vertex)( const GLfloat * );
  586. #if defined(__IBMCPP__) || defined(__IBMC__)
  587.    pFUNtexcoordfv texcoordfv[MAX_TEXTURE_UNITS];
  588. #else
  589.    void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_UNITS])( GLenum, const GLfloat * );
  590. #endif
  591.  
  592.  
  593.    GLuint maxtex = 0;
  594.    GLuint p, length, prim = 0;
  595.  
  596.  
  597.    if (orflag & VERT_BITS_OBJ_234)
  598.       vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv;
  599.    else
  600.       vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv;
  601.  
  602.    if (orflag & VERT_BITS_TEX_ANY) {
  603.       for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) {
  604.         if (orflag & VERT_BIT_TEX(j)) {
  605.            maxtex = j+1;
  606.  
  607.            if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j))
  608.               texcoordfv[j] = glMultiTexCoord4fvARB;
  609.            else if (IM->TexSize & TEX_SIZE_3(j))
  610.               texcoordfv[j] = glMultiTexCoord3fvARB;
  611.            else
  612.               texcoordfv[j] = glMultiTexCoord2fvARB;
  613.         }
  614.       }
  615.    }
  616.  
  617.    for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length)
  618.    {
  619.       prim = IM->Primitive[p];
  620.       length= IM->PrimitiveLength[p];
  621.       ASSERT(length || (prim & PRIM_LAST));
  622.       ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1);
  623.  
  624.       if (prim & PRIM_BEGIN) {
  625.         glBegin(prim & PRIM_MODE_MASK);
  626.       }
  627.  
  628.       for ( i = p ; i <= p+length ; i++) {
  629.         if (flags[i] & VERT_BITS_TEX_ANY) {
  630.            GLuint k;
  631.            for (k = 0 ; k < maxtex ; k++) {
  632.               if (flags[i] & VERT_BIT_TEX(k)) {
  633.                  texcoordfv[k]( GL_TEXTURE0_ARB + k,
  634.                                  IM->Attrib[VERT_ATTRIB_TEX0 + k][i] );
  635.               }
  636.            }
  637.         }
  638.  
  639.         if (flags[i] & VERT_BIT_NORMAL)
  640.            glNormal3fv(IM->Attrib[VERT_ATTRIB_NORMAL][i]);
  641.  
  642.         if (flags[i] & VERT_BIT_COLOR0)
  643.            glColor4fv( IM->Attrib[VERT_ATTRIB_COLOR0][i] );
  644.  
  645.         if (flags[i] & VERT_BIT_COLOR1)
  646.            _glapi_Dispatch->SecondaryColor3fvEXT( IM->Attrib[VERT_ATTRIB_COLOR1][i] );
  647.  
  648.         if (flags[i] & VERT_BIT_FOG)
  649.            _glapi_Dispatch->FogCoordfEXT( IM->Attrib[VERT_ATTRIB_FOG][i][0] );
  650.  
  651.         if (flags[i] & VERT_BIT_INDEX)
  652.            glIndexi( IM->Index[i] );
  653.  
  654.         if (flags[i] & VERT_BIT_EDGEFLAG)
  655.            glEdgeFlag( IM->EdgeFlag[i] );
  656.  
  657.         if (flags[i] & VERT_BIT_MATERIAL)
  658.            emit_material( IM->Material[i], IM->MaterialMask[i] );
  659.  
  660.         if (flags[i]&VERT_BITS_OBJ_234)
  661.            vertex( IM->Attrib[VERT_ATTRIB_POS][i] );
  662.         else if (flags[i] & VERT_BIT_EVAL_C1)
  663.            glEvalCoord1f( IM->Attrib[VERT_ATTRIB_POS][i][0] );
  664.         else if (flags[i] & VERT_BIT_EVAL_P1)
  665.            glEvalPoint1( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0] );
  666.         else if (flags[i] & VERT_BIT_EVAL_C2)
  667.            glEvalCoord2f( IM->Attrib[VERT_ATTRIB_POS][i][0],
  668.                            IM->Attrib[VERT_ATTRIB_POS][i][1] );
  669.         else if (flags[i] & VERT_BIT_EVAL_P2)
  670.            glEvalPoint2( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0],
  671.                           (GLint) IM->Attrib[VERT_ATTRIB_POS][i][1] );
  672.       }
  673.  
  674.       if (prim & PRIM_END) {
  675.         glEnd();
  676.       }
  677.    }
  678. }
  679.