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