Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
      5  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
      6  *
      7  * Permission is hereby granted, free of charge, to any person obtaining a
      8  * copy of this software and associated documentation files (the "Software"),
      9  * to deal in the Software without restriction, including without limitation
     10  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     11  * and/or sell copies of the Software, and to permit persons to whom the
     12  * Software is furnished to do so, subject to the following conditions:
     13  *
     14  * The above copyright notice and this permission notice shall be included
     15  * in all copies or substantial portions of the Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     23  * OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 
     27 /**
     28  * \file dlist.c
     29  * Display lists management functions.
     30  */
     31 
     32 #include "c99_math.h"
     33 #include "glheader.h"
     34 #include "imports.h"
     35 #include "api_arrayelt.h"
     36 #include "api_exec.h"
     37 #include "api_loopback.h"
     38 #include "api_validate.h"
     39 #include "atifragshader.h"
     40 #include "config.h"
     41 #include "bufferobj.h"
     42 #include "arrayobj.h"
     43 #include "context.h"
     44 #include "dlist.h"
     45 #include "enums.h"
     46 #include "eval.h"
     47 #include "fbobject.h"
     48 #include "framebuffer.h"
     49 #include "glapi/glapi.h"
     50 #include "glformats.h"
     51 #include "hash.h"
     52 #include "image.h"
     53 #include "light.h"
     54 #include "macros.h"
     55 #include "pack.h"
     56 #include "pbo.h"
     57 #include "queryobj.h"
     58 #include "samplerobj.h"
     59 #include "shaderapi.h"
     60 #include "syncobj.h"
     61 #include "teximage.h"
     62 #include "texstorage.h"
     63 #include "mtypes.h"
     64 #include "varray.h"
     65 #include "arbprogram.h"
     66 #include "transformfeedback.h"
     67 
     68 #include "math/m_matrix.h"
     69 
     70 #include "main/dispatch.h"
     71 
     72 #include "vbo/vbo.h"
     73 
     74 
     75 #define USE_BITMAP_ATLAS 1
     76 
     77 
     78 
     79 /**
     80  * Other parts of Mesa (such as the VBO module) can plug into the display
     81  * list system.  This structure describes new display list instructions.
     82  */
     83 struct gl_list_instruction
     84 {
     85    GLuint Size;
     86    void (*Execute)( struct gl_context *ctx, void *data );
     87    void (*Destroy)( struct gl_context *ctx, void *data );
     88    void (*Print)( struct gl_context *ctx, void *data, FILE *f );
     89 };
     90 
     91 
     92 #define MAX_DLIST_EXT_OPCODES 16
     93 
     94 /**
     95  * Used by device drivers to hook new commands into display lists.
     96  */
     97 struct gl_list_extensions
     98 {
     99    struct gl_list_instruction Opcode[MAX_DLIST_EXT_OPCODES];
    100    GLuint NumOpcodes;
    101 };
    102 
    103 
    104 
    105 /**
    106  * Flush vertices.
    107  *
    108  * \param ctx GL context.
    109  *
    110  * Checks if dd_function_table::SaveNeedFlush is marked to flush
    111  * stored (save) vertices, and calls vbo_save_SaveFlushVertices if so.
    112  */
    113 #define SAVE_FLUSH_VERTICES(ctx)                     \
    114    do {                                              \
    115       if (ctx->Driver.SaveNeedFlush)                 \
    116          vbo_save_SaveFlushVertices(ctx);            \
    117    } while (0)
    118 
    119 
    120 /**
    121  * Macro to assert that the API call was made outside the
    122  * glBegin()/glEnd() pair, with return value.
    123  *
    124  * \param ctx GL context.
    125  * \param retval value to return value in case the assertion fails.
    126  */
    127 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval)          \
    128    do {                                                                 \
    129       if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) {               \
    130          _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
    131          return retval;                                                 \
    132       }                                                                 \
    133    } while (0)
    134 
    135 /**
    136  * Macro to assert that the API call was made outside the
    137  * glBegin()/glEnd() pair.
    138  *
    139  * \param ctx GL context.
    140  */
    141 #define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx)                              \
    142    do {                                                                 \
    143       if (ctx->Driver.CurrentSavePrimitive <= PRIM_MAX) {               \
    144          _mesa_compile_error( ctx, GL_INVALID_OPERATION, "glBegin/End" ); \
    145          return;                                                        \
    146       }                                                                 \
    147    } while (0)
    148 
    149 /**
    150  * Macro to assert that the API call was made outside the
    151  * glBegin()/glEnd() pair and flush the vertices.
    152  *
    153  * \param ctx GL context.
    154  */
    155 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx)                    \
    156    do {                                                                 \
    157       ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);                               \
    158       SAVE_FLUSH_VERTICES(ctx);                                         \
    159    } while (0)
    160 
    161 /**
    162  * Macro to assert that the API call was made outside the
    163  * glBegin()/glEnd() pair and flush the vertices, with return value.
    164  *
    165  * \param ctx GL context.
    166  * \param retval value to return value in case the assertion fails.
    167  */
    168 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval) \
    169    do {                                                                 \
    170       ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval);           \
    171       SAVE_FLUSH_VERTICES(ctx);                                         \
    172    } while (0)
    173 
    174 
    175 /**
    176  * Display list opcodes.
    177  *
    178  * The fact that these identifiers are assigned consecutive
    179  * integer values starting at 0 is very important, see InstSize array usage)
    180  */
    181 typedef enum
    182 {
    183    OPCODE_INVALID = -1,         /* Force signed enum */
    184    OPCODE_ACCUM,
    185    OPCODE_ALPHA_FUNC,
    186    OPCODE_BIND_TEXTURE,
    187    OPCODE_BITMAP,
    188    OPCODE_BLEND_COLOR,
    189    OPCODE_BLEND_EQUATION,
    190    OPCODE_BLEND_EQUATION_SEPARATE,
    191    OPCODE_BLEND_FUNC_SEPARATE,
    192 
    193    OPCODE_BLEND_EQUATION_I,
    194    OPCODE_BLEND_EQUATION_SEPARATE_I,
    195    OPCODE_BLEND_FUNC_I,
    196    OPCODE_BLEND_FUNC_SEPARATE_I,
    197 
    198    OPCODE_CALL_LIST,
    199    OPCODE_CALL_LISTS,
    200    OPCODE_CLEAR,
    201    OPCODE_CLEAR_ACCUM,
    202    OPCODE_CLEAR_COLOR,
    203    OPCODE_CLEAR_DEPTH,
    204    OPCODE_CLEAR_INDEX,
    205    OPCODE_CLEAR_STENCIL,
    206    OPCODE_CLEAR_BUFFER_IV,
    207    OPCODE_CLEAR_BUFFER_UIV,
    208    OPCODE_CLEAR_BUFFER_FV,
    209    OPCODE_CLEAR_BUFFER_FI,
    210    OPCODE_CLIP_PLANE,
    211    OPCODE_COLOR_MASK,
    212    OPCODE_COLOR_MASK_INDEXED,
    213    OPCODE_COLOR_MATERIAL,
    214    OPCODE_COPY_PIXELS,
    215    OPCODE_COPY_TEX_IMAGE1D,
    216    OPCODE_COPY_TEX_IMAGE2D,
    217    OPCODE_COPY_TEX_SUB_IMAGE1D,
    218    OPCODE_COPY_TEX_SUB_IMAGE2D,
    219    OPCODE_COPY_TEX_SUB_IMAGE3D,
    220    OPCODE_CULL_FACE,
    221    OPCODE_DEPTH_FUNC,
    222    OPCODE_DEPTH_MASK,
    223    OPCODE_DEPTH_RANGE,
    224    OPCODE_DISABLE,
    225    OPCODE_DISABLE_INDEXED,
    226    OPCODE_DRAW_BUFFER,
    227    OPCODE_DRAW_PIXELS,
    228    OPCODE_ENABLE,
    229    OPCODE_ENABLE_INDEXED,
    230    OPCODE_EVALMESH1,
    231    OPCODE_EVALMESH2,
    232    OPCODE_FOG,
    233    OPCODE_FRONT_FACE,
    234    OPCODE_FRUSTUM,
    235    OPCODE_HINT,
    236    OPCODE_INDEX_MASK,
    237    OPCODE_INIT_NAMES,
    238    OPCODE_LIGHT,
    239    OPCODE_LIGHT_MODEL,
    240    OPCODE_LINE_STIPPLE,
    241    OPCODE_LINE_WIDTH,
    242    OPCODE_LIST_BASE,
    243    OPCODE_LOAD_IDENTITY,
    244    OPCODE_LOAD_MATRIX,
    245    OPCODE_LOAD_NAME,
    246    OPCODE_LOGIC_OP,
    247    OPCODE_MAP1,
    248    OPCODE_MAP2,
    249    OPCODE_MAPGRID1,
    250    OPCODE_MAPGRID2,
    251    OPCODE_MATRIX_MODE,
    252    OPCODE_MULT_MATRIX,
    253    OPCODE_ORTHO,
    254    OPCODE_PASSTHROUGH,
    255    OPCODE_PIXEL_MAP,
    256    OPCODE_PIXEL_TRANSFER,
    257    OPCODE_PIXEL_ZOOM,
    258    OPCODE_POINT_SIZE,
    259    OPCODE_POINT_PARAMETERS,
    260    OPCODE_POLYGON_MODE,
    261    OPCODE_POLYGON_STIPPLE,
    262    OPCODE_POLYGON_OFFSET,
    263    OPCODE_POP_ATTRIB,
    264    OPCODE_POP_MATRIX,
    265    OPCODE_POP_NAME,
    266    OPCODE_PRIORITIZE_TEXTURE,
    267    OPCODE_PUSH_ATTRIB,
    268    OPCODE_PUSH_MATRIX,
    269    OPCODE_PUSH_NAME,
    270    OPCODE_RASTER_POS,
    271    OPCODE_READ_BUFFER,
    272    OPCODE_ROTATE,
    273    OPCODE_SCALE,
    274    OPCODE_SCISSOR,
    275    OPCODE_SELECT_TEXTURE_SGIS,
    276    OPCODE_SELECT_TEXTURE_COORD_SET,
    277    OPCODE_SHADE_MODEL,
    278    OPCODE_STENCIL_FUNC,
    279    OPCODE_STENCIL_MASK,
    280    OPCODE_STENCIL_OP,
    281    OPCODE_TEXENV,
    282    OPCODE_TEXGEN,
    283    OPCODE_TEXPARAMETER,
    284    OPCODE_TEX_IMAGE1D,
    285    OPCODE_TEX_IMAGE2D,
    286    OPCODE_TEX_IMAGE3D,
    287    OPCODE_TEX_SUB_IMAGE1D,
    288    OPCODE_TEX_SUB_IMAGE2D,
    289    OPCODE_TEX_SUB_IMAGE3D,
    290    OPCODE_TRANSLATE,
    291    OPCODE_VIEWPORT,
    292    OPCODE_WINDOW_POS,
    293    /* GL_ARB_multitexture */
    294    OPCODE_ACTIVE_TEXTURE,
    295    /* GL_ARB_texture_compression */
    296    OPCODE_COMPRESSED_TEX_IMAGE_1D,
    297    OPCODE_COMPRESSED_TEX_IMAGE_2D,
    298    OPCODE_COMPRESSED_TEX_IMAGE_3D,
    299    OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D,
    300    OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D,
    301    OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D,
    302    /* GL_ARB_multisample */
    303    OPCODE_SAMPLE_COVERAGE,
    304    /* GL_ARB_window_pos */
    305    OPCODE_WINDOW_POS_ARB,
    306    /* GL_ARB_vertex_program */
    307    OPCODE_BIND_PROGRAM_ARB,
    308    OPCODE_PROGRAM_LOCAL_PARAMETER_ARB,
    309    /* GL_EXT_stencil_two_side */
    310    OPCODE_ACTIVE_STENCIL_FACE_EXT,
    311    /* GL_EXT_depth_bounds_test */
    312    OPCODE_DEPTH_BOUNDS_EXT,
    313    /* GL_ARB_vertex/fragment_program */
    314    OPCODE_PROGRAM_STRING_ARB,
    315    OPCODE_PROGRAM_ENV_PARAMETER_ARB,
    316    /* GL_ARB_occlusion_query */
    317    OPCODE_BEGIN_QUERY_ARB,
    318    OPCODE_END_QUERY_ARB,
    319    /* GL_ARB_draw_buffers */
    320    OPCODE_DRAW_BUFFERS_ARB,
    321    /* GL_ATI_fragment_shader */
    322    OPCODE_BIND_FRAGMENT_SHADER_ATI,
    323    OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
    324    /* OpenGL 2.0 */
    325    OPCODE_STENCIL_FUNC_SEPARATE,
    326    OPCODE_STENCIL_OP_SEPARATE,
    327    OPCODE_STENCIL_MASK_SEPARATE,
    328    /* GL_NV_primitive_restart */
    329    OPCODE_PRIMITIVE_RESTART_NV,
    330    /* GL_ARB_shader_objects */
    331    OPCODE_USE_PROGRAM,
    332    OPCODE_UNIFORM_1F,
    333    OPCODE_UNIFORM_2F,
    334    OPCODE_UNIFORM_3F,
    335    OPCODE_UNIFORM_4F,
    336    OPCODE_UNIFORM_1FV,
    337    OPCODE_UNIFORM_2FV,
    338    OPCODE_UNIFORM_3FV,
    339    OPCODE_UNIFORM_4FV,
    340    OPCODE_UNIFORM_1I,
    341    OPCODE_UNIFORM_2I,
    342    OPCODE_UNIFORM_3I,
    343    OPCODE_UNIFORM_4I,
    344    OPCODE_UNIFORM_1IV,
    345    OPCODE_UNIFORM_2IV,
    346    OPCODE_UNIFORM_3IV,
    347    OPCODE_UNIFORM_4IV,
    348    OPCODE_UNIFORM_MATRIX22,
    349    OPCODE_UNIFORM_MATRIX33,
    350    OPCODE_UNIFORM_MATRIX44,
    351    OPCODE_UNIFORM_MATRIX23,
    352    OPCODE_UNIFORM_MATRIX32,
    353    OPCODE_UNIFORM_MATRIX24,
    354    OPCODE_UNIFORM_MATRIX42,
    355    OPCODE_UNIFORM_MATRIX34,
    356    OPCODE_UNIFORM_MATRIX43,
    357 
    358    /* OpenGL 3.0 */
    359    OPCODE_UNIFORM_1UI,
    360    OPCODE_UNIFORM_2UI,
    361    OPCODE_UNIFORM_3UI,
    362    OPCODE_UNIFORM_4UI,
    363    OPCODE_UNIFORM_1UIV,
    364    OPCODE_UNIFORM_2UIV,
    365    OPCODE_UNIFORM_3UIV,
    366    OPCODE_UNIFORM_4UIV,
    367 
    368    /* OpenGL 4.2 / GL_ARB_separate_shader_objects */
    369    OPCODE_USE_PROGRAM_STAGES,
    370    OPCODE_PROGRAM_UNIFORM_1F,
    371    OPCODE_PROGRAM_UNIFORM_2F,
    372    OPCODE_PROGRAM_UNIFORM_3F,
    373    OPCODE_PROGRAM_UNIFORM_4F,
    374    OPCODE_PROGRAM_UNIFORM_1FV,
    375    OPCODE_PROGRAM_UNIFORM_2FV,
    376    OPCODE_PROGRAM_UNIFORM_3FV,
    377    OPCODE_PROGRAM_UNIFORM_4FV,
    378    OPCODE_PROGRAM_UNIFORM_1I,
    379    OPCODE_PROGRAM_UNIFORM_2I,
    380    OPCODE_PROGRAM_UNIFORM_3I,
    381    OPCODE_PROGRAM_UNIFORM_4I,
    382    OPCODE_PROGRAM_UNIFORM_1IV,
    383    OPCODE_PROGRAM_UNIFORM_2IV,
    384    OPCODE_PROGRAM_UNIFORM_3IV,
    385    OPCODE_PROGRAM_UNIFORM_4IV,
    386    OPCODE_PROGRAM_UNIFORM_1UI,
    387    OPCODE_PROGRAM_UNIFORM_2UI,
    388    OPCODE_PROGRAM_UNIFORM_3UI,
    389    OPCODE_PROGRAM_UNIFORM_4UI,
    390    OPCODE_PROGRAM_UNIFORM_1UIV,
    391    OPCODE_PROGRAM_UNIFORM_2UIV,
    392    OPCODE_PROGRAM_UNIFORM_3UIV,
    393    OPCODE_PROGRAM_UNIFORM_4UIV,
    394    OPCODE_PROGRAM_UNIFORM_MATRIX22F,
    395    OPCODE_PROGRAM_UNIFORM_MATRIX33F,
    396    OPCODE_PROGRAM_UNIFORM_MATRIX44F,
    397    OPCODE_PROGRAM_UNIFORM_MATRIX23F,
    398    OPCODE_PROGRAM_UNIFORM_MATRIX32F,
    399    OPCODE_PROGRAM_UNIFORM_MATRIX24F,
    400    OPCODE_PROGRAM_UNIFORM_MATRIX42F,
    401    OPCODE_PROGRAM_UNIFORM_MATRIX34F,
    402    OPCODE_PROGRAM_UNIFORM_MATRIX43F,
    403 
    404    /* GL_ARB_clip_control */
    405    OPCODE_CLIP_CONTROL,
    406 
    407    /* GL_ARB_color_buffer_float */
    408    OPCODE_CLAMP_COLOR,
    409 
    410    /* GL_EXT_framebuffer_blit */
    411    OPCODE_BLIT_FRAMEBUFFER,
    412 
    413    /* Vertex attributes -- fallback for when optimized display
    414     * list build isn't active.
    415     */
    416    OPCODE_ATTR_1F_NV,
    417    OPCODE_ATTR_2F_NV,
    418    OPCODE_ATTR_3F_NV,
    419    OPCODE_ATTR_4F_NV,
    420    OPCODE_ATTR_1F_ARB,
    421    OPCODE_ATTR_2F_ARB,
    422    OPCODE_ATTR_3F_ARB,
    423    OPCODE_ATTR_4F_ARB,
    424    OPCODE_MATERIAL,
    425    OPCODE_BEGIN,
    426    OPCODE_END,
    427    OPCODE_RECTF,
    428    OPCODE_EVAL_C1,
    429    OPCODE_EVAL_C2,
    430    OPCODE_EVAL_P1,
    431    OPCODE_EVAL_P2,
    432 
    433    /* GL_EXT_provoking_vertex */
    434    OPCODE_PROVOKING_VERTEX,
    435 
    436    /* GL_EXT_transform_feedback */
    437    OPCODE_BEGIN_TRANSFORM_FEEDBACK,
    438    OPCODE_END_TRANSFORM_FEEDBACK,
    439    OPCODE_BIND_TRANSFORM_FEEDBACK,
    440    OPCODE_PAUSE_TRANSFORM_FEEDBACK,
    441    OPCODE_RESUME_TRANSFORM_FEEDBACK,
    442    OPCODE_DRAW_TRANSFORM_FEEDBACK,
    443 
    444    /* GL_EXT_texture_integer */
    445    OPCODE_CLEARCOLOR_I,
    446    OPCODE_CLEARCOLOR_UI,
    447    OPCODE_TEXPARAMETER_I,
    448    OPCODE_TEXPARAMETER_UI,
    449 
    450    /* GL_ARB_instanced_arrays */
    451    OPCODE_VERTEX_ATTRIB_DIVISOR,
    452 
    453    /* GL_NV_texture_barrier */
    454    OPCODE_TEXTURE_BARRIER_NV,
    455 
    456    /* GL_ARB_sampler_object */
    457    OPCODE_BIND_SAMPLER,
    458    OPCODE_SAMPLER_PARAMETERIV,
    459    OPCODE_SAMPLER_PARAMETERFV,
    460    OPCODE_SAMPLER_PARAMETERIIV,
    461    OPCODE_SAMPLER_PARAMETERUIV,
    462 
    463    /* GL_ARB_sync */
    464    OPCODE_WAIT_SYNC,
    465 
    466    /* GL_NV_conditional_render */
    467    OPCODE_BEGIN_CONDITIONAL_RENDER,
    468    OPCODE_END_CONDITIONAL_RENDER,
    469 
    470    /* ARB_timer_query */
    471    OPCODE_QUERY_COUNTER,
    472 
    473    /* ARB_transform_feedback3 */
    474    OPCODE_BEGIN_QUERY_INDEXED,
    475    OPCODE_END_QUERY_INDEXED,
    476    OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM,
    477 
    478    /* ARB_transform_feedback_instanced */
    479    OPCODE_DRAW_TRANSFORM_FEEDBACK_INSTANCED,
    480    OPCODE_DRAW_TRANSFORM_FEEDBACK_STREAM_INSTANCED,
    481 
    482    /* ARB_uniform_buffer_object */
    483    OPCODE_UNIFORM_BLOCK_BINDING,
    484 
    485    /* EXT_polygon_offset_clamp */
    486    OPCODE_POLYGON_OFFSET_CLAMP,
    487 
    488    /* EXT_window_rectangles */
    489    OPCODE_WINDOW_RECTANGLES,
    490 
    491    /* The following three are meta instructions */
    492    OPCODE_ERROR,                /* raise compiled-in error */
    493    OPCODE_CONTINUE,
    494    OPCODE_NOP,                  /* No-op (used for 8-byte alignment */
    495    OPCODE_END_OF_LIST,
    496    OPCODE_EXT_0
    497 } OpCode;
    498 
    499 
    500 
    501 /**
    502  * Display list node.
    503  *
    504  * Display list instructions are stored as sequences of "nodes".  Nodes
    505  * are allocated in blocks.  Each block has BLOCK_SIZE nodes.  Blocks
    506  * are linked together with a pointer.
    507  *
    508  * Each instruction in the display list is stored as a sequence of
    509  * contiguous nodes in memory.
    510  * Each node is the union of a variety of data types.
    511  *
    512  * Note, all of these members should be 4 bytes in size or less for the
    513  * sake of compact display lists.  We store 8-byte pointers in a pair of
    514  * these nodes using the save/get_pointer() functions below.
    515  */
    516 union gl_dlist_node
    517 {
    518    OpCode opcode;
    519    GLboolean b;
    520    GLbitfield bf;
    521    GLubyte ub;
    522    GLshort s;
    523    GLushort us;
    524    GLint i;
    525    GLuint ui;
    526    GLenum e;
    527    GLfloat f;
    528    GLsizei si;
    529 };
    530 
    531 
    532 typedef union gl_dlist_node Node;
    533 
    534 
    535 /** How many 4-byte dwords to store a pointer */
    536 #define POINTER_DWORDS (sizeof(void *) / 4)
    537 
    538 /* We want to keep sizeof(union gl_dlist_node) == 4 to minimize
    539  * space for display lists.  The following types and functions are
    540  * used to help store 4- and 8-byte pointers in 1 or 2 dlist_nodes.
    541  */
    542 union pointer
    543 {
    544    void *ptr;
    545    GLuint dwords[POINTER_DWORDS];
    546 };
    547 
    548 
    549 /**
    550  * Save a 4 or 8-byte pointer at dest (and dest+1).
    551  */
    552 static inline void
    553 save_pointer(Node *dest, void *src)
    554 {
    555    union pointer p;
    556    unsigned i;
    557 
    558    STATIC_ASSERT(POINTER_DWORDS == 1 || POINTER_DWORDS == 2);
    559    STATIC_ASSERT(sizeof(Node) == 4);
    560 
    561    p.ptr = src;
    562 
    563    for (i = 0; i < POINTER_DWORDS; i++)
    564       dest[i].ui = p.dwords[i];
    565 }
    566 
    567 
    568 /**
    569  * Retrieve a 4 or 8-byte pointer from node (node+1).
    570  */
    571 static inline void *
    572 get_pointer(const Node *node)
    573 {
    574    union pointer p;
    575    unsigned i;
    576 
    577    for (i = 0; i < POINTER_DWORDS; i++)
    578       p.dwords[i] = node[i].ui;
    579 
    580    return p.ptr;
    581 }
    582 
    583 
    584 /**
    585  * Used to store a 64-bit uint in a pair of "Nodes" for the sake of 32-bit
    586  * environment.
    587  */
    588 union uint64_pair
    589 {
    590    GLuint64 uint64;
    591    GLuint uint32[2];
    592 };
    593 
    594 
    595 /**
    596  * How many nodes to allocate at a time.  Note that bulk vertex data
    597  * from glBegin/glVertex/glEnd primitives will typically wind up in
    598  * a VBO, and not directly in the display list itself.
    599  */
    600 #define BLOCK_SIZE 256
    601 
    602 
    603 
    604 /**
    605  * Number of nodes of storage needed for each instruction.
    606  * Sizes for dynamically allocated opcodes are stored in the context struct.
    607  */
    608 static GLuint InstSize[OPCODE_END_OF_LIST + 1];
    609 
    610 
    611 void mesa_print_display_list(GLuint list);
    612 
    613 
    614 /**
    615  * Does the given display list only contain a single glBitmap call?
    616  */
    617 static bool
    618 is_bitmap_list(const struct gl_display_list *dlist)
    619 {
    620    const Node *n = dlist->Head;
    621    if (n[0].opcode == OPCODE_BITMAP) {
    622       n += InstSize[OPCODE_BITMAP];
    623       if (n[0].opcode == OPCODE_END_OF_LIST)
    624          return true;
    625    }
    626    return false;
    627 }
    628 
    629 
    630 /**
    631  * Is the given display list an empty list?
    632  */
    633 static bool
    634 is_empty_list(const struct gl_display_list *dlist)
    635 {
    636    const Node *n = dlist->Head;
    637    return n[0].opcode == OPCODE_END_OF_LIST;
    638 }
    639 
    640 
    641 /**
    642  * Delete/free a gl_bitmap_atlas.  Called during context tear-down.
    643  */
    644 void
    645 _mesa_delete_bitmap_atlas(struct gl_context *ctx, struct gl_bitmap_atlas *atlas)
    646 {
    647    if (atlas->texObj) {
    648       ctx->Driver.DeleteTexture(ctx, atlas->texObj);
    649    }
    650    free(atlas->glyphs);
    651 }
    652 
    653 
    654 /**
    655  * Lookup a gl_bitmap_atlas by listBase ID.
    656  */
    657 static struct gl_bitmap_atlas *
    658 lookup_bitmap_atlas(struct gl_context *ctx, GLuint listBase)
    659 {
    660    struct gl_bitmap_atlas *atlas;
    661 
    662    assert(listBase > 0);
    663    atlas = _mesa_HashLookup(ctx->Shared->BitmapAtlas, listBase);
    664    return atlas;
    665 }
    666 
    667 
    668 /**
    669  * Create new bitmap atlas and insert into hash table.
    670  */
    671 static struct gl_bitmap_atlas *
    672 alloc_bitmap_atlas(struct gl_context *ctx, GLuint listBase)
    673 {
    674    struct gl_bitmap_atlas *atlas;
    675 
    676    assert(listBase > 0);
    677    assert(_mesa_HashLookup(ctx->Shared->BitmapAtlas, listBase) == NULL);
    678 
    679    atlas = calloc(1, sizeof(*atlas));
    680    if (atlas) {
    681       _mesa_HashInsert(ctx->Shared->BitmapAtlas, listBase, atlas);
    682    }
    683 
    684    return atlas;
    685 }
    686 
    687 
    688 /**
    689  * Try to build a bitmap atlas.  This involves examining a sequence of
    690  * display lists which contain glBitmap commands and putting the bitmap
    691  * images into a texture map (the atlas).
    692  * If we succeed, gl_bitmap_atlas::complete will be set to true.
    693  * If we fail, gl_bitmap_atlas::incomplete will be set to true.
    694  */
    695 static void
    696 build_bitmap_atlas(struct gl_context *ctx, struct gl_bitmap_atlas *atlas,
    697                    GLuint listBase)
    698 {
    699    unsigned i, row_height = 0, xpos = 0, ypos = 0;
    700    GLubyte *map;
    701    GLint map_stride;
    702 
    703    assert(atlas);
    704    assert(!atlas->complete);
    705    assert(atlas->numBitmaps > 0);
    706 
    707    /* We use a rectangle texture (non-normalized coords) for the atlas */
    708    assert(ctx->Extensions.NV_texture_rectangle);
    709    assert(ctx->Const.MaxTextureRectSize >= 1024);
    710 
    711    atlas->texWidth = 1024;
    712    atlas->texHeight = 0;  /* determined below */
    713 
    714    atlas->glyphs = malloc(atlas->numBitmaps * sizeof(atlas->glyphs[0]));
    715    if (!atlas->glyphs) {
    716       /* give up */
    717       atlas->incomplete = true;
    718       return;
    719    }
    720 
    721    /* Loop over the display lists.  They should all contain a single glBitmap
    722     * call.  If not, bail out.  Also, compute the position and sizes of each
    723     * bitmap in the atlas to determine the texture atlas size.
    724     */
    725    for (i = 0; i < atlas->numBitmaps; i++) {
    726       const struct gl_display_list *list = _mesa_lookup_list(ctx, listBase + i);
    727       const Node *n;
    728       struct gl_bitmap_glyph *g = &atlas->glyphs[i];
    729       unsigned bitmap_width, bitmap_height;
    730       float bitmap_xmove, bitmap_ymove, bitmap_xorig, bitmap_yorig;
    731 
    732       if (!list || is_empty_list(list)) {
    733          /* stop here */
    734          atlas->numBitmaps = i;
    735          break;
    736       }
    737 
    738       if (!is_bitmap_list(list)) {
    739          /* This list does not contain exactly one glBitmap command. Give up. */
    740          atlas->incomplete = true;
    741          return;
    742       }
    743 
    744       /* get bitmap info from the display list command */
    745       n = list->Head;
    746       assert(n[0].opcode == OPCODE_BITMAP);
    747       bitmap_width = n[1].i;
    748       bitmap_height = n[2].i;
    749       bitmap_xorig = n[3].f;
    750       bitmap_yorig = n[4].f;
    751       bitmap_xmove = n[5].f;
    752       bitmap_ymove = n[6].f;
    753 
    754       if (xpos + bitmap_width > atlas->texWidth) {
    755          /* advance to the next row of the texture */
    756          xpos = 0;
    757          ypos += row_height;
    758          row_height = 0;
    759       }
    760 
    761       /* save the bitmap's position in the atlas */
    762       g->x = xpos;
    763       g->y = ypos;
    764       g->w = bitmap_width;
    765       g->h = bitmap_height;
    766       g->xorig = bitmap_xorig;
    767       g->yorig = bitmap_yorig;
    768       g->xmove = bitmap_xmove;
    769       g->ymove = bitmap_ymove;
    770 
    771       xpos += bitmap_width;
    772 
    773       /* keep track of tallest bitmap in the row */
    774       row_height = MAX2(row_height, bitmap_height);
    775    }
    776 
    777    /* Now we know the texture height */
    778    atlas->texHeight = ypos + row_height;
    779 
    780    if (atlas->texHeight == 0) {
    781       /* no glyphs found, give up */
    782       goto fail;
    783    }
    784    else if (atlas->texHeight > ctx->Const.MaxTextureRectSize) {
    785       /* too large, give up */
    786       goto fail;
    787    }
    788 
    789    /* Create atlas texture (texture ID is irrelevant) */
    790    atlas->texObj = ctx->Driver.NewTextureObject(ctx, 999, GL_TEXTURE_RECTANGLE);
    791    if (!atlas->texObj) {
    792       goto out_of_memory;
    793    }
    794 
    795    atlas->texObj->Sampler.MinFilter = GL_NEAREST;
    796    atlas->texObj->Sampler.MagFilter = GL_NEAREST;
    797    atlas->texObj->MaxLevel = 0;
    798    atlas->texObj->Immutable = GL_TRUE;
    799 
    800    atlas->texImage = _mesa_get_tex_image(ctx, atlas->texObj,
    801                                          GL_TEXTURE_RECTANGLE, 0);
    802    if (!atlas->texImage) {
    803       goto out_of_memory;
    804    }
    805 
    806    _mesa_init_teximage_fields(ctx, atlas->texImage,
    807                               atlas->texWidth, atlas->texHeight, 1, 0,
    808                               GL_ALPHA, MESA_FORMAT_A_UNORM8);
    809 
    810    /* alloc image storage */
    811    if (!ctx->Driver.AllocTextureImageBuffer(ctx, atlas->texImage)) {
    812       goto out_of_memory;
    813    }
    814 
    815    /* map teximage, load with bitmap glyphs */
    816    ctx->Driver.MapTextureImage(ctx, atlas->texImage, 0,
    817                                0, 0, atlas->texWidth, atlas->texHeight,
    818                                GL_MAP_WRITE_BIT, &map, &map_stride);
    819    if (!map) {
    820       goto out_of_memory;
    821    }
    822 
    823    /* Background/clear pixels are 0xff, foreground/set pixels are 0x0 */
    824    memset(map, 0xff, map_stride * atlas->texHeight);
    825 
    826    for (i = 0; i < atlas->numBitmaps; i++) {
    827       const struct gl_display_list *list = _mesa_lookup_list(ctx, listBase + i);
    828       const Node *n = list->Head;
    829 
    830       assert(n[0].opcode == OPCODE_BITMAP ||
    831              n[0].opcode == OPCODE_END_OF_LIST);
    832 
    833       if (n[0].opcode == OPCODE_BITMAP) {
    834          unsigned bitmap_width = n[1].i;
    835          unsigned bitmap_height = n[2].i;
    836          unsigned xpos = atlas->glyphs[i].x;
    837          unsigned ypos = atlas->glyphs[i].y;
    838          const void *bitmap_image = get_pointer(&n[7]);
    839 
    840          assert(atlas->glyphs[i].w == bitmap_width);
    841          assert(atlas->glyphs[i].h == bitmap_height);
    842 
    843          /* put the bitmap image into the texture image */
    844          _mesa_expand_bitmap(bitmap_width, bitmap_height,
    845                              &ctx->DefaultPacking, bitmap_image,
    846                              map + map_stride * ypos + xpos, /* dest addr */
    847                              map_stride, 0x0);
    848       }
    849    }
    850 
    851    ctx->Driver.UnmapTextureImage(ctx, atlas->texImage, 0);
    852 
    853    atlas->complete = true;
    854 
    855    return;
    856 
    857 out_of_memory:
    858    _mesa_error(ctx, GL_OUT_OF_MEMORY, "Display list bitmap atlas");
    859 fail:
    860    if (atlas->texObj) {
    861       ctx->Driver.DeleteTexture(ctx, atlas->texObj);
    862    }
    863    free(atlas->glyphs);
    864    atlas->glyphs = NULL;
    865    atlas->incomplete = true;
    866 }
    867 
    868 
    869 /**
    870  * Allocate a gl_display_list object with an initial block of storage.
    871  * \param count  how many display list nodes/tokens to allocate
    872  */
    873 static struct gl_display_list *
    874 make_list(GLuint name, GLuint count)
    875 {
    876    struct gl_display_list *dlist = CALLOC_STRUCT(gl_display_list);
    877    dlist->Name = name;
    878    dlist->Head = malloc(sizeof(Node) * count);
    879    dlist->Head[0].opcode = OPCODE_END_OF_LIST;
    880    return dlist;
    881 }
    882 
    883 
    884 /**
    885  * Lookup function to just encapsulate casting.
    886  */
    887 struct gl_display_list *
    888 _mesa_lookup_list(struct gl_context *ctx, GLuint list)
    889 {
    890    return (struct gl_display_list *)
    891       _mesa_HashLookup(ctx->Shared->DisplayList, list);
    892 }
    893 
    894 
    895 /** Is the given opcode an extension code? */
    896 static inline GLboolean
    897 is_ext_opcode(OpCode opcode)
    898 {
    899    return (opcode >= OPCODE_EXT_0);
    900 }
    901 
    902 
    903 /** Destroy an extended opcode instruction */
    904 static GLint
    905 ext_opcode_destroy(struct gl_context *ctx, Node *node)
    906 {
    907    const GLint i = node[0].opcode - OPCODE_EXT_0;
    908    GLint step;
    909    ctx->ListExt->Opcode[i].Destroy(ctx, &node[1]);
    910    step = ctx->ListExt->Opcode[i].Size;
    911    return step;
    912 }
    913 
    914 
    915 /** Execute an extended opcode instruction */
    916 static GLint
    917 ext_opcode_execute(struct gl_context *ctx, Node *node)
    918 {
    919    const GLint i = node[0].opcode - OPCODE_EXT_0;
    920    GLint step;
    921    ctx->ListExt->Opcode[i].Execute(ctx, &node[1]);
    922    step = ctx->ListExt->Opcode[i].Size;
    923    return step;
    924 }
    925 
    926 
    927 /** Print an extended opcode instruction */
    928 static GLint
    929 ext_opcode_print(struct gl_context *ctx, Node *node, FILE *f)
    930 {
    931    const GLint i = node[0].opcode - OPCODE_EXT_0;
    932    GLint step;
    933    ctx->ListExt->Opcode[i].Print(ctx, &node[1], f);
    934    step = ctx->ListExt->Opcode[i].Size;
    935    return step;
    936 }
    937 
    938 
    939 /**
    940  * Delete the named display list, but don't remove from hash table.
    941  * \param dlist - display list pointer
    942  */
    943 void
    944 _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
    945 {
    946    Node *n, *block;
    947    GLboolean done;
    948 
    949    n = block = dlist->Head;
    950 
    951    done = block ? GL_FALSE : GL_TRUE;
    952    while (!done) {
    953       const OpCode opcode = n[0].opcode;
    954 
    955       /* check for extension opcodes first */
    956       if (is_ext_opcode(opcode)) {
    957          n += ext_opcode_destroy(ctx, n);
    958       }
    959       else {
    960          switch (opcode) {
    961             /* for some commands, we need to free malloc'd memory */
    962          case OPCODE_MAP1:
    963             free(get_pointer(&n[6]));
    964             n += InstSize[n[0].opcode];
    965             break;
    966          case OPCODE_MAP2:
    967             free(get_pointer(&n[10]));
    968             n += InstSize[n[0].opcode];
    969             break;
    970          case OPCODE_CALL_LISTS:
    971             free(get_pointer(&n[3]));
    972             n += InstSize[n[0].opcode];
    973             break;
    974          case OPCODE_DRAW_PIXELS:
    975             free(get_pointer(&n[5]));
    976             n += InstSize[n[0].opcode];
    977             break;
    978          case OPCODE_BITMAP:
    979             free(get_pointer(&n[7]));
    980             n += InstSize[n[0].opcode];
    981             break;
    982          case OPCODE_POLYGON_STIPPLE:
    983             free(get_pointer(&n[1]));
    984             n += InstSize[n[0].opcode];
    985             break;
    986          case OPCODE_TEX_IMAGE1D:
    987             free(get_pointer(&n[8]));
    988             n += InstSize[n[0].opcode];
    989             break;
    990          case OPCODE_TEX_IMAGE2D:
    991             free(get_pointer(&n[9]));
    992             n += InstSize[n[0].opcode];
    993             break;
    994          case OPCODE_TEX_IMAGE3D:
    995             free(get_pointer(&n[10]));
    996             n += InstSize[n[0].opcode];
    997             break;
    998          case OPCODE_TEX_SUB_IMAGE1D:
    999             free(get_pointer(&n[7]));
   1000             n += InstSize[n[0].opcode];
   1001             break;
   1002          case OPCODE_TEX_SUB_IMAGE2D:
   1003             free(get_pointer(&n[9]));
   1004             n += InstSize[n[0].opcode];
   1005             break;
   1006          case OPCODE_TEX_SUB_IMAGE3D:
   1007             free(get_pointer(&n[11]));
   1008             n += InstSize[n[0].opcode];
   1009             break;
   1010          case OPCODE_COMPRESSED_TEX_IMAGE_1D:
   1011             free(get_pointer(&n[7]));
   1012             n += InstSize[n[0].opcode];
   1013             break;
   1014          case OPCODE_COMPRESSED_TEX_IMAGE_2D:
   1015             free(get_pointer(&n[8]));
   1016             n += InstSize[n[0].opcode];
   1017             break;
   1018          case OPCODE_COMPRESSED_TEX_IMAGE_3D:
   1019             free(get_pointer(&n[9]));
   1020             n += InstSize[n[0].opcode];
   1021             break;
   1022          case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D:
   1023             free(get_pointer(&n[7]));
   1024             n += InstSize[n[0].opcode];
   1025             break;
   1026          case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D:
   1027             free(get_pointer(&n[9]));
   1028             n += InstSize[n[0].opcode];
   1029             break;
   1030          case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D:
   1031             free(get_pointer(&n[11]));
   1032             n += InstSize[n[0].opcode];
   1033             break;
   1034          case OPCODE_PROGRAM_STRING_ARB:
   1035             free(get_pointer(&n[4]));      /* program string */
   1036             n += InstSize[n[0].opcode];
   1037             break;
   1038          case OPCODE_UNIFORM_1FV:
   1039          case OPCODE_UNIFORM_2FV:
   1040          case OPCODE_UNIFORM_3FV:
   1041          case OPCODE_UNIFORM_4FV:
   1042          case OPCODE_UNIFORM_1IV:
   1043          case OPCODE_UNIFORM_2IV:
   1044          case OPCODE_UNIFORM_3IV:
   1045          case OPCODE_UNIFORM_4IV:
   1046          case OPCODE_UNIFORM_1UIV:
   1047          case OPCODE_UNIFORM_2UIV:
   1048          case OPCODE_UNIFORM_3UIV:
   1049          case OPCODE_UNIFORM_4UIV:
   1050             free(get_pointer(&n[3]));
   1051             n += InstSize[n[0].opcode];
   1052             break;
   1053          case OPCODE_UNIFORM_MATRIX22:
   1054          case OPCODE_UNIFORM_MATRIX33:
   1055          case OPCODE_UNIFORM_MATRIX44:
   1056          case OPCODE_UNIFORM_MATRIX24:
   1057          case OPCODE_UNIFORM_MATRIX42:
   1058          case OPCODE_UNIFORM_MATRIX23:
   1059          case OPCODE_UNIFORM_MATRIX32:
   1060          case OPCODE_UNIFORM_MATRIX34:
   1061          case OPCODE_UNIFORM_MATRIX43:
   1062             free(get_pointer(&n[4]));
   1063             n += InstSize[n[0].opcode];
   1064             break;
   1065          case OPCODE_PROGRAM_UNIFORM_1FV:
   1066          case OPCODE_PROGRAM_UNIFORM_2FV:
   1067          case OPCODE_PROGRAM_UNIFORM_3FV:
   1068          case OPCODE_PROGRAM_UNIFORM_4FV:
   1069          case OPCODE_PROGRAM_UNIFORM_1IV:
   1070          case OPCODE_PROGRAM_UNIFORM_2IV:
   1071          case OPCODE_PROGRAM_UNIFORM_3IV:
   1072          case OPCODE_PROGRAM_UNIFORM_4IV:
   1073          case OPCODE_PROGRAM_UNIFORM_1UIV:
   1074          case OPCODE_PROGRAM_UNIFORM_2UIV:
   1075          case OPCODE_PROGRAM_UNIFORM_3UIV:
   1076          case OPCODE_PROGRAM_UNIFORM_4UIV:
   1077             free(get_pointer(&n[4]));
   1078             n += InstSize[n[0].opcode];
   1079             break;
   1080          case OPCODE_PROGRAM_UNIFORM_MATRIX22F:
   1081          case OPCODE_PROGRAM_UNIFORM_MATRIX33F:
   1082          case OPCODE_PROGRAM_UNIFORM_MATRIX44F:
   1083          case OPCODE_PROGRAM_UNIFORM_MATRIX24F:
   1084          case OPCODE_PROGRAM_UNIFORM_MATRIX42F:
   1085          case OPCODE_PROGRAM_UNIFORM_MATRIX23F:
   1086          case OPCODE_PROGRAM_UNIFORM_MATRIX32F:
   1087          case OPCODE_PROGRAM_UNIFORM_MATRIX34F:
   1088          case OPCODE_PROGRAM_UNIFORM_MATRIX43F:
   1089             free(get_pointer(&n[5]));
   1090             n += InstSize[n[0].opcode];
   1091             break;
   1092          case OPCODE_PIXEL_MAP:
   1093             free(get_pointer(&n[3]));
   1094             n += InstSize[n[0].opcode];
   1095             break;
   1096          case OPCODE_WINDOW_RECTANGLES:
   1097             free(get_pointer(&n[3]));
   1098             n += InstSize[n[0].opcode];
   1099             break;
   1100          case OPCODE_CONTINUE:
   1101             n = (Node *) get_pointer(&n[1]);
   1102             free(block);
   1103             block = n;
   1104             break;
   1105          case OPCODE_END_OF_LIST:
   1106             free(block);
   1107             done = GL_TRUE;
   1108             break;
   1109          default:
   1110             /* Most frequent case */
   1111             n += InstSize[n[0].opcode];
   1112             break;
   1113          }
   1114       }
   1115    }
   1116 
   1117    free(dlist->Label);
   1118    free(dlist);
   1119 }
   1120 
   1121 
   1122 /**
   1123  * Called by _mesa_HashWalk() to check if a display list which is being
   1124  * deleted belongs to a bitmap texture atlas.
   1125  */
   1126 static void
   1127 check_atlas_for_deleted_list(GLuint atlas_id, void *data, void *userData)
   1128 {
   1129    struct gl_bitmap_atlas *atlas = (struct gl_bitmap_atlas *) data;
   1130    GLuint list_id = *((GLuint *) userData);  /* the list being deleted */
   1131 
   1132    /* See if the list_id falls in the range contained in this texture atlas */
   1133    if (atlas->complete &&
   1134        list_id >= atlas_id &&
   1135        list_id < atlas_id + atlas->numBitmaps) {
   1136       /* Mark the atlas as incomplete so it doesn't get used.  But don't
   1137        * delete it yet since we don't want to try to recreate it in the next
   1138        * glCallLists.
   1139        */
   1140       atlas->complete = false;
   1141       atlas->incomplete = true;
   1142    }
   1143 }
   1144 
   1145 
   1146 /**
   1147  * Destroy a display list and remove from hash table.
   1148  * \param list - display list number
   1149  */
   1150 static void
   1151 destroy_list(struct gl_context *ctx, GLuint list)
   1152 {
   1153    struct gl_display_list *dlist;
   1154 
   1155    if (list == 0)
   1156       return;
   1157 
   1158    dlist = _mesa_lookup_list(ctx, list);
   1159    if (!dlist)
   1160       return;
   1161 
   1162    if (is_bitmap_list(dlist)) {
   1163       /* If we're destroying a simple glBitmap display list, there's a
   1164        * chance that we're destroying a bitmap image that's in a texture
   1165        * atlas.  Examine all atlases to see if that's the case.  There's
   1166        * usually few (if any) atlases so this isn't expensive.
   1167        */
   1168       _mesa_HashWalk(ctx->Shared->BitmapAtlas,
   1169                      check_atlas_for_deleted_list, &list);
   1170    }
   1171 
   1172    _mesa_delete_list(ctx, dlist);
   1173    _mesa_HashRemove(ctx->Shared->DisplayList, list);
   1174 }
   1175 
   1176 
   1177 /*
   1178  * Translate the nth element of list from <type> to GLint.
   1179  */
   1180 static GLint
   1181 translate_id(GLsizei n, GLenum type, const GLvoid * list)
   1182 {
   1183    GLbyte *bptr;
   1184    GLubyte *ubptr;
   1185    GLshort *sptr;
   1186    GLushort *usptr;
   1187    GLint *iptr;
   1188    GLuint *uiptr;
   1189    GLfloat *fptr;
   1190 
   1191    switch (type) {
   1192    case GL_BYTE:
   1193       bptr = (GLbyte *) list;
   1194       return (GLint) bptr[n];
   1195    case GL_UNSIGNED_BYTE:
   1196       ubptr = (GLubyte *) list;
   1197       return (GLint) ubptr[n];
   1198    case GL_SHORT:
   1199       sptr = (GLshort *) list;
   1200       return (GLint) sptr[n];
   1201    case GL_UNSIGNED_SHORT:
   1202       usptr = (GLushort *) list;
   1203       return (GLint) usptr[n];
   1204    case GL_INT:
   1205       iptr = (GLint *) list;
   1206       return iptr[n];
   1207    case GL_UNSIGNED_INT:
   1208       uiptr = (GLuint *) list;
   1209       return (GLint) uiptr[n];
   1210    case GL_FLOAT:
   1211       fptr = (GLfloat *) list;
   1212       return (GLint) floorf(fptr[n]);
   1213    case GL_2_BYTES:
   1214       ubptr = ((GLubyte *) list) + 2 * n;
   1215       return (GLint) ubptr[0] * 256
   1216            + (GLint) ubptr[1];
   1217    case GL_3_BYTES:
   1218       ubptr = ((GLubyte *) list) + 3 * n;
   1219       return (GLint) ubptr[0] * 65536
   1220            + (GLint) ubptr[1] * 256
   1221            + (GLint) ubptr[2];
   1222    case GL_4_BYTES:
   1223       ubptr = ((GLubyte *) list) + 4 * n;
   1224       return (GLint) ubptr[0] * 16777216
   1225            + (GLint) ubptr[1] * 65536
   1226            + (GLint) ubptr[2] * 256
   1227            + (GLint) ubptr[3];
   1228    default:
   1229       return 0;
   1230    }
   1231 }
   1232 
   1233 
   1234 /**
   1235  * Wrapper for _mesa_unpack_image/bitmap() that handles pixel buffer objects.
   1236  * If width < 0 or height < 0 or format or type are invalid we'll just
   1237  * return NULL.  We will not generate an error since OpenGL command
   1238  * arguments aren't error-checked until the command is actually executed
   1239  * (not when they're compiled).
   1240  * But if we run out of memory, GL_OUT_OF_MEMORY will be recorded.
   1241  */
   1242 static GLvoid *
   1243 unpack_image(struct gl_context *ctx, GLuint dimensions,
   1244              GLsizei width, GLsizei height, GLsizei depth,
   1245              GLenum format, GLenum type, const GLvoid * pixels,
   1246              const struct gl_pixelstore_attrib *unpack)
   1247 {
   1248    if (width <= 0 || height <= 0) {
   1249       return NULL;
   1250    }
   1251 
   1252    if (_mesa_bytes_per_pixel(format, type) < 0) {
   1253       /* bad format and/or type */
   1254       return NULL;
   1255    }
   1256 
   1257    if (!_mesa_is_bufferobj(unpack->BufferObj)) {
   1258       /* no PBO */
   1259       GLvoid *image;
   1260 
   1261       image = _mesa_unpack_image(dimensions, width, height, depth,
   1262                                  format, type, pixels, unpack);
   1263       if (pixels && !image) {
   1264          _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
   1265       }
   1266       return image;
   1267    }
   1268    else if (_mesa_validate_pbo_access(dimensions, unpack, width, height,
   1269                                       depth, format, type, INT_MAX, pixels)) {
   1270       const GLubyte *map, *src;
   1271       GLvoid *image;
   1272 
   1273       map = (GLubyte *)
   1274          ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
   1275                                     GL_MAP_READ_BIT, unpack->BufferObj,
   1276                                     MAP_INTERNAL);
   1277       if (!map) {
   1278          /* unable to map src buffer! */
   1279          _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO");
   1280          return NULL;
   1281       }
   1282 
   1283       src = ADD_POINTERS(map, pixels);
   1284       image = _mesa_unpack_image(dimensions, width, height, depth,
   1285                                  format, type, src, unpack);
   1286 
   1287       ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL);
   1288 
   1289       if (!image) {
   1290          _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
   1291       }
   1292       return image;
   1293    }
   1294 
   1295    /* bad access! */
   1296    _mesa_error(ctx, GL_INVALID_OPERATION, "invalid PBO access");
   1297    return NULL;
   1298 }
   1299 
   1300 
   1301 /** Return copy of memory */
   1302 static void *
   1303 memdup(const void *src, GLsizei bytes)
   1304 {
   1305    void *b = bytes >= 0 ? malloc(bytes) : NULL;
   1306    if (b)
   1307       memcpy(b, src, bytes);
   1308    return b;
   1309 }
   1310 
   1311 
   1312 /**
   1313  * Allocate space for a display list instruction (opcode + payload space).
   1314  * \param opcode  the instruction opcode (OPCODE_* value)
   1315  * \param bytes   instruction payload size (not counting opcode)
   1316  * \param align8  does the payload need to be 8-byte aligned?
   1317  *                This is only relevant in 64-bit environments.
   1318  * \return pointer to allocated memory (the payload will be at pointer+1)
   1319  */
   1320 static Node *
   1321 dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes, bool align8)
   1322 {
   1323    const GLuint numNodes = 1 + (bytes + sizeof(Node) - 1) / sizeof(Node);
   1324    const GLuint contNodes = 1 + POINTER_DWORDS;  /* size of continue info */
   1325    GLuint nopNode;
   1326    Node *n;
   1327 
   1328    if (opcode < OPCODE_EXT_0) {
   1329       if (InstSize[opcode] == 0) {
   1330          /* save instruction size now */
   1331          InstSize[opcode] = numNodes;
   1332       }
   1333       else {
   1334          /* make sure instruction size agrees */
   1335          assert(numNodes == InstSize[opcode]);
   1336       }
   1337    }
   1338 
   1339    if (sizeof(void *) > sizeof(Node) && align8
   1340        && ctx->ListState.CurrentPos % 2 == 0) {
   1341       /* The opcode would get placed at node[0] and the payload would start
   1342        * at node[1].  But the payload needs to be at an even offset (8-byte
   1343        * multiple).
   1344        */
   1345       nopNode = 1;
   1346    }
   1347    else {
   1348       nopNode = 0;
   1349    }
   1350 
   1351    if (ctx->ListState.CurrentPos + nopNode + numNodes + contNodes
   1352        > BLOCK_SIZE) {
   1353       /* This block is full.  Allocate a new block and chain to it */
   1354       Node *newblock;
   1355       n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
   1356       n[0].opcode = OPCODE_CONTINUE;
   1357       newblock = malloc(sizeof(Node) * BLOCK_SIZE);
   1358       if (!newblock) {
   1359          _mesa_error(ctx, GL_OUT_OF_MEMORY, "Building display list");
   1360          return NULL;
   1361       }
   1362 
   1363       /* a fresh block should be 8-byte aligned on 64-bit systems */
   1364       assert(((GLintptr) newblock) % sizeof(void *) == 0);
   1365 
   1366       save_pointer(&n[1], newblock);
   1367       ctx->ListState.CurrentBlock = newblock;
   1368       ctx->ListState.CurrentPos = 0;
   1369 
   1370       /* Display list nodes are always 4 bytes.  If we need 8-byte alignment
   1371        * we have to insert a NOP so that the payload of the real opcode lands
   1372        * on an even location:
   1373        *   node[0] = OPCODE_NOP
   1374        *   node[1] = OPCODE_x;
   1375        *   node[2] = start of payload
   1376        */
   1377       nopNode = sizeof(void *) > sizeof(Node) && align8;
   1378    }
   1379 
   1380    n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
   1381    if (nopNode) {
   1382       assert(ctx->ListState.CurrentPos % 2 == 0); /* even value */
   1383       n[0].opcode = OPCODE_NOP;
   1384       n++;
   1385       /* The "real" opcode will now be at an odd location and the payload
   1386        * will be at an even location.
   1387        */
   1388    }
   1389    ctx->ListState.CurrentPos += nopNode + numNodes;
   1390 
   1391    n[0].opcode = opcode;
   1392 
   1393    return n;
   1394 }
   1395 
   1396 
   1397 
   1398 /**
   1399  * Allocate space for a display list instruction.  Used by callers outside
   1400  * this file for things like VBO vertex data.
   1401  *
   1402  * \param opcode  the instruction opcode (OPCODE_* value)
   1403  * \param bytes   instruction size in bytes, not counting opcode.
   1404  * \return pointer to the usable data area (not including the internal
   1405  *         opcode).
   1406  */
   1407 void *
   1408 _mesa_dlist_alloc(struct gl_context *ctx, GLuint opcode, GLuint bytes)
   1409 {
   1410    Node *n = dlist_alloc(ctx, (OpCode) opcode, bytes, false);
   1411    if (n)
   1412       return n + 1;  /* return pointer to payload area, after opcode */
   1413    else
   1414       return NULL;
   1415 }
   1416 
   1417 
   1418 /**
   1419  * Same as _mesa_dlist_alloc(), but return a pointer which is 8-byte
   1420  * aligned in 64-bit environments, 4-byte aligned otherwise.
   1421  */
   1422 void *
   1423 _mesa_dlist_alloc_aligned(struct gl_context *ctx, GLuint opcode, GLuint bytes)
   1424 {
   1425    Node *n = dlist_alloc(ctx, (OpCode) opcode, bytes, true);
   1426    if (n)
   1427       return n + 1;  /* return pointer to payload area, after opcode */
   1428    else
   1429       return NULL;
   1430 }
   1431 
   1432 
   1433 /**
   1434  * This function allows modules and drivers to get their own opcodes
   1435  * for extending display list functionality.
   1436  * \param ctx  the rendering context
   1437  * \param size  number of bytes for storing the new display list command
   1438  * \param execute  function to execute the new display list command
   1439  * \param destroy  function to destroy the new display list command
   1440  * \param print  function to print the new display list command
   1441  * \return  the new opcode number or -1 if error
   1442  */
   1443 GLint
   1444 _mesa_dlist_alloc_opcode(struct gl_context *ctx,
   1445                          GLuint size,
   1446                          void (*execute) (struct gl_context *, void *),
   1447                          void (*destroy) (struct gl_context *, void *),
   1448                          void (*print) (struct gl_context *, void *, FILE *))
   1449 {
   1450    if (ctx->ListExt->NumOpcodes < MAX_DLIST_EXT_OPCODES) {
   1451       const GLuint i = ctx->ListExt->NumOpcodes++;
   1452       ctx->ListExt->Opcode[i].Size =
   1453          1 + (size + sizeof(Node) - 1) / sizeof(Node);
   1454       ctx->ListExt->Opcode[i].Execute = execute;
   1455       ctx->ListExt->Opcode[i].Destroy = destroy;
   1456       ctx->ListExt->Opcode[i].Print = print;
   1457       return i + OPCODE_EXT_0;
   1458    }
   1459    return -1;
   1460 }
   1461 
   1462 
   1463 /**
   1464  * Allocate space for a display list instruction.  The space is basically
   1465  * an array of Nodes where node[0] holds the opcode, node[1] is the first
   1466  * function parameter, node[2] is the second parameter, etc.
   1467  *
   1468  * \param opcode  one of OPCODE_x
   1469  * \param nparams  number of function parameters
   1470  * \return  pointer to start of instruction space
   1471  */
   1472 static inline Node *
   1473 alloc_instruction(struct gl_context *ctx, OpCode opcode, GLuint nparams)
   1474 {
   1475    return dlist_alloc(ctx, opcode, nparams * sizeof(Node), false);
   1476 }
   1477 
   1478 
   1479 /**
   1480  * Called by EndList to try to reduce memory used for the list.
   1481  */
   1482 static void
   1483 trim_list(struct gl_context *ctx)
   1484 {
   1485    /* If the list we're ending only has one allocated block of nodes/tokens
   1486     * and its size isn't a full block size, realloc the block to use less
   1487     * memory.  This is important for apps that create many small display
   1488     * lists and apps that use glXUseXFont (many lists each containing one
   1489     * glBitmap call).
   1490     * Note: we currently only trim display lists that allocated one block
   1491     * of tokens.  That hits the short list case which is what we're mainly
   1492     * concerned with.  Trimming longer lists would involve traversing the
   1493     * linked list of blocks.
   1494     */
   1495    struct gl_dlist_state *list = &ctx->ListState;
   1496 
   1497    if ((list->CurrentList->Head == list->CurrentBlock) &&
   1498        (list->CurrentPos < BLOCK_SIZE)) {
   1499       /* There's only one block and it's not full, so realloc */
   1500       GLuint newSize = list->CurrentPos * sizeof(Node);
   1501       list->CurrentList->Head =
   1502       list->CurrentBlock = realloc(list->CurrentBlock, newSize);
   1503       if (!list->CurrentBlock) {
   1504          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEndList");
   1505       }
   1506    }
   1507 }
   1508 
   1509 
   1510 
   1511 /*
   1512  * Display List compilation functions
   1513  */
   1514 static void GLAPIENTRY
   1515 save_Accum(GLenum op, GLfloat value)
   1516 {
   1517    GET_CURRENT_CONTEXT(ctx);
   1518    Node *n;
   1519    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1520    n = alloc_instruction(ctx, OPCODE_ACCUM, 2);
   1521    if (n) {
   1522       n[1].e = op;
   1523       n[2].f = value;
   1524    }
   1525    if (ctx->ExecuteFlag) {
   1526       CALL_Accum(ctx->Exec, (op, value));
   1527    }
   1528 }
   1529 
   1530 
   1531 static void GLAPIENTRY
   1532 save_AlphaFunc(GLenum func, GLclampf ref)
   1533 {
   1534    GET_CURRENT_CONTEXT(ctx);
   1535    Node *n;
   1536    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1537    n = alloc_instruction(ctx, OPCODE_ALPHA_FUNC, 2);
   1538    if (n) {
   1539       n[1].e = func;
   1540       n[2].f = (GLfloat) ref;
   1541    }
   1542    if (ctx->ExecuteFlag) {
   1543       CALL_AlphaFunc(ctx->Exec, (func, ref));
   1544    }
   1545 }
   1546 
   1547 
   1548 static void GLAPIENTRY
   1549 save_BindTexture(GLenum target, GLuint texture)
   1550 {
   1551    GET_CURRENT_CONTEXT(ctx);
   1552    Node *n;
   1553    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1554    n = alloc_instruction(ctx, OPCODE_BIND_TEXTURE, 2);
   1555    if (n) {
   1556       n[1].e = target;
   1557       n[2].ui = texture;
   1558    }
   1559    if (ctx->ExecuteFlag) {
   1560       CALL_BindTexture(ctx->Exec, (target, texture));
   1561    }
   1562 }
   1563 
   1564 
   1565 static void GLAPIENTRY
   1566 save_Bitmap(GLsizei width, GLsizei height,
   1567             GLfloat xorig, GLfloat yorig,
   1568             GLfloat xmove, GLfloat ymove, const GLubyte * pixels)
   1569 {
   1570    GET_CURRENT_CONTEXT(ctx);
   1571    Node *n;
   1572    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1573    n = alloc_instruction(ctx, OPCODE_BITMAP, 6 + POINTER_DWORDS);
   1574    if (n) {
   1575       n[1].i = (GLint) width;
   1576       n[2].i = (GLint) height;
   1577       n[3].f = xorig;
   1578       n[4].f = yorig;
   1579       n[5].f = xmove;
   1580       n[6].f = ymove;
   1581       save_pointer(&n[7],
   1582                    unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
   1583                                 GL_BITMAP, pixels, &ctx->Unpack));
   1584    }
   1585    if (ctx->ExecuteFlag) {
   1586       CALL_Bitmap(ctx->Exec, (width, height,
   1587                               xorig, yorig, xmove, ymove, pixels));
   1588    }
   1589 }
   1590 
   1591 
   1592 static void GLAPIENTRY
   1593 save_BlendEquation(GLenum mode)
   1594 {
   1595    GET_CURRENT_CONTEXT(ctx);
   1596    Node *n;
   1597    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1598    n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION, 1);
   1599    if (n) {
   1600       n[1].e = mode;
   1601    }
   1602    if (ctx->ExecuteFlag) {
   1603       CALL_BlendEquation(ctx->Exec, (mode));
   1604    }
   1605 }
   1606 
   1607 
   1608 static void GLAPIENTRY
   1609 save_BlendEquationSeparateEXT(GLenum modeRGB, GLenum modeA)
   1610 {
   1611    GET_CURRENT_CONTEXT(ctx);
   1612    Node *n;
   1613    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1614    n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION_SEPARATE, 2);
   1615    if (n) {
   1616       n[1].e = modeRGB;
   1617       n[2].e = modeA;
   1618    }
   1619    if (ctx->ExecuteFlag) {
   1620       CALL_BlendEquationSeparate(ctx->Exec, (modeRGB, modeA));
   1621    }
   1622 }
   1623 
   1624 
   1625 static void GLAPIENTRY
   1626 save_BlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB,
   1627                           GLenum sfactorA, GLenum dfactorA)
   1628 {
   1629    GET_CURRENT_CONTEXT(ctx);
   1630    Node *n;
   1631    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1632    n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_SEPARATE, 4);
   1633    if (n) {
   1634       n[1].e = sfactorRGB;
   1635       n[2].e = dfactorRGB;
   1636       n[3].e = sfactorA;
   1637       n[4].e = dfactorA;
   1638    }
   1639    if (ctx->ExecuteFlag) {
   1640       CALL_BlendFuncSeparate(ctx->Exec,
   1641                                 (sfactorRGB, dfactorRGB, sfactorA, dfactorA));
   1642    }
   1643 }
   1644 
   1645 
   1646 static void GLAPIENTRY
   1647 save_BlendFunc(GLenum srcfactor, GLenum dstfactor)
   1648 {
   1649    save_BlendFuncSeparateEXT(srcfactor, dstfactor, srcfactor, dstfactor);
   1650 }
   1651 
   1652 
   1653 static void GLAPIENTRY
   1654 save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
   1655 {
   1656    GET_CURRENT_CONTEXT(ctx);
   1657    Node *n;
   1658    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1659    n = alloc_instruction(ctx, OPCODE_BLEND_COLOR, 4);
   1660    if (n) {
   1661       n[1].f = red;
   1662       n[2].f = green;
   1663       n[3].f = blue;
   1664       n[4].f = alpha;
   1665    }
   1666    if (ctx->ExecuteFlag) {
   1667       CALL_BlendColor(ctx->Exec, (red, green, blue, alpha));
   1668    }
   1669 }
   1670 
   1671 /* GL_ARB_draw_buffers_blend */
   1672 static void GLAPIENTRY
   1673 save_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
   1674                         GLenum sfactorA, GLenum dfactorA)
   1675 {
   1676    GET_CURRENT_CONTEXT(ctx);
   1677    Node *n;
   1678    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1679    n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_SEPARATE_I, 5);
   1680    if (n) {
   1681       n[1].ui = buf;
   1682       n[2].e = sfactorRGB;
   1683       n[3].e = dfactorRGB;
   1684       n[4].e = sfactorA;
   1685       n[5].e = dfactorA;
   1686    }
   1687    if (ctx->ExecuteFlag) {
   1688       CALL_BlendFuncSeparateiARB(ctx->Exec, (buf, sfactorRGB, dfactorRGB,
   1689                                              sfactorA, dfactorA));
   1690    }
   1691 }
   1692 
   1693 /* GL_ARB_draw_buffers_blend */
   1694 static void GLAPIENTRY
   1695 save_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
   1696 {
   1697    GET_CURRENT_CONTEXT(ctx);
   1698    Node *n;
   1699    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1700    n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_I, 3);
   1701    if (n) {
   1702       n[1].ui = buf;
   1703       n[2].e = sfactor;
   1704       n[3].e = dfactor;
   1705    }
   1706    if (ctx->ExecuteFlag) {
   1707       CALL_BlendFunciARB(ctx->Exec, (buf, sfactor, dfactor));
   1708    }
   1709 }
   1710 
   1711 /* GL_ARB_draw_buffers_blend */
   1712 static void GLAPIENTRY
   1713 save_BlendEquationi(GLuint buf, GLenum mode)
   1714 {
   1715    GET_CURRENT_CONTEXT(ctx);
   1716    Node *n;
   1717    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1718    n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION_I, 2);
   1719    if (n) {
   1720       n[1].ui = buf;
   1721       n[2].e = mode;
   1722    }
   1723    if (ctx->ExecuteFlag) {
   1724       CALL_BlendEquationiARB(ctx->Exec, (buf, mode));
   1725    }
   1726 }
   1727 
   1728 /* GL_ARB_draw_buffers_blend */
   1729 static void GLAPIENTRY
   1730 save_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
   1731 {
   1732    GET_CURRENT_CONTEXT(ctx);
   1733    Node *n;
   1734    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1735    n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION_SEPARATE_I, 3);
   1736    if (n) {
   1737       n[1].ui = buf;
   1738       n[2].e = modeRGB;
   1739       n[3].e = modeA;
   1740    }
   1741    if (ctx->ExecuteFlag) {
   1742       CALL_BlendEquationSeparateiARB(ctx->Exec, (buf, modeRGB, modeA));
   1743    }
   1744 }
   1745 
   1746 
   1747 /* GL_ARB_draw_instanced. */
   1748 static void GLAPIENTRY
   1749 save_DrawArraysInstancedARB(UNUSED GLenum mode,
   1750                             UNUSED GLint first,
   1751                             UNUSED GLsizei count,
   1752                             UNUSED GLsizei primcount)
   1753 {
   1754    GET_CURRENT_CONTEXT(ctx);
   1755    _mesa_error(ctx, GL_INVALID_OPERATION,
   1756                "glDrawArraysInstanced() during display list compile");
   1757 }
   1758 
   1759 static void GLAPIENTRY
   1760 save_DrawElementsInstancedARB(UNUSED GLenum mode,
   1761                               UNUSED GLsizei count,
   1762                               UNUSED GLenum type,
   1763                               UNUSED const GLvoid *indices,
   1764                               UNUSED GLsizei primcount)
   1765 {
   1766    GET_CURRENT_CONTEXT(ctx);
   1767    _mesa_error(ctx, GL_INVALID_OPERATION,
   1768                "glDrawElementsInstanced() during display list compile");
   1769 }
   1770 
   1771 static void GLAPIENTRY
   1772 save_DrawElementsInstancedBaseVertexARB(UNUSED GLenum mode,
   1773                                         UNUSED GLsizei count,
   1774                                         UNUSED GLenum type,
   1775                                         UNUSED const GLvoid *indices,
   1776                                         UNUSED GLsizei primcount,
   1777                                         UNUSED GLint basevertex)
   1778 {
   1779    GET_CURRENT_CONTEXT(ctx);
   1780    _mesa_error(ctx, GL_INVALID_OPERATION,
   1781                "glDrawElementsInstancedBaseVertex() during display list compile");
   1782 }
   1783 
   1784 /* GL_ARB_base_instance. */
   1785 static void GLAPIENTRY
   1786 save_DrawArraysInstancedBaseInstance(UNUSED GLenum mode,
   1787                                      UNUSED GLint first,
   1788                                      UNUSED GLsizei count,
   1789                                      UNUSED GLsizei primcount,
   1790                                      UNUSED GLuint baseinstance)
   1791 {
   1792    GET_CURRENT_CONTEXT(ctx);
   1793    _mesa_error(ctx, GL_INVALID_OPERATION,
   1794                "glDrawArraysInstancedBaseInstance() during display list compile");
   1795 }
   1796 
   1797 static void APIENTRY
   1798 save_DrawElementsInstancedBaseInstance(UNUSED GLenum mode,
   1799                                        UNUSED GLsizei count,
   1800                                        UNUSED GLenum type,
   1801                                        UNUSED const void *indices,
   1802                                        UNUSED GLsizei primcount,
   1803                                        UNUSED GLuint baseinstance)
   1804 {
   1805    GET_CURRENT_CONTEXT(ctx);
   1806    _mesa_error(ctx, GL_INVALID_OPERATION,
   1807                "glDrawElementsInstancedBaseInstance() during display list compile");
   1808 }
   1809 
   1810 static void APIENTRY
   1811 save_DrawElementsInstancedBaseVertexBaseInstance(UNUSED GLenum mode,
   1812                                                  UNUSED GLsizei count,
   1813                                                  UNUSED GLenum type,
   1814                                                  UNUSED const void *indices,
   1815                                                  UNUSED GLsizei primcount,
   1816                                                  UNUSED GLint basevertex,
   1817                                                  UNUSED GLuint baseinstance)
   1818 {
   1819    GET_CURRENT_CONTEXT(ctx);
   1820    _mesa_error(ctx, GL_INVALID_OPERATION,
   1821                "glDrawElementsInstancedBaseVertexBaseInstance() during display list compile");
   1822 }
   1823 
   1824 
   1825 /**
   1826  * While building a display list we cache some OpenGL state.
   1827  * Under some circumstances we need to invalidate that state (immediately
   1828  * when we start compiling a list, or after glCallList(s)).
   1829  */
   1830 static void
   1831 invalidate_saved_current_state(struct gl_context *ctx)
   1832 {
   1833    GLint i;
   1834 
   1835    for (i = 0; i < VERT_ATTRIB_MAX; i++)
   1836       ctx->ListState.ActiveAttribSize[i] = 0;
   1837 
   1838    for (i = 0; i < MAT_ATTRIB_MAX; i++)
   1839       ctx->ListState.ActiveMaterialSize[i] = 0;
   1840 
   1841    memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
   1842 
   1843    ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
   1844 }
   1845 
   1846 
   1847 static void GLAPIENTRY
   1848 save_CallList(GLuint list)
   1849 {
   1850    GET_CURRENT_CONTEXT(ctx);
   1851    Node *n;
   1852    SAVE_FLUSH_VERTICES(ctx);
   1853 
   1854    n = alloc_instruction(ctx, OPCODE_CALL_LIST, 1);
   1855    if (n) {
   1856       n[1].ui = list;
   1857    }
   1858 
   1859    /* After this, we don't know what state we're in.  Invalidate all
   1860     * cached information previously gathered:
   1861     */
   1862    invalidate_saved_current_state( ctx );
   1863 
   1864    if (ctx->ExecuteFlag) {
   1865       _mesa_CallList(list);
   1866    }
   1867 }
   1868 
   1869 
   1870 static void GLAPIENTRY
   1871 save_CallLists(GLsizei num, GLenum type, const GLvoid * lists)
   1872 {
   1873    GET_CURRENT_CONTEXT(ctx);
   1874    unsigned type_size;
   1875    Node *n;
   1876    void *lists_copy;
   1877 
   1878    SAVE_FLUSH_VERTICES(ctx);
   1879 
   1880    switch (type) {
   1881    case GL_BYTE:
   1882    case GL_UNSIGNED_BYTE:
   1883       type_size = 1;
   1884       break;
   1885    case GL_SHORT:
   1886    case GL_UNSIGNED_SHORT:
   1887    case GL_2_BYTES:
   1888       type_size = 2;
   1889       break;
   1890    case GL_3_BYTES:
   1891       type_size = 3;
   1892       break;
   1893    case GL_INT:
   1894    case GL_UNSIGNED_INT:
   1895    case GL_FLOAT:
   1896    case GL_4_BYTES:
   1897       type_size = 4;
   1898       break;
   1899    default:
   1900       type_size = 0;
   1901    }
   1902 
   1903    if (num > 0 && type_size > 0) {
   1904       /* create a copy of the array of list IDs to save in the display list */
   1905       lists_copy = memdup(lists, num * type_size);
   1906    } else {
   1907       lists_copy = NULL;
   1908    }
   1909 
   1910    n = alloc_instruction(ctx, OPCODE_CALL_LISTS, 2 + POINTER_DWORDS);
   1911    if (n) {
   1912       n[1].i = num;
   1913       n[2].e = type;
   1914       save_pointer(&n[3], lists_copy);
   1915    }
   1916 
   1917    /* After this, we don't know what state we're in.  Invalidate all
   1918     * cached information previously gathered:
   1919     */
   1920    invalidate_saved_current_state( ctx );
   1921 
   1922    if (ctx->ExecuteFlag) {
   1923       CALL_CallLists(ctx->Exec, (num, type, lists));
   1924    }
   1925 }
   1926 
   1927 
   1928 static void GLAPIENTRY
   1929 save_Clear(GLbitfield mask)
   1930 {
   1931    GET_CURRENT_CONTEXT(ctx);
   1932    Node *n;
   1933    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1934    n = alloc_instruction(ctx, OPCODE_CLEAR, 1);
   1935    if (n) {
   1936       n[1].bf = mask;
   1937    }
   1938    if (ctx->ExecuteFlag) {
   1939       CALL_Clear(ctx->Exec, (mask));
   1940    }
   1941 }
   1942 
   1943 
   1944 static void GLAPIENTRY
   1945 save_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
   1946 {
   1947    GET_CURRENT_CONTEXT(ctx);
   1948    Node *n;
   1949    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1950    n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_IV, 6);
   1951    if (n) {
   1952       n[1].e = buffer;
   1953       n[2].i = drawbuffer;
   1954       n[3].i = value[0];
   1955       if (buffer == GL_COLOR) {
   1956          n[4].i = value[1];
   1957          n[5].i = value[2];
   1958          n[6].i = value[3];
   1959       }
   1960       else {
   1961          n[4].i = 0;
   1962          n[5].i = 0;
   1963          n[6].i = 0;
   1964       }
   1965    }
   1966    if (ctx->ExecuteFlag) {
   1967       CALL_ClearBufferiv(ctx->Exec, (buffer, drawbuffer, value));
   1968    }
   1969 }
   1970 
   1971 
   1972 static void GLAPIENTRY
   1973 save_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
   1974 {
   1975    GET_CURRENT_CONTEXT(ctx);
   1976    Node *n;
   1977    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   1978    n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_UIV, 6);
   1979    if (n) {
   1980       n[1].e = buffer;
   1981       n[2].i = drawbuffer;
   1982       n[3].ui = value[0];
   1983       if (buffer == GL_COLOR) {
   1984          n[4].ui = value[1];
   1985          n[5].ui = value[2];
   1986          n[6].ui = value[3];
   1987       }
   1988       else {
   1989          n[4].ui = 0;
   1990          n[5].ui = 0;
   1991          n[6].ui = 0;
   1992       }
   1993    }
   1994    if (ctx->ExecuteFlag) {
   1995       CALL_ClearBufferuiv(ctx->Exec, (buffer, drawbuffer, value));
   1996    }
   1997 }
   1998 
   1999 
   2000 static void GLAPIENTRY
   2001 save_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
   2002 {
   2003    GET_CURRENT_CONTEXT(ctx);
   2004    Node *n;
   2005    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2006    n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_FV, 6);
   2007    if (n) {
   2008       n[1].e = buffer;
   2009       n[2].i = drawbuffer;
   2010       n[3].f = value[0];
   2011       if (buffer == GL_COLOR) {
   2012          n[4].f = value[1];
   2013          n[5].f = value[2];
   2014          n[6].f = value[3];
   2015       }
   2016       else {
   2017          n[4].f = 0.0F;
   2018          n[5].f = 0.0F;
   2019          n[6].f = 0.0F;
   2020       }
   2021    }
   2022    if (ctx->ExecuteFlag) {
   2023       CALL_ClearBufferfv(ctx->Exec, (buffer, drawbuffer, value));
   2024    }
   2025 }
   2026 
   2027 
   2028 static void GLAPIENTRY
   2029 save_ClearBufferfi(GLenum buffer, GLint drawbuffer,
   2030                    GLfloat depth, GLint stencil)
   2031 {
   2032    GET_CURRENT_CONTEXT(ctx);
   2033    Node *n;
   2034    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2035    n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_FI, 4);
   2036    if (n) {
   2037       n[1].e = buffer;
   2038       n[2].i = drawbuffer;
   2039       n[3].f = depth;
   2040       n[4].i = stencil;
   2041    }
   2042    if (ctx->ExecuteFlag) {
   2043       CALL_ClearBufferfi(ctx->Exec, (buffer, drawbuffer, depth, stencil));
   2044    }
   2045 }
   2046 
   2047 
   2048 static void GLAPIENTRY
   2049 save_ClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
   2050 {
   2051    GET_CURRENT_CONTEXT(ctx);
   2052    Node *n;
   2053    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2054    n = alloc_instruction(ctx, OPCODE_CLEAR_ACCUM, 4);
   2055    if (n) {
   2056       n[1].f = red;
   2057       n[2].f = green;
   2058       n[3].f = blue;
   2059       n[4].f = alpha;
   2060    }
   2061    if (ctx->ExecuteFlag) {
   2062       CALL_ClearAccum(ctx->Exec, (red, green, blue, alpha));
   2063    }
   2064 }
   2065 
   2066 
   2067 static void GLAPIENTRY
   2068 save_ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
   2069 {
   2070    GET_CURRENT_CONTEXT(ctx);
   2071    Node *n;
   2072    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2073    n = alloc_instruction(ctx, OPCODE_CLEAR_COLOR, 4);
   2074    if (n) {
   2075       n[1].f = red;
   2076       n[2].f = green;
   2077       n[3].f = blue;
   2078       n[4].f = alpha;
   2079    }
   2080    if (ctx->ExecuteFlag) {
   2081       CALL_ClearColor(ctx->Exec, (red, green, blue, alpha));
   2082    }
   2083 }
   2084 
   2085 
   2086 static void GLAPIENTRY
   2087 save_ClearDepth(GLclampd depth)
   2088 {
   2089    GET_CURRENT_CONTEXT(ctx);
   2090    Node *n;
   2091    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2092    n = alloc_instruction(ctx, OPCODE_CLEAR_DEPTH, 1);
   2093    if (n) {
   2094       n[1].f = (GLfloat) depth;
   2095    }
   2096    if (ctx->ExecuteFlag) {
   2097       CALL_ClearDepth(ctx->Exec, (depth));
   2098    }
   2099 }
   2100 
   2101 
   2102 static void GLAPIENTRY
   2103 save_ClearIndex(GLfloat c)
   2104 {
   2105    GET_CURRENT_CONTEXT(ctx);
   2106    Node *n;
   2107    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2108    n = alloc_instruction(ctx, OPCODE_CLEAR_INDEX, 1);
   2109    if (n) {
   2110       n[1].f = c;
   2111    }
   2112    if (ctx->ExecuteFlag) {
   2113       CALL_ClearIndex(ctx->Exec, (c));
   2114    }
   2115 }
   2116 
   2117 
   2118 static void GLAPIENTRY
   2119 save_ClearStencil(GLint s)
   2120 {
   2121    GET_CURRENT_CONTEXT(ctx);
   2122    Node *n;
   2123    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2124    n = alloc_instruction(ctx, OPCODE_CLEAR_STENCIL, 1);
   2125    if (n) {
   2126       n[1].i = s;
   2127    }
   2128    if (ctx->ExecuteFlag) {
   2129       CALL_ClearStencil(ctx->Exec, (s));
   2130    }
   2131 }
   2132 
   2133 
   2134 static void GLAPIENTRY
   2135 save_ClipPlane(GLenum plane, const GLdouble * equ)
   2136 {
   2137    GET_CURRENT_CONTEXT(ctx);
   2138    Node *n;
   2139    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2140    n = alloc_instruction(ctx, OPCODE_CLIP_PLANE, 5);
   2141    if (n) {
   2142       n[1].e = plane;
   2143       n[2].f = (GLfloat) equ[0];
   2144       n[3].f = (GLfloat) equ[1];
   2145       n[4].f = (GLfloat) equ[2];
   2146       n[5].f = (GLfloat) equ[3];
   2147    }
   2148    if (ctx->ExecuteFlag) {
   2149       CALL_ClipPlane(ctx->Exec, (plane, equ));
   2150    }
   2151 }
   2152 
   2153 
   2154 
   2155 static void GLAPIENTRY
   2156 save_ColorMask(GLboolean red, GLboolean green,
   2157                GLboolean blue, GLboolean alpha)
   2158 {
   2159    GET_CURRENT_CONTEXT(ctx);
   2160    Node *n;
   2161    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2162    n = alloc_instruction(ctx, OPCODE_COLOR_MASK, 4);
   2163    if (n) {
   2164       n[1].b = red;
   2165       n[2].b = green;
   2166       n[3].b = blue;
   2167       n[4].b = alpha;
   2168    }
   2169    if (ctx->ExecuteFlag) {
   2170       CALL_ColorMask(ctx->Exec, (red, green, blue, alpha));
   2171    }
   2172 }
   2173 
   2174 
   2175 static void GLAPIENTRY
   2176 save_ColorMaskIndexed(GLuint buf, GLboolean red, GLboolean green,
   2177                       GLboolean blue, GLboolean alpha)
   2178 {
   2179    GET_CURRENT_CONTEXT(ctx);
   2180    Node *n;
   2181    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2182    n = alloc_instruction(ctx, OPCODE_COLOR_MASK_INDEXED, 5);
   2183    if (n) {
   2184       n[1].ui = buf;
   2185       n[2].b = red;
   2186       n[3].b = green;
   2187       n[4].b = blue;
   2188       n[5].b = alpha;
   2189    }
   2190    if (ctx->ExecuteFlag) {
   2191       /*CALL_ColorMaski(ctx->Exec, (buf, red, green, blue, alpha));*/
   2192    }
   2193 }
   2194 
   2195 
   2196 static void GLAPIENTRY
   2197 save_ColorMaterial(GLenum face, GLenum mode)
   2198 {
   2199    GET_CURRENT_CONTEXT(ctx);
   2200    Node *n;
   2201    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2202 
   2203    n = alloc_instruction(ctx, OPCODE_COLOR_MATERIAL, 2);
   2204    if (n) {
   2205       n[1].e = face;
   2206       n[2].e = mode;
   2207    }
   2208    if (ctx->ExecuteFlag) {
   2209       CALL_ColorMaterial(ctx->Exec, (face, mode));
   2210    }
   2211 }
   2212 
   2213 
   2214 static void GLAPIENTRY
   2215 save_CopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
   2216 {
   2217    GET_CURRENT_CONTEXT(ctx);
   2218    Node *n;
   2219    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2220    n = alloc_instruction(ctx, OPCODE_COPY_PIXELS, 5);
   2221    if (n) {
   2222       n[1].i = x;
   2223       n[2].i = y;
   2224       n[3].i = (GLint) width;
   2225       n[4].i = (GLint) height;
   2226       n[5].e = type;
   2227    }
   2228    if (ctx->ExecuteFlag) {
   2229       CALL_CopyPixels(ctx->Exec, (x, y, width, height, type));
   2230    }
   2231 }
   2232 
   2233 
   2234 
   2235 static void GLAPIENTRY
   2236 save_CopyTexImage1D(GLenum target, GLint level, GLenum internalformat,
   2237                     GLint x, GLint y, GLsizei width, GLint border)
   2238 {
   2239    GET_CURRENT_CONTEXT(ctx);
   2240    Node *n;
   2241    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2242    n = alloc_instruction(ctx, OPCODE_COPY_TEX_IMAGE1D, 7);
   2243    if (n) {
   2244       n[1].e = target;
   2245       n[2].i = level;
   2246       n[3].e = internalformat;
   2247       n[4].i = x;
   2248       n[5].i = y;
   2249       n[6].i = width;
   2250       n[7].i = border;
   2251    }
   2252    if (ctx->ExecuteFlag) {
   2253       CALL_CopyTexImage1D(ctx->Exec, (target, level, internalformat,
   2254                                       x, y, width, border));
   2255    }
   2256 }
   2257 
   2258 
   2259 static void GLAPIENTRY
   2260 save_CopyTexImage2D(GLenum target, GLint level,
   2261                     GLenum internalformat,
   2262                     GLint x, GLint y, GLsizei width,
   2263                     GLsizei height, GLint border)
   2264 {
   2265    GET_CURRENT_CONTEXT(ctx);
   2266    Node *n;
   2267    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2268    n = alloc_instruction(ctx, OPCODE_COPY_TEX_IMAGE2D, 8);
   2269    if (n) {
   2270       n[1].e = target;
   2271       n[2].i = level;
   2272       n[3].e = internalformat;
   2273       n[4].i = x;
   2274       n[5].i = y;
   2275       n[6].i = width;
   2276       n[7].i = height;
   2277       n[8].i = border;
   2278    }
   2279    if (ctx->ExecuteFlag) {
   2280       CALL_CopyTexImage2D(ctx->Exec, (target, level, internalformat,
   2281                                       x, y, width, height, border));
   2282    }
   2283 }
   2284 
   2285 
   2286 
   2287 static void GLAPIENTRY
   2288 save_CopyTexSubImage1D(GLenum target, GLint level,
   2289                        GLint xoffset, GLint x, GLint y, GLsizei width)
   2290 {
   2291    GET_CURRENT_CONTEXT(ctx);
   2292    Node *n;
   2293    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2294    n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE1D, 6);
   2295    if (n) {
   2296       n[1].e = target;
   2297       n[2].i = level;
   2298       n[3].i = xoffset;
   2299       n[4].i = x;
   2300       n[5].i = y;
   2301       n[6].i = width;
   2302    }
   2303    if (ctx->ExecuteFlag) {
   2304       CALL_CopyTexSubImage1D(ctx->Exec,
   2305                              (target, level, xoffset, x, y, width));
   2306    }
   2307 }
   2308 
   2309 
   2310 static void GLAPIENTRY
   2311 save_CopyTexSubImage2D(GLenum target, GLint level,
   2312                        GLint xoffset, GLint yoffset,
   2313                        GLint x, GLint y, GLsizei width, GLint height)
   2314 {
   2315    GET_CURRENT_CONTEXT(ctx);
   2316    Node *n;
   2317    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2318    n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE2D, 8);
   2319    if (n) {
   2320       n[1].e = target;
   2321       n[2].i = level;
   2322       n[3].i = xoffset;
   2323       n[4].i = yoffset;
   2324       n[5].i = x;
   2325       n[6].i = y;
   2326       n[7].i = width;
   2327       n[8].i = height;
   2328    }
   2329    if (ctx->ExecuteFlag) {
   2330       CALL_CopyTexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
   2331                                          x, y, width, height));
   2332    }
   2333 }
   2334 
   2335 
   2336 static void GLAPIENTRY
   2337 save_CopyTexSubImage3D(GLenum target, GLint level,
   2338                        GLint xoffset, GLint yoffset, GLint zoffset,
   2339                        GLint x, GLint y, GLsizei width, GLint height)
   2340 {
   2341    GET_CURRENT_CONTEXT(ctx);
   2342    Node *n;
   2343    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2344    n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE3D, 9);
   2345    if (n) {
   2346       n[1].e = target;
   2347       n[2].i = level;
   2348       n[3].i = xoffset;
   2349       n[4].i = yoffset;
   2350       n[5].i = zoffset;
   2351       n[6].i = x;
   2352       n[7].i = y;
   2353       n[8].i = width;
   2354       n[9].i = height;
   2355    }
   2356    if (ctx->ExecuteFlag) {
   2357       CALL_CopyTexSubImage3D(ctx->Exec, (target, level,
   2358                                          xoffset, yoffset, zoffset,
   2359                                          x, y, width, height));
   2360    }
   2361 }
   2362 
   2363 
   2364 static void GLAPIENTRY
   2365 save_CullFace(GLenum mode)
   2366 {
   2367    GET_CURRENT_CONTEXT(ctx);
   2368    Node *n;
   2369    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2370    n = alloc_instruction(ctx, OPCODE_CULL_FACE, 1);
   2371    if (n) {
   2372       n[1].e = mode;
   2373    }
   2374    if (ctx->ExecuteFlag) {
   2375       CALL_CullFace(ctx->Exec, (mode));
   2376    }
   2377 }
   2378 
   2379 
   2380 static void GLAPIENTRY
   2381 save_DepthFunc(GLenum func)
   2382 {
   2383    GET_CURRENT_CONTEXT(ctx);
   2384    Node *n;
   2385    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2386    n = alloc_instruction(ctx, OPCODE_DEPTH_FUNC, 1);
   2387    if (n) {
   2388       n[1].e = func;
   2389    }
   2390    if (ctx->ExecuteFlag) {
   2391       CALL_DepthFunc(ctx->Exec, (func));
   2392    }
   2393 }
   2394 
   2395 
   2396 static void GLAPIENTRY
   2397 save_DepthMask(GLboolean mask)
   2398 {
   2399    GET_CURRENT_CONTEXT(ctx);
   2400    Node *n;
   2401    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2402    n = alloc_instruction(ctx, OPCODE_DEPTH_MASK, 1);
   2403    if (n) {
   2404       n[1].b = mask;
   2405    }
   2406    if (ctx->ExecuteFlag) {
   2407       CALL_DepthMask(ctx->Exec, (mask));
   2408    }
   2409 }
   2410 
   2411 
   2412 static void GLAPIENTRY
   2413 save_DepthRange(GLclampd nearval, GLclampd farval)
   2414 {
   2415    GET_CURRENT_CONTEXT(ctx);
   2416    Node *n;
   2417    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2418    n = alloc_instruction(ctx, OPCODE_DEPTH_RANGE, 2);
   2419    if (n) {
   2420       n[1].f = (GLfloat) nearval;
   2421       n[2].f = (GLfloat) farval;
   2422    }
   2423    if (ctx->ExecuteFlag) {
   2424       CALL_DepthRange(ctx->Exec, (nearval, farval));
   2425    }
   2426 }
   2427 
   2428 
   2429 static void GLAPIENTRY
   2430 save_Disable(GLenum cap)
   2431 {
   2432    GET_CURRENT_CONTEXT(ctx);
   2433    Node *n;
   2434    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2435    n = alloc_instruction(ctx, OPCODE_DISABLE, 1);
   2436    if (n) {
   2437       n[1].e = cap;
   2438    }
   2439    if (ctx->ExecuteFlag) {
   2440       CALL_Disable(ctx->Exec, (cap));
   2441    }
   2442 }
   2443 
   2444 
   2445 static void GLAPIENTRY
   2446 save_DisableIndexed(GLuint index, GLenum cap)
   2447 {
   2448    GET_CURRENT_CONTEXT(ctx);
   2449    Node *n;
   2450    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2451    n = alloc_instruction(ctx, OPCODE_DISABLE_INDEXED, 2);
   2452    if (n) {
   2453       n[1].ui = index;
   2454       n[2].e = cap;
   2455    }
   2456    if (ctx->ExecuteFlag) {
   2457       CALL_Disablei(ctx->Exec, (index, cap));
   2458    }
   2459 }
   2460 
   2461 
   2462 static void GLAPIENTRY
   2463 save_DrawBuffer(GLenum mode)
   2464 {
   2465    GET_CURRENT_CONTEXT(ctx);
   2466    Node *n;
   2467    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2468    n = alloc_instruction(ctx, OPCODE_DRAW_BUFFER, 1);
   2469    if (n) {
   2470       n[1].e = mode;
   2471    }
   2472    if (ctx->ExecuteFlag) {
   2473       CALL_DrawBuffer(ctx->Exec, (mode));
   2474    }
   2475 }
   2476 
   2477 
   2478 static void GLAPIENTRY
   2479 save_DrawPixels(GLsizei width, GLsizei height,
   2480                 GLenum format, GLenum type, const GLvoid * pixels)
   2481 {
   2482    GET_CURRENT_CONTEXT(ctx);
   2483    Node *n;
   2484 
   2485    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2486 
   2487    n = alloc_instruction(ctx, OPCODE_DRAW_PIXELS, 4 + POINTER_DWORDS);
   2488    if (n) {
   2489       n[1].i = width;
   2490       n[2].i = height;
   2491       n[3].e = format;
   2492       n[4].e = type;
   2493       save_pointer(&n[5],
   2494                    unpack_image(ctx, 2, width, height, 1, format, type,
   2495                                 pixels, &ctx->Unpack));
   2496    }
   2497    if (ctx->ExecuteFlag) {
   2498       CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels));
   2499    }
   2500 }
   2501 
   2502 
   2503 
   2504 static void GLAPIENTRY
   2505 save_Enable(GLenum cap)
   2506 {
   2507    GET_CURRENT_CONTEXT(ctx);
   2508    Node *n;
   2509    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2510    n = alloc_instruction(ctx, OPCODE_ENABLE, 1);
   2511    if (n) {
   2512       n[1].e = cap;
   2513    }
   2514    if (ctx->ExecuteFlag) {
   2515       CALL_Enable(ctx->Exec, (cap));
   2516    }
   2517 }
   2518 
   2519 
   2520 
   2521 static void GLAPIENTRY
   2522 save_EnableIndexed(GLuint index, GLenum cap)
   2523 {
   2524    GET_CURRENT_CONTEXT(ctx);
   2525    Node *n;
   2526    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2527    n = alloc_instruction(ctx, OPCODE_ENABLE_INDEXED, 2);
   2528    if (n) {
   2529       n[1].ui = index;
   2530       n[2].e = cap;
   2531    }
   2532    if (ctx->ExecuteFlag) {
   2533       CALL_Enablei(ctx->Exec, (index, cap));
   2534    }
   2535 }
   2536 
   2537 
   2538 
   2539 static void GLAPIENTRY
   2540 save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
   2541 {
   2542    GET_CURRENT_CONTEXT(ctx);
   2543    Node *n;
   2544    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2545    n = alloc_instruction(ctx, OPCODE_EVALMESH1, 3);
   2546    if (n) {
   2547       n[1].e = mode;
   2548       n[2].i = i1;
   2549       n[3].i = i2;
   2550    }
   2551    if (ctx->ExecuteFlag) {
   2552       CALL_EvalMesh1(ctx->Exec, (mode, i1, i2));
   2553    }
   2554 }
   2555 
   2556 
   2557 static void GLAPIENTRY
   2558 save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
   2559 {
   2560    GET_CURRENT_CONTEXT(ctx);
   2561    Node *n;
   2562    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2563    n = alloc_instruction(ctx, OPCODE_EVALMESH2, 5);
   2564    if (n) {
   2565       n[1].e = mode;
   2566       n[2].i = i1;
   2567       n[3].i = i2;
   2568       n[4].i = j1;
   2569       n[5].i = j2;
   2570    }
   2571    if (ctx->ExecuteFlag) {
   2572       CALL_EvalMesh2(ctx->Exec, (mode, i1, i2, j1, j2));
   2573    }
   2574 }
   2575 
   2576 
   2577 
   2578 
   2579 static void GLAPIENTRY
   2580 save_Fogfv(GLenum pname, const GLfloat *params)
   2581 {
   2582    GET_CURRENT_CONTEXT(ctx);
   2583    Node *n;
   2584    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2585    n = alloc_instruction(ctx, OPCODE_FOG, 5);
   2586    if (n) {
   2587       n[1].e = pname;
   2588       n[2].f = params[0];
   2589       n[3].f = params[1];
   2590       n[4].f = params[2];
   2591       n[5].f = params[3];
   2592    }
   2593    if (ctx->ExecuteFlag) {
   2594       CALL_Fogfv(ctx->Exec, (pname, params));
   2595    }
   2596 }
   2597 
   2598 
   2599 static void GLAPIENTRY
   2600 save_Fogf(GLenum pname, GLfloat param)
   2601 {
   2602    GLfloat parray[4];
   2603    parray[0] = param;
   2604    parray[1] = parray[2] = parray[3] = 0.0F;
   2605    save_Fogfv(pname, parray);
   2606 }
   2607 
   2608 
   2609 static void GLAPIENTRY
   2610 save_Fogiv(GLenum pname, const GLint *params)
   2611 {
   2612    GLfloat p[4];
   2613    switch (pname) {
   2614    case GL_FOG_MODE:
   2615    case GL_FOG_DENSITY:
   2616    case GL_FOG_START:
   2617    case GL_FOG_END:
   2618    case GL_FOG_INDEX:
   2619       p[0] = (GLfloat) *params;
   2620       p[1] = 0.0f;
   2621       p[2] = 0.0f;
   2622       p[3] = 0.0f;
   2623       break;
   2624    case GL_FOG_COLOR:
   2625       p[0] = INT_TO_FLOAT(params[0]);
   2626       p[1] = INT_TO_FLOAT(params[1]);
   2627       p[2] = INT_TO_FLOAT(params[2]);
   2628       p[3] = INT_TO_FLOAT(params[3]);
   2629       break;
   2630    default:
   2631       /* Error will be caught later in gl_Fogfv */
   2632       ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
   2633    }
   2634    save_Fogfv(pname, p);
   2635 }
   2636 
   2637 
   2638 static void GLAPIENTRY
   2639 save_Fogi(GLenum pname, GLint param)
   2640 {
   2641    GLint parray[4];
   2642    parray[0] = param;
   2643    parray[1] = parray[2] = parray[3] = 0;
   2644    save_Fogiv(pname, parray);
   2645 }
   2646 
   2647 
   2648 static void GLAPIENTRY
   2649 save_FrontFace(GLenum mode)
   2650 {
   2651    GET_CURRENT_CONTEXT(ctx);
   2652    Node *n;
   2653    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2654    n = alloc_instruction(ctx, OPCODE_FRONT_FACE, 1);
   2655    if (n) {
   2656       n[1].e = mode;
   2657    }
   2658    if (ctx->ExecuteFlag) {
   2659       CALL_FrontFace(ctx->Exec, (mode));
   2660    }
   2661 }
   2662 
   2663 
   2664 static void GLAPIENTRY
   2665 save_Frustum(GLdouble left, GLdouble right,
   2666              GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
   2667 {
   2668    GET_CURRENT_CONTEXT(ctx);
   2669    Node *n;
   2670    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2671    n = alloc_instruction(ctx, OPCODE_FRUSTUM, 6);
   2672    if (n) {
   2673       n[1].f = (GLfloat) left;
   2674       n[2].f = (GLfloat) right;
   2675       n[3].f = (GLfloat) bottom;
   2676       n[4].f = (GLfloat) top;
   2677       n[5].f = (GLfloat) nearval;
   2678       n[6].f = (GLfloat) farval;
   2679    }
   2680    if (ctx->ExecuteFlag) {
   2681       CALL_Frustum(ctx->Exec, (left, right, bottom, top, nearval, farval));
   2682    }
   2683 }
   2684 
   2685 
   2686 static void GLAPIENTRY
   2687 save_Hint(GLenum target, GLenum mode)
   2688 {
   2689    GET_CURRENT_CONTEXT(ctx);
   2690    Node *n;
   2691    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2692    n = alloc_instruction(ctx, OPCODE_HINT, 2);
   2693    if (n) {
   2694       n[1].e = target;
   2695       n[2].e = mode;
   2696    }
   2697    if (ctx->ExecuteFlag) {
   2698       CALL_Hint(ctx->Exec, (target, mode));
   2699    }
   2700 }
   2701 
   2702 
   2703 static void GLAPIENTRY
   2704 save_IndexMask(GLuint mask)
   2705 {
   2706    GET_CURRENT_CONTEXT(ctx);
   2707    Node *n;
   2708    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2709    n = alloc_instruction(ctx, OPCODE_INDEX_MASK, 1);
   2710    if (n) {
   2711       n[1].ui = mask;
   2712    }
   2713    if (ctx->ExecuteFlag) {
   2714       CALL_IndexMask(ctx->Exec, (mask));
   2715    }
   2716 }
   2717 
   2718 
   2719 static void GLAPIENTRY
   2720 save_InitNames(void)
   2721 {
   2722    GET_CURRENT_CONTEXT(ctx);
   2723    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2724    (void) alloc_instruction(ctx, OPCODE_INIT_NAMES, 0);
   2725    if (ctx->ExecuteFlag) {
   2726       CALL_InitNames(ctx->Exec, ());
   2727    }
   2728 }
   2729 
   2730 
   2731 static void GLAPIENTRY
   2732 save_Lightfv(GLenum light, GLenum pname, const GLfloat *params)
   2733 {
   2734    GET_CURRENT_CONTEXT(ctx);
   2735    Node *n;
   2736    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2737    n = alloc_instruction(ctx, OPCODE_LIGHT, 6);
   2738    if (n) {
   2739       GLint i, nParams;
   2740       n[1].e = light;
   2741       n[2].e = pname;
   2742       switch (pname) {
   2743       case GL_AMBIENT:
   2744          nParams = 4;
   2745          break;
   2746       case GL_DIFFUSE:
   2747          nParams = 4;
   2748          break;
   2749       case GL_SPECULAR:
   2750          nParams = 4;
   2751          break;
   2752       case GL_POSITION:
   2753          nParams = 4;
   2754          break;
   2755       case GL_SPOT_DIRECTION:
   2756          nParams = 3;
   2757          break;
   2758       case GL_SPOT_EXPONENT:
   2759          nParams = 1;
   2760          break;
   2761       case GL_SPOT_CUTOFF:
   2762          nParams = 1;
   2763          break;
   2764       case GL_CONSTANT_ATTENUATION:
   2765          nParams = 1;
   2766          break;
   2767       case GL_LINEAR_ATTENUATION:
   2768          nParams = 1;
   2769          break;
   2770       case GL_QUADRATIC_ATTENUATION:
   2771          nParams = 1;
   2772          break;
   2773       default:
   2774          nParams = 0;
   2775       }
   2776       for (i = 0; i < nParams; i++) {
   2777          n[3 + i].f = params[i];
   2778       }
   2779    }
   2780    if (ctx->ExecuteFlag) {
   2781       CALL_Lightfv(ctx->Exec, (light, pname, params));
   2782    }
   2783 }
   2784 
   2785 
   2786 static void GLAPIENTRY
   2787 save_Lightf(GLenum light, GLenum pname, GLfloat param)
   2788 {
   2789    GLfloat parray[4];
   2790    parray[0] = param;
   2791    parray[1] = parray[2] = parray[3] = 0.0F;
   2792    save_Lightfv(light, pname, parray);
   2793 }
   2794 
   2795 
   2796 static void GLAPIENTRY
   2797 save_Lightiv(GLenum light, GLenum pname, const GLint *params)
   2798 {
   2799    GLfloat fparam[4];
   2800    switch (pname) {
   2801    case GL_AMBIENT:
   2802    case GL_DIFFUSE:
   2803    case GL_SPECULAR:
   2804       fparam[0] = INT_TO_FLOAT(params[0]);
   2805       fparam[1] = INT_TO_FLOAT(params[1]);
   2806       fparam[2] = INT_TO_FLOAT(params[2]);
   2807       fparam[3] = INT_TO_FLOAT(params[3]);
   2808       break;
   2809    case GL_POSITION:
   2810       fparam[0] = (GLfloat) params[0];
   2811       fparam[1] = (GLfloat) params[1];
   2812       fparam[2] = (GLfloat) params[2];
   2813       fparam[3] = (GLfloat) params[3];
   2814       break;
   2815    case GL_SPOT_DIRECTION:
   2816       fparam[0] = (GLfloat) params[0];
   2817       fparam[1] = (GLfloat) params[1];
   2818       fparam[2] = (GLfloat) params[2];
   2819       break;
   2820    case GL_SPOT_EXPONENT:
   2821    case GL_SPOT_CUTOFF:
   2822    case GL_CONSTANT_ATTENUATION:
   2823    case GL_LINEAR_ATTENUATION:
   2824    case GL_QUADRATIC_ATTENUATION:
   2825       fparam[0] = (GLfloat) params[0];
   2826       break;
   2827    default:
   2828       /* error will be caught later in gl_Lightfv */
   2829       ;
   2830    }
   2831    save_Lightfv(light, pname, fparam);
   2832 }
   2833 
   2834 
   2835 static void GLAPIENTRY
   2836 save_Lighti(GLenum light, GLenum pname, GLint param)
   2837 {
   2838    GLint parray[4];
   2839    parray[0] = param;
   2840    parray[1] = parray[2] = parray[3] = 0;
   2841    save_Lightiv(light, pname, parray);
   2842 }
   2843 
   2844 
   2845 static void GLAPIENTRY
   2846 save_LightModelfv(GLenum pname, const GLfloat *params)
   2847 {
   2848    GET_CURRENT_CONTEXT(ctx);
   2849    Node *n;
   2850    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2851    n = alloc_instruction(ctx, OPCODE_LIGHT_MODEL, 5);
   2852    if (n) {
   2853       n[1].e = pname;
   2854       n[2].f = params[0];
   2855       n[3].f = params[1];
   2856       n[4].f = params[2];
   2857       n[5].f = params[3];
   2858    }
   2859    if (ctx->ExecuteFlag) {
   2860       CALL_LightModelfv(ctx->Exec, (pname, params));
   2861    }
   2862 }
   2863 
   2864 
   2865 static void GLAPIENTRY
   2866 save_LightModelf(GLenum pname, GLfloat param)
   2867 {
   2868    GLfloat parray[4];
   2869    parray[0] = param;
   2870    parray[1] = parray[2] = parray[3] = 0.0F;
   2871    save_LightModelfv(pname, parray);
   2872 }
   2873 
   2874 
   2875 static void GLAPIENTRY
   2876 save_LightModeliv(GLenum pname, const GLint *params)
   2877 {
   2878    GLfloat fparam[4];
   2879    switch (pname) {
   2880    case GL_LIGHT_MODEL_AMBIENT:
   2881       fparam[0] = INT_TO_FLOAT(params[0]);
   2882       fparam[1] = INT_TO_FLOAT(params[1]);
   2883       fparam[2] = INT_TO_FLOAT(params[2]);
   2884       fparam[3] = INT_TO_FLOAT(params[3]);
   2885       break;
   2886    case GL_LIGHT_MODEL_LOCAL_VIEWER:
   2887    case GL_LIGHT_MODEL_TWO_SIDE:
   2888    case GL_LIGHT_MODEL_COLOR_CONTROL:
   2889       fparam[0] = (GLfloat) params[0];
   2890       fparam[1] = 0.0F;
   2891       fparam[2] = 0.0F;
   2892       fparam[3] = 0.0F;
   2893       break;
   2894    default:
   2895       /* Error will be caught later in gl_LightModelfv */
   2896       ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
   2897    }
   2898    save_LightModelfv(pname, fparam);
   2899 }
   2900 
   2901 
   2902 static void GLAPIENTRY
   2903 save_LightModeli(GLenum pname, GLint param)
   2904 {
   2905    GLint parray[4];
   2906    parray[0] = param;
   2907    parray[1] = parray[2] = parray[3] = 0;
   2908    save_LightModeliv(pname, parray);
   2909 }
   2910 
   2911 
   2912 static void GLAPIENTRY
   2913 save_LineStipple(GLint factor, GLushort pattern)
   2914 {
   2915    GET_CURRENT_CONTEXT(ctx);
   2916    Node *n;
   2917    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2918    n = alloc_instruction(ctx, OPCODE_LINE_STIPPLE, 2);
   2919    if (n) {
   2920       n[1].i = factor;
   2921       n[2].us = pattern;
   2922    }
   2923    if (ctx->ExecuteFlag) {
   2924       CALL_LineStipple(ctx->Exec, (factor, pattern));
   2925    }
   2926 }
   2927 
   2928 
   2929 static void GLAPIENTRY
   2930 save_LineWidth(GLfloat width)
   2931 {
   2932    GET_CURRENT_CONTEXT(ctx);
   2933    Node *n;
   2934    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2935    n = alloc_instruction(ctx, OPCODE_LINE_WIDTH, 1);
   2936    if (n) {
   2937       n[1].f = width;
   2938    }
   2939    if (ctx->ExecuteFlag) {
   2940       CALL_LineWidth(ctx->Exec, (width));
   2941    }
   2942 }
   2943 
   2944 
   2945 static void GLAPIENTRY
   2946 save_ListBase(GLuint base)
   2947 {
   2948    GET_CURRENT_CONTEXT(ctx);
   2949    Node *n;
   2950    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2951    n = alloc_instruction(ctx, OPCODE_LIST_BASE, 1);
   2952    if (n) {
   2953       n[1].ui = base;
   2954    }
   2955    if (ctx->ExecuteFlag) {
   2956       CALL_ListBase(ctx->Exec, (base));
   2957    }
   2958 }
   2959 
   2960 
   2961 static void GLAPIENTRY
   2962 save_LoadIdentity(void)
   2963 {
   2964    GET_CURRENT_CONTEXT(ctx);
   2965    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2966    (void) alloc_instruction(ctx, OPCODE_LOAD_IDENTITY, 0);
   2967    if (ctx->ExecuteFlag) {
   2968       CALL_LoadIdentity(ctx->Exec, ());
   2969    }
   2970 }
   2971 
   2972 
   2973 static void GLAPIENTRY
   2974 save_LoadMatrixf(const GLfloat * m)
   2975 {
   2976    GET_CURRENT_CONTEXT(ctx);
   2977    Node *n;
   2978    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   2979    n = alloc_instruction(ctx, OPCODE_LOAD_MATRIX, 16);
   2980    if (n) {
   2981       GLuint i;
   2982       for (i = 0; i < 16; i++) {
   2983          n[1 + i].f = m[i];
   2984       }
   2985    }
   2986    if (ctx->ExecuteFlag) {
   2987       CALL_LoadMatrixf(ctx->Exec, (m));
   2988    }
   2989 }
   2990 
   2991 
   2992 static void GLAPIENTRY
   2993 save_LoadMatrixd(const GLdouble * m)
   2994 {
   2995    GLfloat f[16];
   2996    GLint i;
   2997    for (i = 0; i < 16; i++) {
   2998       f[i] = (GLfloat) m[i];
   2999    }
   3000    save_LoadMatrixf(f);
   3001 }
   3002 
   3003 
   3004 static void GLAPIENTRY
   3005 save_LoadName(GLuint name)
   3006 {
   3007    GET_CURRENT_CONTEXT(ctx);
   3008    Node *n;
   3009    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3010    n = alloc_instruction(ctx, OPCODE_LOAD_NAME, 1);
   3011    if (n) {
   3012       n[1].ui = name;
   3013    }
   3014    if (ctx->ExecuteFlag) {
   3015       CALL_LoadName(ctx->Exec, (name));
   3016    }
   3017 }
   3018 
   3019 
   3020 static void GLAPIENTRY
   3021 save_LogicOp(GLenum opcode)
   3022 {
   3023    GET_CURRENT_CONTEXT(ctx);
   3024    Node *n;
   3025    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3026    n = alloc_instruction(ctx, OPCODE_LOGIC_OP, 1);
   3027    if (n) {
   3028       n[1].e = opcode;
   3029    }
   3030    if (ctx->ExecuteFlag) {
   3031       CALL_LogicOp(ctx->Exec, (opcode));
   3032    }
   3033 }
   3034 
   3035 
   3036 static void GLAPIENTRY
   3037 save_Map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride,
   3038            GLint order, const GLdouble * points)
   3039 {
   3040    GET_CURRENT_CONTEXT(ctx);
   3041    Node *n;
   3042    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3043    n = alloc_instruction(ctx, OPCODE_MAP1, 5 + POINTER_DWORDS);
   3044    if (n) {
   3045       GLfloat *pnts = _mesa_copy_map_points1d(target, stride, order, points);
   3046       n[1].e = target;
   3047       n[2].f = (GLfloat) u1;
   3048       n[3].f = (GLfloat) u2;
   3049       n[4].i = _mesa_evaluator_components(target);      /* stride */
   3050       n[5].i = order;
   3051       save_pointer(&n[6], pnts);
   3052    }
   3053    if (ctx->ExecuteFlag) {
   3054       CALL_Map1d(ctx->Exec, (target, u1, u2, stride, order, points));
   3055    }
   3056 }
   3057 
   3058 static void GLAPIENTRY
   3059 save_Map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride,
   3060            GLint order, const GLfloat * points)
   3061 {
   3062    GET_CURRENT_CONTEXT(ctx);
   3063    Node *n;
   3064    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3065    n = alloc_instruction(ctx, OPCODE_MAP1, 5 + POINTER_DWORDS);
   3066    if (n) {
   3067       GLfloat *pnts = _mesa_copy_map_points1f(target, stride, order, points);
   3068       n[1].e = target;
   3069       n[2].f = u1;
   3070       n[3].f = u2;
   3071       n[4].i = _mesa_evaluator_components(target);      /* stride */
   3072       n[5].i = order;
   3073       save_pointer(&n[6], pnts);
   3074    }
   3075    if (ctx->ExecuteFlag) {
   3076       CALL_Map1f(ctx->Exec, (target, u1, u2, stride, order, points));
   3077    }
   3078 }
   3079 
   3080 
   3081 static void GLAPIENTRY
   3082 save_Map2d(GLenum target,
   3083            GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
   3084            GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
   3085            const GLdouble * points)
   3086 {
   3087    GET_CURRENT_CONTEXT(ctx);
   3088    Node *n;
   3089    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3090    n = alloc_instruction(ctx, OPCODE_MAP2, 9 + POINTER_DWORDS);
   3091    if (n) {
   3092       GLfloat *pnts = _mesa_copy_map_points2d(target, ustride, uorder,
   3093                                               vstride, vorder, points);
   3094       n[1].e = target;
   3095       n[2].f = (GLfloat) u1;
   3096       n[3].f = (GLfloat) u2;
   3097       n[4].f = (GLfloat) v1;
   3098       n[5].f = (GLfloat) v2;
   3099       /* XXX verify these strides are correct */
   3100       n[6].i = _mesa_evaluator_components(target) * vorder;     /*ustride */
   3101       n[7].i = _mesa_evaluator_components(target);      /*vstride */
   3102       n[8].i = uorder;
   3103       n[9].i = vorder;
   3104       save_pointer(&n[10], pnts);
   3105    }
   3106    if (ctx->ExecuteFlag) {
   3107       CALL_Map2d(ctx->Exec, (target,
   3108                              u1, u2, ustride, uorder,
   3109                              v1, v2, vstride, vorder, points));
   3110    }
   3111 }
   3112 
   3113 
   3114 static void GLAPIENTRY
   3115 save_Map2f(GLenum target,
   3116            GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
   3117            GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
   3118            const GLfloat * points)
   3119 {
   3120    GET_CURRENT_CONTEXT(ctx);
   3121    Node *n;
   3122    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3123    n = alloc_instruction(ctx, OPCODE_MAP2, 9 + POINTER_DWORDS);
   3124    if (n) {
   3125       GLfloat *pnts = _mesa_copy_map_points2f(target, ustride, uorder,
   3126                                               vstride, vorder, points);
   3127       n[1].e = target;
   3128       n[2].f = u1;
   3129       n[3].f = u2;
   3130       n[4].f = v1;
   3131       n[5].f = v2;
   3132       /* XXX verify these strides are correct */
   3133       n[6].i = _mesa_evaluator_components(target) * vorder;     /*ustride */
   3134       n[7].i = _mesa_evaluator_components(target);      /*vstride */
   3135       n[8].i = uorder;
   3136       n[9].i = vorder;
   3137       save_pointer(&n[10], pnts);
   3138    }
   3139    if (ctx->ExecuteFlag) {
   3140       CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder,
   3141                              v1, v2, vstride, vorder, points));
   3142    }
   3143 }
   3144 
   3145 
   3146 static void GLAPIENTRY
   3147 save_MapGrid1f(GLint un, GLfloat u1, GLfloat u2)
   3148 {
   3149    GET_CURRENT_CONTEXT(ctx);
   3150    Node *n;
   3151    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3152    n = alloc_instruction(ctx, OPCODE_MAPGRID1, 3);
   3153    if (n) {
   3154       n[1].i = un;
   3155       n[2].f = u1;
   3156       n[3].f = u2;
   3157    }
   3158    if (ctx->ExecuteFlag) {
   3159       CALL_MapGrid1f(ctx->Exec, (un, u1, u2));
   3160    }
   3161 }
   3162 
   3163 
   3164 static void GLAPIENTRY
   3165 save_MapGrid1d(GLint un, GLdouble u1, GLdouble u2)
   3166 {
   3167    save_MapGrid1f(un, (GLfloat) u1, (GLfloat) u2);
   3168 }
   3169 
   3170 
   3171 static void GLAPIENTRY
   3172 save_MapGrid2f(GLint un, GLfloat u1, GLfloat u2,
   3173                GLint vn, GLfloat v1, GLfloat v2)
   3174 {
   3175    GET_CURRENT_CONTEXT(ctx);
   3176    Node *n;
   3177    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3178    n = alloc_instruction(ctx, OPCODE_MAPGRID2, 6);
   3179    if (n) {
   3180       n[1].i = un;
   3181       n[2].f = u1;
   3182       n[3].f = u2;
   3183       n[4].i = vn;
   3184       n[5].f = v1;
   3185       n[6].f = v2;
   3186    }
   3187    if (ctx->ExecuteFlag) {
   3188       CALL_MapGrid2f(ctx->Exec, (un, u1, u2, vn, v1, v2));
   3189    }
   3190 }
   3191 
   3192 
   3193 
   3194 static void GLAPIENTRY
   3195 save_MapGrid2d(GLint un, GLdouble u1, GLdouble u2,
   3196                GLint vn, GLdouble v1, GLdouble v2)
   3197 {
   3198    save_MapGrid2f(un, (GLfloat) u1, (GLfloat) u2,
   3199                   vn, (GLfloat) v1, (GLfloat) v2);
   3200 }
   3201 
   3202 
   3203 static void GLAPIENTRY
   3204 save_MatrixMode(GLenum mode)
   3205 {
   3206    GET_CURRENT_CONTEXT(ctx);
   3207    Node *n;
   3208    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3209    n = alloc_instruction(ctx, OPCODE_MATRIX_MODE, 1);
   3210    if (n) {
   3211       n[1].e = mode;
   3212    }
   3213    if (ctx->ExecuteFlag) {
   3214       CALL_MatrixMode(ctx->Exec, (mode));
   3215    }
   3216 }
   3217 
   3218 
   3219 static void GLAPIENTRY
   3220 save_MultMatrixf(const GLfloat * m)
   3221 {
   3222    GET_CURRENT_CONTEXT(ctx);
   3223    Node *n;
   3224    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3225    n = alloc_instruction(ctx, OPCODE_MULT_MATRIX, 16);
   3226    if (n) {
   3227       GLuint i;
   3228       for (i = 0; i < 16; i++) {
   3229          n[1 + i].f = m[i];
   3230       }
   3231    }
   3232    if (ctx->ExecuteFlag) {
   3233       CALL_MultMatrixf(ctx->Exec, (m));
   3234    }
   3235 }
   3236 
   3237 
   3238 static void GLAPIENTRY
   3239 save_MultMatrixd(const GLdouble * m)
   3240 {
   3241    GLfloat f[16];
   3242    GLint i;
   3243    for (i = 0; i < 16; i++) {
   3244       f[i] = (GLfloat) m[i];
   3245    }
   3246    save_MultMatrixf(f);
   3247 }
   3248 
   3249 
   3250 static void GLAPIENTRY
   3251 save_NewList(GLuint name, GLenum mode)
   3252 {
   3253    GET_CURRENT_CONTEXT(ctx);
   3254    /* It's an error to call this function while building a display list */
   3255    _mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
   3256    (void) name;
   3257    (void) mode;
   3258 }
   3259 
   3260 
   3261 
   3262 static void GLAPIENTRY
   3263 save_Ortho(GLdouble left, GLdouble right,
   3264            GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
   3265 {
   3266    GET_CURRENT_CONTEXT(ctx);
   3267    Node *n;
   3268    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3269    n = alloc_instruction(ctx, OPCODE_ORTHO, 6);
   3270    if (n) {
   3271       n[1].f = (GLfloat) left;
   3272       n[2].f = (GLfloat) right;
   3273       n[3].f = (GLfloat) bottom;
   3274       n[4].f = (GLfloat) top;
   3275       n[5].f = (GLfloat) nearval;
   3276       n[6].f = (GLfloat) farval;
   3277    }
   3278    if (ctx->ExecuteFlag) {
   3279       CALL_Ortho(ctx->Exec, (left, right, bottom, top, nearval, farval));
   3280    }
   3281 }
   3282 
   3283 
   3284 static void GLAPIENTRY
   3285 save_PixelMapfv(GLenum map, GLint mapsize, const GLfloat *values)
   3286 {
   3287    GET_CURRENT_CONTEXT(ctx);
   3288    Node *n;
   3289    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3290    n = alloc_instruction(ctx, OPCODE_PIXEL_MAP, 2 + POINTER_DWORDS);
   3291    if (n) {
   3292       n[1].e = map;
   3293       n[2].i = mapsize;
   3294       save_pointer(&n[3], memdup(values, mapsize * sizeof(GLfloat)));
   3295    }
   3296    if (ctx->ExecuteFlag) {
   3297       CALL_PixelMapfv(ctx->Exec, (map, mapsize, values));
   3298    }
   3299 }
   3300 
   3301 
   3302 static void GLAPIENTRY
   3303 save_PixelMapuiv(GLenum map, GLint mapsize, const GLuint *values)
   3304 {
   3305    GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
   3306    GLint i;
   3307    if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
   3308       for (i = 0; i < mapsize; i++) {
   3309          fvalues[i] = (GLfloat) values[i];
   3310       }
   3311    }
   3312    else {
   3313       for (i = 0; i < mapsize; i++) {
   3314          fvalues[i] = UINT_TO_FLOAT(values[i]);
   3315       }
   3316    }
   3317    save_PixelMapfv(map, mapsize, fvalues);
   3318 }
   3319 
   3320 
   3321 static void GLAPIENTRY
   3322 save_PixelMapusv(GLenum map, GLint mapsize, const GLushort *values)
   3323 {
   3324    GLfloat fvalues[MAX_PIXEL_MAP_TABLE];
   3325    GLint i;
   3326    if (map == GL_PIXEL_MAP_I_TO_I || map == GL_PIXEL_MAP_S_TO_S) {
   3327       for (i = 0; i < mapsize; i++) {
   3328          fvalues[i] = (GLfloat) values[i];
   3329       }
   3330    }
   3331    else {
   3332       for (i = 0; i < mapsize; i++) {
   3333          fvalues[i] = USHORT_TO_FLOAT(values[i]);
   3334       }
   3335    }
   3336    save_PixelMapfv(map, mapsize, fvalues);
   3337 }
   3338 
   3339 
   3340 static void GLAPIENTRY
   3341 save_PixelTransferf(GLenum pname, GLfloat param)
   3342 {
   3343    GET_CURRENT_CONTEXT(ctx);
   3344    Node *n;
   3345    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3346    n = alloc_instruction(ctx, OPCODE_PIXEL_TRANSFER, 2);
   3347    if (n) {
   3348       n[1].e = pname;
   3349       n[2].f = param;
   3350    }
   3351    if (ctx->ExecuteFlag) {
   3352       CALL_PixelTransferf(ctx->Exec, (pname, param));
   3353    }
   3354 }
   3355 
   3356 
   3357 static void GLAPIENTRY
   3358 save_PixelTransferi(GLenum pname, GLint param)
   3359 {
   3360    save_PixelTransferf(pname, (GLfloat) param);
   3361 }
   3362 
   3363 
   3364 static void GLAPIENTRY
   3365 save_PixelZoom(GLfloat xfactor, GLfloat yfactor)
   3366 {
   3367    GET_CURRENT_CONTEXT(ctx);
   3368    Node *n;
   3369    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3370    n = alloc_instruction(ctx, OPCODE_PIXEL_ZOOM, 2);
   3371    if (n) {
   3372       n[1].f = xfactor;
   3373       n[2].f = yfactor;
   3374    }
   3375    if (ctx->ExecuteFlag) {
   3376       CALL_PixelZoom(ctx->Exec, (xfactor, yfactor));
   3377    }
   3378 }
   3379 
   3380 
   3381 static void GLAPIENTRY
   3382 save_PointParameterfvEXT(GLenum pname, const GLfloat *params)
   3383 {
   3384    GET_CURRENT_CONTEXT(ctx);
   3385    Node *n;
   3386    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3387    n = alloc_instruction(ctx, OPCODE_POINT_PARAMETERS, 4);
   3388    if (n) {
   3389       n[1].e = pname;
   3390       n[2].f = params[0];
   3391       n[3].f = params[1];
   3392       n[4].f = params[2];
   3393    }
   3394    if (ctx->ExecuteFlag) {
   3395       CALL_PointParameterfv(ctx->Exec, (pname, params));
   3396    }
   3397 }
   3398 
   3399 
   3400 static void GLAPIENTRY
   3401 save_PointParameterfEXT(GLenum pname, GLfloat param)
   3402 {
   3403    GLfloat parray[3];
   3404    parray[0] = param;
   3405    parray[1] = parray[2] = 0.0F;
   3406    save_PointParameterfvEXT(pname, parray);
   3407 }
   3408 
   3409 static void GLAPIENTRY
   3410 save_PointParameteriNV(GLenum pname, GLint param)
   3411 {
   3412    GLfloat parray[3];
   3413    parray[0] = (GLfloat) param;
   3414    parray[1] = parray[2] = 0.0F;
   3415    save_PointParameterfvEXT(pname, parray);
   3416 }
   3417 
   3418 static void GLAPIENTRY
   3419 save_PointParameterivNV(GLenum pname, const GLint * param)
   3420 {
   3421    GLfloat parray[3];
   3422    parray[0] = (GLfloat) param[0];
   3423    parray[1] = parray[2] = 0.0F;
   3424    save_PointParameterfvEXT(pname, parray);
   3425 }
   3426 
   3427 
   3428 static void GLAPIENTRY
   3429 save_PointSize(GLfloat size)
   3430 {
   3431    GET_CURRENT_CONTEXT(ctx);
   3432    Node *n;
   3433    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3434    n = alloc_instruction(ctx, OPCODE_POINT_SIZE, 1);
   3435    if (n) {
   3436       n[1].f = size;
   3437    }
   3438    if (ctx->ExecuteFlag) {
   3439       CALL_PointSize(ctx->Exec, (size));
   3440    }
   3441 }
   3442 
   3443 
   3444 static void GLAPIENTRY
   3445 save_PolygonMode(GLenum face, GLenum mode)
   3446 {
   3447    GET_CURRENT_CONTEXT(ctx);
   3448    Node *n;
   3449    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3450    n = alloc_instruction(ctx, OPCODE_POLYGON_MODE, 2);
   3451    if (n) {
   3452       n[1].e = face;
   3453       n[2].e = mode;
   3454    }
   3455    if (ctx->ExecuteFlag) {
   3456       CALL_PolygonMode(ctx->Exec, (face, mode));
   3457    }
   3458 }
   3459 
   3460 
   3461 static void GLAPIENTRY
   3462 save_PolygonStipple(const GLubyte * pattern)
   3463 {
   3464    GET_CURRENT_CONTEXT(ctx);
   3465    Node *n;
   3466 
   3467    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3468 
   3469    n = alloc_instruction(ctx, OPCODE_POLYGON_STIPPLE, POINTER_DWORDS);
   3470    if (n) {
   3471       save_pointer(&n[1],
   3472                    unpack_image(ctx, 2, 32, 32, 1, GL_COLOR_INDEX, GL_BITMAP,
   3473                                 pattern, &ctx->Unpack));
   3474    }
   3475    if (ctx->ExecuteFlag) {
   3476       CALL_PolygonStipple(ctx->Exec, ((GLubyte *) pattern));
   3477    }
   3478 }
   3479 
   3480 
   3481 static void GLAPIENTRY
   3482 save_PolygonOffset(GLfloat factor, GLfloat units)
   3483 {
   3484    GET_CURRENT_CONTEXT(ctx);
   3485    Node *n;
   3486    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3487    n = alloc_instruction(ctx, OPCODE_POLYGON_OFFSET, 2);
   3488    if (n) {
   3489       n[1].f = factor;
   3490       n[2].f = units;
   3491    }
   3492    if (ctx->ExecuteFlag) {
   3493       CALL_PolygonOffset(ctx->Exec, (factor, units));
   3494    }
   3495 }
   3496 
   3497 
   3498 static void GLAPIENTRY
   3499 save_PolygonOffsetEXT(GLfloat factor, GLfloat bias)
   3500 {
   3501    GET_CURRENT_CONTEXT(ctx);
   3502    /* XXX mult by DepthMaxF here??? */
   3503    save_PolygonOffset(factor, ctx->DrawBuffer->_DepthMaxF * bias);
   3504 }
   3505 
   3506 static void GLAPIENTRY
   3507 save_PolygonOffsetClampEXT(GLfloat factor, GLfloat units, GLfloat clamp)
   3508 {
   3509    GET_CURRENT_CONTEXT(ctx);
   3510    Node *n;
   3511    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3512    n = alloc_instruction(ctx, OPCODE_POLYGON_OFFSET_CLAMP, 3);
   3513    if (n) {
   3514       n[1].f = factor;
   3515       n[2].f = units;
   3516       n[3].f = clamp;
   3517    }
   3518    if (ctx->ExecuteFlag) {
   3519       CALL_PolygonOffsetClampEXT(ctx->Exec, (factor, units, clamp));
   3520    }
   3521 }
   3522 
   3523 static void GLAPIENTRY
   3524 save_PopAttrib(void)
   3525 {
   3526    GET_CURRENT_CONTEXT(ctx);
   3527    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3528    (void) alloc_instruction(ctx, OPCODE_POP_ATTRIB, 0);
   3529    if (ctx->ExecuteFlag) {
   3530       CALL_PopAttrib(ctx->Exec, ());
   3531    }
   3532 }
   3533 
   3534 
   3535 static void GLAPIENTRY
   3536 save_PopMatrix(void)
   3537 {
   3538    GET_CURRENT_CONTEXT(ctx);
   3539    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3540    (void) alloc_instruction(ctx, OPCODE_POP_MATRIX, 0);
   3541    if (ctx->ExecuteFlag) {
   3542       CALL_PopMatrix(ctx->Exec, ());
   3543    }
   3544 }
   3545 
   3546 
   3547 static void GLAPIENTRY
   3548 save_PopName(void)
   3549 {
   3550    GET_CURRENT_CONTEXT(ctx);
   3551    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3552    (void) alloc_instruction(ctx, OPCODE_POP_NAME, 0);
   3553    if (ctx->ExecuteFlag) {
   3554       CALL_PopName(ctx->Exec, ());
   3555    }
   3556 }
   3557 
   3558 
   3559 static void GLAPIENTRY
   3560 save_PrioritizeTextures(GLsizei num, const GLuint * textures,
   3561                         const GLclampf * priorities)
   3562 {
   3563    GET_CURRENT_CONTEXT(ctx);
   3564    GLint i;
   3565    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3566 
   3567    for (i = 0; i < num; i++) {
   3568       Node *n;
   3569       n = alloc_instruction(ctx, OPCODE_PRIORITIZE_TEXTURE, 2);
   3570       if (n) {
   3571          n[1].ui = textures[i];
   3572          n[2].f = priorities[i];
   3573       }
   3574    }
   3575    if (ctx->ExecuteFlag) {
   3576       CALL_PrioritizeTextures(ctx->Exec, (num, textures, priorities));
   3577    }
   3578 }
   3579 
   3580 
   3581 static void GLAPIENTRY
   3582 save_PushAttrib(GLbitfield mask)
   3583 {
   3584    GET_CURRENT_CONTEXT(ctx);
   3585    Node *n;
   3586    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3587    n = alloc_instruction(ctx, OPCODE_PUSH_ATTRIB, 1);
   3588    if (n) {
   3589       n[1].bf = mask;
   3590    }
   3591    if (ctx->ExecuteFlag) {
   3592       CALL_PushAttrib(ctx->Exec, (mask));
   3593    }
   3594 }
   3595 
   3596 
   3597 static void GLAPIENTRY
   3598 save_PushMatrix(void)
   3599 {
   3600    GET_CURRENT_CONTEXT(ctx);
   3601    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3602    (void) alloc_instruction(ctx, OPCODE_PUSH_MATRIX, 0);
   3603    if (ctx->ExecuteFlag) {
   3604       CALL_PushMatrix(ctx->Exec, ());
   3605    }
   3606 }
   3607 
   3608 
   3609 static void GLAPIENTRY
   3610 save_PushName(GLuint name)
   3611 {
   3612    GET_CURRENT_CONTEXT(ctx);
   3613    Node *n;
   3614    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3615    n = alloc_instruction(ctx, OPCODE_PUSH_NAME, 1);
   3616    if (n) {
   3617       n[1].ui = name;
   3618    }
   3619    if (ctx->ExecuteFlag) {
   3620       CALL_PushName(ctx->Exec, (name));
   3621    }
   3622 }
   3623 
   3624 
   3625 static void GLAPIENTRY
   3626 save_RasterPos4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   3627 {
   3628    GET_CURRENT_CONTEXT(ctx);
   3629    Node *n;
   3630    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3631    n = alloc_instruction(ctx, OPCODE_RASTER_POS, 4);
   3632    if (n) {
   3633       n[1].f = x;
   3634       n[2].f = y;
   3635       n[3].f = z;
   3636       n[4].f = w;
   3637    }
   3638    if (ctx->ExecuteFlag) {
   3639       CALL_RasterPos4f(ctx->Exec, (x, y, z, w));
   3640    }
   3641 }
   3642 
   3643 static void GLAPIENTRY
   3644 save_RasterPos2d(GLdouble x, GLdouble y)
   3645 {
   3646    save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
   3647 }
   3648 
   3649 static void GLAPIENTRY
   3650 save_RasterPos2f(GLfloat x, GLfloat y)
   3651 {
   3652    save_RasterPos4f(x, y, 0.0F, 1.0F);
   3653 }
   3654 
   3655 static void GLAPIENTRY
   3656 save_RasterPos2i(GLint x, GLint y)
   3657 {
   3658    save_RasterPos4f((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
   3659 }
   3660 
   3661 static void GLAPIENTRY
   3662 save_RasterPos2s(GLshort x, GLshort y)
   3663 {
   3664    save_RasterPos4f(x, y, 0.0F, 1.0F);
   3665 }
   3666 
   3667 static void GLAPIENTRY
   3668 save_RasterPos3d(GLdouble x, GLdouble y, GLdouble z)
   3669 {
   3670    save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
   3671 }
   3672 
   3673 static void GLAPIENTRY
   3674 save_RasterPos3f(GLfloat x, GLfloat y, GLfloat z)
   3675 {
   3676    save_RasterPos4f(x, y, z, 1.0F);
   3677 }
   3678 
   3679 static void GLAPIENTRY
   3680 save_RasterPos3i(GLint x, GLint y, GLint z)
   3681 {
   3682    save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
   3683 }
   3684 
   3685 static void GLAPIENTRY
   3686 save_RasterPos3s(GLshort x, GLshort y, GLshort z)
   3687 {
   3688    save_RasterPos4f(x, y, z, 1.0F);
   3689 }
   3690 
   3691 static void GLAPIENTRY
   3692 save_RasterPos4d(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
   3693 {
   3694    save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
   3695 }
   3696 
   3697 static void GLAPIENTRY
   3698 save_RasterPos4i(GLint x, GLint y, GLint z, GLint w)
   3699 {
   3700    save_RasterPos4f((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
   3701 }
   3702 
   3703 static void GLAPIENTRY
   3704 save_RasterPos4s(GLshort x, GLshort y, GLshort z, GLshort w)
   3705 {
   3706    save_RasterPos4f(x, y, z, w);
   3707 }
   3708 
   3709 static void GLAPIENTRY
   3710 save_RasterPos2dv(const GLdouble * v)
   3711 {
   3712    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
   3713 }
   3714 
   3715 static void GLAPIENTRY
   3716 save_RasterPos2fv(const GLfloat * v)
   3717 {
   3718    save_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
   3719 }
   3720 
   3721 static void GLAPIENTRY
   3722 save_RasterPos2iv(const GLint * v)
   3723 {
   3724    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
   3725 }
   3726 
   3727 static void GLAPIENTRY
   3728 save_RasterPos2sv(const GLshort * v)
   3729 {
   3730    save_RasterPos4f(v[0], v[1], 0.0F, 1.0F);
   3731 }
   3732 
   3733 static void GLAPIENTRY
   3734 save_RasterPos3dv(const GLdouble * v)
   3735 {
   3736    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
   3737 }
   3738 
   3739 static void GLAPIENTRY
   3740 save_RasterPos3fv(const GLfloat * v)
   3741 {
   3742    save_RasterPos4f(v[0], v[1], v[2], 1.0F);
   3743 }
   3744 
   3745 static void GLAPIENTRY
   3746 save_RasterPos3iv(const GLint * v)
   3747 {
   3748    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
   3749 }
   3750 
   3751 static void GLAPIENTRY
   3752 save_RasterPos3sv(const GLshort * v)
   3753 {
   3754    save_RasterPos4f(v[0], v[1], v[2], 1.0F);
   3755 }
   3756 
   3757 static void GLAPIENTRY
   3758 save_RasterPos4dv(const GLdouble * v)
   3759 {
   3760    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1],
   3761                     (GLfloat) v[2], (GLfloat) v[3]);
   3762 }
   3763 
   3764 static void GLAPIENTRY
   3765 save_RasterPos4fv(const GLfloat * v)
   3766 {
   3767    save_RasterPos4f(v[0], v[1], v[2], v[3]);
   3768 }
   3769 
   3770 static void GLAPIENTRY
   3771 save_RasterPos4iv(const GLint * v)
   3772 {
   3773    save_RasterPos4f((GLfloat) v[0], (GLfloat) v[1],
   3774                     (GLfloat) v[2], (GLfloat) v[3]);
   3775 }
   3776 
   3777 static void GLAPIENTRY
   3778 save_RasterPos4sv(const GLshort * v)
   3779 {
   3780    save_RasterPos4f(v[0], v[1], v[2], v[3]);
   3781 }
   3782 
   3783 
   3784 static void GLAPIENTRY
   3785 save_PassThrough(GLfloat token)
   3786 {
   3787    GET_CURRENT_CONTEXT(ctx);
   3788    Node *n;
   3789    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3790    n = alloc_instruction(ctx, OPCODE_PASSTHROUGH, 1);
   3791    if (n) {
   3792       n[1].f = token;
   3793    }
   3794    if (ctx->ExecuteFlag) {
   3795       CALL_PassThrough(ctx->Exec, (token));
   3796    }
   3797 }
   3798 
   3799 
   3800 static void GLAPIENTRY
   3801 save_ReadBuffer(GLenum mode)
   3802 {
   3803    GET_CURRENT_CONTEXT(ctx);
   3804    Node *n;
   3805    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3806    n = alloc_instruction(ctx, OPCODE_READ_BUFFER, 1);
   3807    if (n) {
   3808       n[1].e = mode;
   3809    }
   3810    if (ctx->ExecuteFlag) {
   3811       CALL_ReadBuffer(ctx->Exec, (mode));
   3812    }
   3813 }
   3814 
   3815 
   3816 static void GLAPIENTRY
   3817 save_Rotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
   3818 {
   3819    GET_CURRENT_CONTEXT(ctx);
   3820    Node *n;
   3821    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3822    n = alloc_instruction(ctx, OPCODE_ROTATE, 4);
   3823    if (n) {
   3824       n[1].f = angle;
   3825       n[2].f = x;
   3826       n[3].f = y;
   3827       n[4].f = z;
   3828    }
   3829    if (ctx->ExecuteFlag) {
   3830       CALL_Rotatef(ctx->Exec, (angle, x, y, z));
   3831    }
   3832 }
   3833 
   3834 
   3835 static void GLAPIENTRY
   3836 save_Rotated(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
   3837 {
   3838    save_Rotatef((GLfloat) angle, (GLfloat) x, (GLfloat) y, (GLfloat) z);
   3839 }
   3840 
   3841 
   3842 static void GLAPIENTRY
   3843 save_Scalef(GLfloat x, GLfloat y, GLfloat z)
   3844 {
   3845    GET_CURRENT_CONTEXT(ctx);
   3846    Node *n;
   3847    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3848    n = alloc_instruction(ctx, OPCODE_SCALE, 3);
   3849    if (n) {
   3850       n[1].f = x;
   3851       n[2].f = y;
   3852       n[3].f = z;
   3853    }
   3854    if (ctx->ExecuteFlag) {
   3855       CALL_Scalef(ctx->Exec, (x, y, z));
   3856    }
   3857 }
   3858 
   3859 
   3860 static void GLAPIENTRY
   3861 save_Scaled(GLdouble x, GLdouble y, GLdouble z)
   3862 {
   3863    save_Scalef((GLfloat) x, (GLfloat) y, (GLfloat) z);
   3864 }
   3865 
   3866 
   3867 static void GLAPIENTRY
   3868 save_Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
   3869 {
   3870    GET_CURRENT_CONTEXT(ctx);
   3871    Node *n;
   3872    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3873    n = alloc_instruction(ctx, OPCODE_SCISSOR, 4);
   3874    if (n) {
   3875       n[1].i = x;
   3876       n[2].i = y;
   3877       n[3].i = width;
   3878       n[4].i = height;
   3879    }
   3880    if (ctx->ExecuteFlag) {
   3881       CALL_Scissor(ctx->Exec, (x, y, width, height));
   3882    }
   3883 }
   3884 
   3885 
   3886 static void GLAPIENTRY
   3887 save_ShadeModel(GLenum mode)
   3888 {
   3889    GET_CURRENT_CONTEXT(ctx);
   3890    Node *n;
   3891    ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx);
   3892 
   3893    if (ctx->ExecuteFlag) {
   3894       CALL_ShadeModel(ctx->Exec, (mode));
   3895    }
   3896 
   3897    /* Don't compile this call if it's a no-op.
   3898     * By avoiding this state change we have a better chance of
   3899     * coalescing subsequent drawing commands into one batch.
   3900     */
   3901    if (ctx->ListState.Current.ShadeModel == mode)
   3902       return;
   3903 
   3904    SAVE_FLUSH_VERTICES(ctx);
   3905 
   3906    ctx->ListState.Current.ShadeModel = mode;
   3907 
   3908    n = alloc_instruction(ctx, OPCODE_SHADE_MODEL, 1);
   3909    if (n) {
   3910       n[1].e = mode;
   3911    }
   3912 }
   3913 
   3914 
   3915 static void GLAPIENTRY
   3916 save_StencilFunc(GLenum func, GLint ref, GLuint mask)
   3917 {
   3918    GET_CURRENT_CONTEXT(ctx);
   3919    Node *n;
   3920    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3921    n = alloc_instruction(ctx, OPCODE_STENCIL_FUNC, 3);
   3922    if (n) {
   3923       n[1].e = func;
   3924       n[2].i = ref;
   3925       n[3].ui = mask;
   3926    }
   3927    if (ctx->ExecuteFlag) {
   3928       CALL_StencilFunc(ctx->Exec, (func, ref, mask));
   3929    }
   3930 }
   3931 
   3932 
   3933 static void GLAPIENTRY
   3934 save_StencilMask(GLuint mask)
   3935 {
   3936    GET_CURRENT_CONTEXT(ctx);
   3937    Node *n;
   3938    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3939    n = alloc_instruction(ctx, OPCODE_STENCIL_MASK, 1);
   3940    if (n) {
   3941       n[1].ui = mask;
   3942    }
   3943    if (ctx->ExecuteFlag) {
   3944       CALL_StencilMask(ctx->Exec, (mask));
   3945    }
   3946 }
   3947 
   3948 
   3949 static void GLAPIENTRY
   3950 save_StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
   3951 {
   3952    GET_CURRENT_CONTEXT(ctx);
   3953    Node *n;
   3954    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3955    n = alloc_instruction(ctx, OPCODE_STENCIL_OP, 3);
   3956    if (n) {
   3957       n[1].e = fail;
   3958       n[2].e = zfail;
   3959       n[3].e = zpass;
   3960    }
   3961    if (ctx->ExecuteFlag) {
   3962       CALL_StencilOp(ctx->Exec, (fail, zfail, zpass));
   3963    }
   3964 }
   3965 
   3966 
   3967 static void GLAPIENTRY
   3968 save_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
   3969 {
   3970    GET_CURRENT_CONTEXT(ctx);
   3971    Node *n;
   3972    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3973    n = alloc_instruction(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
   3974    if (n) {
   3975       n[1].e = face;
   3976       n[2].e = func;
   3977       n[3].i = ref;
   3978       n[4].ui = mask;
   3979    }
   3980    if (ctx->ExecuteFlag) {
   3981       CALL_StencilFuncSeparate(ctx->Exec, (face, func, ref, mask));
   3982    }
   3983 }
   3984 
   3985 
   3986 static void GLAPIENTRY
   3987 save_StencilFuncSeparateATI(GLenum frontfunc, GLenum backfunc, GLint ref,
   3988                             GLuint mask)
   3989 {
   3990    GET_CURRENT_CONTEXT(ctx);
   3991    Node *n;
   3992    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   3993    /* GL_FRONT */
   3994    n = alloc_instruction(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
   3995    if (n) {
   3996       n[1].e = GL_FRONT;
   3997       n[2].e = frontfunc;
   3998       n[3].i = ref;
   3999       n[4].ui = mask;
   4000    }
   4001    /* GL_BACK */
   4002    n = alloc_instruction(ctx, OPCODE_STENCIL_FUNC_SEPARATE, 4);
   4003    if (n) {
   4004       n[1].e = GL_BACK;
   4005       n[2].e = backfunc;
   4006       n[3].i = ref;
   4007       n[4].ui = mask;
   4008    }
   4009    if (ctx->ExecuteFlag) {
   4010       CALL_StencilFuncSeparate(ctx->Exec, (GL_FRONT, frontfunc, ref, mask));
   4011       CALL_StencilFuncSeparate(ctx->Exec, (GL_BACK, backfunc, ref, mask));
   4012    }
   4013 }
   4014 
   4015 
   4016 static void GLAPIENTRY
   4017 save_StencilMaskSeparate(GLenum face, GLuint mask)
   4018 {
   4019    GET_CURRENT_CONTEXT(ctx);
   4020    Node *n;
   4021    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4022    n = alloc_instruction(ctx, OPCODE_STENCIL_MASK_SEPARATE, 2);
   4023    if (n) {
   4024       n[1].e = face;
   4025       n[2].ui = mask;
   4026    }
   4027    if (ctx->ExecuteFlag) {
   4028       CALL_StencilMaskSeparate(ctx->Exec, (face, mask));
   4029    }
   4030 }
   4031 
   4032 
   4033 static void GLAPIENTRY
   4034 save_StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
   4035 {
   4036    GET_CURRENT_CONTEXT(ctx);
   4037    Node *n;
   4038    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4039    n = alloc_instruction(ctx, OPCODE_STENCIL_OP_SEPARATE, 4);
   4040    if (n) {
   4041       n[1].e = face;
   4042       n[2].e = fail;
   4043       n[3].e = zfail;
   4044       n[4].e = zpass;
   4045    }
   4046    if (ctx->ExecuteFlag) {
   4047       CALL_StencilOpSeparate(ctx->Exec, (face, fail, zfail, zpass));
   4048    }
   4049 }
   4050 
   4051 
   4052 static void GLAPIENTRY
   4053 save_TexEnvfv(GLenum target, GLenum pname, const GLfloat *params)
   4054 {
   4055    GET_CURRENT_CONTEXT(ctx);
   4056    Node *n;
   4057    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4058    n = alloc_instruction(ctx, OPCODE_TEXENV, 6);
   4059    if (n) {
   4060       n[1].e = target;
   4061       n[2].e = pname;
   4062       if (pname == GL_TEXTURE_ENV_COLOR) {
   4063          n[3].f = params[0];
   4064          n[4].f = params[1];
   4065          n[5].f = params[2];
   4066          n[6].f = params[3];
   4067       }
   4068       else {
   4069          n[3].f = params[0];
   4070          n[4].f = n[5].f = n[6].f = 0.0F;
   4071       }
   4072    }
   4073    if (ctx->ExecuteFlag) {
   4074       CALL_TexEnvfv(ctx->Exec, (target, pname, params));
   4075    }
   4076 }
   4077 
   4078 
   4079 static void GLAPIENTRY
   4080 save_TexEnvf(GLenum target, GLenum pname, GLfloat param)
   4081 {
   4082    GLfloat parray[4];
   4083    parray[0] = (GLfloat) param;
   4084    parray[1] = parray[2] = parray[3] = 0.0F;
   4085    save_TexEnvfv(target, pname, parray);
   4086 }
   4087 
   4088 
   4089 static void GLAPIENTRY
   4090 save_TexEnvi(GLenum target, GLenum pname, GLint param)
   4091 {
   4092    GLfloat p[4];
   4093    p[0] = (GLfloat) param;
   4094    p[1] = p[2] = p[3] = 0.0F;
   4095    save_TexEnvfv(target, pname, p);
   4096 }
   4097 
   4098 
   4099 static void GLAPIENTRY
   4100 save_TexEnviv(GLenum target, GLenum pname, const GLint * param)
   4101 {
   4102    GLfloat p[4];
   4103    if (pname == GL_TEXTURE_ENV_COLOR) {
   4104       p[0] = INT_TO_FLOAT(param[0]);
   4105       p[1] = INT_TO_FLOAT(param[1]);
   4106       p[2] = INT_TO_FLOAT(param[2]);
   4107       p[3] = INT_TO_FLOAT(param[3]);
   4108    }
   4109    else {
   4110       p[0] = (GLfloat) param[0];
   4111       p[1] = p[2] = p[3] = 0.0F;
   4112    }
   4113    save_TexEnvfv(target, pname, p);
   4114 }
   4115 
   4116 
   4117 static void GLAPIENTRY
   4118 save_TexGenfv(GLenum coord, GLenum pname, const GLfloat *params)
   4119 {
   4120    GET_CURRENT_CONTEXT(ctx);
   4121    Node *n;
   4122    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4123    n = alloc_instruction(ctx, OPCODE_TEXGEN, 6);
   4124    if (n) {
   4125       n[1].e = coord;
   4126       n[2].e = pname;
   4127       n[3].f = params[0];
   4128       n[4].f = params[1];
   4129       n[5].f = params[2];
   4130       n[6].f = params[3];
   4131    }
   4132    if (ctx->ExecuteFlag) {
   4133       CALL_TexGenfv(ctx->Exec, (coord, pname, params));
   4134    }
   4135 }
   4136 
   4137 
   4138 static void GLAPIENTRY
   4139 save_TexGeniv(GLenum coord, GLenum pname, const GLint *params)
   4140 {
   4141    GLfloat p[4];
   4142    p[0] = (GLfloat) params[0];
   4143    p[1] = (GLfloat) params[1];
   4144    p[2] = (GLfloat) params[2];
   4145    p[3] = (GLfloat) params[3];
   4146    save_TexGenfv(coord, pname, p);
   4147 }
   4148 
   4149 
   4150 static void GLAPIENTRY
   4151 save_TexGend(GLenum coord, GLenum pname, GLdouble param)
   4152 {
   4153    GLfloat parray[4];
   4154    parray[0] = (GLfloat) param;
   4155    parray[1] = parray[2] = parray[3] = 0.0F;
   4156    save_TexGenfv(coord, pname, parray);
   4157 }
   4158 
   4159 
   4160 static void GLAPIENTRY
   4161 save_TexGendv(GLenum coord, GLenum pname, const GLdouble *params)
   4162 {
   4163    GLfloat p[4];
   4164    p[0] = (GLfloat) params[0];
   4165    p[1] = (GLfloat) params[1];
   4166    p[2] = (GLfloat) params[2];
   4167    p[3] = (GLfloat) params[3];
   4168    save_TexGenfv(coord, pname, p);
   4169 }
   4170 
   4171 
   4172 static void GLAPIENTRY
   4173 save_TexGenf(GLenum coord, GLenum pname, GLfloat param)
   4174 {
   4175    GLfloat parray[4];
   4176    parray[0] = param;
   4177    parray[1] = parray[2] = parray[3] = 0.0F;
   4178    save_TexGenfv(coord, pname, parray);
   4179 }
   4180 
   4181 
   4182 static void GLAPIENTRY
   4183 save_TexGeni(GLenum coord, GLenum pname, GLint param)
   4184 {
   4185    GLint parray[4];
   4186    parray[0] = param;
   4187    parray[1] = parray[2] = parray[3] = 0;
   4188    save_TexGeniv(coord, pname, parray);
   4189 }
   4190 
   4191 
   4192 static void GLAPIENTRY
   4193 save_TexParameterfv(GLenum target, GLenum pname, const GLfloat *params)
   4194 {
   4195    GET_CURRENT_CONTEXT(ctx);
   4196    Node *n;
   4197    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4198    n = alloc_instruction(ctx, OPCODE_TEXPARAMETER, 6);
   4199    if (n) {
   4200       n[1].e = target;
   4201       n[2].e = pname;
   4202       n[3].f = params[0];
   4203       n[4].f = params[1];
   4204       n[5].f = params[2];
   4205       n[6].f = params[3];
   4206    }
   4207    if (ctx->ExecuteFlag) {
   4208       CALL_TexParameterfv(ctx->Exec, (target, pname, params));
   4209    }
   4210 }
   4211 
   4212 
   4213 static void GLAPIENTRY
   4214 save_TexParameterf(GLenum target, GLenum pname, GLfloat param)
   4215 {
   4216    GLfloat parray[4];
   4217    parray[0] = param;
   4218    parray[1] = parray[2] = parray[3] = 0.0F;
   4219    save_TexParameterfv(target, pname, parray);
   4220 }
   4221 
   4222 
   4223 static void GLAPIENTRY
   4224 save_TexParameteri(GLenum target, GLenum pname, GLint param)
   4225 {
   4226    GLfloat fparam[4];
   4227    fparam[0] = (GLfloat) param;
   4228    fparam[1] = fparam[2] = fparam[3] = 0.0F;
   4229    save_TexParameterfv(target, pname, fparam);
   4230 }
   4231 
   4232 
   4233 static void GLAPIENTRY
   4234 save_TexParameteriv(GLenum target, GLenum pname, const GLint *params)
   4235 {
   4236    GLfloat fparam[4];
   4237    fparam[0] = (GLfloat) params[0];
   4238    fparam[1] = fparam[2] = fparam[3] = 0.0F;
   4239    save_TexParameterfv(target, pname, fparam);
   4240 }
   4241 
   4242 
   4243 static void GLAPIENTRY
   4244 save_TexImage1D(GLenum target,
   4245                 GLint level, GLint components,
   4246                 GLsizei width, GLint border,
   4247                 GLenum format, GLenum type, const GLvoid * pixels)
   4248 {
   4249    GET_CURRENT_CONTEXT(ctx);
   4250    if (target == GL_PROXY_TEXTURE_1D) {
   4251       /* don't compile, execute immediately */
   4252       CALL_TexImage1D(ctx->Exec, (target, level, components, width,
   4253                                   border, format, type, pixels));
   4254    }
   4255    else {
   4256       Node *n;
   4257       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4258       n = alloc_instruction(ctx, OPCODE_TEX_IMAGE1D, 7 + POINTER_DWORDS);
   4259       if (n) {
   4260          n[1].e = target;
   4261          n[2].i = level;
   4262          n[3].i = components;
   4263          n[4].i = (GLint) width;
   4264          n[5].i = border;
   4265          n[6].e = format;
   4266          n[7].e = type;
   4267          save_pointer(&n[8],
   4268                       unpack_image(ctx, 1, width, 1, 1, format, type,
   4269                                    pixels, &ctx->Unpack));
   4270       }
   4271       if (ctx->ExecuteFlag) {
   4272          CALL_TexImage1D(ctx->Exec, (target, level, components, width,
   4273                                      border, format, type, pixels));
   4274       }
   4275    }
   4276 }
   4277 
   4278 
   4279 static void GLAPIENTRY
   4280 save_TexImage2D(GLenum target,
   4281                 GLint level, GLint components,
   4282                 GLsizei width, GLsizei height, GLint border,
   4283                 GLenum format, GLenum type, const GLvoid * pixels)
   4284 {
   4285    GET_CURRENT_CONTEXT(ctx);
   4286    if (target == GL_PROXY_TEXTURE_2D) {
   4287       /* don't compile, execute immediately */
   4288       CALL_TexImage2D(ctx->Exec, (target, level, components, width,
   4289                                   height, border, format, type, pixels));
   4290    }
   4291    else {
   4292       Node *n;
   4293       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4294       n = alloc_instruction(ctx, OPCODE_TEX_IMAGE2D, 8 + POINTER_DWORDS);
   4295       if (n) {
   4296          n[1].e = target;
   4297          n[2].i = level;
   4298          n[3].i = components;
   4299          n[4].i = (GLint) width;
   4300          n[5].i = (GLint) height;
   4301          n[6].i = border;
   4302          n[7].e = format;
   4303          n[8].e = type;
   4304          save_pointer(&n[9],
   4305                       unpack_image(ctx, 2, width, height, 1, format, type,
   4306                                    pixels, &ctx->Unpack));
   4307       }
   4308       if (ctx->ExecuteFlag) {
   4309          CALL_TexImage2D(ctx->Exec, (target, level, components, width,
   4310                                      height, border, format, type, pixels));
   4311       }
   4312    }
   4313 }
   4314 
   4315 
   4316 static void GLAPIENTRY
   4317 save_TexImage3D(GLenum target,
   4318                 GLint level, GLint internalFormat,
   4319                 GLsizei width, GLsizei height, GLsizei depth,
   4320                 GLint border,
   4321                 GLenum format, GLenum type, const GLvoid * pixels)
   4322 {
   4323    GET_CURRENT_CONTEXT(ctx);
   4324    if (target == GL_PROXY_TEXTURE_3D) {
   4325       /* don't compile, execute immediately */
   4326       CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width,
   4327                                   height, depth, border, format, type,
   4328                                   pixels));
   4329    }
   4330    else {
   4331       Node *n;
   4332       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4333       n = alloc_instruction(ctx, OPCODE_TEX_IMAGE3D, 9 + POINTER_DWORDS);
   4334       if (n) {
   4335          n[1].e = target;
   4336          n[2].i = level;
   4337          n[3].i = (GLint) internalFormat;
   4338          n[4].i = (GLint) width;
   4339          n[5].i = (GLint) height;
   4340          n[6].i = (GLint) depth;
   4341          n[7].i = border;
   4342          n[8].e = format;
   4343          n[9].e = type;
   4344          save_pointer(&n[10],
   4345                       unpack_image(ctx, 3, width, height, depth, format, type,
   4346                                    pixels, &ctx->Unpack));
   4347       }
   4348       if (ctx->ExecuteFlag) {
   4349          CALL_TexImage3D(ctx->Exec, (target, level, internalFormat, width,
   4350                                      height, depth, border, format, type,
   4351                                      pixels));
   4352       }
   4353    }
   4354 }
   4355 
   4356 
   4357 static void GLAPIENTRY
   4358 save_TexSubImage1D(GLenum target, GLint level, GLint xoffset,
   4359                    GLsizei width, GLenum format, GLenum type,
   4360                    const GLvoid * pixels)
   4361 {
   4362    GET_CURRENT_CONTEXT(ctx);
   4363    Node *n;
   4364 
   4365    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4366 
   4367    n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE1D, 6 + POINTER_DWORDS);
   4368    if (n) {
   4369       n[1].e = target;
   4370       n[2].i = level;
   4371       n[3].i = xoffset;
   4372       n[4].i = (GLint) width;
   4373       n[5].e = format;
   4374       n[6].e = type;
   4375       save_pointer(&n[7],
   4376                    unpack_image(ctx, 1, width, 1, 1, format, type,
   4377                                 pixels, &ctx->Unpack));
   4378    }
   4379    if (ctx->ExecuteFlag) {
   4380       CALL_TexSubImage1D(ctx->Exec, (target, level, xoffset, width,
   4381                                      format, type, pixels));
   4382    }
   4383 }
   4384 
   4385 
   4386 static void GLAPIENTRY
   4387 save_TexSubImage2D(GLenum target, GLint level,
   4388                    GLint xoffset, GLint yoffset,
   4389                    GLsizei width, GLsizei height,
   4390                    GLenum format, GLenum type, const GLvoid * pixels)
   4391 {
   4392    GET_CURRENT_CONTEXT(ctx);
   4393    Node *n;
   4394 
   4395    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4396 
   4397    n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE2D, 8 + POINTER_DWORDS);
   4398    if (n) {
   4399       n[1].e = target;
   4400       n[2].i = level;
   4401       n[3].i = xoffset;
   4402       n[4].i = yoffset;
   4403       n[5].i = (GLint) width;
   4404       n[6].i = (GLint) height;
   4405       n[7].e = format;
   4406       n[8].e = type;
   4407       save_pointer(&n[9],
   4408                    unpack_image(ctx, 2, width, height, 1, format, type,
   4409                                 pixels, &ctx->Unpack));
   4410    }
   4411    if (ctx->ExecuteFlag) {
   4412       CALL_TexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
   4413                                      width, height, format, type, pixels));
   4414    }
   4415 }
   4416 
   4417 
   4418 static void GLAPIENTRY
   4419 save_TexSubImage3D(GLenum target, GLint level,
   4420                    GLint xoffset, GLint yoffset, GLint zoffset,
   4421                    GLsizei width, GLsizei height, GLsizei depth,
   4422                    GLenum format, GLenum type, const GLvoid * pixels)
   4423 {
   4424    GET_CURRENT_CONTEXT(ctx);
   4425    Node *n;
   4426 
   4427    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4428 
   4429    n = alloc_instruction(ctx, OPCODE_TEX_SUB_IMAGE3D, 10 + POINTER_DWORDS);
   4430    if (n) {
   4431       n[1].e = target;
   4432       n[2].i = level;
   4433       n[3].i = xoffset;
   4434       n[4].i = yoffset;
   4435       n[5].i = zoffset;
   4436       n[6].i = (GLint) width;
   4437       n[7].i = (GLint) height;
   4438       n[8].i = (GLint) depth;
   4439       n[9].e = format;
   4440       n[10].e = type;
   4441       save_pointer(&n[11],
   4442                    unpack_image(ctx, 3, width, height, depth, format, type,
   4443                                 pixels, &ctx->Unpack));
   4444    }
   4445    if (ctx->ExecuteFlag) {
   4446       CALL_TexSubImage3D(ctx->Exec, (target, level,
   4447                                      xoffset, yoffset, zoffset,
   4448                                      width, height, depth, format, type,
   4449                                      pixels));
   4450    }
   4451 }
   4452 
   4453 
   4454 static void GLAPIENTRY
   4455 save_Translatef(GLfloat x, GLfloat y, GLfloat z)
   4456 {
   4457    GET_CURRENT_CONTEXT(ctx);
   4458    Node *n;
   4459    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4460    n = alloc_instruction(ctx, OPCODE_TRANSLATE, 3);
   4461    if (n) {
   4462       n[1].f = x;
   4463       n[2].f = y;
   4464       n[3].f = z;
   4465    }
   4466    if (ctx->ExecuteFlag) {
   4467       CALL_Translatef(ctx->Exec, (x, y, z));
   4468    }
   4469 }
   4470 
   4471 
   4472 static void GLAPIENTRY
   4473 save_Translated(GLdouble x, GLdouble y, GLdouble z)
   4474 {
   4475    save_Translatef((GLfloat) x, (GLfloat) y, (GLfloat) z);
   4476 }
   4477 
   4478 
   4479 
   4480 static void GLAPIENTRY
   4481 save_Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
   4482 {
   4483    GET_CURRENT_CONTEXT(ctx);
   4484    Node *n;
   4485    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4486    n = alloc_instruction(ctx, OPCODE_VIEWPORT, 4);
   4487    if (n) {
   4488       n[1].i = x;
   4489       n[2].i = y;
   4490       n[3].i = (GLint) width;
   4491       n[4].i = (GLint) height;
   4492    }
   4493    if (ctx->ExecuteFlag) {
   4494       CALL_Viewport(ctx->Exec, (x, y, width, height));
   4495    }
   4496 }
   4497 
   4498 
   4499 static void GLAPIENTRY
   4500 save_WindowPos4fMESA(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   4501 {
   4502    GET_CURRENT_CONTEXT(ctx);
   4503    Node *n;
   4504    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4505    n = alloc_instruction(ctx, OPCODE_WINDOW_POS, 4);
   4506    if (n) {
   4507       n[1].f = x;
   4508       n[2].f = y;
   4509       n[3].f = z;
   4510       n[4].f = w;
   4511    }
   4512    if (ctx->ExecuteFlag) {
   4513       CALL_WindowPos4fMESA(ctx->Exec, (x, y, z, w));
   4514    }
   4515 }
   4516 
   4517 static void GLAPIENTRY
   4518 save_WindowPos2dMESA(GLdouble x, GLdouble y)
   4519 {
   4520    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
   4521 }
   4522 
   4523 static void GLAPIENTRY
   4524 save_WindowPos2fMESA(GLfloat x, GLfloat y)
   4525 {
   4526    save_WindowPos4fMESA(x, y, 0.0F, 1.0F);
   4527 }
   4528 
   4529 static void GLAPIENTRY
   4530 save_WindowPos2iMESA(GLint x, GLint y)
   4531 {
   4532    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, 0.0F, 1.0F);
   4533 }
   4534 
   4535 static void GLAPIENTRY
   4536 save_WindowPos2sMESA(GLshort x, GLshort y)
   4537 {
   4538    save_WindowPos4fMESA(x, y, 0.0F, 1.0F);
   4539 }
   4540 
   4541 static void GLAPIENTRY
   4542 save_WindowPos3dMESA(GLdouble x, GLdouble y, GLdouble z)
   4543 {
   4544    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
   4545 }
   4546 
   4547 static void GLAPIENTRY
   4548 save_WindowPos3fMESA(GLfloat x, GLfloat y, GLfloat z)
   4549 {
   4550    save_WindowPos4fMESA(x, y, z, 1.0F);
   4551 }
   4552 
   4553 static void GLAPIENTRY
   4554 save_WindowPos3iMESA(GLint x, GLint y, GLint z)
   4555 {
   4556    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, 1.0F);
   4557 }
   4558 
   4559 static void GLAPIENTRY
   4560 save_WindowPos3sMESA(GLshort x, GLshort y, GLshort z)
   4561 {
   4562    save_WindowPos4fMESA(x, y, z, 1.0F);
   4563 }
   4564 
   4565 static void GLAPIENTRY
   4566 save_WindowPos4dMESA(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
   4567 {
   4568    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
   4569 }
   4570 
   4571 static void GLAPIENTRY
   4572 save_WindowPos4iMESA(GLint x, GLint y, GLint z, GLint w)
   4573 {
   4574    save_WindowPos4fMESA((GLfloat) x, (GLfloat) y, (GLfloat) z, (GLfloat) w);
   4575 }
   4576 
   4577 static void GLAPIENTRY
   4578 save_WindowPos4sMESA(GLshort x, GLshort y, GLshort z, GLshort w)
   4579 {
   4580    save_WindowPos4fMESA(x, y, z, w);
   4581 }
   4582 
   4583 static void GLAPIENTRY
   4584 save_WindowPos2dvMESA(const GLdouble * v)
   4585 {
   4586    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
   4587 }
   4588 
   4589 static void GLAPIENTRY
   4590 save_WindowPos2fvMESA(const GLfloat * v)
   4591 {
   4592    save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F);
   4593 }
   4594 
   4595 static void GLAPIENTRY
   4596 save_WindowPos2ivMESA(const GLint * v)
   4597 {
   4598    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], 0.0F, 1.0F);
   4599 }
   4600 
   4601 static void GLAPIENTRY
   4602 save_WindowPos2svMESA(const GLshort * v)
   4603 {
   4604    save_WindowPos4fMESA(v[0], v[1], 0.0F, 1.0F);
   4605 }
   4606 
   4607 static void GLAPIENTRY
   4608 save_WindowPos3dvMESA(const GLdouble * v)
   4609 {
   4610    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
   4611 }
   4612 
   4613 static void GLAPIENTRY
   4614 save_WindowPos3fvMESA(const GLfloat * v)
   4615 {
   4616    save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F);
   4617 }
   4618 
   4619 static void GLAPIENTRY
   4620 save_WindowPos3ivMESA(const GLint * v)
   4621 {
   4622    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1], (GLfloat) v[2], 1.0F);
   4623 }
   4624 
   4625 static void GLAPIENTRY
   4626 save_WindowPos3svMESA(const GLshort * v)
   4627 {
   4628    save_WindowPos4fMESA(v[0], v[1], v[2], 1.0F);
   4629 }
   4630 
   4631 static void GLAPIENTRY
   4632 save_WindowPos4dvMESA(const GLdouble * v)
   4633 {
   4634    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1],
   4635                         (GLfloat) v[2], (GLfloat) v[3]);
   4636 }
   4637 
   4638 static void GLAPIENTRY
   4639 save_WindowPos4fvMESA(const GLfloat * v)
   4640 {
   4641    save_WindowPos4fMESA(v[0], v[1], v[2], v[3]);
   4642 }
   4643 
   4644 static void GLAPIENTRY
   4645 save_WindowPos4ivMESA(const GLint * v)
   4646 {
   4647    save_WindowPos4fMESA((GLfloat) v[0], (GLfloat) v[1],
   4648                         (GLfloat) v[2], (GLfloat) v[3]);
   4649 }
   4650 
   4651 static void GLAPIENTRY
   4652 save_WindowPos4svMESA(const GLshort * v)
   4653 {
   4654    save_WindowPos4fMESA(v[0], v[1], v[2], v[3]);
   4655 }
   4656 
   4657 
   4658 
   4659 /* GL_ARB_multitexture */
   4660 static void GLAPIENTRY
   4661 save_ActiveTextureARB(GLenum target)
   4662 {
   4663    GET_CURRENT_CONTEXT(ctx);
   4664    Node *n;
   4665    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4666    n = alloc_instruction(ctx, OPCODE_ACTIVE_TEXTURE, 1);
   4667    if (n) {
   4668       n[1].e = target;
   4669    }
   4670    if (ctx->ExecuteFlag) {
   4671       CALL_ActiveTexture(ctx->Exec, (target));
   4672    }
   4673 }
   4674 
   4675 
   4676 /* GL_ARB_transpose_matrix */
   4677 
   4678 static void GLAPIENTRY
   4679 save_LoadTransposeMatrixdARB(const GLdouble m[16])
   4680 {
   4681    GLfloat tm[16];
   4682    _math_transposefd(tm, m);
   4683    save_LoadMatrixf(tm);
   4684 }
   4685 
   4686 
   4687 static void GLAPIENTRY
   4688 save_LoadTransposeMatrixfARB(const GLfloat m[16])
   4689 {
   4690    GLfloat tm[16];
   4691    _math_transposef(tm, m);
   4692    save_LoadMatrixf(tm);
   4693 }
   4694 
   4695 
   4696 static void GLAPIENTRY
   4697 save_MultTransposeMatrixdARB(const GLdouble m[16])
   4698 {
   4699    GLfloat tm[16];
   4700    _math_transposefd(tm, m);
   4701    save_MultMatrixf(tm);
   4702 }
   4703 
   4704 
   4705 static void GLAPIENTRY
   4706 save_MultTransposeMatrixfARB(const GLfloat m[16])
   4707 {
   4708    GLfloat tm[16];
   4709    _math_transposef(tm, m);
   4710    save_MultMatrixf(tm);
   4711 }
   4712 
   4713 static GLvoid *copy_data(const GLvoid *data, GLsizei size, const char *func)
   4714 {
   4715    GET_CURRENT_CONTEXT(ctx);
   4716    GLvoid *image;
   4717 
   4718    if (!data)
   4719       return NULL;
   4720 
   4721    image = malloc(size);
   4722    if (!image) {
   4723       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func);
   4724       return NULL;
   4725    }
   4726    memcpy(image, data, size);
   4727 
   4728    return image;
   4729 }
   4730 
   4731 
   4732 /* GL_ARB_texture_compression */
   4733 static void GLAPIENTRY
   4734 save_CompressedTexImage1DARB(GLenum target, GLint level,
   4735                              GLenum internalFormat, GLsizei width,
   4736                              GLint border, GLsizei imageSize,
   4737                              const GLvoid * data)
   4738 {
   4739    GET_CURRENT_CONTEXT(ctx);
   4740    if (target == GL_PROXY_TEXTURE_1D) {
   4741       /* don't compile, execute immediately */
   4742       CALL_CompressedTexImage1D(ctx->Exec, (target, level, internalFormat,
   4743                                                width, border, imageSize,
   4744                                                data));
   4745    }
   4746    else {
   4747       Node *n;
   4748       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4749 
   4750       n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_1D,
   4751                             6 + POINTER_DWORDS);
   4752       if (n) {
   4753          n[1].e = target;
   4754          n[2].i = level;
   4755          n[3].e = internalFormat;
   4756          n[4].i = (GLint) width;
   4757          n[5].i = border;
   4758          n[6].i = imageSize;
   4759          save_pointer(&n[7],
   4760                       copy_data(data, imageSize, "glCompressedTexImage1DARB"));
   4761       }
   4762       if (ctx->ExecuteFlag) {
   4763          CALL_CompressedTexImage1D(ctx->Exec,
   4764                                       (target, level, internalFormat, width,
   4765                                        border, imageSize, data));
   4766       }
   4767    }
   4768 }
   4769 
   4770 
   4771 static void GLAPIENTRY
   4772 save_CompressedTexImage2DARB(GLenum target, GLint level,
   4773                              GLenum internalFormat, GLsizei width,
   4774                              GLsizei height, GLint border, GLsizei imageSize,
   4775                              const GLvoid * data)
   4776 {
   4777    GET_CURRENT_CONTEXT(ctx);
   4778    if (target == GL_PROXY_TEXTURE_2D) {
   4779       /* don't compile, execute immediately */
   4780       CALL_CompressedTexImage2D(ctx->Exec, (target, level, internalFormat,
   4781                                                width, height, border,
   4782                                                imageSize, data));
   4783    }
   4784    else {
   4785       Node *n;
   4786       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4787 
   4788       n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_2D,
   4789                             7 + POINTER_DWORDS);
   4790       if (n) {
   4791          n[1].e = target;
   4792          n[2].i = level;
   4793          n[3].e = internalFormat;
   4794          n[4].i = (GLint) width;
   4795          n[5].i = (GLint) height;
   4796          n[6].i = border;
   4797          n[7].i = imageSize;
   4798          save_pointer(&n[8],
   4799                       copy_data(data, imageSize, "glCompressedTexImage2DARB"));
   4800       }
   4801       if (ctx->ExecuteFlag) {
   4802          CALL_CompressedTexImage2D(ctx->Exec,
   4803                                       (target, level, internalFormat, width,
   4804                                        height, border, imageSize, data));
   4805       }
   4806    }
   4807 }
   4808 
   4809 
   4810 static void GLAPIENTRY
   4811 save_CompressedTexImage3DARB(GLenum target, GLint level,
   4812                              GLenum internalFormat, GLsizei width,
   4813                              GLsizei height, GLsizei depth, GLint border,
   4814                              GLsizei imageSize, const GLvoid * data)
   4815 {
   4816    GET_CURRENT_CONTEXT(ctx);
   4817    if (target == GL_PROXY_TEXTURE_3D) {
   4818       /* don't compile, execute immediately */
   4819       CALL_CompressedTexImage3D(ctx->Exec, (target, level, internalFormat,
   4820                                                width, height, depth, border,
   4821                                                imageSize, data));
   4822    }
   4823    else {
   4824       Node *n;
   4825       ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4826 
   4827       n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_IMAGE_3D,
   4828                             8 + POINTER_DWORDS);
   4829       if (n) {
   4830          n[1].e = target;
   4831          n[2].i = level;
   4832          n[3].e = internalFormat;
   4833          n[4].i = (GLint) width;
   4834          n[5].i = (GLint) height;
   4835          n[6].i = (GLint) depth;
   4836          n[7].i = border;
   4837          n[8].i = imageSize;
   4838          save_pointer(&n[9],
   4839                       copy_data(data, imageSize, "glCompressedTexImage3DARB"));
   4840       }
   4841       if (ctx->ExecuteFlag) {
   4842          CALL_CompressedTexImage3D(ctx->Exec,
   4843                                       (target, level, internalFormat, width,
   4844                                        height, depth, border, imageSize,
   4845                                        data));
   4846       }
   4847    }
   4848 }
   4849 
   4850 
   4851 static void GLAPIENTRY
   4852 save_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
   4853                                 GLsizei width, GLenum format,
   4854                                 GLsizei imageSize, const GLvoid * data)
   4855 {
   4856    Node *n;
   4857    GET_CURRENT_CONTEXT(ctx);
   4858    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4859 
   4860    n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D,
   4861                          6 + POINTER_DWORDS);
   4862    if (n) {
   4863       n[1].e = target;
   4864       n[2].i = level;
   4865       n[3].i = xoffset;
   4866       n[4].i = (GLint) width;
   4867       n[5].e = format;
   4868       n[6].i = imageSize;
   4869       save_pointer(&n[7],
   4870                    copy_data(data, imageSize, "glCompressedTexSubImage1DARB"));
   4871    }
   4872    if (ctx->ExecuteFlag) {
   4873       CALL_CompressedTexSubImage1D(ctx->Exec, (target, level, xoffset,
   4874                                                   width, format, imageSize,
   4875                                                   data));
   4876    }
   4877 }
   4878 
   4879 
   4880 static void GLAPIENTRY
   4881 save_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
   4882                                 GLint yoffset, GLsizei width, GLsizei height,
   4883                                 GLenum format, GLsizei imageSize,
   4884                                 const GLvoid * data)
   4885 {
   4886    Node *n;
   4887    GET_CURRENT_CONTEXT(ctx);
   4888    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4889 
   4890    n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D,
   4891                          8 + POINTER_DWORDS);
   4892    if (n) {
   4893       n[1].e = target;
   4894       n[2].i = level;
   4895       n[3].i = xoffset;
   4896       n[4].i = yoffset;
   4897       n[5].i = (GLint) width;
   4898       n[6].i = (GLint) height;
   4899       n[7].e = format;
   4900       n[8].i = imageSize;
   4901       save_pointer(&n[9],
   4902                    copy_data(data, imageSize, "glCompressedTexSubImage2DARB"));
   4903    }
   4904    if (ctx->ExecuteFlag) {
   4905       CALL_CompressedTexSubImage2D(ctx->Exec,
   4906                                       (target, level, xoffset, yoffset, width,
   4907                                        height, format, imageSize, data));
   4908    }
   4909 }
   4910 
   4911 
   4912 static void GLAPIENTRY
   4913 save_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
   4914                                 GLint yoffset, GLint zoffset, GLsizei width,
   4915                                 GLsizei height, GLsizei depth, GLenum format,
   4916                                 GLsizei imageSize, const GLvoid * data)
   4917 {
   4918    Node *n;
   4919    GET_CURRENT_CONTEXT(ctx);
   4920    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4921 
   4922    n = alloc_instruction(ctx, OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D,
   4923                          10 + POINTER_DWORDS);
   4924    if (n) {
   4925       n[1].e = target;
   4926       n[2].i = level;
   4927       n[3].i = xoffset;
   4928       n[4].i = yoffset;
   4929       n[5].i = zoffset;
   4930       n[6].i = (GLint) width;
   4931       n[7].i = (GLint) height;
   4932       n[8].i = (GLint) depth;
   4933       n[9].e = format;
   4934       n[10].i = imageSize;
   4935       save_pointer(&n[11],
   4936                    copy_data(data, imageSize, "glCompressedTexSubImage3DARB"));
   4937    }
   4938    if (ctx->ExecuteFlag) {
   4939       CALL_CompressedTexSubImage3D(ctx->Exec,
   4940                                       (target, level, xoffset, yoffset,
   4941                                        zoffset, width, height, depth, format,
   4942                                        imageSize, data));
   4943    }
   4944 }
   4945 
   4946 
   4947 /* GL_ARB_multisample */
   4948 static void GLAPIENTRY
   4949 save_SampleCoverageARB(GLclampf value, GLboolean invert)
   4950 {
   4951    GET_CURRENT_CONTEXT(ctx);
   4952    Node *n;
   4953    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4954    n = alloc_instruction(ctx, OPCODE_SAMPLE_COVERAGE, 2);
   4955    if (n) {
   4956       n[1].f = value;
   4957       n[2].b = invert;
   4958    }
   4959    if (ctx->ExecuteFlag) {
   4960       CALL_SampleCoverage(ctx->Exec, (value, invert));
   4961    }
   4962 }
   4963 
   4964 
   4965 /*
   4966  * GL_ARB_vertex_program
   4967  */
   4968 static void GLAPIENTRY
   4969 save_BindProgramARB(GLenum target, GLuint id)
   4970 {
   4971    GET_CURRENT_CONTEXT(ctx);
   4972    Node *n;
   4973    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4974    n = alloc_instruction(ctx, OPCODE_BIND_PROGRAM_ARB, 2);
   4975    if (n) {
   4976       n[1].e = target;
   4977       n[2].ui = id;
   4978    }
   4979    if (ctx->ExecuteFlag) {
   4980       CALL_BindProgramARB(ctx->Exec, (target, id));
   4981    }
   4982 }
   4983 
   4984 static void GLAPIENTRY
   4985 save_ProgramEnvParameter4fARB(GLenum target, GLuint index,
   4986                               GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   4987 {
   4988    GET_CURRENT_CONTEXT(ctx);
   4989    Node *n;
   4990    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   4991    n = alloc_instruction(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
   4992    if (n) {
   4993       n[1].e = target;
   4994       n[2].ui = index;
   4995       n[3].f = x;
   4996       n[4].f = y;
   4997       n[5].f = z;
   4998       n[6].f = w;
   4999    }
   5000    if (ctx->ExecuteFlag) {
   5001       CALL_ProgramEnvParameter4fARB(ctx->Exec, (target, index, x, y, z, w));
   5002    }
   5003 }
   5004 
   5005 
   5006 static void GLAPIENTRY
   5007 save_ProgramEnvParameter4fvARB(GLenum target, GLuint index,
   5008                                const GLfloat *params)
   5009 {
   5010    save_ProgramEnvParameter4fARB(target, index, params[0], params[1],
   5011                                  params[2], params[3]);
   5012 }
   5013 
   5014 
   5015 static void GLAPIENTRY
   5016 save_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
   5017                                 const GLfloat * params)
   5018 {
   5019    GET_CURRENT_CONTEXT(ctx);
   5020    Node *n;
   5021    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5022 
   5023    if (count > 0) {
   5024       GLint i;
   5025       const GLfloat * p = params;
   5026 
   5027       for (i = 0 ; i < count ; i++) {
   5028          n = alloc_instruction(ctx, OPCODE_PROGRAM_ENV_PARAMETER_ARB, 6);
   5029          if (n) {
   5030             n[1].e = target;
   5031             n[2].ui = index;
   5032             n[3].f = p[0];
   5033             n[4].f = p[1];
   5034             n[5].f = p[2];
   5035             n[6].f = p[3];
   5036             p += 4;
   5037          }
   5038       }
   5039    }
   5040 
   5041    if (ctx->ExecuteFlag) {
   5042       CALL_ProgramEnvParameters4fvEXT(ctx->Exec, (target, index, count, params));
   5043    }
   5044 }
   5045 
   5046 
   5047 static void GLAPIENTRY
   5048 save_ProgramEnvParameter4dARB(GLenum target, GLuint index,
   5049                               GLdouble x, GLdouble y, GLdouble z, GLdouble w)
   5050 {
   5051    save_ProgramEnvParameter4fARB(target, index,
   5052                                  (GLfloat) x,
   5053                                  (GLfloat) y, (GLfloat) z, (GLfloat) w);
   5054 }
   5055 
   5056 
   5057 static void GLAPIENTRY
   5058 save_ProgramEnvParameter4dvARB(GLenum target, GLuint index,
   5059                                const GLdouble *params)
   5060 {
   5061    save_ProgramEnvParameter4fARB(target, index,
   5062                                  (GLfloat) params[0],
   5063                                  (GLfloat) params[1],
   5064                                  (GLfloat) params[2], (GLfloat) params[3]);
   5065 }
   5066 
   5067 
   5068 static void GLAPIENTRY
   5069 save_ProgramLocalParameter4fARB(GLenum target, GLuint index,
   5070                                 GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5071 {
   5072    GET_CURRENT_CONTEXT(ctx);
   5073    Node *n;
   5074    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5075    n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
   5076    if (n) {
   5077       n[1].e = target;
   5078       n[2].ui = index;
   5079       n[3].f = x;
   5080       n[4].f = y;
   5081       n[5].f = z;
   5082       n[6].f = w;
   5083    }
   5084    if (ctx->ExecuteFlag) {
   5085       CALL_ProgramLocalParameter4fARB(ctx->Exec, (target, index, x, y, z, w));
   5086    }
   5087 }
   5088 
   5089 
   5090 static void GLAPIENTRY
   5091 save_ProgramLocalParameter4fvARB(GLenum target, GLuint index,
   5092                                  const GLfloat *params)
   5093 {
   5094    GET_CURRENT_CONTEXT(ctx);
   5095    Node *n;
   5096    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5097    n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
   5098    if (n) {
   5099       n[1].e = target;
   5100       n[2].ui = index;
   5101       n[3].f = params[0];
   5102       n[4].f = params[1];
   5103       n[5].f = params[2];
   5104       n[6].f = params[3];
   5105    }
   5106    if (ctx->ExecuteFlag) {
   5107       CALL_ProgramLocalParameter4fvARB(ctx->Exec, (target, index, params));
   5108    }
   5109 }
   5110 
   5111 
   5112 static void GLAPIENTRY
   5113 save_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count,
   5114                                   const GLfloat *params)
   5115 {
   5116    GET_CURRENT_CONTEXT(ctx);
   5117    Node *n;
   5118    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5119 
   5120    if (count > 0) {
   5121       GLint i;
   5122       const GLfloat * p = params;
   5123 
   5124       for (i = 0 ; i < count ; i++) {
   5125          n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
   5126          if (n) {
   5127             n[1].e = target;
   5128             n[2].ui = index;
   5129             n[3].f = p[0];
   5130             n[4].f = p[1];
   5131             n[5].f = p[2];
   5132             n[6].f = p[3];
   5133             p += 4;
   5134          }
   5135       }
   5136    }
   5137 
   5138    if (ctx->ExecuteFlag) {
   5139       CALL_ProgramLocalParameters4fvEXT(ctx->Exec, (target, index, count, params));
   5140    }
   5141 }
   5142 
   5143 
   5144 static void GLAPIENTRY
   5145 save_ProgramLocalParameter4dARB(GLenum target, GLuint index,
   5146                                 GLdouble x, GLdouble y,
   5147                                 GLdouble z, GLdouble w)
   5148 {
   5149    GET_CURRENT_CONTEXT(ctx);
   5150    Node *n;
   5151    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5152    n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
   5153    if (n) {
   5154       n[1].e = target;
   5155       n[2].ui = index;
   5156       n[3].f = (GLfloat) x;
   5157       n[4].f = (GLfloat) y;
   5158       n[5].f = (GLfloat) z;
   5159       n[6].f = (GLfloat) w;
   5160    }
   5161    if (ctx->ExecuteFlag) {
   5162       CALL_ProgramLocalParameter4dARB(ctx->Exec, (target, index, x, y, z, w));
   5163    }
   5164 }
   5165 
   5166 
   5167 static void GLAPIENTRY
   5168 save_ProgramLocalParameter4dvARB(GLenum target, GLuint index,
   5169                                  const GLdouble *params)
   5170 {
   5171    GET_CURRENT_CONTEXT(ctx);
   5172    Node *n;
   5173    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5174    n = alloc_instruction(ctx, OPCODE_PROGRAM_LOCAL_PARAMETER_ARB, 6);
   5175    if (n) {
   5176       n[1].e = target;
   5177       n[2].ui = index;
   5178       n[3].f = (GLfloat) params[0];
   5179       n[4].f = (GLfloat) params[1];
   5180       n[5].f = (GLfloat) params[2];
   5181       n[6].f = (GLfloat) params[3];
   5182    }
   5183    if (ctx->ExecuteFlag) {
   5184       CALL_ProgramLocalParameter4dvARB(ctx->Exec, (target, index, params));
   5185    }
   5186 }
   5187 
   5188 
   5189 /* GL_EXT_stencil_two_side */
   5190 static void GLAPIENTRY
   5191 save_ActiveStencilFaceEXT(GLenum face)
   5192 {
   5193    GET_CURRENT_CONTEXT(ctx);
   5194    Node *n;
   5195    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5196    n = alloc_instruction(ctx, OPCODE_ACTIVE_STENCIL_FACE_EXT, 1);
   5197    if (n) {
   5198       n[1].e = face;
   5199    }
   5200    if (ctx->ExecuteFlag) {
   5201       CALL_ActiveStencilFaceEXT(ctx->Exec, (face));
   5202    }
   5203 }
   5204 
   5205 
   5206 /* GL_EXT_depth_bounds_test */
   5207 static void GLAPIENTRY
   5208 save_DepthBoundsEXT(GLclampd zmin, GLclampd zmax)
   5209 {
   5210    GET_CURRENT_CONTEXT(ctx);
   5211    Node *n;
   5212    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5213    n = alloc_instruction(ctx, OPCODE_DEPTH_BOUNDS_EXT, 2);
   5214    if (n) {
   5215       n[1].f = (GLfloat) zmin;
   5216       n[2].f = (GLfloat) zmax;
   5217    }
   5218    if (ctx->ExecuteFlag) {
   5219       CALL_DepthBoundsEXT(ctx->Exec, (zmin, zmax));
   5220    }
   5221 }
   5222 
   5223 
   5224 
   5225 static void GLAPIENTRY
   5226 save_ProgramStringARB(GLenum target, GLenum format, GLsizei len,
   5227                       const GLvoid * string)
   5228 {
   5229    GET_CURRENT_CONTEXT(ctx);
   5230    Node *n;
   5231 
   5232    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5233 
   5234    n = alloc_instruction(ctx, OPCODE_PROGRAM_STRING_ARB, 3 + POINTER_DWORDS);
   5235    if (n) {
   5236       GLubyte *programCopy = malloc(len);
   5237       if (!programCopy) {
   5238          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glProgramStringARB");
   5239          return;
   5240       }
   5241       memcpy(programCopy, string, len);
   5242       n[1].e = target;
   5243       n[2].e = format;
   5244       n[3].i = len;
   5245       save_pointer(&n[4], programCopy);
   5246    }
   5247    if (ctx->ExecuteFlag) {
   5248       CALL_ProgramStringARB(ctx->Exec, (target, format, len, string));
   5249    }
   5250 }
   5251 
   5252 
   5253 static void GLAPIENTRY
   5254 save_BeginQueryARB(GLenum target, GLuint id)
   5255 {
   5256    GET_CURRENT_CONTEXT(ctx);
   5257    Node *n;
   5258    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5259    n = alloc_instruction(ctx, OPCODE_BEGIN_QUERY_ARB, 2);
   5260    if (n) {
   5261       n[1].e = target;
   5262       n[2].ui = id;
   5263    }
   5264    if (ctx->ExecuteFlag) {
   5265       CALL_BeginQuery(ctx->Exec, (target, id));
   5266    }
   5267 }
   5268 
   5269 static void GLAPIENTRY
   5270 save_EndQueryARB(GLenum target)
   5271 {
   5272    GET_CURRENT_CONTEXT(ctx);
   5273    Node *n;
   5274    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5275    n = alloc_instruction(ctx, OPCODE_END_QUERY_ARB, 1);
   5276    if (n) {
   5277       n[1].e = target;
   5278    }
   5279    if (ctx->ExecuteFlag) {
   5280       CALL_EndQuery(ctx->Exec, (target));
   5281    }
   5282 }
   5283 
   5284 static void GLAPIENTRY
   5285 save_QueryCounter(GLuint id, GLenum target)
   5286 {
   5287    GET_CURRENT_CONTEXT(ctx);
   5288    Node *n;
   5289    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5290    n = alloc_instruction(ctx, OPCODE_QUERY_COUNTER, 2);
   5291    if (n) {
   5292       n[1].ui = id;
   5293       n[2].e = target;
   5294    }
   5295    if (ctx->ExecuteFlag) {
   5296       CALL_QueryCounter(ctx->Exec, (id, target));
   5297    }
   5298 }
   5299 
   5300 static void GLAPIENTRY
   5301 save_BeginQueryIndexed(GLenum target, GLuint index, GLuint id)
   5302 {
   5303    GET_CURRENT_CONTEXT(ctx);
   5304    Node *n;
   5305    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5306    n = alloc_instruction(ctx, OPCODE_BEGIN_QUERY_INDEXED, 3);
   5307    if (n) {
   5308       n[1].e = target;
   5309       n[2].ui = index;
   5310       n[3].ui = id;
   5311    }
   5312    if (ctx->ExecuteFlag) {
   5313       CALL_BeginQueryIndexed(ctx->Exec, (target, index, id));
   5314    }
   5315 }
   5316 
   5317 static void GLAPIENTRY
   5318 save_EndQueryIndexed(GLenum target, GLuint index)
   5319 {
   5320    GET_CURRENT_CONTEXT(ctx);
   5321    Node *n;
   5322    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5323    n = alloc_instruction(ctx, OPCODE_END_QUERY_INDEXED, 2);
   5324    if (n) {
   5325       n[1].e = target;
   5326       n[2].ui = index;
   5327    }
   5328    if (ctx->ExecuteFlag) {
   5329       CALL_EndQueryIndexed(ctx->Exec, (target, index));
   5330    }
   5331 }
   5332 
   5333 
   5334 static void GLAPIENTRY
   5335 save_DrawBuffersARB(GLsizei count, const GLenum * buffers)
   5336 {
   5337    GET_CURRENT_CONTEXT(ctx);
   5338    Node *n;
   5339    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5340    n = alloc_instruction(ctx, OPCODE_DRAW_BUFFERS_ARB, 1 + MAX_DRAW_BUFFERS);
   5341    if (n) {
   5342       GLint i;
   5343       n[1].i = count;
   5344       if (count > MAX_DRAW_BUFFERS)
   5345          count = MAX_DRAW_BUFFERS;
   5346       for (i = 0; i < count; i++) {
   5347          n[2 + i].e = buffers[i];
   5348       }
   5349    }
   5350    if (ctx->ExecuteFlag) {
   5351       CALL_DrawBuffers(ctx->Exec, (count, buffers));
   5352    }
   5353 }
   5354 
   5355 static void GLAPIENTRY
   5356 save_BindFragmentShaderATI(GLuint id)
   5357 {
   5358    GET_CURRENT_CONTEXT(ctx);
   5359    Node *n;
   5360 
   5361    n = alloc_instruction(ctx, OPCODE_BIND_FRAGMENT_SHADER_ATI, 1);
   5362    if (n) {
   5363       n[1].ui = id;
   5364    }
   5365    if (ctx->ExecuteFlag) {
   5366       CALL_BindFragmentShaderATI(ctx->Exec, (id));
   5367    }
   5368 }
   5369 
   5370 static void GLAPIENTRY
   5371 save_SetFragmentShaderConstantATI(GLuint dst, const GLfloat *value)
   5372 {
   5373    GET_CURRENT_CONTEXT(ctx);
   5374    Node *n;
   5375 
   5376    n = alloc_instruction(ctx, OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI, 5);
   5377    if (n) {
   5378       n[1].ui = dst;
   5379       n[2].f = value[0];
   5380       n[3].f = value[1];
   5381       n[4].f = value[2];
   5382       n[5].f = value[3];
   5383    }
   5384    if (ctx->ExecuteFlag) {
   5385       CALL_SetFragmentShaderConstantATI(ctx->Exec, (dst, value));
   5386    }
   5387 }
   5388 
   5389 static void GLAPIENTRY
   5390 save_Attr1fNV(GLenum attr, GLfloat x)
   5391 {
   5392    GET_CURRENT_CONTEXT(ctx);
   5393    Node *n;
   5394    SAVE_FLUSH_VERTICES(ctx);
   5395    n = alloc_instruction(ctx, OPCODE_ATTR_1F_NV, 2);
   5396    if (n) {
   5397       n[1].e = attr;
   5398       n[2].f = x;
   5399    }
   5400 
   5401    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5402    ctx->ListState.ActiveAttribSize[attr] = 1;
   5403    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
   5404 
   5405    if (ctx->ExecuteFlag) {
   5406       CALL_VertexAttrib1fNV(ctx->Exec, (attr, x));
   5407    }
   5408 }
   5409 
   5410 static void GLAPIENTRY
   5411 save_Attr2fNV(GLenum attr, GLfloat x, GLfloat y)
   5412 {
   5413    GET_CURRENT_CONTEXT(ctx);
   5414    Node *n;
   5415    SAVE_FLUSH_VERTICES(ctx);
   5416    n = alloc_instruction(ctx, OPCODE_ATTR_2F_NV, 3);
   5417    if (n) {
   5418       n[1].e = attr;
   5419       n[2].f = x;
   5420       n[3].f = y;
   5421    }
   5422 
   5423    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5424    ctx->ListState.ActiveAttribSize[attr] = 2;
   5425    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
   5426 
   5427    if (ctx->ExecuteFlag) {
   5428       CALL_VertexAttrib2fNV(ctx->Exec, (attr, x, y));
   5429    }
   5430 }
   5431 
   5432 static void GLAPIENTRY
   5433 save_Attr3fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
   5434 {
   5435    GET_CURRENT_CONTEXT(ctx);
   5436    Node *n;
   5437    SAVE_FLUSH_VERTICES(ctx);
   5438    n = alloc_instruction(ctx, OPCODE_ATTR_3F_NV, 4);
   5439    if (n) {
   5440       n[1].e = attr;
   5441       n[2].f = x;
   5442       n[3].f = y;
   5443       n[4].f = z;
   5444    }
   5445 
   5446    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5447    ctx->ListState.ActiveAttribSize[attr] = 3;
   5448    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
   5449 
   5450    if (ctx->ExecuteFlag) {
   5451       CALL_VertexAttrib3fNV(ctx->Exec, (attr, x, y, z));
   5452    }
   5453 }
   5454 
   5455 static void GLAPIENTRY
   5456 save_Attr4fNV(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5457 {
   5458    GET_CURRENT_CONTEXT(ctx);
   5459    Node *n;
   5460    SAVE_FLUSH_VERTICES(ctx);
   5461    n = alloc_instruction(ctx, OPCODE_ATTR_4F_NV, 5);
   5462    if (n) {
   5463       n[1].e = attr;
   5464       n[2].f = x;
   5465       n[3].f = y;
   5466       n[4].f = z;
   5467       n[5].f = w;
   5468    }
   5469 
   5470    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5471    ctx->ListState.ActiveAttribSize[attr] = 4;
   5472    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
   5473 
   5474    if (ctx->ExecuteFlag) {
   5475       CALL_VertexAttrib4fNV(ctx->Exec, (attr, x, y, z, w));
   5476    }
   5477 }
   5478 
   5479 
   5480 static void GLAPIENTRY
   5481 save_Attr1fARB(GLenum attr, GLfloat x)
   5482 {
   5483    GET_CURRENT_CONTEXT(ctx);
   5484    Node *n;
   5485    SAVE_FLUSH_VERTICES(ctx);
   5486    n = alloc_instruction(ctx, OPCODE_ATTR_1F_ARB, 2);
   5487    if (n) {
   5488       n[1].e = attr;
   5489       n[2].f = x;
   5490    }
   5491 
   5492    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5493    ctx->ListState.ActiveAttribSize[attr] = 1;
   5494    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, 0, 0, 1);
   5495 
   5496    if (ctx->ExecuteFlag) {
   5497       CALL_VertexAttrib1fARB(ctx->Exec, (attr, x));
   5498    }
   5499 }
   5500 
   5501 static void GLAPIENTRY
   5502 save_Attr2fARB(GLenum attr, GLfloat x, GLfloat y)
   5503 {
   5504    GET_CURRENT_CONTEXT(ctx);
   5505    Node *n;
   5506    SAVE_FLUSH_VERTICES(ctx);
   5507    n = alloc_instruction(ctx, OPCODE_ATTR_2F_ARB, 3);
   5508    if (n) {
   5509       n[1].e = attr;
   5510       n[2].f = x;
   5511       n[3].f = y;
   5512    }
   5513 
   5514    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5515    ctx->ListState.ActiveAttribSize[attr] = 2;
   5516    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, 0, 1);
   5517 
   5518    if (ctx->ExecuteFlag) {
   5519       CALL_VertexAttrib2fARB(ctx->Exec, (attr, x, y));
   5520    }
   5521 }
   5522 
   5523 static void GLAPIENTRY
   5524 save_Attr3fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z)
   5525 {
   5526    GET_CURRENT_CONTEXT(ctx);
   5527    Node *n;
   5528    SAVE_FLUSH_VERTICES(ctx);
   5529    n = alloc_instruction(ctx, OPCODE_ATTR_3F_ARB, 4);
   5530    if (n) {
   5531       n[1].e = attr;
   5532       n[2].f = x;
   5533       n[3].f = y;
   5534       n[4].f = z;
   5535    }
   5536 
   5537    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5538    ctx->ListState.ActiveAttribSize[attr] = 3;
   5539    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, 1);
   5540 
   5541    if (ctx->ExecuteFlag) {
   5542       CALL_VertexAttrib3fARB(ctx->Exec, (attr, x, y, z));
   5543    }
   5544 }
   5545 
   5546 static void GLAPIENTRY
   5547 save_Attr4fARB(GLenum attr, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5548 {
   5549    GET_CURRENT_CONTEXT(ctx);
   5550    Node *n;
   5551    SAVE_FLUSH_VERTICES(ctx);
   5552    n = alloc_instruction(ctx, OPCODE_ATTR_4F_ARB, 5);
   5553    if (n) {
   5554       n[1].e = attr;
   5555       n[2].f = x;
   5556       n[3].f = y;
   5557       n[4].f = z;
   5558       n[5].f = w;
   5559    }
   5560 
   5561    assert(attr < MAX_VERTEX_GENERIC_ATTRIBS);
   5562    ctx->ListState.ActiveAttribSize[attr] = 4;
   5563    ASSIGN_4V(ctx->ListState.CurrentAttrib[attr], x, y, z, w);
   5564 
   5565    if (ctx->ExecuteFlag) {
   5566       CALL_VertexAttrib4fARB(ctx->Exec, (attr, x, y, z, w));
   5567    }
   5568 }
   5569 
   5570 
   5571 static void GLAPIENTRY
   5572 save_EvalCoord1f(GLfloat x)
   5573 {
   5574    GET_CURRENT_CONTEXT(ctx);
   5575    Node *n;
   5576    SAVE_FLUSH_VERTICES(ctx);
   5577    n = alloc_instruction(ctx, OPCODE_EVAL_C1, 1);
   5578    if (n) {
   5579       n[1].f = x;
   5580    }
   5581    if (ctx->ExecuteFlag) {
   5582       CALL_EvalCoord1f(ctx->Exec, (x));
   5583    }
   5584 }
   5585 
   5586 static void GLAPIENTRY
   5587 save_EvalCoord1fv(const GLfloat * v)
   5588 {
   5589    save_EvalCoord1f(v[0]);
   5590 }
   5591 
   5592 static void GLAPIENTRY
   5593 save_EvalCoord2f(GLfloat x, GLfloat y)
   5594 {
   5595    GET_CURRENT_CONTEXT(ctx);
   5596    Node *n;
   5597    SAVE_FLUSH_VERTICES(ctx);
   5598    n = alloc_instruction(ctx, OPCODE_EVAL_C2, 2);
   5599    if (n) {
   5600       n[1].f = x;
   5601       n[2].f = y;
   5602    }
   5603    if (ctx->ExecuteFlag) {
   5604       CALL_EvalCoord2f(ctx->Exec, (x, y));
   5605    }
   5606 }
   5607 
   5608 static void GLAPIENTRY
   5609 save_EvalCoord2fv(const GLfloat * v)
   5610 {
   5611    save_EvalCoord2f(v[0], v[1]);
   5612 }
   5613 
   5614 
   5615 static void GLAPIENTRY
   5616 save_EvalPoint1(GLint x)
   5617 {
   5618    GET_CURRENT_CONTEXT(ctx);
   5619    Node *n;
   5620    SAVE_FLUSH_VERTICES(ctx);
   5621    n = alloc_instruction(ctx, OPCODE_EVAL_P1, 1);
   5622    if (n) {
   5623       n[1].i = x;
   5624    }
   5625    if (ctx->ExecuteFlag) {
   5626       CALL_EvalPoint1(ctx->Exec, (x));
   5627    }
   5628 }
   5629 
   5630 static void GLAPIENTRY
   5631 save_EvalPoint2(GLint x, GLint y)
   5632 {
   5633    GET_CURRENT_CONTEXT(ctx);
   5634    Node *n;
   5635    SAVE_FLUSH_VERTICES(ctx);
   5636    n = alloc_instruction(ctx, OPCODE_EVAL_P2, 2);
   5637    if (n) {
   5638       n[1].i = x;
   5639       n[2].i = y;
   5640    }
   5641    if (ctx->ExecuteFlag) {
   5642       CALL_EvalPoint2(ctx->Exec, (x, y));
   5643    }
   5644 }
   5645 
   5646 static void GLAPIENTRY
   5647 save_Indexf(GLfloat x)
   5648 {
   5649    save_Attr1fNV(VERT_ATTRIB_COLOR_INDEX, x);
   5650 }
   5651 
   5652 static void GLAPIENTRY
   5653 save_Indexfv(const GLfloat * v)
   5654 {
   5655    save_Attr1fNV(VERT_ATTRIB_COLOR_INDEX, v[0]);
   5656 }
   5657 
   5658 static void GLAPIENTRY
   5659 save_EdgeFlag(GLboolean x)
   5660 {
   5661    save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? 1.0f : 0.0f);
   5662 }
   5663 
   5664 
   5665 /**
   5666  * Compare 'count' elements of vectors 'a' and 'b'.
   5667  * \return GL_TRUE if equal, GL_FALSE if different.
   5668  */
   5669 static inline GLboolean
   5670 compare_vec(const GLfloat *a, const GLfloat *b, GLuint count)
   5671 {
   5672    return memcmp( a, b, count * sizeof(GLfloat) ) == 0;
   5673 }
   5674 
   5675 
   5676 /**
   5677  * This glMaterial function is used for glMaterial calls that are outside
   5678  * a glBegin/End pair.  For glMaterial inside glBegin/End, see the VBO code.
   5679  */
   5680 static void GLAPIENTRY
   5681 save_Materialfv(GLenum face, GLenum pname, const GLfloat * param)
   5682 {
   5683    GET_CURRENT_CONTEXT(ctx);
   5684    Node *n;
   5685    int args, i;
   5686    GLuint bitmask;
   5687 
   5688    switch (face) {
   5689    case GL_BACK:
   5690    case GL_FRONT:
   5691    case GL_FRONT_AND_BACK:
   5692       break;
   5693    default:
   5694       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(face)");
   5695       return;
   5696    }
   5697 
   5698    switch (pname) {
   5699    case GL_EMISSION:
   5700    case GL_AMBIENT:
   5701    case GL_DIFFUSE:
   5702    case GL_SPECULAR:
   5703    case GL_AMBIENT_AND_DIFFUSE:
   5704       args = 4;
   5705       break;
   5706    case GL_SHININESS:
   5707       args = 1;
   5708       break;
   5709    case GL_COLOR_INDEXES:
   5710       args = 3;
   5711       break;
   5712    default:
   5713       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMaterial(pname)");
   5714       return;
   5715    }
   5716 
   5717    if (ctx->ExecuteFlag) {
   5718       CALL_Materialfv(ctx->Exec, (face, pname, param));
   5719    }
   5720 
   5721    bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL);
   5722 
   5723    /* Try to eliminate redundant statechanges.  Because it is legal to
   5724     * call glMaterial even inside begin/end calls, don't need to worry
   5725     * about ctx->Driver.CurrentSavePrimitive here.
   5726     */
   5727    for (i = 0; i < MAT_ATTRIB_MAX; i++) {
   5728       if (bitmask & (1 << i)) {
   5729          if (ctx->ListState.ActiveMaterialSize[i] == args &&
   5730              compare_vec(ctx->ListState.CurrentMaterial[i], param, args)) {
   5731             /* no change in material value */
   5732             bitmask &= ~(1 << i);
   5733          }
   5734          else {
   5735             ctx->ListState.ActiveMaterialSize[i] = args;
   5736             COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param);
   5737          }
   5738       }
   5739    }
   5740 
   5741    /* If this call has no effect, return early */
   5742    if (bitmask == 0)
   5743       return;
   5744 
   5745    SAVE_FLUSH_VERTICES(ctx);
   5746 
   5747    n = alloc_instruction(ctx, OPCODE_MATERIAL, 6);
   5748    if (n) {
   5749       n[1].e = face;
   5750       n[2].e = pname;
   5751       for (i = 0; i < args; i++)
   5752          n[3 + i].f = param[i];
   5753    }
   5754 }
   5755 
   5756 static void GLAPIENTRY
   5757 save_Begin(GLenum mode)
   5758 {
   5759    GET_CURRENT_CONTEXT(ctx);
   5760 
   5761    if (!_mesa_is_valid_prim_mode(ctx, mode)) {
   5762       /* compile this error into the display list */
   5763       _mesa_compile_error(ctx, GL_INVALID_ENUM, "glBegin(mode)");
   5764    }
   5765    else if (_mesa_inside_dlist_begin_end(ctx)) {
   5766       /* compile this error into the display list */
   5767       _mesa_compile_error(ctx, GL_INVALID_OPERATION, "recursive glBegin");
   5768    }
   5769    else {
   5770       ctx->Driver.CurrentSavePrimitive = mode;
   5771 
   5772       vbo_save_NotifyBegin(ctx, mode);
   5773    }
   5774 }
   5775 
   5776 static void GLAPIENTRY
   5777 save_End(void)
   5778 {
   5779    GET_CURRENT_CONTEXT(ctx);
   5780    SAVE_FLUSH_VERTICES(ctx);
   5781    (void) alloc_instruction(ctx, OPCODE_END, 0);
   5782    ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
   5783    if (ctx->ExecuteFlag) {
   5784       CALL_End(ctx->Exec, ());
   5785    }
   5786 }
   5787 
   5788 static void GLAPIENTRY
   5789 save_Rectf(GLfloat a, GLfloat b, GLfloat c, GLfloat d)
   5790 {
   5791    GET_CURRENT_CONTEXT(ctx);
   5792    Node *n;
   5793    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   5794    n = alloc_instruction(ctx, OPCODE_RECTF, 4);
   5795    if (n) {
   5796       n[1].f = a;
   5797       n[2].f = b;
   5798       n[3].f = c;
   5799       n[4].f = d;
   5800    }
   5801    if (ctx->ExecuteFlag) {
   5802       CALL_Rectf(ctx->Exec, (a, b, c, d));
   5803    }
   5804 }
   5805 
   5806 
   5807 static void GLAPIENTRY
   5808 save_Vertex2f(GLfloat x, GLfloat y)
   5809 {
   5810    save_Attr2fNV(VERT_ATTRIB_POS, x, y);
   5811 }
   5812 
   5813 static void GLAPIENTRY
   5814 save_Vertex2fv(const GLfloat * v)
   5815 {
   5816    save_Attr2fNV(VERT_ATTRIB_POS, v[0], v[1]);
   5817 }
   5818 
   5819 static void GLAPIENTRY
   5820 save_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
   5821 {
   5822    save_Attr3fNV(VERT_ATTRIB_POS, x, y, z);
   5823 }
   5824 
   5825 static void GLAPIENTRY
   5826 save_Vertex3fv(const GLfloat * v)
   5827 {
   5828    save_Attr3fNV(VERT_ATTRIB_POS, v[0], v[1], v[2]);
   5829 }
   5830 
   5831 static void GLAPIENTRY
   5832 save_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5833 {
   5834    save_Attr4fNV(VERT_ATTRIB_POS, x, y, z, w);
   5835 }
   5836 
   5837 static void GLAPIENTRY
   5838 save_Vertex4fv(const GLfloat * v)
   5839 {
   5840    save_Attr4fNV(VERT_ATTRIB_POS, v[0], v[1], v[2], v[3]);
   5841 }
   5842 
   5843 static void GLAPIENTRY
   5844 save_TexCoord1f(GLfloat x)
   5845 {
   5846    save_Attr1fNV(VERT_ATTRIB_TEX0, x);
   5847 }
   5848 
   5849 static void GLAPIENTRY
   5850 save_TexCoord1fv(const GLfloat * v)
   5851 {
   5852    save_Attr1fNV(VERT_ATTRIB_TEX0, v[0]);
   5853 }
   5854 
   5855 static void GLAPIENTRY
   5856 save_TexCoord2f(GLfloat x, GLfloat y)
   5857 {
   5858    save_Attr2fNV(VERT_ATTRIB_TEX0, x, y);
   5859 }
   5860 
   5861 static void GLAPIENTRY
   5862 save_TexCoord2fv(const GLfloat * v)
   5863 {
   5864    save_Attr2fNV(VERT_ATTRIB_TEX0, v[0], v[1]);
   5865 }
   5866 
   5867 static void GLAPIENTRY
   5868 save_TexCoord3f(GLfloat x, GLfloat y, GLfloat z)
   5869 {
   5870    save_Attr3fNV(VERT_ATTRIB_TEX0, x, y, z);
   5871 }
   5872 
   5873 static void GLAPIENTRY
   5874 save_TexCoord3fv(const GLfloat * v)
   5875 {
   5876    save_Attr3fNV(VERT_ATTRIB_TEX0, v[0], v[1], v[2]);
   5877 }
   5878 
   5879 static void GLAPIENTRY
   5880 save_TexCoord4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5881 {
   5882    save_Attr4fNV(VERT_ATTRIB_TEX0, x, y, z, w);
   5883 }
   5884 
   5885 static void GLAPIENTRY
   5886 save_TexCoord4fv(const GLfloat * v)
   5887 {
   5888    save_Attr4fNV(VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3]);
   5889 }
   5890 
   5891 static void GLAPIENTRY
   5892 save_Normal3f(GLfloat x, GLfloat y, GLfloat z)
   5893 {
   5894    save_Attr3fNV(VERT_ATTRIB_NORMAL, x, y, z);
   5895 }
   5896 
   5897 static void GLAPIENTRY
   5898 save_Normal3fv(const GLfloat * v)
   5899 {
   5900    save_Attr3fNV(VERT_ATTRIB_NORMAL, v[0], v[1], v[2]);
   5901 }
   5902 
   5903 static void GLAPIENTRY
   5904 save_FogCoordfEXT(GLfloat x)
   5905 {
   5906    save_Attr1fNV(VERT_ATTRIB_FOG, x);
   5907 }
   5908 
   5909 static void GLAPIENTRY
   5910 save_FogCoordfvEXT(const GLfloat * v)
   5911 {
   5912    save_Attr1fNV(VERT_ATTRIB_FOG, v[0]);
   5913 }
   5914 
   5915 static void GLAPIENTRY
   5916 save_Color3f(GLfloat x, GLfloat y, GLfloat z)
   5917 {
   5918    save_Attr3fNV(VERT_ATTRIB_COLOR0, x, y, z);
   5919 }
   5920 
   5921 static void GLAPIENTRY
   5922 save_Color3fv(const GLfloat * v)
   5923 {
   5924    save_Attr3fNV(VERT_ATTRIB_COLOR0, v[0], v[1], v[2]);
   5925 }
   5926 
   5927 static void GLAPIENTRY
   5928 save_Color4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
   5929 {
   5930    save_Attr4fNV(VERT_ATTRIB_COLOR0, x, y, z, w);
   5931 }
   5932 
   5933 static void GLAPIENTRY
   5934 save_Color4fv(const GLfloat * v)
   5935 {
   5936    save_Attr4fNV(VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3]);
   5937 }
   5938 
   5939 static void GLAPIENTRY
   5940 save_SecondaryColor3fEXT(GLfloat x, GLfloat y, GLfloat z)
   5941 {
   5942    save_Attr3fNV(VERT_ATTRIB_COLOR1, x, y, z);
   5943 }
   5944 
   5945 static void GLAPIENTRY
   5946 save_SecondaryColor3fvEXT(const GLfloat * v)
   5947 {
   5948    save_Attr3fNV(VERT_ATTRIB_COLOR1, v[0], v[1], v[2]);
   5949 }
   5950 
   5951 
   5952 /* Just call the respective ATTR for texcoord
   5953  */
   5954 static void GLAPIENTRY
   5955 save_MultiTexCoord1f(GLenum target, GLfloat x)
   5956 {
   5957    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5958    save_Attr1fNV(attr, x);
   5959 }
   5960 
   5961 static void GLAPIENTRY
   5962 save_MultiTexCoord1fv(GLenum target, const GLfloat * v)
   5963 {
   5964    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5965    save_Attr1fNV(attr, v[0]);
   5966 }
   5967 
   5968 static void GLAPIENTRY
   5969 save_MultiTexCoord2f(GLenum target, GLfloat x, GLfloat y)
   5970 {
   5971    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5972    save_Attr2fNV(attr, x, y);
   5973 }
   5974 
   5975 static void GLAPIENTRY
   5976 save_MultiTexCoord2fv(GLenum target, const GLfloat * v)
   5977 {
   5978    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5979    save_Attr2fNV(attr, v[0], v[1]);
   5980 }
   5981 
   5982 static void GLAPIENTRY
   5983 save_MultiTexCoord3f(GLenum target, GLfloat x, GLfloat y, GLfloat z)
   5984 {
   5985    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5986    save_Attr3fNV(attr, x, y, z);
   5987 }
   5988 
   5989 static void GLAPIENTRY
   5990 save_MultiTexCoord3fv(GLenum target, const GLfloat * v)
   5991 {
   5992    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   5993    save_Attr3fNV(attr, v[0], v[1], v[2]);
   5994 }
   5995 
   5996 static void GLAPIENTRY
   5997 save_MultiTexCoord4f(GLenum target, GLfloat x, GLfloat y,
   5998                      GLfloat z, GLfloat w)
   5999 {
   6000    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   6001    save_Attr4fNV(attr, x, y, z, w);
   6002 }
   6003 
   6004 static void GLAPIENTRY
   6005 save_MultiTexCoord4fv(GLenum target, const GLfloat * v)
   6006 {
   6007    GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0;
   6008    save_Attr4fNV(attr, v[0], v[1], v[2], v[3]);
   6009 }
   6010 
   6011 
   6012 /**
   6013  * Record a GL_INVALID_VALUE error when an invalid vertex attribute
   6014  * index is found.
   6015  */
   6016 static void
   6017 index_error(void)
   6018 {
   6019    GET_CURRENT_CONTEXT(ctx);
   6020    _mesa_error(ctx, GL_INVALID_VALUE, "VertexAttribf(index)");
   6021 }
   6022 
   6023 
   6024 
   6025 static void GLAPIENTRY
   6026 save_VertexAttrib1fARB(GLuint index, GLfloat x)
   6027 {
   6028    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6029       save_Attr1fARB(index, x);
   6030    else
   6031       index_error();
   6032 }
   6033 
   6034 static void GLAPIENTRY
   6035 save_VertexAttrib1fvARB(GLuint index, const GLfloat * v)
   6036 {
   6037    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6038       save_Attr1fARB(index, v[0]);
   6039    else
   6040       index_error();
   6041 }
   6042 
   6043 static void GLAPIENTRY
   6044 save_VertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y)
   6045 {
   6046    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6047       save_Attr2fARB(index, x, y);
   6048    else
   6049       index_error();
   6050 }
   6051 
   6052 static void GLAPIENTRY
   6053 save_VertexAttrib2fvARB(GLuint index, const GLfloat * v)
   6054 {
   6055    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6056       save_Attr2fARB(index, v[0], v[1]);
   6057    else
   6058       index_error();
   6059 }
   6060 
   6061 static void GLAPIENTRY
   6062 save_VertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z)
   6063 {
   6064    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6065       save_Attr3fARB(index, x, y, z);
   6066    else
   6067       index_error();
   6068 }
   6069 
   6070 static void GLAPIENTRY
   6071 save_VertexAttrib3fvARB(GLuint index, const GLfloat * v)
   6072 {
   6073    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6074       save_Attr3fARB(index, v[0], v[1], v[2]);
   6075    else
   6076       index_error();
   6077 }
   6078 
   6079 static void GLAPIENTRY
   6080 save_VertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z,
   6081                        GLfloat w)
   6082 {
   6083    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6084       save_Attr4fARB(index, x, y, z, w);
   6085    else
   6086       index_error();
   6087 }
   6088 
   6089 static void GLAPIENTRY
   6090 save_VertexAttrib4fvARB(GLuint index, const GLfloat * v)
   6091 {
   6092    if (index < MAX_VERTEX_GENERIC_ATTRIBS)
   6093       save_Attr4fARB(index, v[0], v[1], v[2], v[3]);
   6094    else
   6095       index_error();
   6096 }
   6097 
   6098 static void GLAPIENTRY
   6099 save_PrimitiveRestartNV(void)
   6100 {
   6101    /* Note: this is used when outside a glBegin/End pair in a display list */
   6102    GET_CURRENT_CONTEXT(ctx);
   6103    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   6104    (void) alloc_instruction(ctx, OPCODE_PRIMITIVE_RESTART_NV, 0);
   6105    if (ctx->ExecuteFlag) {
   6106       CALL_PrimitiveRestartNV(ctx->Exec, ());
   6107    }
   6108 }
   6109 
   6110 
   6111 static void GLAPIENTRY
   6112 save_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
   6113                         GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
   6114                         GLbitfield mask, GLenum filter)
   6115 {
   6116    GET_CURRENT_CONTEXT(ctx);
   6117    Node *n;
   6118    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   6119    n = alloc_instruction(ctx, OPCODE_BLIT_FRAMEBUFFER, 10);
   6120    if (n) {
   6121       n[1].i = srcX0;
   6122       n[2].i = srcY0;
   6123       n[3].i = srcX1;
   6124       n[4].i = srcY1;
   6125       n[5].i = dstX0;
   6126       n[6].i = dstY0;
   6127       n[7].i = dstX1;
   6128       n[8].i = dstY1;
   6129       n[9].i = mask;
   6130       n[10].e = filter;
   6131    }
   6132    if (ctx->ExecuteFlag) {
   6133       CALL_BlitFramebuffer(ctx->Exec, (srcX0, srcY0, srcX1, srcY1,
   6134                                           dstX0, dstY0, dstX1, dstY1,
   6135                                           mask, filter));
   6136    }
   6137 }
   6138 
   6139 
   6140 /** GL_EXT_provoking_vertex */
   6141 static void GLAPIENTRY
   6142 save_ProvokingVertexEXT(GLenum mode)
   6143 {
   6144    GET_CURRENT_CONTEXT(ctx);
   6145    Node *n;
   6146    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   6147    n = alloc_instruction(ctx, OPCODE_PROVOKING_VERTEX, 1);
   6148    if (n) {
   6149       n[1].e = mode;
   6150    }
   6151    if (ctx->ExecuteFlag) {
   6152       /*CALL_ProvokingVertex(ctx->Exec, (mode));*/
   6153       _mesa_ProvokingVertex(mode);
   6154    }
   6155 }
   6156 
   6157 
   6158 /** GL_EXT_transform_feedback */
   6159 static void GLAPIENTRY
   6160 save_BeginTransformFeedback(GLenum mode)
   6161 {
   6162    GET_CURRENT_CONTEXT(ctx);
   6163    Node *n;
   6164    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   6165    n = alloc_instruction(ctx, OPCODE_BEGIN_TRANSFORM_FEEDBACK, 1);
   6166    if (n) {
   6167       n[1].e = mode;
   6168    }
   6169    if (ctx->ExecuteFlag) {
   6170       CALL_BeginTransformFeedback(ctx->Exec, (mode));
   6171    }
   6172 }
   6173 
   6174 
   6175 /** GL_EXT_transform_feedback */
   6176 static void GLAPIENTRY
   6177 save_EndTransformFeedback(void)
   6178 {
   6179    GET_CURRENT_CONTEXT(ctx);
   6180    ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
   6181    (void) alloc_instruction(ctx, OPCODE_END_TRANSFORM_FEEDBACK, 0);
   6182    if (ctx->ExecuteFlag) {
   6183       CALL_EndTransformFeedback(ctx->Exec, ());
   6184    }
   6185 }
   6186 
   6187 static void GLAPIENTRY
   6188 save_BindTransformFeedback(GLenum target, GLuint name)
   6189 {