1 /* 2 * Mesa 3-D graphics library 3 * Version: 6.5.1 4 * 5 * Copyright (C) 1999-2006 Brian Paul 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Keith Whitwell <keith (at) tungstengraphics.com> 26 */ 27 28 29 /** 30 * \file t_dd_dmatmp2.h 31 * Template for render stages which build and emit vertices directly 32 * to fixed-size dma buffers. Useful for rendering strips and other 33 * native primitives where clipping and per-vertex tweaks such as 34 * those in t_dd_tritmp.h are not required. 35 * 36 */ 37 38 #if !HAVE_TRIANGLES || !HAVE_POINTS || !HAVE_LINES 39 #error "must have points, lines & triangles to use render template" 40 #endif 41 42 #if !HAVE_TRI_STRIPS || !HAVE_TRI_FANS 43 #error "must have tri strip and fans to use render template" 44 #endif 45 46 #if !HAVE_LINE_STRIPS 47 #error "must have line strips to use render template" 48 #endif 49 50 #if !HAVE_POLYGONS 51 #error "must have polygons to use render template" 52 #endif 53 54 #if !HAVE_ELTS 55 #error "must have elts to use render template" 56 #endif 57 58 59 #ifndef EMIT_TWO_ELTS 60 #define EMIT_TWO_ELTS( dest, offset, elt0, elt1 ) \ 61 do { \ 62 (dest)[offset] = (elt0); \ 63 (dest)[offset+1] = (elt1); \ 64 } while (0) 65 #endif 66 67 68 /**********************************************************************/ 69 /* Render whole begin/end objects */ 70 /**********************************************************************/ 71 72 73 static ELT_TYPE *TAG(emit_elts)( struct gl_context *ctx, 74 ELT_TYPE *dest, 75 GLuint *elts, GLuint nr ) 76 { 77 GLint i; 78 LOCAL_VARS; 79 80 for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) { 81 EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); 82 dest += 2; 83 } 84 if (i < nr) { 85 EMIT_ELT( dest, 0, elts[0] ); 86 dest += 1; 87 } 88 89 return dest; 90 } 91 92 static ELT_TYPE *TAG(emit_consecutive_elts)( struct gl_context *ctx, 93 ELT_TYPE *dest, 94 GLuint start, GLuint nr ) 95 { 96 GLint i; 97 LOCAL_VARS; 98 99 for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) { 100 EMIT_TWO_ELTS( dest, 0, start, start+1 ); 101 dest += 2; 102 } 103 if (i < nr) { 104 EMIT_ELT( dest, 0, start ); 105 dest += 1; 106 } 107 108 return dest; 109 } 110 111 /*********************************************************************** 112 * Render non-indexed primitives. 113 ***********************************************************************/ 114 115 116 117 static void TAG(render_points_verts)( struct gl_context *ctx, 118 GLuint start, 119 GLuint count, 120 GLuint flags ) 121 { 122 if (start < count) { 123 LOCAL_VARS; 124 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 125 EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count ); 126 } 127 } 128 129 static void TAG(render_lines_verts)( struct gl_context *ctx, 130 GLuint start, 131 GLuint count, 132 GLuint flags ) 133 { 134 LOCAL_VARS; 135 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 136 count -= (count-start) & 1; 137 138 if (start+1 >= count) 139 return; 140 141 if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) { 142 RESET_STIPPLE(); 143 AUTO_STIPPLE( GL_TRUE ); 144 } 145 146 EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count ); 147 148 if ((flags & PRIM_END) && ctx->Line.StippleFlag) 149 AUTO_STIPPLE( GL_FALSE ); 150 } 151 152 153 static void TAG(render_line_strip_verts)( struct gl_context *ctx, 154 GLuint start, 155 GLuint count, 156 GLuint flags ) 157 { 158 LOCAL_VARS; 159 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 160 161 if (start+1 >= count) 162 return; 163 164 if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) 165 RESET_STIPPLE(); 166 167 168 if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) 169 { 170 int dmasz = GET_MAX_HW_ELTS(); 171 GLuint j, nr; 172 173 ELT_INIT( GL_LINES, HW_LINES ); 174 175 /* Emit whole number of lines in each full buffer. 176 */ 177 dmasz = dmasz/2; 178 179 180 for (j = start; j + 1 < count; j += nr - 1 ) { 181 ELT_TYPE *dest; 182 GLint i; 183 184 nr = MIN2( dmasz, count - j ); 185 dest = ALLOC_ELTS( (nr-1)*2 ); 186 187 for ( i = j ; i+1 < j+nr ; i+=1 ) { 188 EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); 189 dest += 2; 190 } 191 192 CLOSE_ELTS(); 193 } 194 } 195 else 196 EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count ); 197 } 198 199 200 static void TAG(render_line_loop_verts)( struct gl_context *ctx, 201 GLuint start, 202 GLuint count, 203 GLuint flags ) 204 { 205 LOCAL_VARS; 206 GLuint j, nr; 207 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 208 209 if (flags & PRIM_BEGIN) { 210 j = start; 211 if (ctx->Line.StippleFlag) 212 RESET_STIPPLE( ); 213 } 214 else 215 j = start + 1; 216 217 if (flags & PRIM_END) { 218 219 if (start+1 >= count) 220 return; 221 222 if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) { 223 int dmasz = GET_MAX_HW_ELTS(); 224 225 ELT_INIT( GL_LINES, HW_LINES ); 226 227 /* Emit whole number of lines in each full buffer. 228 */ 229 dmasz = dmasz/2; 230 231 /* Ensure last vertex doesn't wrap: 232 */ 233 dmasz--; 234 235 for (; j + 1 < count; ) { 236 GLint i; 237 ELT_TYPE *dest; 238 239 nr = MIN2( dmasz, count - j ); 240 dest = ALLOC_ELTS( nr*2 ); /* allocs room for 1 more line */ 241 242 for ( i = 0 ; i < nr - 1 ; i+=1 ) { 243 EMIT_TWO_ELTS( dest, 0, (j+i), (j+i+1) ); 244 dest += 2; 245 } 246 247 j += nr - 1; 248 249 /* Emit 1 more line into space alloced above */ 250 if (j + 1 >= count) { 251 EMIT_TWO_ELTS( dest, 0, (j), (start) ); 252 dest += 2; 253 } 254 255 CLOSE_ELTS(); 256 } 257 } 258 else 259 { 260 int dmasz = GET_MAX_HW_ELTS() - 1; 261 262 ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); 263 264 for ( ; j + 1 < count; ) { 265 nr = MIN2( dmasz, count - j ); 266 if (j + nr < count) { 267 ELT_TYPE *dest = ALLOC_ELTS( nr ); 268 dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr ); 269 (void) dest; 270 j += nr - 1; 271 CLOSE_ELTS(); 272 } 273 else if (nr) { 274 ELT_TYPE *dest = ALLOC_ELTS( nr + 1 ); 275 dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr ); 276 dest = TAG(emit_consecutive_elts)( ctx, dest, start, 1 ); 277 (void) dest; 278 j += nr; 279 CLOSE_ELTS(); 280 } 281 } 282 } 283 } else { 284 TAG(render_line_strip_verts)( ctx, j, count, flags ); 285 } 286 } 287 288 289 static void TAG(render_triangles_verts)( struct gl_context *ctx, 290 GLuint start, 291 GLuint count, 292 GLuint flags ) 293 { 294 LOCAL_VARS; 295 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 296 297 count -= (count-start)%3; 298 299 if (start+2 >= count) { 300 return; 301 } 302 303 /* need a PREFER_DISCRETE_ELT_PRIM here too.. 304 */ 305 EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count ); 306 } 307 308 309 310 static void TAG(render_tri_strip_verts)( struct gl_context *ctx, 311 GLuint start, 312 GLuint count, 313 GLuint flags ) 314 { 315 LOCAL_VARS; 316 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 317 318 if (start + 2 >= count) 319 return; 320 321 if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES )) 322 { 323 int dmasz = GET_MAX_HW_ELTS(); 324 int parity = 0; 325 GLuint j, nr; 326 327 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 328 329 /* Emit even number of tris in each full buffer. 330 */ 331 dmasz = dmasz/3; 332 dmasz -= dmasz & 1; 333 334 for (j = start; j + 2 < count; j += nr - 2 ) { 335 ELT_TYPE *dest; 336 GLint i; 337 338 nr = MIN2( dmasz, count - j ); 339 dest = ALLOC_ELTS( (nr-2)*3 ); 340 341 for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) { 342 EMIT_ELT( dest, 0, (i+0+parity) ); 343 EMIT_ELT( dest, 1, (i+1-parity) ); 344 EMIT_ELT( dest, 2, (i+2) ); 345 dest += 3; 346 } 347 348 CLOSE_ELTS(); 349 } 350 } 351 else 352 EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count ); 353 } 354 355 static void TAG(render_tri_fan_verts)( struct gl_context *ctx, 356 GLuint start, 357 GLuint count, 358 GLuint flags ) 359 { 360 LOCAL_VARS; 361 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 362 363 if (start+2 >= count) 364 return; 365 366 if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES )) 367 { 368 int dmasz = GET_MAX_HW_ELTS(); 369 GLuint j, nr; 370 371 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 372 373 dmasz = dmasz/3; 374 375 for (j = start + 1; j + 1 < count; j += nr - 1 ) { 376 ELT_TYPE *dest; 377 GLint i; 378 379 nr = MIN2( dmasz, count - j ); 380 dest = ALLOC_ELTS( (nr-1)*3 ); 381 382 for ( i = j ; i+1 < j+nr ; i++ ) { 383 EMIT_ELT( dest, 0, (start) ); 384 EMIT_ELT( dest, 1, (i) ); 385 EMIT_ELT( dest, 2, (i+1) ); 386 dest += 3; 387 } 388 389 CLOSE_ELTS(); 390 } 391 } 392 else { 393 EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count ); 394 } 395 } 396 397 398 static void TAG(render_poly_verts)( struct gl_context *ctx, 399 GLuint start, 400 GLuint count, 401 GLuint flags ) 402 { 403 LOCAL_VARS; 404 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 405 406 if (start+2 >= count) 407 return; 408 409 EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count ); 410 } 411 412 static void TAG(render_quad_strip_verts)( struct gl_context *ctx, 413 GLuint start, 414 GLuint count, 415 GLuint flags ) 416 { 417 LOCAL_VARS; 418 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 419 420 count -= (count-start) & 1; 421 422 if (start+3 >= count) 423 return; 424 425 if (HAVE_QUAD_STRIPS) { 426 EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count ); 427 } 428 else if (ctx->Light.ShadeModel == GL_FLAT) { 429 LOCAL_VARS; 430 int dmasz = GET_MAX_HW_ELTS(); 431 GLuint j, nr; 432 433 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 434 435 /* Emit whole number of quads in total, and in each buffer. 436 */ 437 dmasz = (dmasz/6)*2; 438 439 for (j = start; j + 3 < count; j += nr - 2 ) { 440 ELT_TYPE *dest; 441 GLint quads, i; 442 443 nr = MIN2( dmasz, count - j ); 444 quads = (nr/2)-1; 445 dest = ALLOC_ELTS( quads*6 ); 446 447 for ( i = j ; i < j+quads*2 ; i+=2 ) { 448 EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); 449 EMIT_TWO_ELTS( dest, 2, (i+2), (i+1) ); 450 EMIT_TWO_ELTS( dest, 4, (i+3), (i+2) ); 451 dest += 6; 452 } 453 454 CLOSE_ELTS(); 455 } 456 } 457 else { 458 EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count ); 459 } 460 } 461 462 463 static void TAG(render_quads_verts)( struct gl_context *ctx, 464 GLuint start, 465 GLuint count, 466 GLuint flags ) 467 { 468 LOCAL_VARS; 469 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 470 count -= (count-start)%4; 471 472 if (start+3 >= count) 473 return; 474 475 if (HAVE_QUADS) { 476 EMIT_PRIM( ctx, GL_QUADS, HW_QUADS, start, count ); 477 } 478 else { 479 /* Hardware doesn't have a quad primitive type -- simulate it 480 * using indexed vertices and the triangle primitive: 481 */ 482 LOCAL_VARS; 483 int dmasz = GET_MAX_HW_ELTS(); 484 GLuint j, nr; 485 486 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 487 488 /* Adjust for rendering as triangles: 489 */ 490 dmasz = (dmasz/6)*4; 491 492 for (j = start; j < count; j += nr ) { 493 ELT_TYPE *dest; 494 GLint quads, i; 495 496 nr = MIN2( dmasz, count - j ); 497 quads = nr/4; 498 dest = ALLOC_ELTS( quads*6 ); 499 500 for ( i = j ; i < j+quads*4 ; i+=4 ) { 501 EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); 502 EMIT_TWO_ELTS( dest, 2, (i+3), (i+1) ); 503 EMIT_TWO_ELTS( dest, 4, (i+2), (i+3) ); 504 dest += 6; 505 } 506 507 CLOSE_ELTS(); 508 } 509 } 510 } 511 512 static void TAG(render_noop)( struct gl_context *ctx, 513 GLuint start, 514 GLuint count, 515 GLuint flags ) 516 { 517 } 518 519 520 521 522 static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] = 523 { 524 TAG(render_points_verts), 525 TAG(render_lines_verts), 526 TAG(render_line_loop_verts), 527 TAG(render_line_strip_verts), 528 TAG(render_triangles_verts), 529 TAG(render_tri_strip_verts), 530 TAG(render_tri_fan_verts), 531 TAG(render_quads_verts), 532 TAG(render_quad_strip_verts), 533 TAG(render_poly_verts), 534 TAG(render_noop), 535 }; 536 537 538 /**************************************************************************** 539 * Render elts using hardware indexed verts * 540 ****************************************************************************/ 541 542 static void TAG(render_points_elts)( struct gl_context *ctx, 543 GLuint start, 544 GLuint count, 545 GLuint flags ) 546 { 547 LOCAL_VARS; 548 int dmasz = GET_MAX_HW_ELTS(); 549 GLuint *elts = GET_MESA_ELTS(); 550 GLuint j, nr; 551 ELT_TYPE *dest; 552 553 ELT_INIT( GL_POINTS, HW_POINTS ); 554 555 for (j = start; j < count; j += nr ) { 556 nr = MIN2( dmasz, count - j ); 557 dest = ALLOC_ELTS( nr ); 558 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 559 (void) dest; 560 CLOSE_ELTS(); 561 } 562 } 563 564 565 566 static void TAG(render_lines_elts)( struct gl_context *ctx, 567 GLuint start, 568 GLuint count, 569 GLuint flags ) 570 { 571 LOCAL_VARS; 572 int dmasz = GET_MAX_HW_ELTS(); 573 GLuint *elts = GET_MESA_ELTS(); 574 GLuint j, nr; 575 ELT_TYPE *dest; 576 577 if (start+1 >= count) 578 return; 579 580 if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) { 581 RESET_STIPPLE(); 582 AUTO_STIPPLE( GL_TRUE ); 583 } 584 585 ELT_INIT( GL_LINES, HW_LINES ); 586 587 /* Emit whole number of lines in total and in each buffer: 588 */ 589 count -= (count-start) & 1; 590 dmasz -= dmasz & 1; 591 592 for (j = start; j < count; j += nr ) { 593 nr = MIN2( dmasz, count - j ); 594 dest = ALLOC_ELTS( nr ); 595 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 596 (void) dest; 597 CLOSE_ELTS(); 598 } 599 600 if ((flags & PRIM_END) && ctx->Line.StippleFlag) 601 AUTO_STIPPLE( GL_FALSE ); 602 } 603 604 605 static void TAG(render_line_strip_elts)( struct gl_context *ctx, 606 GLuint start, 607 GLuint count, 608 GLuint flags ) 609 { 610 LOCAL_VARS; 611 int dmasz = GET_MAX_HW_ELTS(); 612 GLuint *elts = GET_MESA_ELTS(); 613 GLuint j, nr; 614 ELT_TYPE *dest; 615 616 if (start+1 >= count) 617 return; 618 619 ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); 620 621 if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) 622 RESET_STIPPLE(); 623 624 for (j = start; j + 1 < count; j += nr - 1 ) { 625 nr = MIN2( dmasz, count - j ); 626 dest = ALLOC_ELTS( nr ); 627 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 628 (void) dest; 629 CLOSE_ELTS(); 630 } 631 } 632 633 634 static void TAG(render_line_loop_elts)( struct gl_context *ctx, 635 GLuint start, 636 GLuint count, 637 GLuint flags ) 638 { 639 LOCAL_VARS; 640 int dmasz = GET_MAX_HW_ELTS(); 641 GLuint *elts = GET_MESA_ELTS(); 642 GLuint j, nr; 643 ELT_TYPE *dest; 644 645 if (0) fprintf(stderr, "%s\n", __FUNCTION__); 646 647 if (flags & PRIM_BEGIN) 648 j = start; 649 else 650 j = start + 1; 651 652 653 if (flags & PRIM_END) { 654 if (start+1 >= count) 655 return; 656 } 657 else { 658 if (j+1 >= count) 659 return; 660 } 661 662 ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); 663 664 if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) 665 RESET_STIPPLE(); 666 667 668 /* Ensure last vertex doesn't wrap: 669 */ 670 dmasz--; 671 672 for ( ; j + 1 < count; ) { 673 nr = MIN2( dmasz, count - j ); 674 dest = ALLOC_ELTS( nr+1 ); /* Reserve possible space for last elt */ 675 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 676 j += nr - 1; 677 if (j + 1 >= count && (flags & PRIM_END)) { 678 dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); 679 (void) dest; 680 } 681 CLOSE_ELTS(); 682 } 683 } 684 685 686 static void TAG(render_triangles_elts)( struct gl_context *ctx, 687 GLuint start, 688 GLuint count, 689 GLuint flags ) 690 { 691 LOCAL_VARS; 692 GLuint *elts = GET_MESA_ELTS(); 693 int dmasz = GET_MAX_HW_ELTS()/3*3; 694 GLuint j, nr; 695 ELT_TYPE *dest; 696 697 if (start+2 >= count) 698 return; 699 700 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 701 702 703 /* Emit whole number of tris in total. dmasz is already a multiple 704 * of 3. 705 */ 706 count -= (count-start)%3; 707 708 for (j = start; j < count; j += nr) { 709 nr = MIN2( dmasz, count - j ); 710 dest = ALLOC_ELTS( nr ); 711 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 712 (void) dest; 713 CLOSE_ELTS(); 714 } 715 } 716 717 718 719 static void TAG(render_tri_strip_elts)( struct gl_context *ctx, 720 GLuint start, 721 GLuint count, 722 GLuint flags ) 723 { 724 LOCAL_VARS; 725 GLuint j, nr; 726 GLuint *elts = GET_MESA_ELTS(); 727 int dmasz = GET_MAX_HW_ELTS(); 728 ELT_TYPE *dest; 729 730 if (start+2 >= count) 731 return; 732 733 ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 ); 734 735 /* Keep the same winding over multiple buffers: 736 */ 737 dmasz -= (dmasz & 1); 738 739 for (j = start ; j + 2 < count; j += nr - 2 ) { 740 nr = MIN2( dmasz, count - j ); 741 742 dest = ALLOC_ELTS( nr ); 743 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 744 (void) dest; 745 CLOSE_ELTS(); 746 } 747 } 748 749 static void TAG(render_tri_fan_elts)( struct gl_context *ctx, 750 GLuint start, 751 GLuint count, 752 GLuint flags ) 753 { 754 LOCAL_VARS; 755 GLuint *elts = GET_MESA_ELTS(); 756 GLuint j, nr; 757 int dmasz = GET_MAX_HW_ELTS(); 758 ELT_TYPE *dest; 759 760 if (start+2 >= count) 761 return; 762 763 ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN ); 764 765 for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { 766 nr = MIN2( dmasz, count - j + 1 ); 767 dest = ALLOC_ELTS( nr ); 768 dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); 769 dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 ); 770 (void) dest; 771 CLOSE_ELTS(); 772 } 773 } 774 775 776 static void TAG(render_poly_elts)( struct gl_context *ctx, 777 GLuint start, 778 GLuint count, 779 GLuint flags ) 780 { 781 LOCAL_VARS; 782 GLuint *elts = GET_MESA_ELTS(); 783 GLuint j, nr; 784 int dmasz = GET_MAX_HW_ELTS(); 785 ELT_TYPE *dest; 786 787 if (start+2 >= count) 788 return; 789 790 ELT_INIT( GL_POLYGON, HW_POLYGON ); 791 792 for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { 793 nr = MIN2( dmasz, count - j + 1 ); 794 dest = ALLOC_ELTS( nr ); 795 dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); 796 dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 ); 797 (void) dest; 798 CLOSE_ELTS(); 799 } 800 } 801 802 static void TAG(render_quad_strip_elts)( struct gl_context *ctx, 803 GLuint start, 804 GLuint count, 805 GLuint flags ) 806 { 807 if (start+3 >= count) 808 return; 809 810 if (HAVE_QUAD_STRIPS && 0) { 811 } 812 else { 813 LOCAL_VARS; 814 GLuint *elts = GET_MESA_ELTS(); 815 int dmasz = GET_MAX_HW_ELTS(); 816 GLuint j, nr; 817 ELT_TYPE *dest; 818 819 /* Emit whole number of quads in total, and in each buffer. 820 */ 821 dmasz -= dmasz & 1; 822 count -= (count-start) & 1; 823 824 if (ctx->Light.ShadeModel == GL_FLAT) { 825 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 826 827 dmasz = dmasz/6*2; 828 829 for (j = start; j + 3 < count; j += nr - 2 ) { 830 nr = MIN2( dmasz, count - j ); 831 832 if (nr >= 4) 833 { 834 GLint quads = (nr/2)-1; 835 ELT_TYPE *dest = ALLOC_ELTS( quads*6 ); 836 GLint i; 837 838 for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) { 839 EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); 840 EMIT_TWO_ELTS( dest, 2, elts[2], elts[1] ); 841 EMIT_TWO_ELTS( dest, 4, elts[3], elts[2] ); 842 dest += 6; 843 } 844 845 CLOSE_ELTS(); 846 } 847 } 848 } 849 else { 850 ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 ); 851 852 for (j = start; j + 3 < count; j += nr - 2 ) { 853 nr = MIN2( dmasz, count - j ); 854 dest = ALLOC_ELTS( nr ); 855 dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); 856 (void) dest; 857 CLOSE_ELTS(); 858 } 859 } 860 } 861 } 862 863 864 static void TAG(render_quads_elts)( struct gl_context *ctx, 865 GLuint start, 866 GLuint count, 867 GLuint flags ) 868 { 869 if (start+3 >= count) 870 return; 871 872 if (HAVE_QUADS && 0) { 873 } else { 874 LOCAL_VARS; 875 GLuint *elts = GET_MESA_ELTS(); 876 int dmasz = GET_MAX_HW_ELTS(); 877 GLuint j, nr; 878 879 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); 880 881 /* Emit whole number of quads in total, and in each buffer. 882 */ 883 dmasz -= dmasz & 3; 884 count -= (count-start) & 3; 885 886 /* Adjust for rendering as triangles: 887 */ 888 dmasz = dmasz/6*4; 889 890 for (j = start; j + 3 < count; j += nr ) { 891 nr = MIN2( dmasz, count - j ); 892 893 { 894 GLint quads = nr/4; 895 ELT_TYPE *dest = ALLOC_ELTS( quads * 6 ); 896 GLint i; 897 898 for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) { 899 EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); 900 EMIT_TWO_ELTS( dest, 2, elts[3], elts[1] ); 901 EMIT_TWO_ELTS( dest, 4, elts[2], elts[3] ); 902 dest += 6; 903 } 904 905 CLOSE_ELTS(); 906 } 907 } 908 } 909 } 910 911 912 913 static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] = 914 { 915 TAG(render_points_elts), 916 TAG(render_lines_elts), 917 TAG(render_line_loop_elts), 918 TAG(render_line_strip_elts), 919 TAG(render_triangles_elts), 920 TAG(render_tri_strip_elts), 921 TAG(render_tri_fan_elts), 922 TAG(render_quads_elts), 923 TAG(render_quad_strip_elts), 924 TAG(render_poly_elts), 925 TAG(render_noop), 926 }; 927