[MESA/OPENGL32]
[reactos.git] / reactos / dll / opengl / mesa / src / mesa / main / dlist.c
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 "hash.h"
55 #include "image.h"
56 #include "light.h"
57 #include "macros.h"
58 #include "pack.h"
59 #include "pbo.h"
60 #include "queryobj.h"
61 #include "samplerobj.h"
62 #include "shaderapi.h"
63 #include "syncobj.h"
64 #include "teximage.h"
65 #include "texstorage.h"
66 #include "mtypes.h"
67 #include "varray.h"
68 #if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
69 #include "arbprogram.h"
70 #endif
71 #if FEATURE_NV_vertex_program || FEATURE_NV_fragment_program
72 #include "nvprogram.h"
73 #endif
74 #if FEATURE_EXT_transform_feedback
75 #include "transformfeedback.h"
76 #endif
77
78 #include "math/m_matrix.h"
79
80 #include "main/dispatch.h"
81
82
83
84 /**
85 * Other parts of Mesa (such as the VBO module) can plug into the display
86 * list system. This structure describes new display list instructions.
87 */
88 struct gl_list_instruction
89 {
90 GLuint Size;
91 void (*Execute)( struct gl_context *ctx, void *data );
92 void (*Destroy)( struct gl_context *ctx, void *data );
93 void (*Print)( struct gl_context *ctx, void *data );
94 };
95
96
97 #define MAX_DLIST_EXT_OPCODES 16
98
99 /**
100 * Used by device drivers to hook new commands into display lists.
101 */
102 struct gl_list_extensions
103 {
104 struct gl_list_instruction Opcode[MAX_DLIST_EXT_OPCODES];
105 GLuint NumOpcodes;
106 };
107
108
109
110 /**
111 * Flush vertices.
112 *
113 * \param ctx GL context.
114 *
115 * Checks if dd_function_table::SaveNeedFlush is marked to flush
116 * stored (save) vertices, and calls
117 * dd_function_table::SaveFlushVertices if so.
118 */
119 #define SAVE_FLUSH_VERTICES(ctx) \
120 do { \
121 if (ctx->Driver.SaveNeedFlush) \
122 ctx->Driver.SaveFlushVertices(ctx); \
123 } while (0)
124
125
126 /**
127 * Macro to assert that the API call was made outside the
128 * glBegin()/glEnd() pair, with return value.
129 *
130 * \param ctx GL context.
131 * \param retval value to return value in case the assertion fails.
132 */
133 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval) \
134 do { \
135 if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \
136 ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \
137 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \
138 return retval; \
139 } \
140 } while (0)
141
142 /**
143 * Macro to assert that the API call was made outside the
144 * glBegin()/glEnd() pair.
145 *
146 * \param ctx GL context.
147 */
148 #define ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx) \
149 do { \
150 if (ctx->Driver.CurrentSavePrimitive <= GL_POLYGON || \
151 ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM) { \
152 _mesa_compile_error( ctx, GL_INVALID_OPERATION, "begin/end" ); \
153 return; \
154 } \
155 } while (0)
156
157 /**
158 * Macro to assert that the API call was made outside the
159 * glBegin()/glEnd() pair and flush the vertices.
160 *
161 * \param ctx GL context.
162 */
163 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx) \
164 do { \
165 ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); \
166 SAVE_FLUSH_VERTICES(ctx); \
167 } while (0)
168
169 /**
170 * Macro to assert that the API call was made outside the
171 * glBegin()/glEnd() pair and flush the vertices, with return value.
172 *
173 * \param ctx GL context.
174 * \param retval value to return value in case the assertion fails.
175 */
176 #define ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, retval)\
177 do { \
178 ASSERT_OUTSIDE_SAVE_BEGIN_END_WITH_RETVAL(ctx, retval); \
179 SAVE_FLUSH_VERTICES(ctx); \
180 } while (0)
181
182
183
184 /**
185 * Display list opcodes.
186 *
187 * The fact that these identifiers are assigned consecutive
188 * integer values starting at 0 is very important, see InstSize array usage)
189 */
190 typedef enum
191 {
192 OPCODE_INVALID = -1, /* Force signed enum */
193 OPCODE_ACCUM,
194 OPCODE_ALPHA_FUNC,
195 OPCODE_BIND_TEXTURE,
196 OPCODE_BITMAP,
197 OPCODE_BLEND_COLOR,
198 OPCODE_BLEND_EQUATION,
199 OPCODE_BLEND_EQUATION_SEPARATE,
200 OPCODE_BLEND_FUNC_SEPARATE,
201
202 OPCODE_BLEND_EQUATION_I,
203 OPCODE_BLEND_EQUATION_SEPARATE_I,
204 OPCODE_BLEND_FUNC_I,
205 OPCODE_BLEND_FUNC_SEPARATE_I,
206
207 OPCODE_CALL_LIST,
208 OPCODE_CALL_LIST_OFFSET,
209 OPCODE_CLEAR,
210 OPCODE_CLEAR_ACCUM,
211 OPCODE_CLEAR_COLOR,
212 OPCODE_CLEAR_DEPTH,
213 OPCODE_CLEAR_INDEX,
214 OPCODE_CLEAR_STENCIL,
215 OPCODE_CLEAR_BUFFER_IV,
216 OPCODE_CLEAR_BUFFER_UIV,
217 OPCODE_CLEAR_BUFFER_FV,
218 OPCODE_CLEAR_BUFFER_FI,
219 OPCODE_CLIP_PLANE,
220 OPCODE_COLOR_MASK,
221 OPCODE_COLOR_MASK_INDEXED,
222 OPCODE_COLOR_MATERIAL,
223 OPCODE_COLOR_TABLE,
224 OPCODE_COLOR_TABLE_PARAMETER_FV,
225 OPCODE_COLOR_TABLE_PARAMETER_IV,
226 OPCODE_COLOR_SUB_TABLE,
227 OPCODE_CONVOLUTION_FILTER_1D,
228 OPCODE_CONVOLUTION_FILTER_2D,
229 OPCODE_CONVOLUTION_PARAMETER_I,
230 OPCODE_CONVOLUTION_PARAMETER_IV,
231 OPCODE_CONVOLUTION_PARAMETER_F,
232 OPCODE_CONVOLUTION_PARAMETER_FV,
233 OPCODE_COPY_COLOR_SUB_TABLE,
234 OPCODE_COPY_COLOR_TABLE,
235 OPCODE_COPY_PIXELS,
236 OPCODE_COPY_TEX_IMAGE1D,
237 OPCODE_COPY_TEX_IMAGE2D,
238 OPCODE_COPY_TEX_SUB_IMAGE1D,
239 OPCODE_COPY_TEX_SUB_IMAGE2D,
240 OPCODE_COPY_TEX_SUB_IMAGE3D,
241 OPCODE_CULL_FACE,
242 OPCODE_DEPTH_FUNC,
243 OPCODE_DEPTH_MASK,
244 OPCODE_DEPTH_RANGE,
245 OPCODE_DISABLE,
246 OPCODE_DISABLE_INDEXED,
247 OPCODE_DRAW_BUFFER,
248 OPCODE_DRAW_PIXELS,
249 OPCODE_ENABLE,
250 OPCODE_ENABLE_INDEXED,
251 OPCODE_EVALMESH1,
252 OPCODE_EVALMESH2,
253 OPCODE_FOG,
254 OPCODE_FRONT_FACE,
255 OPCODE_FRUSTUM,
256 OPCODE_HINT,
257 OPCODE_HISTOGRAM,
258 OPCODE_INDEX_MASK,
259 OPCODE_INIT_NAMES,
260 OPCODE_LIGHT,
261 OPCODE_LIGHT_MODEL,
262 OPCODE_LINE_STIPPLE,
263 OPCODE_LINE_WIDTH,
264 OPCODE_LIST_BASE,
265 OPCODE_LOAD_IDENTITY,
266 OPCODE_LOAD_MATRIX,
267 OPCODE_LOAD_NAME,
268 OPCODE_LOGIC_OP,
269 OPCODE_MAP1,
270 OPCODE_MAP2,
271 OPCODE_MAPGRID1,
272 OPCODE_MAPGRID2,
273 OPCODE_MATRIX_MODE,
274 OPCODE_MIN_MAX,
275 OPCODE_MULT_MATRIX,
276 OPCODE_ORTHO,
277 OPCODE_PASSTHROUGH,
278 OPCODE_PIXEL_MAP,
279 OPCODE_PIXEL_TRANSFER,
280 OPCODE_PIXEL_ZOOM,
281 OPCODE_POINT_SIZE,
282 OPCODE_POINT_PARAMETERS,
283 OPCODE_POLYGON_MODE,
284 OPCODE_POLYGON_STIPPLE,
285 OPCODE_POLYGON_OFFSET,
286 OPCODE_POP_ATTRIB,
287 OPCODE_POP_MATRIX,
288 OPCODE_POP_NAME,
289 OPCODE_PRIORITIZE_TEXTURE,
290 OPCODE_PUSH_ATTRIB,
291 OPCODE_PUSH_MATRIX,
292 OPCODE_PUSH_NAME,
293 OPCODE_RASTER_POS,
294 OPCODE_READ_BUFFER,
295 OPCODE_RESET_HISTOGRAM,
296 OPCODE_RESET_MIN_MAX,
297 OPCODE_ROTATE,
298 OPCODE_SCALE,
299 OPCODE_SCISSOR,
300 OPCODE_SELECT_TEXTURE_SGIS,
301 OPCODE_SELECT_TEXTURE_COORD_SET,
302 OPCODE_SHADE_MODEL,
303 OPCODE_STENCIL_FUNC,
304 OPCODE_STENCIL_MASK,
305 OPCODE_STENCIL_OP,
306 OPCODE_TEXENV,
307 OPCODE_TEXGEN,
308 OPCODE_TEXPARAMETER,
309 OPCODE_TEX_IMAGE1D,
310 OPCODE_TEX_IMAGE2D,
311 OPCODE_TEX_IMAGE3D,
312 OPCODE_TEX_SUB_IMAGE1D,
313 OPCODE_TEX_SUB_IMAGE2D,
314 OPCODE_TEX_SUB_IMAGE3D,
315 OPCODE_TRANSLATE,
316 OPCODE_VIEWPORT,
317 OPCODE_WINDOW_POS,
318 /* GL_ARB_multitexture */
319 OPCODE_ACTIVE_TEXTURE,
320 /* GL_ARB_texture_compression */
321 OPCODE_COMPRESSED_TEX_IMAGE_1D,
322 OPCODE_COMPRESSED_TEX_IMAGE_2D,
323 OPCODE_COMPRESSED_TEX_IMAGE_3D,
324 OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D,
325 OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D,
326 OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D,
327 /* GL_ARB_multisample */
328 OPCODE_SAMPLE_COVERAGE,
329 /* GL_ARB_window_pos */
330 OPCODE_WINDOW_POS_ARB,
331 /* GL_NV_vertex_program */
332 OPCODE_BIND_PROGRAM_NV,
333 OPCODE_EXECUTE_PROGRAM_NV,
334 OPCODE_REQUEST_RESIDENT_PROGRAMS_NV,
335 OPCODE_LOAD_PROGRAM_NV,
336 OPCODE_TRACK_MATRIX_NV,
337 /* GL_NV_fragment_program */
338 OPCODE_PROGRAM_LOCAL_PARAMETER_ARB,
339 OPCODE_PROGRAM_NAMED_PARAMETER_NV,
340 /* GL_EXT_stencil_two_side */
341 OPCODE_ACTIVE_STENCIL_FACE_EXT,
342 /* GL_EXT_depth_bounds_test */
343 OPCODE_DEPTH_BOUNDS_EXT,
344 /* GL_ARB_vertex/fragment_program */
345 OPCODE_PROGRAM_STRING_ARB,
346 OPCODE_PROGRAM_ENV_PARAMETER_ARB,
347 /* GL_ARB_occlusion_query */
348 OPCODE_BEGIN_QUERY_ARB,
349 OPCODE_END_QUERY_ARB,
350 /* GL_ARB_draw_buffers */
351 OPCODE_DRAW_BUFFERS_ARB,
352 /* GL_ATI_fragment_shader */
353 OPCODE_TEX_BUMP_PARAMETER_ATI,
354 /* GL_ATI_fragment_shader */
355 OPCODE_BIND_FRAGMENT_SHADER_ATI,
356 OPCODE_SET_FRAGMENT_SHADER_CONSTANTS_ATI,
357 /* OpenGL 2.0 */
358 OPCODE_STENCIL_FUNC_SEPARATE,
359 OPCODE_STENCIL_OP_SEPARATE,
360 OPCODE_STENCIL_MASK_SEPARATE,
361
362 /* GL_ARB_shader_objects */
363 OPCODE_USE_PROGRAM,
364 OPCODE_UNIFORM_1F,
365 OPCODE_UNIFORM_2F,
366 OPCODE_UNIFORM_3F,
367 OPCODE_UNIFORM_4F,
368 OPCODE_UNIFORM_1FV,
369 OPCODE_UNIFORM_2FV,
370 OPCODE_UNIFORM_3FV,
371 OPCODE_UNIFORM_4FV,
372 OPCODE_UNIFORM_1I,
373 OPCODE_UNIFORM_2I,
374 OPCODE_UNIFORM_3I,
375 OPCODE_UNIFORM_4I,
376 OPCODE_UNIFORM_1IV,
377 OPCODE_UNIFORM_2IV,
378 OPCODE_UNIFORM_3IV,
379 OPCODE_UNIFORM_4IV,
380 OPCODE_UNIFORM_MATRIX22,
381 OPCODE_UNIFORM_MATRIX33,
382 OPCODE_UNIFORM_MATRIX44,
383 OPCODE_UNIFORM_MATRIX23,
384 OPCODE_UNIFORM_MATRIX32,
385 OPCODE_UNIFORM_MATRIX24,
386 OPCODE_UNIFORM_MATRIX42,
387 OPCODE_UNIFORM_MATRIX34,
388 OPCODE_UNIFORM_MATRIX43,
389
390 /* OpenGL 3.0 */
391 OPCODE_UNIFORM_1UI,
392 OPCODE_UNIFORM_2UI,
393 OPCODE_UNIFORM_3UI,
394 OPCODE_UNIFORM_4UI,
395 OPCODE_UNIFORM_1UIV,
396 OPCODE_UNIFORM_2UIV,
397 OPCODE_UNIFORM_3UIV,
398 OPCODE_UNIFORM_4UIV,
399
400 /* GL_ARB_color_buffer_float */
401 OPCODE_CLAMP_COLOR,
402
403 /* GL_EXT_framebuffer_blit */
404 OPCODE_BLIT_FRAMEBUFFER,
405
406 /* Vertex attributes -- fallback for when optimized display
407 * list build isn't active.
408 */
409 OPCODE_ATTR_1F_NV,
410 OPCODE_ATTR_2F_NV,
411 OPCODE_ATTR_3F_NV,
412 OPCODE_ATTR_4F_NV,
413 OPCODE_ATTR_1F_ARB,
414 OPCODE_ATTR_2F_ARB,
415 OPCODE_ATTR_3F_ARB,
416 OPCODE_ATTR_4F_ARB,
417 OPCODE_MATERIAL,
418 OPCODE_BEGIN,
419 OPCODE_END,
420 OPCODE_RECTF,
421 OPCODE_EVAL_C1,
422 OPCODE_EVAL_C2,
423 OPCODE_EVAL_P1,
424 OPCODE_EVAL_P2,
425
426 /* GL_EXT_provoking_vertex */
427 OPCODE_PROVOKING_VERTEX,
428
429 /* GL_EXT_transform_feedback */
430 OPCODE_BEGIN_TRANSFORM_FEEDBACK,
431 OPCODE_END_TRANSFORM_FEEDBACK,
432 OPCODE_BIND_TRANSFORM_FEEDBACK,
433 OPCODE_PAUSE_TRANSFORM_FEEDBACK,
434 OPCODE_RESUME_TRANSFORM_FEEDBACK,
435 OPCODE_DRAW_TRANSFORM_FEEDBACK,
436
437 /* GL_EXT_texture_integer */
438 OPCODE_CLEARCOLOR_I,
439 OPCODE_CLEARCOLOR_UI,
440 OPCODE_TEXPARAMETER_I,
441 OPCODE_TEXPARAMETER_UI,
442
443 /* GL_EXT_separate_shader_objects */
444 OPCODE_ACTIVE_PROGRAM_EXT,
445 OPCODE_USE_SHADER_PROGRAM_EXT,
446
447 /* GL_ARB_instanced_arrays */
448 OPCODE_VERTEX_ATTRIB_DIVISOR,
449
450 /* GL_NV_texture_barrier */
451 OPCODE_TEXTURE_BARRIER_NV,
452
453 /* GL_ARB_sampler_object */
454 OPCODE_BIND_SAMPLER,
455 OPCODE_SAMPLER_PARAMETERIV,
456 OPCODE_SAMPLER_PARAMETERFV,
457 OPCODE_SAMPLER_PARAMETERIIV,
458 OPCODE_SAMPLER_PARAMETERUIV,
459
460 /* GL_ARB_geometry_shader4 */
461 OPCODE_PROGRAM_PARAMETERI,
462 OPCODE_FRAMEBUFFER_TEXTURE,
463 OPCODE_FRAMEBUFFER_TEXTURE_FACE,
464
465 /* GL_ARB_sync */
466 OPCODE_WAIT_SYNC,
467
468 /* GL_NV_conditional_render */
469 OPCODE_BEGIN_CONDITIONAL_RENDER,
470 OPCODE_END_CONDITIONAL_RENDER,
471
472 /* The following three are meta instructions */
473 OPCODE_ERROR, /* raise compiled-in error */
474 OPCODE_CONTINUE,
475 OPCODE_END_OF_LIST,
476 OPCODE_EXT_0
477 } OpCode;
478
479
480
481 /**
482 * Display list node.
483 *
484 * Display list instructions are stored as sequences of "nodes". Nodes
485 * are allocated in blocks. Each block has BLOCK_SIZE nodes. Blocks
486 * are linked together with a pointer.
487 *
488 * Each instruction in the display list is stored as a sequence of
489 * contiguous nodes in memory.
490 * Each node is the union of a variety of data types.
491 */
492 union gl_dlist_node
493 {
494 OpCode opcode;
495 GLboolean b;
496 GLbitfield bf;
497 GLubyte ub;
498 GLshort s;
499 GLushort us;
500 GLint i;
501 GLuint ui;
502 GLenum e;
503 GLfloat f;
504 GLvoid *data;
505 void *next; /* If prev node's opcode==OPCODE_CONTINUE */
506 };
507
508
509 typedef union gl_dlist_node Node;
510
511
512 /**
513 * Used to store a 64-bit uint in a pair of "Nodes" for the sake of 32-bit
514 * environment. In 64-bit env, sizeof(Node)==8 anyway.
515 */
516 union uint64_pair
517 {
518 GLuint64 uint64;
519 GLuint uint32[2];
520 };
521
522
523 /**
524 * How many nodes to allocate at a time.
525 *
526 * \note Reduced now that we hold vertices etc. elsewhere.
527 */
528 #define BLOCK_SIZE 256
529
530
531
532 /**
533 * Number of nodes of storage needed for each instruction.
534 * Sizes for dynamically allocated opcodes are stored in the context struct.
535 */
536 static GLuint InstSize[OPCODE_END_OF_LIST + 1];
537
538
539 #if FEATURE_dlist
540
541
542 void mesa_print_display_list(GLuint list);
543
544
545 /**********************************************************************/
546 /***** Private *****/
547 /**********************************************************************/
548
549
550 /**
551 * Make an empty display list. This is used by glGenLists() to
552 * reserve display list IDs.
553 */
554 static struct gl_display_list *
555 make_list(GLuint name, GLuint count)
556 {
557 struct gl_display_list *dlist = CALLOC_STRUCT(gl_display_list);
558 dlist->Name = name;
559 dlist->Head = (Node *) malloc(sizeof(Node) * count);
560 dlist->Head[0].opcode = OPCODE_END_OF_LIST;
561 return dlist;
562 }
563
564
565 /**
566 * Lookup function to just encapsulate casting.
567 */
568 static inline struct gl_display_list *
569 lookup_list(struct gl_context *ctx, GLuint list)
570 {
571 return (struct gl_display_list *)
572 _mesa_HashLookup(ctx->Shared->DisplayList, list);
573 }
574
575
576 /** Is the given opcode an extension code? */
577 static inline GLboolean
578 is_ext_opcode(OpCode opcode)
579 {
580 return (opcode >= OPCODE_EXT_0);
581 }
582
583
584 /** Destroy an extended opcode instruction */
585 static GLint
586 ext_opcode_destroy(struct gl_context *ctx, Node *node)
587 {
588 const GLint i = node[0].opcode - OPCODE_EXT_0;
589 GLint step;
590 ctx->ListExt->Opcode[i].Destroy(ctx, &node[1]);
591 step = ctx->ListExt->Opcode[i].Size;
592 return step;
593 }
594
595
596 /** Execute an extended opcode instruction */
597 static GLint
598 ext_opcode_execute(struct gl_context *ctx, Node *node)
599 {
600 const GLint i = node[0].opcode - OPCODE_EXT_0;
601 GLint step;
602 ctx->ListExt->Opcode[i].Execute(ctx, &node[1]);
603 step = ctx->ListExt->Opcode[i].Size;
604 return step;
605 }
606
607
608 /** Print an extended opcode instruction */
609 static GLint
610 ext_opcode_print(struct gl_context *ctx, Node *node)
611 {
612 const GLint i = node[0].opcode - OPCODE_EXT_0;
613 GLint step;
614 ctx->ListExt->Opcode[i].Print(ctx, &node[1]);
615 step = ctx->ListExt->Opcode[i].Size;
616 return step;
617 }
618
619
620 /**
621 * Delete the named display list, but don't remove from hash table.
622 * \param dlist - display list pointer
623 */
624 void
625 _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
626 {
627 Node *n, *block;
628 GLboolean done;
629
630 n = block = dlist->Head;
631
632 done = block ? GL_FALSE : GL_TRUE;
633 while (!done) {
634 const OpCode opcode = n[0].opcode;
635
636 /* check for extension opcodes first */
637 if (is_ext_opcode(opcode)) {
638 n += ext_opcode_destroy(ctx, n);
639 }
640 else {
641 switch (opcode) {
642 /* for some commands, we need to free malloc'd memory */
643 case OPCODE_MAP1:
644 free(n[6].data);
645 n += InstSize[n[0].opcode];
646 break;
647 case OPCODE_MAP2:
648 free(n[10].data);
649 n += InstSize[n[0].opcode];
650 break;
651 case OPCODE_DRAW_PIXELS:
652 free(n[5].data);
653 n += InstSize[n[0].opcode];
654 break;
655 case OPCODE_BITMAP:
656 free(n[7].data);
657 n += InstSize[n[0].opcode];
658 break;
659 case OPCODE_COLOR_TABLE:
660 free(n[6].data);
661 n += InstSize[n[0].opcode];
662 break;
663 case OPCODE_COLOR_SUB_TABLE:
664 free(n[6].data);
665 n += InstSize[n[0].opcode];
666 break;
667 case OPCODE_CONVOLUTION_FILTER_1D:
668 free(n[6].data);
669 n += InstSize[n[0].opcode];
670 break;
671 case OPCODE_CONVOLUTION_FILTER_2D:
672 free(n[7].data);
673 n += InstSize[n[0].opcode];
674 break;
675 case OPCODE_POLYGON_STIPPLE:
676 free(n[1].data);
677 n += InstSize[n[0].opcode];
678 break;
679 case OPCODE_TEX_IMAGE1D:
680 free(n[8].data);
681 n += InstSize[n[0].opcode];
682 break;
683 case OPCODE_TEX_IMAGE2D:
684 free(n[9].data);
685 n += InstSize[n[0].opcode];
686 break;
687 case OPCODE_TEX_IMAGE3D:
688 free(n[10].data);
689 n += InstSize[n[0].opcode];
690 break;
691 case OPCODE_TEX_SUB_IMAGE1D:
692 free(n[7].data);
693 n += InstSize[n[0].opcode];
694 break;
695 case OPCODE_TEX_SUB_IMAGE2D:
696 free(n[9].data);
697 n += InstSize[n[0].opcode];
698 break;
699 case OPCODE_TEX_SUB_IMAGE3D:
700 free(n[11].data);
701 n += InstSize[n[0].opcode];
702 break;
703 case OPCODE_COMPRESSED_TEX_IMAGE_1D:
704 free(n[7].data);
705 n += InstSize[n[0].opcode];
706 break;
707 case OPCODE_COMPRESSED_TEX_IMAGE_2D:
708 free(n[8].data);
709 n += InstSize[n[0].opcode];
710 break;
711 case OPCODE_COMPRESSED_TEX_IMAGE_3D:
712 free(n[9].data);
713 n += InstSize[n[0].opcode];
714 break;
715 case OPCODE_COMPRESSED_TEX_SUB_IMAGE_1D:
716 free(n[7].data);
717 n += InstSize[n[0].opcode];
718 break;
719 case OPCODE_COMPRESSED_TEX_SUB_IMAGE_2D:
720 free(n[9].data);
721 n += InstSize[n[0].opcode];
722 break;
723 case OPCODE_COMPRESSED_TEX_SUB_IMAGE_3D:
724 free(n[11].data);
725 n += InstSize[n[0].opcode];
726 break;
727 #if FEATURE_NV_vertex_program
728 case OPCODE_LOAD_PROGRAM_NV:
729 free(n[4].data); /* program string */
730 n += InstSize[n[0].opcode];
731 break;
732 case OPCODE_REQUEST_RESIDENT_PROGRAMS_NV:
733 free(n[2].data); /* array of program ids */
734 n += InstSize[n[0].opcode];
735 break;
736 #endif
737 #if FEATURE_NV_fragment_program
738 case OPCODE_PROGRAM_NAMED_PARAMETER_NV:
739 free(n[3].data); /* parameter name */
740 n += InstSize[n[0].opcode];
741 break;
742 #endif
743 #if FEATURE_ARB_vertex_program || FEATURE_ARB_fragment_program
744 case OPCODE_PROGRAM_STRING_ARB:
745 free(n[4].data); /* program string */
746 n += InstSize[n[0].opcode];
747 break;
748 #endif
749 case OPCODE_UNIFORM_1FV:
750 case OPCODE_UNIFORM_2FV:
751 case OPCODE_UNIFORM_3FV:
752 case OPCODE_UNIFORM_4FV:
753 case OPCODE_UNIFORM_1IV:
754 case OPCODE_UNIFORM_2IV:
755 case OPCODE_UNIFORM_3IV:
756 case OPCODE_UNIFORM_4IV:
757 case OPCODE_UNIFORM_1UIV:
758 case OPCODE_UNIFORM_2UIV:
759 case OPCODE_UNIFORM_3UIV:
760 case OPCODE_UNIFORM_4UIV:
761 free(n[3].data);
762 n += InstSize[n[0].opcode];
763 break;
764 case OPCODE_UNIFORM_MATRIX22:
765 case OPCODE_UNIFORM_MATRIX33:
766 case OPCODE_UNIFORM_MATRIX44:
767 case OPCODE_UNIFORM_MATRIX24:
768 case OPCODE_UNIFORM_MATRIX42:
769 case OPCODE_UNIFORM_MATRIX23:
770 case OPCODE_UNIFORM_MATRIX32:
771 case OPCODE_UNIFORM_MATRIX34:
772 case OPCODE_UNIFORM_MATRIX43:
773 free(n[4].data);
774 n += InstSize[n[0].opcode];
775 break;
776
777 case OPCODE_CONTINUE:
778 n = (Node *) n[1].next;
779 free(block);
780 block = n;
781 break;
782 case OPCODE_END_OF_LIST:
783 free(block);
784 done = GL_TRUE;
785 break;
786 default:
787 /* Most frequent case */
788 n += InstSize[n[0].opcode];
789 break;
790 }
791 }
792 }
793
794 free(dlist);
795 }
796
797
798 /**
799 * Destroy a display list and remove from hash table.
800 * \param list - display list number
801 */
802 static void
803 destroy_list(struct gl_context *ctx, GLuint list)
804 {
805 struct gl_display_list *dlist;
806
807 if (list == 0)
808 return;
809
810 dlist = lookup_list(ctx, list);
811 if (!dlist)
812 return;
813
814 _mesa_delete_list(ctx, dlist);
815 _mesa_HashRemove(ctx->Shared->DisplayList, list);
816 }
817
818
819 /*
820 * Translate the nth element of list from <type> to GLint.
821 */
822 static GLint
823 translate_id(GLsizei n, GLenum type, const GLvoid * list)
824 {
825 GLbyte *bptr;
826 GLubyte *ubptr;
827 GLshort *sptr;
828 GLushort *usptr;
829 GLint *iptr;
830 GLuint *uiptr;
831 GLfloat *fptr;
832
833 switch (type) {
834 case GL_BYTE:
835 bptr = (GLbyte *) list;
836 return (GLint) bptr[n];
837 case GL_UNSIGNED_BYTE:
838 ubptr = (GLubyte *) list;
839 return (GLint) ubptr[n];
840 case GL_SHORT:
841 sptr = (GLshort *) list;
842 return (GLint) sptr[n];
843 case GL_UNSIGNED_SHORT:
844 usptr = (GLushort *) list;
845 return (GLint) usptr[n];
846 case GL_INT:
847 iptr = (GLint *) list;
848 return iptr[n];
849 case GL_UNSIGNED_INT:
850 uiptr = (GLuint *) list;
851 return (GLint) uiptr[n];
852 case GL_FLOAT:
853 fptr = (GLfloat *) list;
854 return (GLint) FLOORF(fptr[n]);
855 case GL_2_BYTES:
856 ubptr = ((GLubyte *) list) + 2 * n;
857 return (GLint) ubptr[0] * 256
858 + (GLint) ubptr[1];
859 case GL_3_BYTES:
860 ubptr = ((GLubyte *) list) + 3 * n;
861 return (GLint) ubptr[0] * 65536
862 + (GLint) ubptr[1] * 256
863 + (GLint) ubptr[2];
864 case GL_4_BYTES:
865 ubptr = ((GLubyte *) list) + 4 * n;
866 return (GLint) ubptr[0] * 16777216
867 + (GLint) ubptr[1] * 65536
868 + (GLint) ubptr[2] * 256
869 + (GLint) ubptr[3];
870 default:
871 return 0;
872 }
873 }
874
875
876
877
878 /**********************************************************************/
879 /***** Public *****/
880 /**********************************************************************/
881
882 /**
883 * Wrapper for _mesa_unpack_image/bitmap() that handles pixel buffer objects.
884 * If width < 0 or height < 0 or format or type are invalid we'll just
885 * return NULL. We will not generate an error since OpenGL command
886 * arguments aren't error-checked until the command is actually executed
887 * (not when they're compiled).
888 * But if we run out of memory, GL_OUT_OF_MEMORY will be recorded.
889 */
890 static GLvoid *
891 unpack_image(struct gl_context *ctx, GLuint dimensions,
892 GLsizei width, GLsizei height, GLsizei depth,
893 GLenum format, GLenum type, const GLvoid * pixels,
894 const struct gl_pixelstore_attrib *unpack)
895 {
896 if (width <= 0 || height <= 0) {
897 return NULL;
898 }
899
900 if (_mesa_bytes_per_pixel(format, type) < 0) {
901 /* bad format and/or type */
902 return NULL;
903 }
904
905 if (!_mesa_is_bufferobj(unpack->BufferObj)) {
906 /* no PBO */
907 GLvoid *image;
908
909 if (type == GL_BITMAP)
910 image = _mesa_unpack_bitmap(width, height, pixels, unpack);
911 else
912 image = _mesa_unpack_image(dimensions, width, height, depth,
913 format, type, pixels, unpack);
914 if (pixels && !image) {
915 _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
916 }
917 return image;
918 }
919 else if (_mesa_validate_pbo_access(dimensions, unpack, width, height,
920 depth, format, type, INT_MAX, pixels)) {
921 const GLubyte *map, *src;
922 GLvoid *image;
923
924 map = (GLubyte *)
925 ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
926 GL_MAP_READ_BIT, unpack->BufferObj);
927 if (!map) {
928 /* unable to map src buffer! */
929 _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO");
930 return NULL;
931 }
932
933 src = ADD_POINTERS(map, pixels);
934 if (type == GL_BITMAP)
935 image = _mesa_unpack_bitmap(width, height, src, unpack);
936 else
937 image = _mesa_unpack_image(dimensions, width, height, depth,
938 format, type, src, unpack);
939
940 ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
941
942 if (!image) {
943 _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction");
944 }
945 return image;
946 }
947
948 /* bad access! */
949 _mesa_error(ctx, GL_INVALID_OPERATION, "invalid PBO access");
950 return NULL;
951 }
952
953 /**
954 * Allocate space for a display list instruction (opcode + payload space).
955 * \param opcode the instruction opcode (OPCODE_* value)
956 * \param bytes instruction payload size (not counting opcode)
957 * \return pointer to allocated memory (the opcode space)
958 */
959 static Node *
960 dlist_alloc(struct gl_context *ctx, OpCode opcode, GLuint bytes)
961 {
962 const GLuint numNodes = 1 + (bytes + sizeof(Node) - 1) / sizeof(Node);
963 Node *n;
964
965 if (opcode < (GLuint) OPCODE_EXT_0) {
966 if (InstSize[opcode] == 0) {
967 /* save instruction size now */
968 InstSize[opcode] = numNodes;
969 }
970 else {
971 /* make sure instruction size agrees */
972 ASSERT(numNodes == InstSize[opcode]);
973 }
974 }
975
976 if (ctx->ListState.CurrentPos + numNodes + 2 > BLOCK_SIZE) {
977 /* This block is full. Allocate a new block and chain to it */
978 Node *newblock;
979 n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
980 n[0].opcode = OPCODE_CONTINUE;
981 newblock = (Node *) malloc(sizeof(Node) * BLOCK_SIZE);
982 if (!newblock) {
983 _mesa_error(ctx, GL_OUT_OF_MEMORY, "Building display list");
984 return NULL;
985 }
986 n[1].next = (Node *) newblock;
987 ctx->ListState.CurrentBlock = newblock;
988 ctx->ListState.CurrentPos = 0;
989 }
990
991 n = ctx->ListState.CurrentBlock + ctx->ListState.CurrentPos;
992 ctx->ListState.CurrentPos += numNodes;
993
994 n[0].opcode = opcode;
995
996 return n;
997 }
998
999
1000
1001 /**
1002 * Allocate space for a display list instruction. Used by callers outside
1003 * this file for things like VBO vertex data.
1004 *
1005 * \param opcode the instruction opcode (OPCODE_* value)
1006 * \param bytes instruction size in bytes, not counting opcode.
1007 * \return pointer to the usable data area (not including the internal
1008 * opcode).
1009 */
1010 void *
1011 _mesa_dlist_alloc(struct gl_context *ctx, GLuint opcode, GLuint bytes)
1012 {
1013 Node *n = dlist_alloc(ctx, (OpCode) opcode, bytes);
1014 if (n)
1015 return n + 1; /* return pointer to payload area, after opcode */
1016 else
1017 return NULL;
1018 }
1019
1020
1021 /**
1022 * This function allows modules and drivers to get their own opcodes
1023 * for extending display list functionality.
1024 * \param ctx the rendering context
1025 * \param size number of bytes for storing the new display list command
1026 * \param execute function to execute the new display list command
1027 * \param destroy function to destroy the new display list command
1028 * \param print function to print the new display list command
1029 * \return the new opcode number or -1 if error
1030 */
1031 GLint
1032 _mesa_dlist_alloc_opcode(struct gl_context *ctx,
1033 GLuint size,
1034 void (*execute) (struct gl_context *, void *),
1035 void (*destroy) (struct gl_context *, void *),
1036 void (*print) (struct gl_context *, void *))
1037 {
1038 if (ctx->ListExt->NumOpcodes < MAX_DLIST_EXT_OPCODES) {
1039 const GLuint i = ctx->ListExt->NumOpcodes++;
1040 ctx->ListExt->Opcode[i].Size =
1041 1 + (size + sizeof(Node) - 1) / sizeof(Node);
1042 ctx->ListExt->Opcode[i].Execute = execute;
1043 ctx->ListExt->Opcode[i].Destroy = destroy;
1044 ctx->ListExt->Opcode[i].Print = print;
1045 return i + OPCODE_EXT_0;
1046 }
1047 return -1;
1048 }
1049
1050
1051 /**
1052 * Allocate space for a display list instruction. The space is basically
1053 * an array of Nodes where node[0] holds the opcode, node[1] is the first
1054 * function parameter, node[2] is the second parameter, etc.
1055 *
1056 * \param opcode one of OPCODE_x
1057 * \param nparams number of function parameters
1058 * \return pointer to start of instruction space
1059 */
1060 static inline Node *
1061 alloc_instruction(struct gl_context *ctx, OpCode opcode, GLuint nparams)
1062 {
1063 return dlist_alloc(ctx, opcode, nparams * sizeof(Node));
1064 }
1065
1066
1067
1068 /*
1069 * Display List compilation functions
1070 */
1071 static void GLAPIENTRY
1072 save_Accum(GLenum op, GLfloat value)
1073 {
1074 GET_CURRENT_CONTEXT(ctx);
1075 Node *n;
1076 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1077 n = alloc_instruction(ctx, OPCODE_ACCUM, 2);
1078 if (n) {
1079 n[1].e = op;
1080 n[2].f = value;
1081 }
1082 if (ctx->ExecuteFlag) {
1083 CALL_Accum(ctx->Exec, (op, value));
1084 }
1085 }
1086
1087
1088 static void GLAPIENTRY
1089 save_AlphaFunc(GLenum func, GLclampf ref)
1090 {
1091 GET_CURRENT_CONTEXT(ctx);
1092 Node *n;
1093 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1094 n = alloc_instruction(ctx, OPCODE_ALPHA_FUNC, 2);
1095 if (n) {
1096 n[1].e = func;
1097 n[2].f = (GLfloat) ref;
1098 }
1099 if (ctx->ExecuteFlag) {
1100 CALL_AlphaFunc(ctx->Exec, (func, ref));
1101 }
1102 }
1103
1104
1105 static void GLAPIENTRY
1106 save_BindTexture(GLenum target, GLuint texture)
1107 {
1108 GET_CURRENT_CONTEXT(ctx);
1109 Node *n;
1110 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1111 n = alloc_instruction(ctx, OPCODE_BIND_TEXTURE, 2);
1112 if (n) {
1113 n[1].e = target;
1114 n[2].ui = texture;
1115 }
1116 if (ctx->ExecuteFlag) {
1117 CALL_BindTexture(ctx->Exec, (target, texture));
1118 }
1119 }
1120
1121
1122 static void GLAPIENTRY
1123 save_Bitmap(GLsizei width, GLsizei height,
1124 GLfloat xorig, GLfloat yorig,
1125 GLfloat xmove, GLfloat ymove, const GLubyte * pixels)
1126 {
1127 GET_CURRENT_CONTEXT(ctx);
1128 Node *n;
1129 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1130 n = alloc_instruction(ctx, OPCODE_BITMAP, 7);
1131 if (n) {
1132 n[1].i = (GLint) width;
1133 n[2].i = (GLint) height;
1134 n[3].f = xorig;
1135 n[4].f = yorig;
1136 n[5].f = xmove;
1137 n[6].f = ymove;
1138 n[7].data = unpack_image(ctx, 2, width, height, 1, GL_COLOR_INDEX,
1139 GL_BITMAP, pixels, &ctx->Unpack);
1140 }
1141 if (ctx->ExecuteFlag) {
1142 CALL_Bitmap(ctx->Exec, (width, height,
1143 xorig, yorig, xmove, ymove, pixels));
1144 }
1145 }
1146
1147
1148 static void GLAPIENTRY
1149 save_BlendEquation(GLenum mode)
1150 {
1151 GET_CURRENT_CONTEXT(ctx);
1152 Node *n;
1153 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1154 n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION, 1);
1155 if (n) {
1156 n[1].e = mode;
1157 }
1158 if (ctx->ExecuteFlag) {
1159 CALL_BlendEquation(ctx->Exec, (mode));
1160 }
1161 }
1162
1163
1164 static void GLAPIENTRY
1165 save_BlendEquationSeparateEXT(GLenum modeRGB, GLenum modeA)
1166 {
1167 GET_CURRENT_CONTEXT(ctx);
1168 Node *n;
1169 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1170 n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION_SEPARATE, 2);
1171 if (n) {
1172 n[1].e = modeRGB;
1173 n[2].e = modeA;
1174 }
1175 if (ctx->ExecuteFlag) {
1176 CALL_BlendEquationSeparateEXT(ctx->Exec, (modeRGB, modeA));
1177 }
1178 }
1179
1180
1181 static void GLAPIENTRY
1182 save_BlendFuncSeparateEXT(GLenum sfactorRGB, GLenum dfactorRGB,
1183 GLenum sfactorA, GLenum dfactorA)
1184 {
1185 GET_CURRENT_CONTEXT(ctx);
1186 Node *n;
1187 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1188 n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_SEPARATE, 4);
1189 if (n) {
1190 n[1].e = sfactorRGB;
1191 n[2].e = dfactorRGB;
1192 n[3].e = sfactorA;
1193 n[4].e = dfactorA;
1194 }
1195 if (ctx->ExecuteFlag) {
1196 CALL_BlendFuncSeparateEXT(ctx->Exec,
1197 (sfactorRGB, dfactorRGB, sfactorA, dfactorA));
1198 }
1199 }
1200
1201
1202 static void GLAPIENTRY
1203 save_BlendFunc(GLenum srcfactor, GLenum dstfactor)
1204 {
1205 save_BlendFuncSeparateEXT(srcfactor, dstfactor, srcfactor, dstfactor);
1206 }
1207
1208
1209 static void GLAPIENTRY
1210 save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
1211 {
1212 GET_CURRENT_CONTEXT(ctx);
1213 Node *n;
1214 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1215 n = alloc_instruction(ctx, OPCODE_BLEND_COLOR, 4);
1216 if (n) {
1217 n[1].f = red;
1218 n[2].f = green;
1219 n[3].f = blue;
1220 n[4].f = alpha;
1221 }
1222 if (ctx->ExecuteFlag) {
1223 CALL_BlendColor(ctx->Exec, (red, green, blue, alpha));
1224 }
1225 }
1226
1227 /* GL_ARB_draw_buffers_blend */
1228 static void GLAPIENTRY
1229 save_BlendFuncSeparatei(GLuint buf, GLenum sfactorRGB, GLenum dfactorRGB,
1230 GLenum sfactorA, GLenum dfactorA)
1231 {
1232 GET_CURRENT_CONTEXT(ctx);
1233 Node *n;
1234 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1235 n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_SEPARATE_I, 5);
1236 if (n) {
1237 n[1].ui = buf;
1238 n[2].e = sfactorRGB;
1239 n[3].e = dfactorRGB;
1240 n[4].e = sfactorA;
1241 n[5].e = dfactorA;
1242 }
1243 if (ctx->ExecuteFlag) {
1244 CALL_BlendFuncSeparateiARB(ctx->Exec, (buf, sfactorRGB, dfactorRGB,
1245 sfactorA, dfactorA));
1246 }
1247 }
1248
1249 /* GL_ARB_draw_buffers_blend */
1250 static void GLAPIENTRY
1251 save_BlendFunci(GLuint buf, GLenum sfactor, GLenum dfactor)
1252 {
1253 GET_CURRENT_CONTEXT(ctx);
1254 Node *n;
1255 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1256 n = alloc_instruction(ctx, OPCODE_BLEND_FUNC_SEPARATE_I, 3);
1257 if (n) {
1258 n[1].ui = buf;
1259 n[2].e = sfactor;
1260 n[3].e = dfactor;
1261 }
1262 if (ctx->ExecuteFlag) {
1263 CALL_BlendFunciARB(ctx->Exec, (buf, sfactor, dfactor));
1264 }
1265 }
1266
1267 /* GL_ARB_draw_buffers_blend */
1268 static void GLAPIENTRY
1269 save_BlendEquationi(GLuint buf, GLenum mode)
1270 {
1271 GET_CURRENT_CONTEXT(ctx);
1272 Node *n;
1273 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1274 n = alloc_instruction(ctx, OPCODE_BLEND_EQUATION_I, 2);
1275 if (n) {
1276 n[1].ui = buf;
1277 n[2].e = mode;
1278 }
1279 if (ctx->ExecuteFlag) {
1280 CALL_BlendEquationiARB(ctx->Exec, (buf, mode));
1281 }
1282 }
1283
1284 /* GL_ARB_draw_buffers_blend */
1285 static void GLAPIENTRY
1286 save_BlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeA)
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_SEPARATE_I, 3);
1292 if (n) {
1293 n[1].ui = buf;
1294 n[2].e = modeRGB;
1295 n[3].e = modeA;
1296 }
1297 if (ctx->ExecuteFlag) {
1298 CALL_BlendEquationSeparateiARB(ctx->Exec, (buf, modeRGB, modeA));
1299 }
1300 }
1301
1302
1303 /* GL_ARB_draw_instanced. */
1304 static void GLAPIENTRY
1305 save_DrawArraysInstancedARB(GLenum mode,
1306 GLint first,
1307 GLsizei count,
1308 GLsizei primcount)
1309 {
1310 GET_CURRENT_CONTEXT(ctx);
1311 _mesa_error(ctx, GL_INVALID_OPERATION,
1312 "glDrawArraysInstanced() during display list compile");
1313 }
1314
1315 static void GLAPIENTRY
1316 save_DrawElementsInstancedARB(GLenum mode,
1317 GLsizei count,
1318 GLenum type,
1319 const GLvoid *indices,
1320 GLsizei primcount)
1321 {
1322 GET_CURRENT_CONTEXT(ctx);
1323 _mesa_error(ctx, GL_INVALID_OPERATION,
1324 "glDrawElementsInstanced() during display list compile");
1325 }
1326
1327 static void GLAPIENTRY
1328 save_DrawElementsInstancedBaseVertexARB(GLenum mode,
1329 GLsizei count,
1330 GLenum type,
1331 const GLvoid *indices,
1332 GLsizei primcount,
1333 GLint basevertex)
1334 {
1335 GET_CURRENT_CONTEXT(ctx);
1336 _mesa_error(ctx, GL_INVALID_OPERATION,
1337 "glDrawElementsInstancedBaseVertex() during display list compile");
1338 }
1339
1340 static void invalidate_saved_current_state( struct gl_context *ctx )
1341 {
1342 GLint i;
1343
1344 for (i = 0; i < VERT_ATTRIB_MAX; i++)
1345 ctx->ListState.ActiveAttribSize[i] = 0;
1346
1347 for (i = 0; i < MAT_ATTRIB_MAX; i++)
1348 ctx->ListState.ActiveMaterialSize[i] = 0;
1349
1350 memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
1351
1352 ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
1353 }
1354
1355 static void GLAPIENTRY
1356 save_CallList(GLuint list)
1357 {
1358 GET_CURRENT_CONTEXT(ctx);
1359 Node *n;
1360 SAVE_FLUSH_VERTICES(ctx);
1361
1362 n = alloc_instruction(ctx, OPCODE_CALL_LIST, 1);
1363 if (n) {
1364 n[1].ui = list;
1365 }
1366
1367 /* After this, we don't know what state we're in. Invalidate all
1368 * cached information previously gathered:
1369 */
1370 invalidate_saved_current_state( ctx );
1371
1372 if (ctx->ExecuteFlag) {
1373 _mesa_CallList(list);
1374 }
1375 }
1376
1377
1378 static void GLAPIENTRY
1379 save_CallLists(GLsizei num, GLenum type, const GLvoid * lists)
1380 {
1381 GET_CURRENT_CONTEXT(ctx);
1382 GLint i;
1383 GLboolean typeErrorFlag;
1384
1385 SAVE_FLUSH_VERTICES(ctx);
1386
1387 switch (type) {
1388 case GL_BYTE:
1389 case GL_UNSIGNED_BYTE:
1390 case GL_SHORT:
1391 case GL_UNSIGNED_SHORT:
1392 case GL_INT:
1393 case GL_UNSIGNED_INT:
1394 case GL_FLOAT:
1395 case GL_2_BYTES:
1396 case GL_3_BYTES:
1397 case GL_4_BYTES:
1398 typeErrorFlag = GL_FALSE;
1399 break;
1400 default:
1401 typeErrorFlag = GL_TRUE;
1402 }
1403
1404 for (i = 0; i < num; i++) {
1405 GLint list = translate_id(i, type, lists);
1406 Node *n = alloc_instruction(ctx, OPCODE_CALL_LIST_OFFSET, 2);
1407 if (n) {
1408 n[1].i = list;
1409 n[2].b = typeErrorFlag;
1410 }
1411 }
1412
1413 /* After this, we don't know what state we're in. Invalidate all
1414 * cached information previously gathered:
1415 */
1416 invalidate_saved_current_state( ctx );
1417
1418 if (ctx->ExecuteFlag) {
1419 CALL_CallLists(ctx->Exec, (num, type, lists));
1420 }
1421 }
1422
1423
1424 static void GLAPIENTRY
1425 save_Clear(GLbitfield mask)
1426 {
1427 GET_CURRENT_CONTEXT(ctx);
1428 Node *n;
1429 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1430 n = alloc_instruction(ctx, OPCODE_CLEAR, 1);
1431 if (n) {
1432 n[1].bf = mask;
1433 }
1434 if (ctx->ExecuteFlag) {
1435 CALL_Clear(ctx->Exec, (mask));
1436 }
1437 }
1438
1439
1440 static void GLAPIENTRY
1441 save_ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *value)
1442 {
1443 GET_CURRENT_CONTEXT(ctx);
1444 Node *n;
1445 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1446 n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_IV, 6);
1447 if (n) {
1448 n[1].e = buffer;
1449 n[2].i = drawbuffer;
1450 n[3].i = value[0];
1451 if (buffer == GL_COLOR) {
1452 n[4].i = value[1];
1453 n[5].i = value[2];
1454 n[6].i = value[3];
1455 }
1456 else {
1457 n[4].i = 0;
1458 n[5].i = 0;
1459 n[6].i = 0;
1460 }
1461 }
1462 if (ctx->ExecuteFlag) {
1463 CALL_ClearBufferiv(ctx->Exec, (buffer, drawbuffer, value));
1464 }
1465 }
1466
1467
1468 static void GLAPIENTRY
1469 save_ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *value)
1470 {
1471 GET_CURRENT_CONTEXT(ctx);
1472 Node *n;
1473 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1474 n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_UIV, 6);
1475 if (n) {
1476 n[1].e = buffer;
1477 n[2].i = drawbuffer;
1478 n[3].ui = value[0];
1479 if (buffer == GL_COLOR) {
1480 n[4].ui = value[1];
1481 n[5].ui = value[2];
1482 n[6].ui = value[3];
1483 }
1484 else {
1485 n[4].ui = 0;
1486 n[5].ui = 0;
1487 n[6].ui = 0;
1488 }
1489 }
1490 if (ctx->ExecuteFlag) {
1491 CALL_ClearBufferuiv(ctx->Exec, (buffer, drawbuffer, value));
1492 }
1493 }
1494
1495
1496 static void GLAPIENTRY
1497 save_ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *value)
1498 {
1499 GET_CURRENT_CONTEXT(ctx);
1500 Node *n;
1501 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1502 n = alloc_instruction(ctx, OPCODE_CLEAR_BUFFER_FV, 6);
1503 if (n) {
1504 n[1].e = buffer;
1505 n[2].i = drawbuffer;
1506 n[3].f = value[0];
1507 if (buffer == GL_COLOR) {
1508 n[4].f = value[1];
1509 n[5].f = value[2];
1510 n[6].f = value[3];
1511 }
1512 else {
1513 n[4].f = 0.0F;
1514 n[5].f = 0.0F;
1515 n[6].f = 0.0F;
1516 }
1517 }
1518 if (ctx->ExecuteFlag) {
1519 CALL_ClearBufferfv(ctx->Exec, (buffer, drawbuffer, value));
1520 }
1521 }
1522
1523
1524 static void GLAPIENTRY
1525 save_ClearBufferfi(GLenum buffer, GLint drawbuffer,
1526 GLfloat depth, GLint stencil)
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_FI, 4);
1532 if (n) {
1533 n[1].e = buffer;
1534 n[2].i = drawbuffer;
1535 n[3].f = depth;
1536 n[4].i = stencil;
1537 }
1538 if (ctx->ExecuteFlag) {
1539 CALL_ClearBufferfi(ctx->Exec, (buffer, drawbuffer, depth, stencil));
1540 }
1541 }
1542
1543
1544 static void GLAPIENTRY
1545 save_ClearAccum(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
1546 {
1547 GET_CURRENT_CONTEXT(ctx);
1548 Node *n;
1549 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1550 n = alloc_instruction(ctx, OPCODE_CLEAR_ACCUM, 4);
1551 if (n) {
1552 n[1].f = red;
1553 n[2].f = green;
1554 n[3].f = blue;
1555 n[4].f = alpha;
1556 }
1557 if (ctx->ExecuteFlag) {
1558 CALL_ClearAccum(ctx->Exec, (red, green, blue, alpha));
1559 }
1560 }
1561
1562
1563 static void GLAPIENTRY
1564 save_ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
1565 {
1566 GET_CURRENT_CONTEXT(ctx);
1567 Node *n;
1568 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1569 n = alloc_instruction(ctx, OPCODE_CLEAR_COLOR, 4);
1570 if (n) {
1571 n[1].f = red;
1572 n[2].f = green;
1573 n[3].f = blue;
1574 n[4].f = alpha;
1575 }
1576 if (ctx->ExecuteFlag) {
1577 CALL_ClearColor(ctx->Exec, (red, green, blue, alpha));
1578 }
1579 }
1580
1581
1582 static void GLAPIENTRY
1583 save_ClearDepth(GLclampd depth)
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_DEPTH, 1);
1589 if (n) {
1590 n[1].f = (GLfloat) depth;
1591 }
1592 if (ctx->ExecuteFlag) {
1593 CALL_ClearDepth(ctx->Exec, (depth));
1594 }
1595 }
1596
1597
1598 static void GLAPIENTRY
1599 save_ClearIndex(GLfloat c)
1600 {
1601 GET_CURRENT_CONTEXT(ctx);
1602 Node *n;
1603 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1604 n = alloc_instruction(ctx, OPCODE_CLEAR_INDEX, 1);
1605 if (n) {
1606 n[1].f = c;
1607 }
1608 if (ctx->ExecuteFlag) {
1609 CALL_ClearIndex(ctx->Exec, (c));
1610 }
1611 }
1612
1613
1614 static void GLAPIENTRY
1615 save_ClearStencil(GLint s)
1616 {
1617 GET_CURRENT_CONTEXT(ctx);
1618 Node *n;
1619 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1620 n = alloc_instruction(ctx, OPCODE_CLEAR_STENCIL, 1);
1621 if (n) {
1622 n[1].i = s;
1623 }
1624 if (ctx->ExecuteFlag) {
1625 CALL_ClearStencil(ctx->Exec, (s));
1626 }
1627 }
1628
1629
1630 static void GLAPIENTRY
1631 save_ClipPlane(GLenum plane, const GLdouble * equ)
1632 {
1633 GET_CURRENT_CONTEXT(ctx);
1634 Node *n;
1635 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1636 n = alloc_instruction(ctx, OPCODE_CLIP_PLANE, 5);
1637 if (n) {
1638 n[1].e = plane;
1639 n[2].f = (GLfloat) equ[0];
1640 n[3].f = (GLfloat) equ[1];
1641 n[4].f = (GLfloat) equ[2];
1642 n[5].f = (GLfloat) equ[3];
1643 }
1644 if (ctx->ExecuteFlag) {
1645 CALL_ClipPlane(ctx->Exec, (plane, equ));
1646 }
1647 }
1648
1649
1650
1651 static void GLAPIENTRY
1652 save_ColorMask(GLboolean red, GLboolean green,
1653 GLboolean blue, GLboolean alpha)
1654 {
1655 GET_CURRENT_CONTEXT(ctx);
1656 Node *n;
1657 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1658 n = alloc_instruction(ctx, OPCODE_COLOR_MASK, 4);
1659 if (n) {
1660 n[1].b = red;
1661 n[2].b = green;
1662 n[3].b = blue;
1663 n[4].b = alpha;
1664 }
1665 if (ctx->ExecuteFlag) {
1666 CALL_ColorMask(ctx->Exec, (red, green, blue, alpha));
1667 }
1668 }
1669
1670
1671 static void GLAPIENTRY
1672 save_ColorMaskIndexed(GLuint buf, GLboolean red, GLboolean green,
1673 GLboolean blue, GLboolean alpha)
1674 {
1675 GET_CURRENT_CONTEXT(ctx);
1676 Node *n;
1677 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1678 n = alloc_instruction(ctx, OPCODE_COLOR_MASK_INDEXED, 5);
1679 if (n) {
1680 n[1].ui = buf;
1681 n[2].b = red;
1682 n[3].b = green;
1683 n[4].b = blue;
1684 n[5].b = alpha;
1685 }
1686 if (ctx->ExecuteFlag) {
1687 /*CALL_ColorMaskIndexedEXT(ctx->Exec, (buf, red, green, blue, alpha));*/
1688 }
1689 }
1690
1691
1692 static void GLAPIENTRY
1693 save_ColorMaterial(GLenum face, GLenum mode)
1694 {
1695 GET_CURRENT_CONTEXT(ctx);
1696 Node *n;
1697 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1698
1699 n = alloc_instruction(ctx, OPCODE_COLOR_MATERIAL, 2);
1700 if (n) {
1701 n[1].e = face;
1702 n[2].e = mode;
1703 }
1704 if (ctx->ExecuteFlag) {
1705 CALL_ColorMaterial(ctx->Exec, (face, mode));
1706 }
1707 }
1708
1709
1710 static void GLAPIENTRY
1711 save_ColorTable(GLenum target, GLenum internalFormat,
1712 GLsizei width, GLenum format, GLenum type,
1713 const GLvoid * table)
1714 {
1715 GET_CURRENT_CONTEXT(ctx);
1716 if (_mesa_is_proxy_texture(target)) {
1717 /* execute immediately */
1718 CALL_ColorTable(ctx->Exec, (target, internalFormat, width,
1719 format, type, table));
1720 }
1721 else {
1722 Node *n;
1723 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1724 n = alloc_instruction(ctx, OPCODE_COLOR_TABLE, 6);
1725 if (n) {
1726 n[1].e = target;
1727 n[2].e = internalFormat;
1728 n[3].i = width;
1729 n[4].e = format;
1730 n[5].e = type;
1731 n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, table,
1732 &ctx->Unpack);
1733 }
1734 if (ctx->ExecuteFlag) {
1735 CALL_ColorTable(ctx->Exec, (target, internalFormat, width,
1736 format, type, table));
1737 }
1738 }
1739 }
1740
1741
1742
1743 static void GLAPIENTRY
1744 save_ColorTableParameterfv(GLenum target, GLenum pname,
1745 const GLfloat *params)
1746 {
1747 GET_CURRENT_CONTEXT(ctx);
1748 Node *n;
1749
1750 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1751
1752 n = alloc_instruction(ctx, OPCODE_COLOR_TABLE_PARAMETER_FV, 6);
1753 if (n) {
1754 n[1].e = target;
1755 n[2].e = pname;
1756 n[3].f = params[0];
1757 if (pname == GL_COLOR_TABLE_SGI ||
1758 pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
1759 pname == GL_TEXTURE_COLOR_TABLE_SGI) {
1760 n[4].f = params[1];
1761 n[5].f = params[2];
1762 n[6].f = params[3];
1763 }
1764 }
1765
1766 if (ctx->ExecuteFlag) {
1767 CALL_ColorTableParameterfv(ctx->Exec, (target, pname, params));
1768 }
1769 }
1770
1771
1772 static void GLAPIENTRY
1773 save_ColorTableParameteriv(GLenum target, GLenum pname, const GLint *params)
1774 {
1775 GET_CURRENT_CONTEXT(ctx);
1776 Node *n;
1777
1778 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1779
1780 n = alloc_instruction(ctx, OPCODE_COLOR_TABLE_PARAMETER_IV, 6);
1781 if (n) {
1782 n[1].e = target;
1783 n[2].e = pname;
1784 n[3].i = params[0];
1785 if (pname == GL_COLOR_TABLE_SGI ||
1786 pname == GL_POST_CONVOLUTION_COLOR_TABLE_SGI ||
1787 pname == GL_TEXTURE_COLOR_TABLE_SGI) {
1788 n[4].i = params[1];
1789 n[5].i = params[2];
1790 n[6].i = params[3];
1791 }
1792 }
1793
1794 if (ctx->ExecuteFlag) {
1795 CALL_ColorTableParameteriv(ctx->Exec, (target, pname, params));
1796 }
1797 }
1798
1799
1800
1801 static void GLAPIENTRY
1802 save_ColorSubTable(GLenum target, GLsizei start, GLsizei count,
1803 GLenum format, GLenum type, const GLvoid * table)
1804 {
1805 GET_CURRENT_CONTEXT(ctx);
1806 Node *n;
1807 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1808 n = alloc_instruction(ctx, OPCODE_COLOR_SUB_TABLE, 6);
1809 if (n) {
1810 n[1].e = target;
1811 n[2].i = start;
1812 n[3].i = count;
1813 n[4].e = format;
1814 n[5].e = type;
1815 n[6].data = unpack_image(ctx, 1, count, 1, 1, format, type, table,
1816 &ctx->Unpack);
1817 }
1818 if (ctx->ExecuteFlag) {
1819 CALL_ColorSubTable(ctx->Exec,
1820 (target, start, count, format, type, table));
1821 }
1822 }
1823
1824
1825 static void GLAPIENTRY
1826 save_CopyColorSubTable(GLenum target, GLsizei start,
1827 GLint x, GLint y, GLsizei width)
1828 {
1829 GET_CURRENT_CONTEXT(ctx);
1830 Node *n;
1831
1832 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1833 n = alloc_instruction(ctx, OPCODE_COPY_COLOR_SUB_TABLE, 5);
1834 if (n) {
1835 n[1].e = target;
1836 n[2].i = start;
1837 n[3].i = x;
1838 n[4].i = y;
1839 n[5].i = width;
1840 }
1841 if (ctx->ExecuteFlag) {
1842 CALL_CopyColorSubTable(ctx->Exec, (target, start, x, y, width));
1843 }
1844 }
1845
1846
1847 static void GLAPIENTRY
1848 save_CopyColorTable(GLenum target, GLenum internalformat,
1849 GLint x, GLint y, GLsizei width)
1850 {
1851 GET_CURRENT_CONTEXT(ctx);
1852 Node *n;
1853
1854 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1855 n = alloc_instruction(ctx, OPCODE_COPY_COLOR_TABLE, 5);
1856 if (n) {
1857 n[1].e = target;
1858 n[2].e = internalformat;
1859 n[3].i = x;
1860 n[4].i = y;
1861 n[5].i = width;
1862 }
1863 if (ctx->ExecuteFlag) {
1864 CALL_CopyColorTable(ctx->Exec, (target, internalformat, x, y, width));
1865 }
1866 }
1867
1868
1869 static void GLAPIENTRY
1870 save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width,
1871 GLenum format, GLenum type, const GLvoid * filter)
1872 {
1873 GET_CURRENT_CONTEXT(ctx);
1874 Node *n;
1875
1876 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1877
1878 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_FILTER_1D, 6);
1879 if (n) {
1880 n[1].e = target;
1881 n[2].e = internalFormat;
1882 n[3].i = width;
1883 n[4].e = format;
1884 n[5].e = type;
1885 n[6].data = unpack_image(ctx, 1, width, 1, 1, format, type, filter,
1886 &ctx->Unpack);
1887 }
1888 if (ctx->ExecuteFlag) {
1889 CALL_ConvolutionFilter1D(ctx->Exec, (target, internalFormat, width,
1890 format, type, filter));
1891 }
1892 }
1893
1894
1895 static void GLAPIENTRY
1896 save_ConvolutionFilter2D(GLenum target, GLenum internalFormat,
1897 GLsizei width, GLsizei height, GLenum format,
1898 GLenum type, const GLvoid * filter)
1899 {
1900 GET_CURRENT_CONTEXT(ctx);
1901 Node *n;
1902
1903 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1904
1905 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_FILTER_2D, 7);
1906 if (n) {
1907 n[1].e = target;
1908 n[2].e = internalFormat;
1909 n[3].i = width;
1910 n[4].i = height;
1911 n[5].e = format;
1912 n[6].e = type;
1913 n[7].data = unpack_image(ctx, 2, width, height, 1, format, type, filter,
1914 &ctx->Unpack);
1915 }
1916 if (ctx->ExecuteFlag) {
1917 CALL_ConvolutionFilter2D(ctx->Exec,
1918 (target, internalFormat, width, height, format,
1919 type, filter));
1920 }
1921 }
1922
1923
1924 static void GLAPIENTRY
1925 save_ConvolutionParameteri(GLenum target, GLenum pname, GLint param)
1926 {
1927 GET_CURRENT_CONTEXT(ctx);
1928 Node *n;
1929 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1930 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_I, 3);
1931 if (n) {
1932 n[1].e = target;
1933 n[2].e = pname;
1934 n[3].i = param;
1935 }
1936 if (ctx->ExecuteFlag) {
1937 CALL_ConvolutionParameteri(ctx->Exec, (target, pname, param));
1938 }
1939 }
1940
1941
1942 static void GLAPIENTRY
1943 save_ConvolutionParameteriv(GLenum target, GLenum pname, const GLint *params)
1944 {
1945 GET_CURRENT_CONTEXT(ctx);
1946 Node *n;
1947 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1948 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_IV, 6);
1949 if (n) {
1950 n[1].e = target;
1951 n[2].e = pname;
1952 n[3].i = params[0];
1953 if (pname == GL_CONVOLUTION_BORDER_COLOR ||
1954 pname == GL_CONVOLUTION_FILTER_SCALE ||
1955 pname == GL_CONVOLUTION_FILTER_BIAS) {
1956 n[4].i = params[1];
1957 n[5].i = params[2];
1958 n[6].i = params[3];
1959 }
1960 else {
1961 n[4].i = n[5].i = n[6].i = 0;
1962 }
1963 }
1964 if (ctx->ExecuteFlag) {
1965 CALL_ConvolutionParameteriv(ctx->Exec, (target, pname, params));
1966 }
1967 }
1968
1969
1970 static void GLAPIENTRY
1971 save_ConvolutionParameterf(GLenum target, GLenum pname, GLfloat param)
1972 {
1973 GET_CURRENT_CONTEXT(ctx);
1974 Node *n;
1975 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1976 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_F, 3);
1977 if (n) {
1978 n[1].e = target;
1979 n[2].e = pname;
1980 n[3].f = param;
1981 }
1982 if (ctx->ExecuteFlag) {
1983 CALL_ConvolutionParameterf(ctx->Exec, (target, pname, param));
1984 }
1985 }
1986
1987
1988 static void GLAPIENTRY
1989 save_ConvolutionParameterfv(GLenum target, GLenum pname,
1990 const GLfloat *params)
1991 {
1992 GET_CURRENT_CONTEXT(ctx);
1993 Node *n;
1994 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
1995 n = alloc_instruction(ctx, OPCODE_CONVOLUTION_PARAMETER_FV, 6);
1996 if (n) {
1997 n[1].e = target;
1998 n[2].e = pname;
1999 n[3].f = params[0];
2000 if (pname == GL_CONVOLUTION_BORDER_COLOR ||
2001 pname == GL_CONVOLUTION_FILTER_SCALE ||
2002 pname == GL_CONVOLUTION_FILTER_BIAS) {
2003 n[4].f = params[1];
2004 n[5].f = params[2];
2005 n[6].f = params[3];
2006 }
2007 else {
2008 n[4].f = n[5].f = n[6].f = 0.0F;
2009 }
2010 }
2011 if (ctx->ExecuteFlag) {
2012 CALL_ConvolutionParameterfv(ctx->Exec, (target, pname, params));
2013 }
2014 }
2015
2016
2017 static void GLAPIENTRY
2018 save_CopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
2019 {
2020 GET_CURRENT_CONTEXT(ctx);
2021 Node *n;
2022 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2023 n = alloc_instruction(ctx, OPCODE_COPY_PIXELS, 5);
2024 if (n) {
2025 n[1].i = x;
2026 n[2].i = y;
2027 n[3].i = (GLint) width;
2028 n[4].i = (GLint) height;
2029 n[5].e = type;
2030 }
2031 if (ctx->ExecuteFlag) {
2032 CALL_CopyPixels(ctx->Exec, (x, y, width, height, type));
2033 }
2034 }
2035
2036
2037
2038 static void GLAPIENTRY
2039 save_CopyTexImage1D(GLenum target, GLint level, GLenum internalformat,
2040 GLint x, GLint y, GLsizei width, GLint border)
2041 {
2042 GET_CURRENT_CONTEXT(ctx);
2043 Node *n;
2044 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2045 n = alloc_instruction(ctx, OPCODE_COPY_TEX_IMAGE1D, 7);
2046 if (n) {
2047 n[1].e = target;
2048 n[2].i = level;
2049 n[3].e = internalformat;
2050 n[4].i = x;
2051 n[5].i = y;
2052 n[6].i = width;
2053 n[7].i = border;
2054 }
2055 if (ctx->ExecuteFlag) {
2056 CALL_CopyTexImage1D(ctx->Exec, (target, level, internalformat,
2057 x, y, width, border));
2058 }
2059 }
2060
2061
2062 static void GLAPIENTRY
2063 save_CopyTexImage2D(GLenum target, GLint level,
2064 GLenum internalformat,
2065 GLint x, GLint y, GLsizei width,
2066 GLsizei height, GLint border)
2067 {
2068 GET_CURRENT_CONTEXT(ctx);
2069 Node *n;
2070 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2071 n = alloc_instruction(ctx, OPCODE_COPY_TEX_IMAGE2D, 8);
2072 if (n) {
2073 n[1].e = target;
2074 n[2].i = level;
2075 n[3].e = internalformat;
2076 n[4].i = x;
2077 n[5].i = y;
2078 n[6].i = width;
2079 n[7].i = height;
2080 n[8].i = border;
2081 }
2082 if (ctx->ExecuteFlag) {
2083 CALL_CopyTexImage2D(ctx->Exec, (target, level, internalformat,
2084 x, y, width, height, border));
2085 }
2086 }
2087
2088
2089
2090 static void GLAPIENTRY
2091 save_CopyTexSubImage1D(GLenum target, GLint level,
2092 GLint xoffset, GLint x, GLint y, GLsizei width)
2093 {
2094 GET_CURRENT_CONTEXT(ctx);
2095 Node *n;
2096 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2097 n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE1D, 6);
2098 if (n) {
2099 n[1].e = target;
2100 n[2].i = level;
2101 n[3].i = xoffset;
2102 n[4].i = x;
2103 n[5].i = y;
2104 n[6].i = width;
2105 }
2106 if (ctx->ExecuteFlag) {
2107 CALL_CopyTexSubImage1D(ctx->Exec,
2108 (target, level, xoffset, x, y, width));
2109 }
2110 }
2111
2112
2113 static void GLAPIENTRY
2114 save_CopyTexSubImage2D(GLenum target, GLint level,
2115 GLint xoffset, GLint yoffset,
2116 GLint x, GLint y, GLsizei width, GLint height)
2117 {
2118 GET_CURRENT_CONTEXT(ctx);
2119 Node *n;
2120 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2121 n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE2D, 8);
2122 if (n) {
2123 n[1].e = target;
2124 n[2].i = level;
2125 n[3].i = xoffset;
2126 n[4].i = yoffset;
2127 n[5].i = x;
2128 n[6].i = y;
2129 n[7].i = width;
2130 n[8].i = height;
2131 }
2132 if (ctx->ExecuteFlag) {
2133 CALL_CopyTexSubImage2D(ctx->Exec, (target, level, xoffset, yoffset,
2134 x, y, width, height));
2135 }
2136 }
2137
2138
2139 static void GLAPIENTRY
2140 save_CopyTexSubImage3D(GLenum target, GLint level,
2141 GLint xoffset, GLint yoffset, GLint zoffset,
2142 GLint x, GLint y, GLsizei width, GLint height)
2143 {
2144 GET_CURRENT_CONTEXT(ctx);
2145 Node *n;
2146 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2147 n = alloc_instruction(ctx, OPCODE_COPY_TEX_SUB_IMAGE3D, 9);
2148 if (n) {
2149 n[1].e = target;
2150 n[2].i = level;
2151 n[3].i = xoffset;
2152 n[4].i = yoffset;
2153 n[5].i = zoffset;
2154 n[6].i = x;
2155 n[7].i = y;
2156 n[8].i = width;
2157 n[9].i = height;
2158 }
2159 if (ctx->ExecuteFlag) {
2160 CALL_CopyTexSubImage3D(ctx->Exec, (target, level,
2161 xoffset, yoffset, zoffset,
2162 x, y, width, height));
2163 }
2164 }
2165
2166
2167 static void GLAPIENTRY
2168 save_CullFace(GLenum mode)
2169 {
2170 GET_CURRENT_CONTEXT(ctx);
2171 Node *n;
2172 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2173 n = alloc_instruction(ctx, OPCODE_CULL_FACE, 1);
2174 if (n) {
2175 n[1].e = mode;
2176 }
2177 if (ctx->ExecuteFlag) {
2178 CALL_CullFace(ctx->Exec, (mode));
2179 }
2180 }
2181
2182
2183 static void GLAPIENTRY
2184 save_DepthFunc(GLenum func)
2185 {
2186 GET_CURRENT_CONTEXT(ctx);
2187 Node *n;
2188 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2189 n = alloc_instruction(ctx, OPCODE_DEPTH_FUNC, 1);
2190 if (n) {
2191 n[1].e = func;
2192 }
2193 if (ctx->ExecuteFlag) {
2194 CALL_DepthFunc(ctx->Exec, (func));
2195 }
2196 }
2197
2198
2199 static void GLAPIENTRY
2200 save_DepthMask(GLboolean mask)
2201 {
2202 GET_CURRENT_CONTEXT(ctx);
2203 Node *n;
2204 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2205 n = alloc_instruction(ctx, OPCODE_DEPTH_MASK, 1);
2206 if (n) {
2207 n[1].b = mask;
2208 }
2209 if (ctx->ExecuteFlag) {
2210 CALL_DepthMask(ctx->Exec, (mask));
2211 }
2212 }
2213
2214
2215 static void GLAPIENTRY
2216 save_DepthRange(GLclampd nearval, GLclampd farval)
2217 {
2218 GET_CURRENT_CONTEXT(ctx);
2219 Node *n;
2220 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2221 n = alloc_instruction(ctx, OPCODE_DEPTH_RANGE, 2);
2222 if (n) {
2223 n[1].f = (GLfloat) nearval;
2224 n[2].f = (GLfloat) farval;
2225 }
2226 if (ctx->ExecuteFlag) {
2227 CALL_DepthRange(ctx->Exec, (nearval, farval));
2228 }
2229 }
2230
2231
2232 static void GLAPIENTRY
2233 save_Disable(GLenum cap)
2234 {
2235 GET_CURRENT_CONTEXT(ctx);
2236 Node *n;
2237 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2238 n = alloc_instruction(ctx, OPCODE_DISABLE, 1);
2239 if (n) {
2240 n[1].e = cap;
2241 }
2242 if (ctx->ExecuteFlag) {
2243 CALL_Disable(ctx->Exec, (cap));
2244 }
2245 }
2246
2247
2248 static void GLAPIENTRY
2249 save_DisableIndexed(GLuint index, GLenum cap)
2250 {
2251 GET_CURRENT_CONTEXT(ctx);
2252 Node *n;
2253 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2254 n = alloc_instruction(ctx, OPCODE_DISABLE_INDEXED, 2);
2255 if (n) {
2256 n[1].ui = index;
2257 n[2].e = cap;
2258 }
2259 if (ctx->ExecuteFlag) {
2260 CALL_DisableIndexedEXT(ctx->Exec, (index, cap));
2261 }
2262 }
2263
2264
2265 static void GLAPIENTRY
2266 save_DrawBuffer(GLenum mode)
2267 {
2268 GET_CURRENT_CONTEXT(ctx);
2269 Node *n;
2270 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2271 n = alloc_instruction(ctx, OPCODE_DRAW_BUFFER, 1);
2272 if (n) {
2273 n[1].e = mode;
2274 }
2275 if (ctx->ExecuteFlag) {
2276 CALL_DrawBuffer(ctx->Exec, (mode));
2277 }
2278 }
2279
2280
2281 static void GLAPIENTRY
2282 save_DrawPixels(GLsizei width, GLsizei height,
2283 GLenum format, GLenum type, const GLvoid * pixels)
2284 {
2285 GET_CURRENT_CONTEXT(ctx);
2286 Node *n;
2287
2288 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2289
2290 n = alloc_instruction(ctx, OPCODE_DRAW_PIXELS, 5);
2291 if (n) {
2292 n[1].i = width;
2293 n[2].i = height;
2294 n[3].e = format;
2295 n[4].e = type;
2296 n[5].data = unpack_image(ctx, 2, width, height, 1, format, type,
2297 pixels, &ctx->Unpack);
2298 }
2299 if (ctx->ExecuteFlag) {
2300 CALL_DrawPixels(ctx->Exec, (width, height, format, type, pixels));
2301 }
2302 }
2303
2304
2305
2306 static void GLAPIENTRY
2307 save_Enable(GLenum cap)
2308 {
2309 GET_CURRENT_CONTEXT(ctx);
2310 Node *n;
2311 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2312 n = alloc_instruction(ctx, OPCODE_ENABLE, 1);
2313 if (n) {
2314 n[1].e = cap;
2315 }
2316 if (ctx->ExecuteFlag) {
2317 CALL_Enable(ctx->Exec, (cap));
2318 }
2319 }
2320
2321
2322
2323 static void GLAPIENTRY
2324 save_EnableIndexed(GLuint index, GLenum cap)
2325 {
2326 GET_CURRENT_CONTEXT(ctx);
2327 Node *n;
2328 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2329 n = alloc_instruction(ctx, OPCODE_ENABLE_INDEXED, 2);
2330 if (n) {
2331 n[1].ui = index;
2332 n[2].e = cap;
2333 }
2334 if (ctx->ExecuteFlag) {
2335 CALL_EnableIndexedEXT(ctx->Exec, (index, cap));
2336 }
2337 }
2338
2339
2340
2341 static void GLAPIENTRY
2342 save_EvalMesh1(GLenum mode, GLint i1, GLint i2)
2343 {
2344 GET_CURRENT_CONTEXT(ctx);
2345 Node *n;
2346 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2347 n = alloc_instruction(ctx, OPCODE_EVALMESH1, 3);
2348 if (n) {
2349 n[1].e = mode;
2350 n[2].i = i1;
2351 n[3].i = i2;
2352 }
2353 if (ctx->ExecuteFlag) {
2354 CALL_EvalMesh1(ctx->Exec, (mode, i1, i2));
2355 }
2356 }
2357
2358
2359 static void GLAPIENTRY
2360 save_EvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2)
2361 {
2362 GET_CURRENT_CONTEXT(ctx);
2363 Node *n;
2364 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2365 n = alloc_instruction(ctx, OPCODE_EVALMESH2, 5);
2366 if (n) {
2367 n[1].e = mode;
2368 n[2].i = i1;
2369 n[3].i = i2;
2370 n[4].i = j1;
2371 n[5].i = j2;
2372 }
2373 if (ctx->ExecuteFlag) {
2374 CALL_EvalMesh2(ctx->Exec, (mode, i1, i2, j1, j2));
2375 }
2376 }
2377
2378
2379
2380
2381 static void GLAPIENTRY
2382 save_Fogfv(GLenum pname, const GLfloat *params)
2383 {
2384 GET_CURRENT_CONTEXT(ctx);
2385 Node *n;
2386 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2387 n = alloc_instruction(ctx, OPCODE_FOG, 5);
2388 if (n) {
2389 n[1].e = pname;
2390 n[2].f = params[0];
2391 n[3].f = params[1];
2392 n[4].f = params[2];
2393 n[5].f = params[3];
2394 }
2395 if (ctx->ExecuteFlag) {
2396 CALL_Fogfv(ctx->Exec, (pname, params));
2397 }
2398 }
2399
2400
2401 static void GLAPIENTRY
2402 save_Fogf(GLenum pname, GLfloat param)
2403 {
2404 GLfloat parray[4];
2405 parray[0] = param;
2406 parray[1] = parray[2] = parray[3] = 0.0F;
2407 save_Fogfv(pname, parray);
2408 }
2409
2410
2411 static void GLAPIENTRY
2412 save_Fogiv(GLenum pname, const GLint *params)
2413 {
2414 GLfloat p[4];
2415 switch (pname) {
2416 case GL_FOG_MODE:
2417 case GL_FOG_DENSITY:
2418 case GL_FOG_START:
2419 case GL_FOG_END:
2420 case GL_FOG_INDEX:
2421 p[0] = (GLfloat) *params;
2422 p[1] = 0.0f;
2423 p[2] = 0.0f;
2424 p[3] = 0.0f;
2425 break;
2426 case GL_FOG_COLOR:
2427 p[0] = INT_TO_FLOAT(params[0]);
2428 p[1] = INT_TO_FLOAT(params[1]);
2429 p[2] = INT_TO_FLOAT(params[2]);
2430 p[3] = INT_TO_FLOAT(params[3]);
2431 break;
2432 default:
2433 /* Error will be caught later in gl_Fogfv */
2434 ASSIGN_4V(p, 0.0F, 0.0F, 0.0F, 0.0F);
2435 }
2436 save_Fogfv(pname, p);
2437 }
2438
2439
2440 static void GLAPIENTRY
2441 save_Fogi(GLenum pname, GLint param)
2442 {
2443 GLint parray[4];
2444 parray[0] = param;
2445 parray[1] = parray[2] = parray[3] = 0;
2446 save_Fogiv(pname, parray);
2447 }
2448
2449
2450 static void GLAPIENTRY
2451 save_FrontFace(GLenum mode)
2452 {
2453 GET_CURRENT_CONTEXT(ctx);
2454 Node *n;
2455 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2456 n = alloc_instruction(ctx, OPCODE_FRONT_FACE, 1);
2457 if (n) {
2458 n[1].e = mode;
2459 }
2460 if (ctx->ExecuteFlag) {
2461 CALL_FrontFace(ctx->Exec, (mode));
2462 }
2463 }
2464
2465
2466 static void GLAPIENTRY
2467 save_Frustum(GLdouble left, GLdouble right,
2468 GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
2469 {
2470 GET_CURRENT_CONTEXT(ctx);
2471 Node *n;
2472 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2473 n = alloc_instruction(ctx, OPCODE_FRUSTUM, 6);
2474 if (n) {
2475 n[1].f = (GLfloat) left;
2476 n[2].f = (GLfloat) right;
2477 n[3].f = (GLfloat) bottom;
2478 n[4].f = (GLfloat) top;
2479 n[5].f = (GLfloat) nearval;
2480 n[6].f = (GLfloat) farval;
2481 }
2482 if (ctx->ExecuteFlag) {
2483 CALL_Frustum(ctx->Exec, (left, right, bottom, top, nearval, farval));
2484 }
2485 }
2486
2487
2488 static void GLAPIENTRY
2489 save_Hint(GLenum target, GLenum mode)
2490 {
2491 GET_CURRENT_CONTEXT(ctx);
2492 Node *n;
2493 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2494 n = alloc_instruction(ctx, OPCODE_HINT, 2);
2495 if (n) {
2496 n[1].e = target;
2497 n[2].e = mode;
2498 }
2499 if (ctx->ExecuteFlag) {
2500 CALL_Hint(ctx->Exec, (target, mode));
2501 }
2502 }
2503
2504
2505 static void GLAPIENTRY
2506 save_Histogram(GLenum target, GLsizei width, GLenum internalFormat,
2507 GLboolean sink)
2508 {
2509 GET_CURRENT_CONTEXT(ctx);
2510 Node *n;
2511
2512 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2513 n = alloc_instruction(ctx, OPCODE_HISTOGRAM, 4);
2514 if (n) {
2515 n[1].e = target;
2516 n[2].i = width;
2517 n[3].e = internalFormat;
2518 n[4].b = sink;
2519 }
2520 if (ctx->ExecuteFlag) {
2521 CALL_Histogram(ctx->Exec, (target, width, internalFormat, sink));
2522 }
2523 }
2524
2525
2526 static void GLAPIENTRY
2527 save_IndexMask(GLuint mask)
2528 {
2529 GET_CURRENT_CONTEXT(ctx);
2530 Node *n;
2531 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2532 n = alloc_instruction(ctx, OPCODE_INDEX_MASK, 1);
2533 if (n) {
2534 n[1].ui = mask;
2535 }
2536 if (ctx->ExecuteFlag) {
2537 CALL_IndexMask(ctx->Exec, (mask));
2538 }
2539 }
2540
2541
2542 static void GLAPIENTRY
2543 save_InitNames(void)
2544 {
2545 GET_CURRENT_CONTEXT(ctx);
2546 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2547 (void) alloc_instruction(ctx, OPCODE_INIT_NAMES, 0);
2548 if (ctx->ExecuteFlag) {
2549 CALL_InitNames(ctx->Exec, ());
2550 }
2551 }
2552
2553
2554 static void GLAPIENTRY
2555 save_Lightfv(GLenum light, GLenum pname, const GLfloat *params)
2556 {
2557 GET_CURRENT_CONTEXT(ctx);
2558 Node *n;
2559 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2560 n = alloc_instruction(ctx, OPCODE_LIGHT, 6);
2561 if (n) {
2562 GLint i, nParams;
2563 n[1].e = light;
2564 n[2].e = pname;
2565 switch (pname) {
2566 case GL_AMBIENT:
2567 nParams = 4;
2568 break;
2569 case GL_DIFFUSE:
2570 nParams = 4;
2571 break;
2572 case GL_SPECULAR:
2573 nParams = 4;
2574 break;
2575 case GL_POSITION:
2576 nParams = 4;
2577 break;
2578 case GL_SPOT_DIRECTION:
2579 nParams = 3;
2580 break;
2581 case GL_SPOT_EXPONENT:
2582 nParams = 1;
2583 break;
2584 case GL_SPOT_CUTOFF:
2585 nParams = 1;
2586 break;
2587 case GL_CONSTANT_ATTENUATION:
2588 nParams = 1;
2589 break;
2590 case GL_LINEAR_ATTENUATION:
2591 nParams = 1;
2592 break;
2593 case GL_QUADRATIC_ATTENUATION:
2594 nParams = 1;
2595 break;
2596 default:
2597 nParams = 0;
2598 }
2599 for (i = 0; i < nParams; i++) {
2600 n[3 + i].f = params[i];
2601 }
2602 }
2603 if (ctx->ExecuteFlag) {
2604 CALL_Lightfv(ctx->Exec, (light, pname, params));
2605 }
2606 }
2607
2608
2609 static void GLAPIENTRY
2610 save_Lightf(GLenum light, GLenum pname, GLfloat param)
2611 {
2612 GLfloat parray[4];
2613 parray[0] = param;
2614 parray[1] = parray[2] = parray[3] = 0.0F;
2615 save_Lightfv(light, pname, parray);
2616 }
2617
2618
2619 static void GLAPIENTRY
2620 save_Lightiv(GLenum light, GLenum pname, const GLint *params)
2621 {
2622 GLfloat fparam[4];
2623 switch (pname) {
2624 case GL_AMBIENT:
2625 case GL_DIFFUSE:
2626 case GL_SPECULAR:
2627 fparam[0] = INT_TO_FLOAT(params[0]);
2628 fparam[1] = INT_TO_FLOAT(params[1]);
2629 fparam[2] = INT_TO_FLOAT(params[2]);
2630 fparam[3] = INT_TO_FLOAT(params[3]);
2631 break;
2632 case GL_POSITION:
2633 fparam[0] = (GLfloat) params[0];
2634 fparam[1] = (GLfloat) params[1];
2635 fparam[2] = (GLfloat) params[2];
2636 fparam[3] = (GLfloat) params[3];
2637 break;
2638 case GL_SPOT_DIRECTION:
2639 fparam[0] = (GLfloat) params[0];
2640 fparam[1] = (GLfloat) params[1];
2641 fparam[2] = (GLfloat) params[2];
2642 break;
2643 case GL_SPOT_EXPONENT:
2644 case GL_SPOT_CUTOFF:
2645 case GL_CONSTANT_ATTENUATION:
2646 case GL_LINEAR_ATTENUATION:
2647 case GL_QUADRATIC_ATTENUATION:
2648 fparam[0] = (GLfloat) params[0];
2649 break;
2650 default:
2651 /* error will be caught later in gl_Lightfv */
2652 ;
2653 }
2654 save_Lightfv(light, pname, fparam);
2655 }
2656
2657
2658 static void GLAPIENTRY
2659 save_Lighti(GLenum light, GLenum pname, GLint param)
2660 {
2661 GLint parray[4];
2662 parray[0] = param;
2663 parray[1] = parray[2] = parray[3] = 0;
2664 save_Lightiv(light, pname, parray);
2665 }
2666
2667
2668 static void GLAPIENTRY
2669 save_LightModelfv(GLenum pname, const GLfloat *params)
2670 {
2671 GET_CURRENT_CONTEXT(ctx);
2672 Node *n;
2673 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2674 n = alloc_instruction(ctx, OPCODE_LIGHT_MODEL, 5);
2675 if (n) {
2676 n[1].e = pname;
2677 n[2].f = params[0];
2678 n[3].f = params[1];
2679 n[4].f = params[2];
2680 n[5].f = params[3];
2681 }
2682 if (ctx->ExecuteFlag) {
2683 CALL_LightModelfv(ctx->Exec, (pname, params));
2684 }
2685 }
2686
2687
2688 static void GLAPIENTRY
2689 save_LightModelf(GLenum pname, GLfloat param)
2690 {
2691 GLfloat parray[4];
2692 parray[0] = param;
2693 parray[1] = parray[2] = parray[3] = 0.0F;
2694 save_LightModelfv(pname, parray);
2695 }
2696
2697
2698 static void GLAPIENTRY
2699 save_LightModeliv(GLenum pname, const GLint *params)
2700 {
2701 GLfloat fparam[4];
2702 switch (pname) {
2703 case GL_LIGHT_MODEL_AMBIENT:
2704 fparam[0] = INT_TO_FLOAT(params[0]);
2705 fparam[1] = INT_TO_FLOAT(params[1]);
2706 fparam[2] = INT_TO_FLOAT(params[2]);
2707 fparam[3] = INT_TO_FLOAT(params[3]);
2708 break;
2709 case GL_LIGHT_MODEL_LOCAL_VIEWER:
2710 case GL_LIGHT_MODEL_TWO_SIDE:
2711 case GL_LIGHT_MODEL_COLOR_CONTROL:
2712 fparam[0] = (GLfloat) params[0];
2713 fparam[1] = 0.0F;
2714 fparam[2] = 0.0F;
2715 fparam[3] = 0.0F;
2716 break;
2717 default:
2718 /* Error will be caught later in gl_LightModelfv */
2719 ASSIGN_4V(fparam, 0.0F, 0.0F, 0.0F, 0.0F);
2720 }
2721 save_LightModelfv(pname, fparam);
2722 }
2723
2724
2725 static void GLAPIENTRY
2726 save_LightModeli(GLenum pname, GLint param)
2727 {
2728 GLint parray[4];
2729 parray[0] = param;
2730 parray[1] = parray[2] = parray[3] = 0;
2731 save_LightModeliv(pname, parray);
2732 }
2733
2734
2735 static void GLAPIENTRY
2736 save_LineStipple(GLint factor, GLushort pattern)
2737 {
2738 GET_CURRENT_CONTEXT(ctx);
2739 Node *n;
2740 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2741 n = alloc_instruction(ctx, OPCODE_LINE_STIPPLE, 2);
2742 if (n) {
2743 n[1].i = factor;
2744 n[2].us = pattern;
2745 }
2746 if (ctx->ExecuteFlag) {
2747 CALL_LineStipple(ctx->Exec, (factor, pattern));
2748 }
2749 }
2750
2751
2752 static void GLAPIENTRY
2753 save_LineWidth(GLfloat width)
2754 {
2755 GET_CURRENT_CONTEXT(ctx);
2756 Node *n;
2757 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2758 n = alloc_instruction(ctx, OPCODE_LINE_WIDTH, 1);
2759 if (n) {
2760 n[1].f = width;
2761 }
2762 if (ctx->ExecuteFlag) {
2763 CALL_LineWidth(ctx->Exec, (width));
2764 }
2765 }
2766
2767
2768 static void GLAPIENTRY
2769 save_ListBase(GLuint base)
2770 {
2771 GET_CURRENT_CONTEXT(ctx);
2772 Node *n;
2773 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2774 n = alloc_instruction(ctx, OPCODE_LIST_BASE, 1);
2775 if (n) {
2776 n[1].ui = base;
2777 }
2778 if (ctx->ExecuteFlag) {
2779 CALL_ListBase(ctx->Exec, (base));
2780 }
2781 }
2782
2783
2784 static void GLAPIENTRY
2785 save_LoadIdentity(void)
2786 {
2787 GET_CURRENT_CONTEXT(ctx);
2788 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2789 (void) alloc_instruction(ctx, OPCODE_LOAD_IDENTITY, 0);
2790 if (ctx->ExecuteFlag) {
2791 CALL_LoadIdentity(ctx->Exec, ());
2792 }
2793 }
2794
2795
2796 static void GLAPIENTRY
2797 save_LoadMatrixf(const GLfloat * m)
2798 {
2799 GET_CURRENT_CONTEXT(ctx);
2800 Node *n;
2801 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2802 n = alloc_instruction(ctx, OPCODE_LOAD_MATRIX, 16);
2803 if (n) {
2804 GLuint i;
2805 for (i = 0; i < 16; i++) {
2806 n[1 + i].f = m[i];
2807 }
2808 }
2809 if (ctx->ExecuteFlag) {
2810 CALL_LoadMatrixf(ctx->Exec, (m));
2811 }
2812 }
2813
2814
2815 static void GLAPIENTRY
2816 save_LoadMatrixd(const GLdouble * m)
2817 {
2818 GLfloat f[16];
2819 GLint i;
2820 for (i = 0; i < 16; i++) {
2821 f[i] = (GLfloat) m[i];
2822 }
2823 save_LoadMatrixf(f);
2824 }
2825
2826
2827 static void GLAPIENTRY
2828 save_LoadName(GLuint name)
2829 {
2830 GET_CURRENT_CONTEXT(ctx);
2831 Node *n;
2832 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2833 n = alloc_instruction(ctx, OPCODE_LOAD_NAME, 1);
2834 if (n) {
2835 n[1].ui = name;
2836 }
2837 if (ctx->ExecuteFlag) {
2838 CALL_LoadName(ctx->Exec, (name));
2839 }
2840 }
2841
2842
2843 static void GLAPIENTRY
2844 save_LogicOp(GLenum opcode)
2845 {
2846 GET_CURRENT_CONTEXT(ctx);
2847 Node *n;
2848 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2849 n = alloc_instruction(ctx, OPCODE_LOGIC_OP, 1);
2850 if (n) {
2851 n[1].e = opcode;
2852 }
2853 if (ctx->ExecuteFlag) {
2854 CALL_LogicOp(ctx->Exec, (opcode));
2855 }
2856 }
2857
2858
2859 static void GLAPIENTRY
2860 save_Map1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride,
2861 GLint order, const GLdouble * points)
2862 {
2863 GET_CURRENT_CONTEXT(ctx);
2864 Node *n;
2865 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2866 n = alloc_instruction(ctx, OPCODE_MAP1, 6);
2867 if (n) {
2868 GLfloat *pnts = _mesa_copy_map_points1d(target, stride, order, points);
2869 n[1].e = target;
2870 n[2].f = (GLfloat) u1;
2871 n[3].f = (GLfloat) u2;
2872 n[4].i = _mesa_evaluator_components(target); /* stride */
2873 n[5].i = order;
2874 n[6].data = (void *) pnts;
2875 }
2876 if (ctx->ExecuteFlag) {
2877 CALL_Map1d(ctx->Exec, (target, u1, u2, stride, order, points));
2878 }
2879 }
2880
2881 static void GLAPIENTRY
2882 save_Map1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride,
2883 GLint order, const GLfloat * points)
2884 {
2885 GET_CURRENT_CONTEXT(ctx);
2886 Node *n;
2887 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2888 n = alloc_instruction(ctx, OPCODE_MAP1, 6);
2889 if (n) {
2890 GLfloat *pnts = _mesa_copy_map_points1f(target, stride, order, points);
2891 n[1].e = target;
2892 n[2].f = u1;
2893 n[3].f = u2;
2894 n[4].i = _mesa_evaluator_components(target); /* stride */
2895 n[5].i = order;
2896 n[6].data = (void *) pnts;
2897 }
2898 if (ctx->ExecuteFlag) {
2899 CALL_Map1f(ctx->Exec, (target, u1, u2, stride, order, points));
2900 }
2901 }
2902
2903
2904 static void GLAPIENTRY
2905 save_Map2d(GLenum target,
2906 GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
2907 GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
2908 const GLdouble * points)
2909 {
2910 GET_CURRENT_CONTEXT(ctx);
2911 Node *n;
2912 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2913 n = alloc_instruction(ctx, OPCODE_MAP2, 10);
2914 if (n) {
2915 GLfloat *pnts = _mesa_copy_map_points2d(target, ustride, uorder,
2916 vstride, vorder, points);
2917 n[1].e = target;
2918 n[2].f = (GLfloat) u1;
2919 n[3].f = (GLfloat) u2;
2920 n[4].f = (GLfloat) v1;
2921 n[5].f = (GLfloat) v2;
2922 /* XXX verify these strides are correct */
2923 n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride */
2924 n[7].i = _mesa_evaluator_components(target); /*vstride */
2925 n[8].i = uorder;
2926 n[9].i = vorder;
2927 n[10].data = (void *) pnts;
2928 }
2929 if (ctx->ExecuteFlag) {
2930 CALL_Map2d(ctx->Exec, (target,
2931 u1, u2, ustride, uorder,
2932 v1, v2, vstride, vorder, points));
2933 }
2934 }
2935
2936
2937 static void GLAPIENTRY
2938 save_Map2f(GLenum target,
2939 GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
2940 GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
2941 const GLfloat * points)
2942 {
2943 GET_CURRENT_CONTEXT(ctx);
2944 Node *n;
2945 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2946 n = alloc_instruction(ctx, OPCODE_MAP2, 10);
2947 if (n) {
2948 GLfloat *pnts = _mesa_copy_map_points2f(target, ustride, uorder,
2949 vstride, vorder, points);
2950 n[1].e = target;
2951 n[2].f = u1;
2952 n[3].f = u2;
2953 n[4].f = v1;
2954 n[5].f = v2;
2955 /* XXX verify these strides are correct */
2956 n[6].i = _mesa_evaluator_components(target) * vorder; /*ustride */
2957 n[7].i = _mesa_evaluator_components(target); /*vstride */
2958 n[8].i = uorder;
2959 n[9].i = vorder;
2960 n[10].data = (void *) pnts;
2961 }
2962 if (ctx->ExecuteFlag) {
2963 CALL_Map2f(ctx->Exec, (target, u1, u2, ustride, uorder,
2964 v1, v2, vstride, vorder, points));
2965 }
2966 }
2967
2968
2969 static void GLAPIENTRY
2970 save_MapGrid1f(GLint un, GLfloat u1, GLfloat u2)
2971 {
2972 GET_CURRENT_CONTEXT(ctx);
2973 Node *n;
2974 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
2975 n = alloc_instruction(ctx, OPCODE_MAPGRID1, 3);
2976 if (n) {
2977 n[1].i = un;
2978 n[2].f = u1;
2979 n[3].f = u2;
2980 }
2981 if (ctx->ExecuteFlag) {
2982 CALL_MapGrid1f(ctx->Exec, (un, u1, u2));
2983 }
2984 }
2985
2986
2987 static void GLAPIENTRY
2988 save_MapGrid1d(GLint un, GLdouble u1, GLdouble u2)
2989 {
2990 save_MapGrid1f(un, (GLfloat) u1, (GLfloat) u2);
2991 }
2992
2993
2994 static void GLAPIENTRY
2995 save_MapGrid2f(GLint un, GLfloat u1, GLfloat u2,
2996 GLint vn, GLfloat v1, GLfloat v2)
2997 {
2998 GET_CURRENT_CONTEXT(ctx);
2999 Node *n;
3000 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3001 n = alloc_instruction(ctx, OPCODE_MAPGRID2, 6);
3002 if (n) {
3003 n[1].i = un;
3004 n[2].f = u1;
3005 n[3].f = u2;
3006 n[4].i = vn;
3007 n[5].f = v1;
3008 n[6].f = v2;
3009 }
3010 if (ctx->ExecuteFlag) {
3011 CALL_MapGrid2f(ctx->Exec, (un, u1, u2, vn, v1, v2));
3012 }
3013 }
3014
3015
3016
3017 static void GLAPIENTRY
3018 save_MapGrid2d(GLint un, GLdouble u1, GLdouble u2,
3019 GLint vn, GLdouble v1, GLdouble v2)
3020 {
3021 save_MapGrid2f(un, (GLfloat) u1, (GLfloat) u2,
3022 vn, (GLfloat) v1, (GLfloat) v2);
3023 }
3024
3025
3026 static void GLAPIENTRY
3027 save_MatrixMode(GLenum mode)
3028 {
3029 GET_CURRENT_CONTEXT(ctx);
3030 Node *n;
3031 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3032 n = alloc_instruction(ctx, OPCODE_MATRIX_MODE, 1);
3033 if (n) {
3034 n[1].e = mode;
3035 }
3036 if (ctx->ExecuteFlag) {
3037 CALL_MatrixMode(ctx->Exec, (mode));
3038 }
3039 }
3040
3041
3042 static void GLAPIENTRY
3043 save_Minmax(GLenum target, GLenum internalFormat, GLboolean sink)
3044 {
3045 GET_CURRENT_CONTEXT(ctx);
3046 Node *n;
3047
3048 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3049 n = alloc_instruction(ctx, OPCODE_MIN_MAX, 3);
3050 if (n) {
3051 n[1].e = target;
3052 n[2].e = internalFormat;
3053 n[3].b = sink;
3054 }
3055 if (ctx->ExecuteFlag) {
3056 CALL_Minmax(ctx->Exec, (target, internalFormat, sink));
3057 }
3058 }
3059
3060
3061 static void GLAPIENTRY
3062 save_MultMatrixf(const GLfloat * m)
3063 {
3064 GET_CURRENT_CONTEXT(ctx);
3065 Node *n;
3066 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3067 n = alloc_instruction(ctx, OPCODE_MULT_MATRIX, 16);
3068 if (n) {
3069 GLuint i;
3070 for (i = 0; i < 16; i++) {
3071 n[1 + i].f = m[i];
3072 }
3073 }
3074 if (ctx->ExecuteFlag) {
3075 CALL_MultMatrixf(ctx->Exec, (m));
3076 }
3077 }
3078
3079
3080 static void GLAPIENTRY
3081 save_MultMatrixd(const GLdouble * m)
3082 {
3083 GLfloat f[16];
3084 GLint i;
3085 for (i = 0; i < 16; i++) {
3086 f[i] = (GLfloat) m[i];
3087 }
3088 save_MultMatrixf(f);
3089 }
3090
3091
3092 static void GLAPIENTRY
3093 save_NewList(GLuint name, GLenum mode)
3094 {
3095 GET_CURRENT_CONTEXT(ctx);
3096 /* It's an error to call this function while building a display list */
3097 _mesa_error(ctx, GL_INVALID_OPERATION, "glNewList");
3098 (void) name;
3099 (void) mode;
3100 }
3101
3102
3103
3104 static void GLAPIENTRY
3105 save_Ortho(GLdouble left, GLdouble right,
3106 GLdouble bottom, GLdouble top, GLdouble nearval, GLdouble farval)
3107 {
3108 GET_CURRENT_CONTEXT(ctx);
3109 Node *n;
3110 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3111 n = alloc_instruction(ctx, OPCODE_ORTHO, 6);
3112 if (n) {
3113 n[1].f = (GLfloat) left;
3114 n[2].f = (GLfloat) right;
3115 n[3].f = (GLfloat) bottom;
3116 n[4].f = (GLfloat) top;
3117 n[5].f = (GLfloat) nearval;
3118 n[6].f = (GLfloat) farval;
3119 }
3120 if (ctx->ExecuteFlag) {
3121 CALL_Ortho(ctx->Exec, (left, right, bottom, top, nearval, farval));
3122 }
3123 }
3124
3125
3126 static void GLAPIENTRY
3127 save_PixelMapfv(GLenum map, GLint mapsize, const GLfloat *values)
3128 {
3129 GET_CURRENT_CONTEXT(ctx);
3130 Node *n;
3131 ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
3132 n = alloc_instruction(ctx, OPCODE_PIXEL_MAP, 3);
3133 if (n) {
3134 n[1].e = map;
3135 n[2].i = mapsize;
3136 n[3].data = (void *) malloc(mapsize * sizeof(GLfloat));
3137 memcpy(n[3<