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