X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Ftnl_dd%2Ft_dd_dmatmp.h;h=52ea2bf739c1196fb18db0985a4649ab6741b190;hb=faaca237341abc0f784edfb16df50104110365b8;hp=d9f709389d1bd142d5f74b4be723da9d5ea06d85;hpb=5df82c82bd53db90eb72c5aad4dd20cf6f1116b1;p=mesa.git diff --git a/src/mesa/tnl_dd/t_dd_dmatmp.h b/src/mesa/tnl_dd/t_dd_dmatmp.h index d9f709389d1..52ea2bf739c 100644 --- a/src/mesa/tnl_dd/t_dd_dmatmp.h +++ b/src/mesa/tnl_dd/t_dd_dmatmp.h @@ -1,9 +1,7 @@ - /* * Mesa 3-D graphics library - * Version: 3.5 * - * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -18,16 +16,19 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. * * Authors: - * Keith Whitwell + * Keith Whitwell */ -/* Template for render stages which build and emit vertices directly +/** + * \file t_dd_dmatmp.h + * Template for render stages which build and emit vertices directly * to fixed-size dma buffers. Useful for rendering strips and other * native primitives where clipping and per-vertex tweaks such as * those in t_dd_tritmp.h are not required. @@ -36,8 +37,6 @@ * Where various primitive types are unaccelerated by hardware, the * code attempts to fallback to other primitive types (quadstrips to * tristrips, lineloops to linestrips), or to indexed vertices. - * Ultimately, a FALLBACK() macro is invoked if there is no way to - * render the primitive natively. */ #if !defined(HAVE_TRIANGLES) @@ -45,15 +44,14 @@ #endif #if !HAVE_ELTS -#define ELTS_VARS -#define ALLOC_ELTS( nr ) +#define ELTS_VARS(buf) +#define ALLOC_ELTS(nr) 0 #define EMIT_ELT( offset, elt ) #define EMIT_TWO_ELTS( offset, elt0, elt1 ) #define INCR_ELTS( nr ) #define ELT_INIT(prim) #define GET_CURRENT_VB_MAX_ELTS() 0 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0 -#define ALLOC_ELTS_NEW_PRIMITIVE(nr) #define RELEASE_ELT_VERTS() #define EMIT_INDEXED_VERTS( ctx, start, count ) #endif @@ -66,9 +64,6 @@ do { \ } while (0) #endif -#ifndef FINISH -#define FINISH -#endif /**********************************************************************/ /* Render whole begin/end objects */ @@ -76,50 +71,40 @@ do { \ -static GLboolean TAG(emit_elt_verts)( GLcontext *ctx, - GLuint start, GLuint count ) -{ - if (HAVE_ELTS) { - LOCAL_VARS; - GLuint nr = count - start; - - if ( nr >= GET_SUBSEQUENT_VB_MAX_VERTS() ) /* assumes same packing for - * indexed and regualar verts - */ - return GL_FALSE; - - NEW_PRIMITIVE(); /* finish last prim */ - EMIT_INDEXED_VERTS( ctx, start, count ); - return GL_TRUE; - } else { - return GL_FALSE; - } -} #if (HAVE_ELTS) -static void TAG(emit_elts)( GLcontext *ctx, GLuint *elts, GLuint nr ) +static void *TAG(emit_elts)( struct gl_context *ctx, GLuint *elts, GLuint nr, + void *buf) { GLint i; LOCAL_VARS; - ELTS_VARS; - - ALLOC_ELTS( nr ); + ELTS_VARS(buf); - for ( i = 0 ; i < nr ; i+=2, elts += 2 ) { + for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) { EMIT_TWO_ELTS( 0, elts[0], elts[1] ); INCR_ELTS( 2 ); } + + if (i < nr) { + EMIT_ELT( 0, elts[0] ); + INCR_ELTS( 1 ); + } + + return (void *)ELTPTR; } #endif +static __inline void *TAG(emit_verts)( struct gl_context *ctx, GLuint start, + GLuint count, void *buf ) +{ + return EMIT_VERTS(ctx, start, count, buf); +} /*********************************************************************** * Render non-indexed primitives. ***********************************************************************/ - - -static void TAG(render_points_verts)( GLcontext *ctx, +static void TAG(render_points_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -127,28 +112,28 @@ static void TAG(render_points_verts)( GLcontext *ctx, if (HAVE_POINTS) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; GLuint j, nr; INIT( GL_POINTS ); + currentsz = GET_CURRENT_VB_MAX_VERTS(); if (currentsz < 8) currentsz = dmasz; for (j = start; j < count; j += nr ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; - } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_lines_verts)( GLcontext *ctx, +static void TAG(render_lines_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -156,7 +141,7 @@ static void TAG(render_lines_verts)( GLcontext *ctx, if (HAVE_LINES) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; GLuint j, nr; INIT( GL_LINES ); @@ -164,6 +149,7 @@ static void TAG(render_lines_verts)( GLcontext *ctx, /* Emit whole number of lines in total and in each buffer: */ count -= (count-start) & 1; + currentsz = GET_CURRENT_VB_MAX_VERTS(); currentsz -= currentsz & 1; dmasz -= dmasz & 1; @@ -172,19 +158,18 @@ static void TAG(render_lines_verts)( GLcontext *ctx, for (j = start; j < count; j += nr ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; - } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_line_strip_verts)( GLcontext *ctx, +static void TAG(render_line_strip_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -192,30 +177,31 @@ static void TAG(render_line_strip_verts)( GLcontext *ctx, if (HAVE_LINE_STRIPS) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; GLuint j, nr; - NEW_PRIMITIVE(); /* always a new primitive */ INIT( GL_LINE_STRIP ); + currentsz = GET_CURRENT_VB_MAX_VERTS(); if (currentsz < 8) currentsz = dmasz; for (j = start; j + 1 < count; j += nr - 1 ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; + FLUSH(); } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_line_loop_verts)( GLcontext *ctx, +static void TAG(render_line_loop_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -223,10 +209,9 @@ static void TAG(render_line_loop_verts)( GLcontext *ctx, if (HAVE_LINE_STRIPS) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; GLuint j, nr; - NEW_PRIMITIVE(); INIT( GL_LINE_STRIP ); if (flags & PRIM_BEGIN) @@ -236,49 +221,66 @@ static void TAG(render_line_loop_verts)( GLcontext *ctx, /* Ensure last vertex won't wrap buffers: */ + currentsz = GET_CURRENT_VB_MAX_VERTS(); currentsz--; dmasz--; if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } if (j + 1 < count) { for ( ; j + 1 < count; j += nr - 1 ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); - currentsz = dmasz; + + if (j + nr >= count && + start < count - 1 && + (flags & PRIM_END)) + { + void *tmp; + tmp = ALLOC_VERTS(nr+1); + tmp = TAG(emit_verts)( ctx, j, nr, tmp ); + tmp = TAG(emit_verts)( ctx, start, 1, tmp ); + (void) tmp; + } + else { + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); + currentsz = dmasz; + } } - if (start < count - 1 && (flags & PRIM_END)) - EMIT_VERTS( ctx, start, 1 ); } else if (start + 1 < count && (flags & PRIM_END)) { - EMIT_VERTS( ctx, start+1, 1 ); - EMIT_VERTS( ctx, start, 1 ); + void *tmp; + tmp = ALLOC_VERTS(2); + tmp = TAG(emit_verts)( ctx, start+1, 1, tmp ); + tmp = TAG(emit_verts)( ctx, start, 1, tmp ); + (void) tmp; } - FINISH; + FLUSH(); } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_triangles_verts)( GLcontext *ctx, +static void TAG(render_triangles_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) { LOCAL_VARS; int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3; - int currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3; + int currentsz; GLuint j, nr; INIT(GL_TRIANGLES); + currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3; + /* Emit whole number of tris in total. dmasz is already a multiple * of 3. */ @@ -289,15 +291,14 @@ static void TAG(render_triangles_verts)( GLcontext *ctx, for (j = start; j < count; j += nr) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; } -static void TAG(render_tri_strip_verts)( GLcontext *ctx, +static void TAG(render_tri_strip_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -309,23 +310,13 @@ static void TAG(render_tri_strip_verts)( GLcontext *ctx, int currentsz; INIT(GL_TRIANGLE_STRIP); - NEW_PRIMITIVE(); currentsz = GET_CURRENT_VB_MAX_VERTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - if ((flags & PRIM_PARITY) && count - start > 2) { - if (HAVE_TRI_STRIP_1 && 0) { - } else { - EMIT_VERTS( ctx, start, 1 ); - currentsz--; - } - } - /* From here on emit even numbers of tris when wrapping over buffers: */ dmasz -= (dmasz & 1); @@ -333,18 +324,19 @@ static void TAG(render_tri_strip_verts)( GLcontext *ctx, for (j = start ; j + 2 < count; j += nr - 2 ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; + FLUSH(); } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_tri_fan_verts)( GLcontext *ctx, +static void TAG(render_tri_fan_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -353,36 +345,38 @@ static void TAG(render_tri_fan_verts)( GLcontext *ctx, LOCAL_VARS; GLuint j, nr; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; - NEW_PRIMITIVE(); INIT(GL_TRIANGLE_FAN); + currentsz = GET_CURRENT_VB_MAX_VERTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { + for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { + void *tmp; nr = MIN2( currentsz, count - j + 1 ); - EMIT_VERTS( ctx, start, 1 ); - EMIT_VERTS( ctx, j, nr - 1 ); + tmp = ALLOC_VERTS( nr ); + tmp = TAG(emit_verts)( ctx, start, 1, tmp ); + tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp ); + (void) tmp; currentsz = dmasz; } - FINISH; - + FLUSH(); } else { /* Could write code to emit these as indexed vertices (for the * g400, for instance). */ - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_poly_verts)( GLcontext *ctx, +static void TAG(render_poly_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -391,34 +385,36 @@ static void TAG(render_poly_verts)( GLcontext *ctx, LOCAL_VARS; GLuint j, nr; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; - NEW_PRIMITIVE(); INIT(GL_POLYGON); + currentsz = GET_CURRENT_VB_MAX_VERTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { + for (j = start + 1 ; j + 1 < count ; j += nr - 2 ) { + void *tmp; nr = MIN2( currentsz, count - j + 1 ); - EMIT_VERTS( ctx, start, 1 ); - EMIT_VERTS( ctx, j, nr - 1 ); + tmp = ALLOC_VERTS( nr ); + tmp = TAG(emit_verts)( ctx, start, 1, tmp ); + tmp = TAG(emit_verts)( ctx, j, nr - 1, tmp ); + (void) tmp; currentsz = dmasz; } - FINISH; - + FLUSH(); } - else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) { + else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) { TAG(render_tri_fan_verts)( ctx, start, count, flags ); } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_quad_strip_verts)( GLcontext *ctx, +static void TAG(render_quad_strip_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -432,12 +428,9 @@ static void TAG(render_quad_strip_verts)( GLcontext *ctx, int currentsz; INIT(GL_QUAD_STRIP); - NEW_PRIMITIVE(); currentsz = GET_CURRENT_VB_MAX_VERTS(); - if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } @@ -446,22 +439,25 @@ static void TAG(render_quad_strip_verts)( GLcontext *ctx, for (j = start ; j + 3 < count; j += nr - 2 ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; + FLUSH(); - } else if (HAVE_TRI_STRIPS && (ctx->_TriangleCaps & DD_FLATSHADE)) { - if (TAG(emit_elt_verts)( ctx, start, count )) { + } else if (HAVE_TRI_STRIPS && + ctx->Light.ShadeModel == GL_FLAT && + TNL_CONTEXT(ctx)->vb.AttribPtr[_TNL_ATTRIB_COLOR0]->stride) { + if (HAVE_ELTS) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); int currentsz; GLuint j, nr; + EMIT_INDEXED_VERTS( ctx, start, count ); + /* Simulate flat-shaded quadstrips using indexed vertices: */ - NEW_PRIMITIVE(); ELT_INIT( GL_TRIANGLES ); currentsz = GET_CURRENT_VB_MAX_ELTS(); @@ -483,10 +479,7 @@ static void TAG(render_quad_strip_verts)( GLcontext *ctx, if (nr >= 4) { GLint quads = (nr/2)-1; GLint i; - ELTS_VARS; - - NEW_PRIMITIVE(); - ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + ELTS_VARS( ALLOC_ELTS( quads*6 ) ); for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) { EMIT_TWO_ELTS( 0, (i+0), (i+1) ); @@ -495,56 +488,59 @@ static void TAG(render_quad_strip_verts)( GLcontext *ctx, INCR_ELTS( 6 ); } - NEW_PRIMITIVE(); + FLUSH(); } currentsz = dmasz; } RELEASE_ELT_VERTS(); + FLUSH(); } else { - /* Vertices won't fit in a single buffer or elts not available, - * VERT_FALLBACK. + /* Vertices won't fit in a single buffer or elts not + * available - should never happen. */ - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } else if (HAVE_TRI_STRIPS) { LOCAL_VARS; int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); - int currentsz = GET_CURRENT_VB_MAX_VERTS(); + int currentsz; /* Emit smooth-shaded quadstrips as tristrips: */ - NEW_PRIMITIVE(); + FLUSH(); INIT( GL_TRIANGLE_STRIP ); /* Emit whole number of quads in total, and in each buffer. */ dmasz -= dmasz & 1; + currentsz = GET_CURRENT_VB_MAX_VERTS(); currentsz -= currentsz & 1; count -= (count-start) & 1; if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } for (j = start; j + 3 < count; j += nr - 2 ) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; + FLUSH(); } else { - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_quads_verts)( GLcontext *ctx, +static void TAG(render_quads_verts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -552,7 +548,7 @@ static void TAG(render_quads_verts)( GLcontext *ctx, if (HAVE_QUADS) { LOCAL_VARS; int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4; - int currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4; + int currentsz; GLuint j, nr; INIT(GL_QUADS); @@ -562,16 +558,17 @@ static void TAG(render_quads_verts)( GLcontext *ctx, */ count -= (count-start)%4; + currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4; if (currentsz < 8) currentsz = dmasz; for (j = start; j < count; j += nr) { nr = MIN2( currentsz, count - j ); - EMIT_VERTS( ctx, j, nr ); + TAG(emit_verts)( ctx, j, nr, ALLOC_VERTS(nr) ); currentsz = dmasz; } - FINISH; - } else if (TAG(emit_elt_verts)( ctx, start, count )) { + } + else if (HAVE_ELTS) { /* Hardware doesn't have a quad primitive type -- try to * simulate it using indexed vertices and the triangle * primitive: @@ -581,7 +578,9 @@ static void TAG(render_quads_verts)( GLcontext *ctx, int currentsz; GLuint j, nr; - NEW_PRIMITIVE(); + EMIT_INDEXED_VERTS( ctx, start, count ); + + FLUSH(); ELT_INIT( GL_TRIANGLES ); currentsz = GET_CURRENT_VB_MAX_ELTS(); @@ -604,10 +603,7 @@ static void TAG(render_quads_verts)( GLcontext *ctx, if (nr >= 4) { GLint quads = nr/4; GLint i; - ELTS_VARS; - - NEW_PRIMITIVE(); - ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + ELTS_VARS( ALLOC_ELTS( quads*6 ) ); for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) { EMIT_TWO_ELTS( 0, (i+0), (i+1) ); @@ -616,21 +612,44 @@ static void TAG(render_quads_verts)( GLcontext *ctx, INCR_ELTS( 6 ); } - NEW_PRIMITIVE(); + FLUSH(); } currentsz = dmasz; } RELEASE_ELT_VERTS(); } + else if (HAVE_TRIANGLES) { + /* Hardware doesn't have a quad primitive type -- try to + * simulate it using triangle primitive. This is a win for + * gears, but is it useful in the broader world? + */ + LOCAL_VARS; + GLuint j; + + INIT(GL_TRIANGLES); + + for (j = start; j < count-3; j += 4) { + void *tmp = ALLOC_VERTS( 6 ); + /* Send v0, v1, v3 + */ + tmp = EMIT_VERTS(ctx, j, 2, tmp); + tmp = EMIT_VERTS(ctx, j + 3, 1, tmp); + /* Send v1, v2, v3 + */ + tmp = EMIT_VERTS(ctx, j + 1, 3, tmp); + (void) tmp; + } + } else { - /* Vertices won't fit in a single buffer, fallback. + /* Vertices won't fit in a single buffer, should never happen. */ - VERT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_noop)( GLcontext *ctx, +static void TAG(render_noop)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -640,7 +659,7 @@ static void TAG(render_noop)( GLcontext *ctx, -static render_func TAG(render_tab_verts)[GL_POLYGON+2] = +static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] = { TAG(render_points_verts), TAG(render_lines_verts), @@ -661,7 +680,7 @@ static render_func TAG(render_tab_verts)[GL_POLYGON+2] = ****************************************************************************/ #if (HAVE_ELTS) -static void TAG(render_points_elts)( GLcontext *ctx, +static void TAG(render_points_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -681,18 +700,19 @@ static void TAG(render_points_elts)( GLcontext *ctx, for (j = start; j < count; j += nr ) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } else { - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_lines_elts)( GLcontext *ctx, +static void TAG(render_lines_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -718,17 +738,18 @@ static void TAG(render_lines_elts)( GLcontext *ctx, for (j = start; j < count; j += nr ) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } else { - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_line_strip_elts)( GLcontext *ctx, +static void TAG(render_line_strip_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -740,7 +761,7 @@ static void TAG(render_line_strip_elts)( GLcontext *ctx, GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; GLuint j, nr; - NEW_PRIMITIVE(); /* always a new primitive */ + FLUSH(); /* always a new primitive */ ELT_INIT( GL_LINE_STRIP ); currentsz = GET_CURRENT_VB_MAX_ELTS(); @@ -749,19 +770,20 @@ static void TAG(render_line_strip_elts)( GLcontext *ctx, for (j = start; j + 1 < count; j += nr - 1 ) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } else { /* TODO: Try to emit as indexed lines. */ - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_line_loop_elts)( GLcontext *ctx, +static void TAG(render_line_loop_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -773,7 +795,7 @@ static void TAG(render_line_loop_elts)( GLcontext *ctx, GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; GLuint j, nr; - NEW_PRIMITIVE(); + FLUSH(); ELT_INIT( GL_LINE_STRIP ); if (flags & PRIM_BEGIN) @@ -783,7 +805,6 @@ static void TAG(render_line_loop_elts)( GLcontext *ctx, currentsz = GET_CURRENT_VB_MAX_ELTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } @@ -792,20 +813,40 @@ static void TAG(render_line_loop_elts)( GLcontext *ctx, currentsz--; dmasz--; - for ( ; j + 1 < count; j += nr - 1 ) { - nr = MIN2( currentsz, count - j ); -/* NEW_PRIMITIVE(); */ - TAG(emit_elts)( ctx, elts+j, nr ); - currentsz = dmasz; - } + if (j + 1 < count) { + for ( ; j + 1 < count; j += nr - 1 ) { + nr = MIN2( currentsz, count - j ); - if (flags & PRIM_END) - TAG(emit_elts)( ctx, elts+start, 1 ); + if (j + nr >= count && + start < count - 1 && + (flags & PRIM_END)) + { + void *tmp; + tmp = ALLOC_ELTS(nr+1); + tmp = TAG(emit_elts)( ctx, elts+j, nr, tmp ); + tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); + (void) tmp; + } + else { + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + currentsz = dmasz; + } + } - NEW_PRIMITIVE(); + } + else if (start + 1 < count && (flags & PRIM_END)) { + void *tmp; + tmp = ALLOC_ELTS(2); + tmp = TAG(emit_elts)( ctx, elts+start+1, 1, tmp ); + tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); + (void) tmp; + } + + FLUSH(); } else { /* TODO: Try to emit as indexed lines */ - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } @@ -814,7 +855,7 @@ static void TAG(render_line_loop_elts)( GLcontext *ctx, * buffers. For elts, this is probably no better (worse?) than the * standard path. */ -static void TAG(render_triangles_elts)( GLcontext *ctx, +static void TAG(render_triangles_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -825,7 +866,7 @@ static void TAG(render_triangles_elts)( GLcontext *ctx, int currentsz; GLuint j, nr; - NEW_PRIMITIVE(); + FLUSH(); ELT_INIT( GL_TRIANGLES ); currentsz = GET_CURRENT_VB_MAX_ELTS(); @@ -840,15 +881,15 @@ static void TAG(render_triangles_elts)( GLcontext *ctx, for (j = start; j < count; j += nr) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } -static void TAG(render_tri_strip_elts)( GLcontext *ctx, +static void TAG(render_tri_strip_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -860,19 +901,14 @@ static void TAG(render_tri_strip_elts)( GLcontext *ctx, int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); int currentsz; - NEW_PRIMITIVE(); + FLUSH(); ELT_INIT( GL_TRIANGLE_STRIP ); currentsz = GET_CURRENT_VB_MAX_ELTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - if ((flags & PRIM_PARITY) && count - start > 2) { - TAG(emit_elts)( ctx, elts+start, 1 ); - } - /* Keep the same winding over multiple buffers: */ dmasz -= (dmasz & 1); @@ -880,17 +916,18 @@ static void TAG(render_tri_strip_elts)( GLcontext *ctx, for (j = start ; j + 2 < count; j += nr - 2 ) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } else { /* TODO: try to emit as indexed triangles */ - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_tri_fan_elts)( GLcontext *ctx, +static void TAG(render_tri_fan_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -902,64 +939,71 @@ static void TAG(render_tri_fan_elts)( GLcontext *ctx, int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); int currentsz; - NEW_PRIMITIVE(); + FLUSH(); ELT_INIT( GL_TRIANGLE_FAN ); currentsz = GET_CURRENT_VB_MAX_ELTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { + for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { + void *tmp; nr = MIN2( currentsz, count - j + 1 ); - TAG(emit_elts)( ctx, elts+start, 1 ); - TAG(emit_elts)( ctx, elts+j, nr - 1 ); - NEW_PRIMITIVE(); + tmp = ALLOC_ELTS( nr ); + tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); + tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp ); + (void) tmp; + FLUSH(); currentsz = dmasz; } } else { /* TODO: try to emit as indexed triangles */ - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_poly_elts)( GLcontext *ctx, +static void TAG(render_poly_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) { - if (HAVE_POLYGONS && 0) { - } else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) { + if (HAVE_POLYGONS) { LOCAL_VARS; GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; GLuint j, nr; int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); int currentsz; - NEW_PRIMITIVE(); - ELT_INIT( GL_TRIANGLE_FAN ); + FLUSH(); + ELT_INIT( GL_POLYGON ); currentsz = GET_CURRENT_VB_MAX_ELTS(); if (currentsz < 8) { - NEW_BUFFER(); currentsz = dmasz; } - for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { + for (j = start + 1 ; j + 1 < count; j += nr - 2 ) { + void *tmp; nr = MIN2( currentsz, count - j + 1 ); - TAG(emit_elts)( ctx, elts+start, 1 ); - TAG(emit_elts)( ctx, elts+j, nr - 1 ); - NEW_PRIMITIVE(); + tmp = ALLOC_ELTS( nr ); + tmp = TAG(emit_elts)( ctx, elts+start, 1, tmp ); + tmp = TAG(emit_elts)( ctx, elts+j, nr - 1, tmp ); + (void) tmp; + FLUSH(); currentsz = dmasz; } + } else if (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH) { + TAG(render_tri_fan_verts)( ctx, start, count, flags ); } else { - ELT_FALLBACK( ctx, start, count, flags ); + fprintf(stderr, "%s - cannot draw primitive\n", __FUNCTION__); + return; } } -static void TAG(render_quad_strip_elts)( GLcontext *ctx, +static void TAG(render_quad_strip_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) @@ -973,7 +1017,7 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, int currentsz; GLuint j, nr; - NEW_PRIMITIVE(); + FLUSH(); currentsz = GET_CURRENT_VB_MAX_ELTS(); /* Emit whole number of quads in total, and in each buffer. @@ -985,7 +1029,7 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, if (currentsz < 12) currentsz = dmasz; - if (ctx->_TriangleCaps & DD_FLATSHADE) { + if (ctx->Light.ShadeModel == GL_FLAT) { ELT_INIT( GL_TRIANGLES ); currentsz = currentsz/6*2; @@ -998,11 +1042,7 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, { GLint i; GLint quads = (nr/2)-1; - ELTS_VARS; - - - NEW_PRIMITIVE(); - ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + ELTS_VARS( ALLOC_ELTS( quads*6 ) ); for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) { EMIT_TWO_ELTS( 0, elts[0], elts[1] ); @@ -1011,7 +1051,7 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, INCR_ELTS( 6 ); } - NEW_PRIMITIVE(); + FLUSH(); } currentsz = dmasz; @@ -1022,8 +1062,8 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, for (j = start; j + 3 < count; j += nr - 2 ) { nr = MIN2( currentsz, count - j ); - TAG(emit_elts)( ctx, elts+j, nr ); - NEW_PRIMITIVE(); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); currentsz = dmasz; } } @@ -1031,12 +1071,34 @@ static void TAG(render_quad_strip_elts)( GLcontext *ctx, } -static void TAG(render_quads_elts)( GLcontext *ctx, +static void TAG(render_quads_elts)( struct gl_context *ctx, GLuint start, GLuint count, GLuint flags ) { - if (HAVE_QUADS && 0) { + if (HAVE_QUADS) { + LOCAL_VARS; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/4*4; + int currentsz; + GLuint j, nr; + + FLUSH(); + ELT_INIT( GL_TRIANGLES ); + + currentsz = GET_CURRENT_VB_MAX_ELTS()/4*4; + + count -= (count-start)%4; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr, ALLOC_ELTS(nr) ); + FLUSH(); + currentsz = dmasz; + } } else { LOCAL_VARS; GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; @@ -1068,9 +1130,7 @@ static void TAG(render_quads_elts)( GLcontext *ctx, { GLint quads = nr/4; GLint i; - ELTS_VARS; - NEW_PRIMITIVE(); - ALLOC_ELTS_NEW_PRIMITIVE( quads * 6 ); + ELTS_VARS( ALLOC_ELTS( quads * 6 ) ); for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) { EMIT_TWO_ELTS( 0, elts[0], elts[1] ); @@ -1078,9 +1138,10 @@ static void TAG(render_quads_elts)( GLcontext *ctx, EMIT_TWO_ELTS( 4, elts[2], elts[3] ); INCR_ELTS( 6 ); } + + FLUSH(); } - NEW_PRIMITIVE(); currentsz = dmasz; } } @@ -1088,7 +1149,7 @@ static void TAG(render_quads_elts)( GLcontext *ctx, -static render_func TAG(render_tab_elts)[GL_POLYGON+2] = +static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] = { TAG(render_points_elts), TAG(render_lines_elts), @@ -1102,4 +1163,104 @@ static render_func TAG(render_tab_elts)[GL_POLYGON+2] = TAG(render_poly_elts), TAG(render_noop), }; + + + #endif + + + +/* Pre-check the primitives in the VB to prevent the need for + * fallbacks later on. + */ +static GLboolean TAG(validate_render)( struct gl_context *ctx, + struct vertex_buffer *VB ) +{ + GLint i; + + if (VB->ClipOrMask & ~CLIP_CULL_BIT) + return GL_FALSE; + + if (VB->Elts && !HAVE_ELTS) + return GL_FALSE; + + for (i = 0 ; i < VB->PrimitiveCount ; i++) { + GLuint prim = VB->Primitive[i].mode; + GLuint count = VB->Primitive[i].count; + GLboolean ok = GL_FALSE; + + if (!count) + continue; + + switch (prim & PRIM_MODE_MASK) { + case GL_POINTS: + ok = HAVE_POINTS; + break; + case GL_LINES: + ok = HAVE_LINES && !ctx->Line.StippleFlag; + break; + case GL_LINE_STRIP: + ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag; + break; + case GL_LINE_LOOP: + ok = HAVE_LINE_STRIPS && !ctx->Line.StippleFlag; + break; + case GL_TRIANGLES: + ok = HAVE_TRIANGLES; + break; + case GL_TRIANGLE_STRIP: + ok = HAVE_TRI_STRIPS; + break; + case GL_TRIANGLE_FAN: + ok = HAVE_TRI_FANS; + break; + case GL_POLYGON: + if (HAVE_POLYGONS) { + ok = GL_TRUE; + } + else { + ok = (HAVE_TRI_FANS && ctx->Light.ShadeModel == GL_SMOOTH); + } + break; + case GL_QUAD_STRIP: + if (VB->Elts) { + ok = HAVE_TRI_STRIPS; + } + else if (HAVE_QUAD_STRIPS) { + ok = GL_TRUE; + } else if (HAVE_TRI_STRIPS && + ctx->Light.ShadeModel == GL_FLAT && + VB->AttribPtr[_TNL_ATTRIB_COLOR0]->stride != 0) { + if (HAVE_ELTS) { + ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS(); + } + else { + ok = GL_FALSE; + } + } + else + ok = HAVE_TRI_STRIPS; + break; + case GL_QUADS: + if (HAVE_QUADS) { + ok = GL_TRUE; + } else if (HAVE_ELTS) { + ok = (GLint) count < GET_SUBSEQUENT_VB_MAX_ELTS(); + } + else { + ok = HAVE_TRIANGLES; /* flatshading is ok. */ + } + break; + default: + break; + } + + if (!ok) { +/* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */ + return GL_FALSE; + } + } + + return GL_TRUE; +} +