Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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@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.