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