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)