17117f1b4Smrg/*
27117f1b4Smrg * Mesa 3-D graphics library
37117f1b4Smrg *
47117f1b4Smrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
57117f1b4Smrg *
67117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77117f1b4Smrg * copy of this software and associated documentation files (the "Software"),
87117f1b4Smrg * to deal in the Software without restriction, including without limitation
97117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the
117117f1b4Smrg * Software is furnished to do so, subject to the following conditions:
127117f1b4Smrg *
137117f1b4Smrg * The above copyright notice and this permission notice shall be included
147117f1b4Smrg * in all copies or substantial portions of the Software.
157117f1b4Smrg *
167117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
177117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE.
237117f1b4Smrg *
247117f1b4Smrg * Authors:
25af69d88dSmrg *    Keith Whitwell <keithw@vmware.com>
267117f1b4Smrg */
277117f1b4Smrg
287117f1b4Smrg
297117f1b4Smrg#ifndef POSTFIX
307117f1b4Smrg#define POSTFIX
317117f1b4Smrg#endif
327117f1b4Smrg
337117f1b4Smrg#ifndef INIT
347117f1b4Smrg#define INIT(x)
357117f1b4Smrg#endif
367117f1b4Smrg
377117f1b4Smrg#ifndef NEED_EDGEFLAG_SETUP
387117f1b4Smrg#define NEED_EDGEFLAG_SETUP 0
397117f1b4Smrg#define EDGEFLAG_GET(a) 0
407117f1b4Smrg#define EDGEFLAG_SET(a,b) (void)b
417117f1b4Smrg#endif
427117f1b4Smrg
437117f1b4Smrg#ifndef RESET_STIPPLE
447117f1b4Smrg#define RESET_STIPPLE
457117f1b4Smrg#endif
467117f1b4Smrg
477117f1b4Smrg#ifndef TEST_PRIM_END
487117f1b4Smrg#define TEST_PRIM_END(prim) (flags & PRIM_END)
497117f1b4Smrg#define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN)
507117f1b4Smrg#endif
517117f1b4Smrg
527117f1b4Smrg#ifndef ELT
537117f1b4Smrg#define ELT(x) x
547117f1b4Smrg#endif
557117f1b4Smrg
567117f1b4Smrg#ifndef RENDER_TAB_QUALIFIER
577117f1b4Smrg#define RENDER_TAB_QUALIFIER static
587117f1b4Smrg#endif
597117f1b4Smrg
603464ebd5Sriastradhstatic void TAG(render_points)( struct gl_context *ctx,
617117f1b4Smrg				GLuint start,
627117f1b4Smrg				GLuint count,
637117f1b4Smrg				GLuint flags )
647117f1b4Smrg{
657117f1b4Smrg   LOCAL_VARS;
667117f1b4Smrg   (void) flags;
677117f1b4Smrg
687117f1b4Smrg   INIT(GL_POINTS);
697117f1b4Smrg   RENDER_POINTS( start, count );
707117f1b4Smrg   POSTFIX;
717117f1b4Smrg}
727117f1b4Smrg
733464ebd5Sriastradhstatic void TAG(render_lines)( struct gl_context *ctx,
747117f1b4Smrg			       GLuint start,
757117f1b4Smrg			       GLuint count,
767117f1b4Smrg			       GLuint flags )
777117f1b4Smrg{
787117f1b4Smrg   GLuint j;
797117f1b4Smrg   LOCAL_VARS;
807117f1b4Smrg   (void) flags;
817117f1b4Smrg
827117f1b4Smrg   INIT(GL_LINES);
837117f1b4Smrg   for (j=start+1; j<count; j+=2 ) {
847117f1b4Smrg      RESET_STIPPLE;
854a49301eSmrg      if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
864a49301eSmrg         RENDER_LINE( ELT(j-1), ELT(j) );
874a49301eSmrg      else
884a49301eSmrg         RENDER_LINE( ELT(j), ELT(j-1) );
897117f1b4Smrg   }
907117f1b4Smrg   POSTFIX;
917117f1b4Smrg}
927117f1b4Smrg
937117f1b4Smrg
943464ebd5Sriastradhstatic void TAG(render_line_strip)( struct gl_context *ctx,
957117f1b4Smrg				    GLuint start,
967117f1b4Smrg				    GLuint count,
977117f1b4Smrg				    GLuint flags )
987117f1b4Smrg{
997117f1b4Smrg   GLuint j;
1007117f1b4Smrg   LOCAL_VARS;
1017117f1b4Smrg   (void) flags;
1027117f1b4Smrg
1037117f1b4Smrg   INIT(GL_LINE_STRIP);
1047117f1b4Smrg
1057117f1b4Smrg   if (TEST_PRIM_BEGIN(flags)) {
1067117f1b4Smrg      RESET_STIPPLE;
1077117f1b4Smrg   }
1087117f1b4Smrg
1094a49301eSmrg   for (j=start+1; j<count; j++ ) {
1104a49301eSmrg      if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1114a49301eSmrg         RENDER_LINE( ELT(j-1), ELT(j) );
1124a49301eSmrg      else
1134a49301eSmrg         RENDER_LINE( ELT(j), ELT(j-1) );
1144a49301eSmrg   }
1157117f1b4Smrg   POSTFIX;
1167117f1b4Smrg}
1177117f1b4Smrg
1187117f1b4Smrg
1193464ebd5Sriastradhstatic void TAG(render_line_loop)( struct gl_context *ctx,
1207117f1b4Smrg				   GLuint start,
1217117f1b4Smrg				   GLuint count,
1227117f1b4Smrg				   GLuint flags )
1237117f1b4Smrg{
1247117f1b4Smrg   GLuint i;
1257117f1b4Smrg   LOCAL_VARS;
1267117f1b4Smrg
1277117f1b4Smrg   INIT(GL_LINE_LOOP);
1287117f1b4Smrg
1297117f1b4Smrg   if (start+1 < count) {
1307117f1b4Smrg      if (TEST_PRIM_BEGIN(flags)) {
1317117f1b4Smrg	 RESET_STIPPLE;
13201e04c3fSmrg         /* draw the first line from v[0] to v[1] */
1334a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1344a49301eSmrg            RENDER_LINE( ELT(start), ELT(start+1) );
1354a49301eSmrg         else
1364a49301eSmrg            RENDER_LINE( ELT(start+1), ELT(start) );
1377117f1b4Smrg      }
1387117f1b4Smrg
13901e04c3fSmrg      /* draw lines from v[1] to v[n-1] */
1407117f1b4Smrg      for ( i = start+2 ; i < count ; i++) {
1414a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1424a49301eSmrg            RENDER_LINE( ELT(i-1), ELT(i) );
1434a49301eSmrg         else
1444a49301eSmrg            RENDER_LINE( ELT(i), ELT(i-1) );
1457117f1b4Smrg      }
1467117f1b4Smrg
1477117f1b4Smrg      if ( TEST_PRIM_END(flags)) {
14801e04c3fSmrg         /* draw final line from v[n-1] to v[0] (the very first vertex) */
1494a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1504a49301eSmrg            RENDER_LINE( ELT(count-1), ELT(start) );
1514a49301eSmrg         else
1524a49301eSmrg            RENDER_LINE( ELT(start), ELT(count-1) );
1537117f1b4Smrg      }
1547117f1b4Smrg   }
1557117f1b4Smrg
1567117f1b4Smrg   POSTFIX;
1577117f1b4Smrg}
1587117f1b4Smrg
1597117f1b4Smrg
1603464ebd5Sriastradhstatic void TAG(render_triangles)( struct gl_context *ctx,
1617117f1b4Smrg				   GLuint start,
1627117f1b4Smrg				   GLuint count,
1637117f1b4Smrg				   GLuint flags )
1647117f1b4Smrg{
1657117f1b4Smrg   GLuint j;
1667117f1b4Smrg   LOCAL_VARS;
1677117f1b4Smrg   (void) flags;
1687117f1b4Smrg
1697117f1b4Smrg   INIT(GL_TRIANGLES);
1707117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
1717117f1b4Smrg      for (j=start+2; j<count; j+=3) {
1727117f1b4Smrg	 /* Leave the edgeflags as supplied by the user.
1737117f1b4Smrg	  */
1747117f1b4Smrg	 RESET_STIPPLE;
1754a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1764a49301eSmrg            RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
1774a49301eSmrg         else
1784a49301eSmrg            RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
1797117f1b4Smrg      }
1807117f1b4Smrg   } else {
1817117f1b4Smrg      for (j=start+2; j<count; j+=3) {
1824a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
1834a49301eSmrg            RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
1844a49301eSmrg         else
1854a49301eSmrg            RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
1867117f1b4Smrg      }
1877117f1b4Smrg   }
1887117f1b4Smrg   POSTFIX;
1897117f1b4Smrg}
1907117f1b4Smrg
1917117f1b4Smrg
1927117f1b4Smrg
1933464ebd5Sriastradhstatic void TAG(render_tri_strip)( struct gl_context *ctx,
1947117f1b4Smrg				   GLuint start,
1957117f1b4Smrg				   GLuint count,
1967117f1b4Smrg				   GLuint flags )
1977117f1b4Smrg{
1987117f1b4Smrg   GLuint j;
1997117f1b4Smrg   GLuint parity = 0;
2007117f1b4Smrg   LOCAL_VARS;
2017117f1b4Smrg
2027117f1b4Smrg   INIT(GL_TRIANGLE_STRIP);
2037117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
2047117f1b4Smrg      for (j=start+2;j<count;j++,parity^=1) {
2054a49301eSmrg         GLuint ej2, ej1, ej;
2064a49301eSmrg         GLboolean ef2, ef1, ef;
2074a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
2084a49301eSmrg            ej2 = ELT(j-2+parity);
2094a49301eSmrg            ej1 = ELT(j-1-parity);
2104a49301eSmrg            ej = ELT(j);
2114a49301eSmrg         }
2124a49301eSmrg         else {
2134a49301eSmrg            ej2 = ELT(j-1+parity);
2144a49301eSmrg            ej1 = ELT(j-parity);
2154a49301eSmrg            ej = ELT(j-2);
2164a49301eSmrg         }
2174a49301eSmrg	 ef2 = EDGEFLAG_GET( ej2 );
2184a49301eSmrg	 ef1 = EDGEFLAG_GET( ej1 );
2194a49301eSmrg	 ef = EDGEFLAG_GET( ej );
2207117f1b4Smrg	 if (TEST_PRIM_BEGIN(flags)) {
2217117f1b4Smrg	    RESET_STIPPLE;
2227117f1b4Smrg	 }
2237117f1b4Smrg	 EDGEFLAG_SET( ej2, GL_TRUE );
2247117f1b4Smrg	 EDGEFLAG_SET( ej1, GL_TRUE );
2257117f1b4Smrg	 EDGEFLAG_SET( ej, GL_TRUE );
2264a49301eSmrg         RENDER_TRI( ej2, ej1, ej );
2277117f1b4Smrg	 EDGEFLAG_SET( ej2, ef2 );
2287117f1b4Smrg	 EDGEFLAG_SET( ej1, ef1 );
2297117f1b4Smrg	 EDGEFLAG_SET( ej, ef );
2307117f1b4Smrg      }
2317117f1b4Smrg   } else {
2327117f1b4Smrg      for (j=start+2; j<count ; j++, parity^=1) {
2334a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
2344a49301eSmrg            RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
2354a49301eSmrg         else
2364a49301eSmrg            RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
2377117f1b4Smrg      }
2387117f1b4Smrg   }
2397117f1b4Smrg   POSTFIX;
2407117f1b4Smrg}
2417117f1b4Smrg
2427117f1b4Smrg
2433464ebd5Sriastradhstatic void TAG(render_tri_fan)( struct gl_context *ctx,
2447117f1b4Smrg				 GLuint start,
2457117f1b4Smrg				 GLuint count,
2467117f1b4Smrg				 GLuint flags )
2477117f1b4Smrg{
2487117f1b4Smrg   GLuint j;
2497117f1b4Smrg   LOCAL_VARS;
2507117f1b4Smrg   (void) flags;
2517117f1b4Smrg
2527117f1b4Smrg   INIT(GL_TRIANGLE_FAN);
2537117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
2547117f1b4Smrg      for (j=start+2;j<count;j++) {
2557117f1b4Smrg	 /* For trifans, all edges are boundary.
2567117f1b4Smrg	  */
2577117f1b4Smrg	 GLuint ejs = ELT(start);
2587117f1b4Smrg	 GLuint ej1 = ELT(j-1);
2597117f1b4Smrg	 GLuint ej = ELT(j);
2607117f1b4Smrg	 GLboolean efs = EDGEFLAG_GET( ejs );
2617117f1b4Smrg	 GLboolean ef1 = EDGEFLAG_GET( ej1 );
2627117f1b4Smrg	 GLboolean ef = EDGEFLAG_GET( ej );
2637117f1b4Smrg	 if (TEST_PRIM_BEGIN(flags)) {
2647117f1b4Smrg	    RESET_STIPPLE;
2657117f1b4Smrg	 }
2667117f1b4Smrg	 EDGEFLAG_SET( ejs, GL_TRUE );
2677117f1b4Smrg	 EDGEFLAG_SET( ej1, GL_TRUE );
2687117f1b4Smrg	 EDGEFLAG_SET( ej, GL_TRUE );
2694a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
2704a49301eSmrg            RENDER_TRI( ejs, ej1, ej);
2714a49301eSmrg         else
2724a49301eSmrg            RENDER_TRI( ej, ejs, ej1);
2737117f1b4Smrg	 EDGEFLAG_SET( ejs, efs );
2747117f1b4Smrg	 EDGEFLAG_SET( ej1, ef1 );
2757117f1b4Smrg	 EDGEFLAG_SET( ej, ef );
2767117f1b4Smrg      }
2777117f1b4Smrg   } else {
2787117f1b4Smrg      for (j=start+2;j<count;j++) {
2794a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
2804a49301eSmrg            RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
2814a49301eSmrg         else
2824a49301eSmrg            RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
2837117f1b4Smrg      }
2847117f1b4Smrg   }
2857117f1b4Smrg
2867117f1b4Smrg   POSTFIX;
2877117f1b4Smrg}
2887117f1b4Smrg
2897117f1b4Smrg
2903464ebd5Sriastradhstatic void TAG(render_poly)( struct gl_context *ctx,
2917117f1b4Smrg			      GLuint start,
2927117f1b4Smrg			      GLuint count,
2937117f1b4Smrg			      GLuint flags )
2947117f1b4Smrg{
2957117f1b4Smrg   GLuint j = start+2;
2967117f1b4Smrg   LOCAL_VARS;
2977117f1b4Smrg   (void) flags;
2987117f1b4Smrg
2997117f1b4Smrg   INIT(GL_POLYGON);
3007117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
3017117f1b4Smrg      GLboolean efstart = EDGEFLAG_GET( ELT(start) );
3027117f1b4Smrg      GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
3037117f1b4Smrg
3047117f1b4Smrg      /* If the primitive does not begin here, the first edge
3057117f1b4Smrg       * is non-boundary.
3067117f1b4Smrg       */
3077117f1b4Smrg      if (!TEST_PRIM_BEGIN(flags))
3087117f1b4Smrg	 EDGEFLAG_SET( ELT(start), GL_FALSE );
3097117f1b4Smrg      else {
3107117f1b4Smrg	 RESET_STIPPLE;
3117117f1b4Smrg      }
3127117f1b4Smrg
3137117f1b4Smrg      /* If the primitive does not end here, the final edge is
3147117f1b4Smrg       * non-boundary.
3157117f1b4Smrg       */
3167117f1b4Smrg      if (!TEST_PRIM_END(flags))
3177117f1b4Smrg	 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
3187117f1b4Smrg
3197117f1b4Smrg      /* Draw the first triangles (possibly zero)
3207117f1b4Smrg       */
3217117f1b4Smrg      if (j+1<count) {
3227117f1b4Smrg	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
3237117f1b4Smrg	 EDGEFLAG_SET( ELT(j), GL_FALSE );
3247117f1b4Smrg	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
3257117f1b4Smrg	 EDGEFLAG_SET( ELT(j), ef );
3267117f1b4Smrg	 j++;
3277117f1b4Smrg
3287117f1b4Smrg	 /* Don't render the first edge again:
3297117f1b4Smrg	  */
3307117f1b4Smrg	 EDGEFLAG_SET( ELT(start), GL_FALSE );
3317117f1b4Smrg
3327117f1b4Smrg	 for (;j+1<count;j++) {
3337117f1b4Smrg	    GLboolean efj = EDGEFLAG_GET( ELT(j) );
3347117f1b4Smrg	    EDGEFLAG_SET( ELT(j), GL_FALSE );
3357117f1b4Smrg	    RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
3367117f1b4Smrg	    EDGEFLAG_SET( ELT(j), efj );
3377117f1b4Smrg	 }
3387117f1b4Smrg      }
3397117f1b4Smrg
3407117f1b4Smrg      /* Draw the last or only triangle
3417117f1b4Smrg       */
3427117f1b4Smrg      if (j < count)
3437117f1b4Smrg	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
3447117f1b4Smrg
3457117f1b4Smrg      /* Restore the first and last edgeflags:
3467117f1b4Smrg       */
3477117f1b4Smrg      EDGEFLAG_SET( ELT(count-1), efcount );
3487117f1b4Smrg      EDGEFLAG_SET( ELT(start), efstart );
3497117f1b4Smrg
3507117f1b4Smrg   }
3517117f1b4Smrg   else {
3527117f1b4Smrg      for (j=start+2;j<count;j++) {
3537117f1b4Smrg	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
3547117f1b4Smrg      }
3557117f1b4Smrg   }
3567117f1b4Smrg   POSTFIX;
3577117f1b4Smrg}
3587117f1b4Smrg
3593464ebd5Sriastradhstatic void TAG(render_quads)( struct gl_context *ctx,
3607117f1b4Smrg			       GLuint start,
3617117f1b4Smrg			       GLuint count,
3627117f1b4Smrg			       GLuint flags )
3637117f1b4Smrg{
3647117f1b4Smrg   GLuint j;
3657117f1b4Smrg   LOCAL_VARS;
3667117f1b4Smrg   (void) flags;
3677117f1b4Smrg
3687117f1b4Smrg   INIT(GL_QUADS);
3697117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
3707117f1b4Smrg      for (j=start+3; j<count; j+=4) {
3717117f1b4Smrg	 /* Use user-specified edgeflags for quads.
3727117f1b4Smrg	  */
3737117f1b4Smrg	 RESET_STIPPLE;
3744a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
3754a49301eSmrg             !ctx->Const.QuadsFollowProvokingVertexConvention)
3764a49301eSmrg            RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
3774a49301eSmrg         else
3784a49301eSmrg            RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
3797117f1b4Smrg      }
3807117f1b4Smrg   } else {
3817117f1b4Smrg      for (j=start+3; j<count; j+=4) {
3824a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
3834a49301eSmrg             !ctx->Const.QuadsFollowProvokingVertexConvention)
3844a49301eSmrg            RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
3854a49301eSmrg         else
3864a49301eSmrg            RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
3877117f1b4Smrg      }
3887117f1b4Smrg   }
3897117f1b4Smrg   POSTFIX;
3907117f1b4Smrg}
3917117f1b4Smrg
3923464ebd5Sriastradhstatic void TAG(render_quad_strip)( struct gl_context *ctx,
3937117f1b4Smrg				    GLuint start,
3947117f1b4Smrg				    GLuint count,
3957117f1b4Smrg				    GLuint flags )
3967117f1b4Smrg{
3977117f1b4Smrg   GLuint j;
3987117f1b4Smrg   LOCAL_VARS;
3997117f1b4Smrg   (void) flags;
4007117f1b4Smrg
4017117f1b4Smrg   INIT(GL_QUAD_STRIP);
4027117f1b4Smrg   if (NEED_EDGEFLAG_SETUP) {
4037117f1b4Smrg      for (j=start+3;j<count;j+=2) {
4047117f1b4Smrg	 /* All edges are boundary.  Set edgeflags to 1, draw the
4057117f1b4Smrg	  * quad, and restore them to the original values.
4067117f1b4Smrg	  */
4077117f1b4Smrg	 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
4087117f1b4Smrg	 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
4097117f1b4Smrg	 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
4107117f1b4Smrg	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
4117117f1b4Smrg	 if (TEST_PRIM_BEGIN(flags)) {
4127117f1b4Smrg	    RESET_STIPPLE;
4137117f1b4Smrg	 }
4147117f1b4Smrg	 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
4157117f1b4Smrg	 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
4167117f1b4Smrg	 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
4177117f1b4Smrg	 EDGEFLAG_SET( ELT(j), GL_TRUE );
4184a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
4194a49301eSmrg             !ctx->Const.QuadsFollowProvokingVertexConvention)
4204a49301eSmrg            RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
4214a49301eSmrg         else
4224a49301eSmrg            RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
4237117f1b4Smrg	 EDGEFLAG_SET( ELT(j-3), ef3 );
4247117f1b4Smrg	 EDGEFLAG_SET( ELT(j-2), ef2 );
4257117f1b4Smrg	 EDGEFLAG_SET( ELT(j-1), ef1 );
4267117f1b4Smrg	 EDGEFLAG_SET( ELT(j), ef );
4277117f1b4Smrg      }
4287117f1b4Smrg   } else {
4297117f1b4Smrg      for (j=start+3;j<count;j+=2) {
4304a49301eSmrg         if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
4314a49301eSmrg             !ctx->Const.QuadsFollowProvokingVertexConvention)
4324a49301eSmrg            RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
4334a49301eSmrg         else
4344a49301eSmrg            RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
4357117f1b4Smrg      }
4367117f1b4Smrg   }
4377117f1b4Smrg   POSTFIX;
4387117f1b4Smrg}
4397117f1b4Smrg
4403464ebd5Sriastradhstatic void TAG(render_noop)( struct gl_context *ctx,
4417117f1b4Smrg			      GLuint start,
4427117f1b4Smrg			      GLuint count,
4437117f1b4Smrg			      GLuint flags )
4447117f1b4Smrg{
4457117f1b4Smrg   (void)(ctx && start && count && flags);
4467117f1b4Smrg}
4477117f1b4Smrg
4483464ebd5SriastradhRENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
4497117f1b4Smrg							   GLuint,
4507117f1b4Smrg							   GLuint,
4517117f1b4Smrg							   GLuint) =
4527117f1b4Smrg{
4537117f1b4Smrg   TAG(render_points),
4547117f1b4Smrg   TAG(render_lines),
4557117f1b4Smrg   TAG(render_line_loop),
4567117f1b4Smrg   TAG(render_line_strip),
4577117f1b4Smrg   TAG(render_triangles),
4587117f1b4Smrg   TAG(render_tri_strip),
4597117f1b4Smrg   TAG(render_tri_fan),
4607117f1b4Smrg   TAG(render_quads),
4617117f1b4Smrg   TAG(render_quad_strip),
4627117f1b4Smrg   TAG(render_poly),
4637117f1b4Smrg   TAG(render_noop),
4647117f1b4Smrg};
4657117f1b4Smrg
4667117f1b4Smrg
4677117f1b4Smrg
4687117f1b4Smrg#ifndef PRESERVE_VB_DEFS
4697117f1b4Smrg#undef RENDER_TRI
4707117f1b4Smrg#undef RENDER_QUAD
4717117f1b4Smrg#undef RENDER_LINE
4727117f1b4Smrg#undef RENDER_POINTS
4737117f1b4Smrg#undef LOCAL_VARS
4747117f1b4Smrg#undef INIT
4757117f1b4Smrg#undef POSTFIX
4767117f1b4Smrg#undef RESET_STIPPLE
4777117f1b4Smrg#undef DBG
4787117f1b4Smrg#undef ELT
4797117f1b4Smrg#undef RENDER_TAB_QUALIFIER
4807117f1b4Smrg#endif
4817117f1b4Smrg
4827117f1b4Smrg#ifndef PRESERVE_TAG
4837117f1b4Smrg#undef TAG
4847117f1b4Smrg#endif
4857117f1b4Smrg
4867117f1b4Smrg#undef PRESERVE_VB_DEFS
4877117f1b4Smrg#undef PRESERVE_TAG
488