From 5df82c82bd53db90eb72c5aad4dd20cf6f1116b1 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Fri, 22 Aug 2003 20:11:43 +0000 Subject: patch to import Jon Smirl's work from Bitkeeper --- src/mesa/tnl_dd/imm/NOTES.imm | 112 ++++ src/mesa/tnl_dd/imm/t_dd_imm_capi.h | 419 ++++++++++++ src/mesa/tnl_dd/imm/t_dd_imm_napi.h | 226 +++++++ src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h | 570 ++++++++++++++++ src/mesa/tnl_dd/imm/t_dd_imm_tapi.h | 75 +++ src/mesa/tnl_dd/imm/t_dd_imm_vapi.h | 159 +++++ src/mesa/tnl_dd/imm/t_dd_imm_vb.c | 204 ++++++ src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h | 268 ++++++++ src/mesa/tnl_dd/t_dd.c | 58 ++ src/mesa/tnl_dd/t_dd_dmatmp.h | 1105 ++++++++++++++++++++++++++++++++ src/mesa/tnl_dd/t_dd_dmatmp2.h | 949 +++++++++++++++++++++++++++ src/mesa/tnl_dd/t_dd_rendertmp.h | 437 +++++++++++++ src/mesa/tnl_dd/t_dd_triemit.h | 157 +++++ src/mesa/tnl_dd/t_dd_tritmp.h | 739 +++++++++++++++++++++ src/mesa/tnl_dd/t_dd_unfilled.h | 212 ++++++ src/mesa/tnl_dd/t_dd_vb.c | 392 +++++++++++ src/mesa/tnl_dd/t_dd_vbtmp.h | 834 ++++++++++++++++++++++++ src/mesa/tnl_dd/t_dd_vertex.h | 78 +++ 18 files changed, 6994 insertions(+) create mode 100644 src/mesa/tnl_dd/imm/NOTES.imm create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_capi.h create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_napi.h create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_tapi.h create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_vapi.h create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_vb.c create mode 100644 src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h create mode 100644 src/mesa/tnl_dd/t_dd.c create mode 100644 src/mesa/tnl_dd/t_dd_dmatmp.h create mode 100644 src/mesa/tnl_dd/t_dd_dmatmp2.h create mode 100644 src/mesa/tnl_dd/t_dd_rendertmp.h create mode 100644 src/mesa/tnl_dd/t_dd_triemit.h create mode 100644 src/mesa/tnl_dd/t_dd_tritmp.h create mode 100644 src/mesa/tnl_dd/t_dd_unfilled.h create mode 100644 src/mesa/tnl_dd/t_dd_vb.c create mode 100644 src/mesa/tnl_dd/t_dd_vbtmp.h create mode 100644 src/mesa/tnl_dd/t_dd_vertex.h (limited to 'src/mesa/tnl_dd') diff --git a/src/mesa/tnl_dd/imm/NOTES.imm b/src/mesa/tnl_dd/imm/NOTES.imm new file mode 100644 index 00000000000..9b2bd65e4bf --- /dev/null +++ b/src/mesa/tnl_dd/imm/NOTES.imm @@ -0,0 +1,112 @@ + +NOTE: + +These files are incomplete. They do not yet form a working +implementation of hte concepts discused below. + + +OVERVIEW + +The t_dd_imm_* files form a set of templates to produce driver - +specific software tnl modules for a small subset of transformation and +lighting states. + +The approach is quite different to the large vertex buffers of the +src/tnl module, and is based around a cache of four recent vertices +and a 'current' vertex which is updated directly from the Color, +Normal, Texcoord, SecondaryColor and Fog entrypoints. + +The current vertex is actually a composite of the ctx->Current values +and a partial hardware vertex maintained where the hardware values +differ from those in ctx->Current. For example, clamped color values +are kept in the hardware vertex, while texcoords remain in +ctx->Current. + +A crude diagram: + + +--------------+ +-------------------+ + | ctx->Current | | Current-HW-vertex | + +--------------+ +-------------------+ + \ / + \ / + \ / + \ / + --------- -------- + | | + v v + +--------+ +--------+ +--------+ +--------+ + | vert-0 | | vert-1 | | vert-2 | | vert-3 | + +--------+ +--------+ +--------+ +--------+ + | + | + v + + DMA + + +Here values from ctx->Current and current-HW-vertex are merged to +build vert-2, which is then dumped to hardware (DMA). A state machine +determines which vertex is built in turn, and how the vertices are +used to present primitives to hardware. These actions all occur +during a call to Vertex{234}f{v}. + +Each vert-n includes clip coordinates and a clipmask in addition to +the hardware (window) coordinates. This information allows clipping +to take place directly on these vertices, if need be. + +t_dd_imm_capi.h + + Color{34}{fub}{v}() implementations. These update both + ctx->Current (unclamped float colors) and current-HW-vertex + with hardware-specific color values (typically unsigned + bytes). + + When lighting is enabled, the functions from src/api_noop.c + should be used, which just update ctx->Current. (The + current-hw-vertex colors are produced from lighting, which is + keyed to Normal3f). + +t_dd_imm_vb.c + + Support functions for clipping and fallback. See + t_dd_imm_primtmp.h. + +t_dd_imm_napi.c +t_dd_imm_napi.h + + Versions of Normal3f{v} to perform lighting with one or more + infinite lights. Updates ctx->Current.Normal and the current + HW colors. + + When lighting is disabled, use the functions from api_noop.c + instead. + + +t_dd_imm_primtmp.h + + State machine to control emission of vertices and primitives + to hardware. Called indirectly from Vertex{234}f{v}. Capable + of supporting hardware strip and fan primitives, and of + decomposing to discreet primitives for clipping or fallback, + or where the native primitive is unavailable. + +t_dd_imm_tapi.h + + Implementations of TexCoord{v} and MultiTexCoord4f{v}ARB to + fire a callback when transitioning to projective texture. + Most drivers will need to change vertex format at this point, + some may need to enable a software rasterization fallback. + +t_dd_imm_vapi.h + + Implementations of Vertex{234}f{v}. These perform + transformation and cliptesting on their arguments, then jump + into the state machine implemented in primtmp.h. + +t_dd_imm_vertex.h + + Support functions for building and clip-interpolating hardware + vertices. Called from primtmp.h. + + +Keith Whitwell, June 2001. \ No newline at end of file diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_capi.h b/src/mesa/tnl_dd/imm/t_dd_imm_capi.h new file mode 100644 index 00000000000..77f3a4ab497 --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_capi.h @@ -0,0 +1,419 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Gareth Hughes + */ + +/* Template for immediate mode color functions. + * + * FIXME: Floating-point color versions of these... + */ + + +static void TAG(Color3f)( GLfloat r, GLfloat g, GLfloat b ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = CLAMP(r, 0.0f, 1.0f); + CURRENT_COLOR( GCOMP ) = CLAMP(g, 0.0f, 1.0f); + CURRENT_COLOR( BCOMP ) = CLAMP(b, 0.0f, 1.0f); + CURRENT_COLOR( ACOMP ) = 1.0f; +#else + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), r ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), g ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), b ); + CURRENT_COLOR( ACOMP ) = 255; +#endif +} + +static void TAG(Color3fv)( const GLfloat *v ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = CLAMP(v[0], 0.0f, 1.0f); + CURRENT_COLOR( GCOMP ) = CLAMP(v[1], 0.0f, 1.0f); + CURRENT_COLOR( BCOMP ) = CLAMP(v[2], 0.0f, 1.0f); + CURRENT_COLOR( ACOMP ) = 1.0f; +#else + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), v[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), v[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), v[2] ); + CURRENT_COLOR( ACOMP ) = 255; +#endif +} + +static void TAG(Color3ub)( GLubyte r, GLubyte g, GLubyte b ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( r ); + CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( g ); + CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( b ); + CURRENT_COLOR( ACOMP ) = 1.0f; +#else + CURRENT_COLOR( RCOMP ) = r; + CURRENT_COLOR( GCOMP ) = g; + CURRENT_COLOR( BCOMP ) = b; + CURRENT_COLOR( ACOMP ) = 255; +#endif +} + +static void TAG(Color3ubv)( const GLubyte *v ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( v[0] ); + CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( v[1] ); + CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( v[2] ); + CURRENT_COLOR( ACOMP ) = 1.0f; +#else + CURRENT_COLOR( RCOMP ) = v[0]; + CURRENT_COLOR( GCOMP ) = v[1]; + CURRENT_COLOR( BCOMP ) = v[2]; + CURRENT_COLOR( ACOMP ) = 255; +#endif +} + +static void TAG(Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = CLAMP(r, 0.0f, 1.0f); + CURRENT_COLOR( GCOMP ) = CLAMP(g, 0.0f, 1.0f); + CURRENT_COLOR( BCOMP ) = CLAMP(b, 0.0f, 1.0f); + CURRENT_COLOR( ACOMP ) = CLAMP(a, 0.0f, 1.0f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), r ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), g ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), b ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( ACOMP ), a ); +#endif +} + +static void TAG(Color4fv)( const GLfloat *v ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = CLAMP(v[0], 0.0f, 1.0f); + CURRENT_COLOR( GCOMP ) = CLAMP(v[1], 0.0f, 1.0f); + CURRENT_COLOR( BCOMP ) = CLAMP(v[2], 0.0f, 1.0f); + CURRENT_COLOR( ACOMP ) = CLAMP(v[3], 0.0f, 1.0f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), v[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), v[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), v[2] ); + UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( ACOMP ), v[3] ); +#endif +} + +static void TAG(Color4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( r ); + CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( g ); + CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( b ); + CURRENT_COLOR( ACOMP ) = UBYTE_TO_FLOAT( a ); +#else + CURRENT_COLOR( RCOMP ) = r; + CURRENT_COLOR( GCOMP ) = g; + CURRENT_COLOR( BCOMP ) = b; + CURRENT_COLOR( ACOMP ) = a; +#endif +} + +static void TAG(Color4ubv)( const GLubyte *v ) +{ + GET_CURRENT; +#ifdef COLOR_IS_FLOAT + CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( v[0] ); + CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( v[1] ); + CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( v[2] ); + CURRENT_COLOR( ACOMP ) = UBYTE_TO_FLOAT( v[3] ); +#else + CURRENT_COLOR( RCOMP ) = v[0]; + CURRENT_COLOR( GCOMP ) = v[1]; + CURRENT_COLOR( BCOMP ) = v[2]; + CURRENT_COLOR( ACOMP ) = v[3]; +#endif +} + + +static void TAG(ColorMaterial3f)( GLfloat r, GLfloat g, GLfloat b ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = 1.0; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = v[0]; + color[1] = v[1]; + color[2] = v[2]; + color[3] = 1.0; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial3ub)( GLubyte r, GLubyte g, GLubyte b ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = UBYTE_TO_FLOAT( r ); + color[1] = UBYTE_TO_FLOAT( g ); + color[2] = UBYTE_TO_FLOAT( b ); + color[3] = 1.0; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial3ubv)( const GLubyte *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = UBYTE_TO_FLOAT( v[0] ); + color[1] = UBYTE_TO_FLOAT( v[1] ); + color[2] = UBYTE_TO_FLOAT( v[2] ); + color[3] = 1.0; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = r; + color[1] = g; + color[2] = b; + color[3] = a; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = v[0]; + color[1] = v[1]; + color[2] = v[2]; + color[3] = v[3]; + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = UBYTE_TO_FLOAT( r ); + color[1] = UBYTE_TO_FLOAT( g ); + color[2] = UBYTE_TO_FLOAT( b ); + color[3] = UBYTE_TO_FLOAT( a ); + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + +static void TAG(ColorMaterial4ubv)( const GLubyte *v ) +{ + GET_CURRENT_CONTEXT(ctx); + GLfloat *color = ctx->Current.Color; + + color[0] = UBYTE_TO_FLOAT( v[0] ); + color[1] = UBYTE_TO_FLOAT( v[1] ); + color[2] = UBYTE_TO_FLOAT( v[2] ); + color[3] = UBYTE_TO_FLOAT( v[3] ); + + _mesa_update_color_material( ctx, color ); + RECALC_BASE_COLOR( ctx ); +} + + + + + +/* ============================================================= + * Color chooser functions: + */ + +static void TAG(choose_Color3f)( GLfloat r, GLfloat g, GLfloat b ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color3f = TAG(ColorMaterial3f); + } else { + ctx->Exec->Color3f = _mesa_noop_Color3f; + } + } else { + ctx->Exec->Color3f = TAG(Color3f); + } + glColor3f( r, g, b ); +} + +static void TAG(choose_Color3fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color3fv = TAG(ColorMaterial3fv); + } else { + ctx->Exec->Color3fv = _mesa_noop_Color3fv; + } + } else { + ctx->Exec->Color3fv = TAG(Color3fv); + } + glColor3fv( v ); +} + +static void TAG(choose_Color3ub)( GLubyte r, GLubyte g, GLubyte b ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color3ub = TAG(ColorMaterial3ub); + } else { + ctx->Exec->Color3ub = _mesa_noop_Color3ub; + } + } else { + ctx->Exec->Color3ub = TAG(Color3ub); + } + glColor3ub( r, g, b ); +} + +static void TAG(choose_Color3ubv)( const GLubyte *v ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color3ubv = TAG(ColorMaterial3ubv); + } else { + ctx->Exec->Color3ubv = _mesa_noop_Color3ubv; + } + } else { + ctx->Exec->Color3ubv = TAG(Color3ubv); + } + glColor3ubv( v ); +} + +static void TAG(choose_Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color4f = TAG(ColorMaterial4f); + } else { + ctx->Exec->Color4f = _mesa_noop_Color4f; + } + } else { + ctx->Exec->Color4f = TAG(Color4f); + } + glColor4f( r, g, b, a ); +} + +static void TAG(choose_Color4fv)( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color4fv = TAG(ColorMaterial4fv); + } else { + ctx->Exec->Color4fv = _mesa_noop_Color4fv; + } + } else { + ctx->Exec->Color4fv = TAG(Color4fv); + } + glColor4fv( v ); +} + +static void TAG(choose_Color4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color4ub = TAG(ColorMaterial4ub); + } else { + ctx->Exec->Color4ub = _mesa_noop_Color4ub; + } + } else { + ctx->Exec->Color4ub = TAG(Color4ub); + } + glColor4ub( r, g, b, a ); +} + +static void TAG(choose_Color4ubv)( const GLubyte *v ) +{ + GET_CURRENT_CONTEXT(ctx); + + if ( ctx->Light.Enabled ) { + if ( ctx->Light.ColorMaterialEnabled ) { + ctx->Exec->Color4ubv = TAG(ColorMaterial4ubv); + } else { + ctx->Exec->Color4ubv = _mesa_noop_Color4ubv; + } + } else { + ctx->Exec->Color4ubv = TAG(Color4ubv); + } + glColor4ubv( v ); +} + + + +#undef GET_CURRENT +#undef CURRENT_COLOR +#undef CURRENT_SPECULAR +#undef COLOR_IS_FLOAT +#undef RECALC_BASE_COLOR +#undef TAG diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_napi.h b/src/mesa/tnl_dd/imm/t_dd_imm_napi.h new file mode 100644 index 00000000000..9844f615ffe --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_napi.h @@ -0,0 +1,226 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Gareth Hughes + * Keith Whitwell + */ + +/* Template for immediate mode normal functions. Optimize for infinite + * lights when doing software lighting. + */ + +static void TAG(Normal3f_single)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_VERTEX; + const struct gl_light *light = ctx->Light.EnabledList.prev; + GLfloat n_dot_h, n_dot_VP, spec, sum[3]; + GLfloat *normal = ctx->Current.Normal; + GLfloat scale = 1.0; + + ASSIGN_3V( normal, x, y, z ); + COPY_3V( sum, BASE_COLOR ); + + if ( IND & NORM_RESCALE ) { + scale = ctx->_ModelViewInvScale; + } else if ( IND & NORM_NORMALIZE ) { + scale = LEN_3FV( normal ); + if ( scale != 0.0 ) scale = 1.0 / scale; + } + + n_dot_VP = DOT3( normal, light->_VP_inf_norm ) * scale; + if ( n_dot_VP > 0.0F ) { + ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] ); + n_dot_h = DOT3( normal, light->_h_inf_norm ) * scale; + if ( n_dot_h > 0.0F ) { + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] ); + } + } + +#ifdef LIT_COLOR_IS_FLOAT + LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f); + LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f); + LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] ); +#endif + LIT_COLOR( ACOMP ) = LIT_ALPHA; +} + +static void TAG(Normal3fv_single)( const GLfloat *normal ) +{ + GET_CURRENT_VERTEX; + const struct gl_light *light = ctx->Light.EnabledList.prev; + GLfloat n_dot_h, n_dot_VP, spec, sum[3]; + GLfloat scale = 1.0; + + COPY_3V( ctx->Current.Normal, normal ); + COPY_3V( sum, BASE_COLOR ); + + if ( IND & NORM_RESCALE ) { + scale = ctx->_ModelViewInvScale; + } else if ( IND & NORM_NORMALIZE ) { + scale = LEN_3FV( normal ); + if ( scale != 0.0 ) scale = 1.0 / scale; + } + + n_dot_VP = DOT3( normal, light->_VP_inf_norm ) * scale; + if ( n_dot_VP > 0.0F ) { + ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] ); + n_dot_h = DOT3( normal, light->_h_inf_norm ) * scale; + if ( n_dot_h > 0.0F ) { + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] ); + } + } + +#ifdef LIT_COLOR_IS_FLOAT + LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f); + LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f); + LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] ); +#endif + LIT_COLOR( ACOMP ) = LIT_ALPHA; +} + + +static void TAG(Normal3f_multi)( GLfloat x, GLfloat y, GLfloat z ) +{ + GET_CURRENT_VERTEX; + struct gl_light *light; + GLfloat n_dot_h, n_dot_VP, spec, sum[3], tmp[3]; + GLfloat *normal; + + ASSIGN_3V( ctx->Current.Normal, x, y, z ); + COPY_3V( sum, BASE_COLOR ); + + if ( IND & NORM_RESCALE ) { + normal = tmp; + ASSIGN_3V( normal, x, y, z ); + SELF_SCALE_SCALAR_3V( normal, ctx->_ModelViewInvScale ); + } else if ( IND & NORM_NORMALIZE ) { + normal = tmp; + ASSIGN_3V( normal, x, y, z ); + NORMALIZE_3FV( normal ); + } else { + normal = ctx->Current.Normal; + } + + foreach ( light, &ctx->Light.EnabledList ) { + n_dot_VP = DOT3( normal, light->_VP_inf_norm ); + if ( n_dot_VP > 0.0F ) { + ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] ); + n_dot_h = DOT3( normal, light->_h_inf_norm ); + if ( n_dot_h > 0.0F ) { + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] ); + } + } + } + +#ifdef LIT_COLOR_IS_FLOAT + LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f); + LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f); + LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] ); +#endif + LIT_COLOR( ACOMP ) = LIT_ALPHA; +} + +static void TAG(Normal3fv_multi)( const GLfloat *n ) +{ + GET_CURRENT_VERTEX; + struct gl_light *light; + GLfloat n_dot_h, n_dot_VP, spec, sum[3], tmp[3]; + GLfloat *normal; + + COPY_3V( ctx->Current.Normal, n ); + COPY_3V( sum, BASE_COLOR ); + + if ( IND & NORM_RESCALE ) { + normal = tmp; + COPY_3V( normal, n ); + SELF_SCALE_SCALAR_3V( normal, ctx->_ModelViewInvScale ); + } else if ( IND & NORM_NORMALIZE ) { + normal = tmp; + COPY_3V( normal, n ); + NORMALIZE_3FV( normal ); + } else { + normal = ctx->Current.Normal; + } + + foreach ( light, &ctx->Light.EnabledList ) { + n_dot_VP = DOT3( normal, light->_VP_inf_norm ); + if ( n_dot_VP > 0.0F ) { + ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] ); + n_dot_h = DOT3( normal, light->_h_inf_norm ); + if ( n_dot_h > 0.0F ) { + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] ); + } + } + } + +#ifdef LIT_COLOR_IS_FLOAT + LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f); + LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f); + LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f); +#else + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] ); + UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] ); +#endif + LIT_COLOR( ACOMP ) = LIT_ALPHA; +} + + + +static void TAG(init_norm)( void ) +{ + norm_tab[IND].normal3f_single = TAG(Normal3f_single); + norm_tab[IND].normal3fv_single = TAG(Normal3fv_single); + norm_tab[IND].normal3f_multi = TAG(Normal3f_multi); + norm_tab[IND].normal3fv_multi = TAG(Normal3fv_multi); +} + + + +#ifndef PRESERVE_NORMAL_DEFS +#undef GET_CURRENT +#undef GET_CURRENT_VERTEX +#undef LIT_COLOR +#undef LIT_COLOR_IS_FLOAT +#endif +#undef PRESERVE_NORMAL_DEFS +#undef IND +#undef TAG diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h b/src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h new file mode 100644 index 00000000000..97dca3fd421 --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h @@ -0,0 +1,570 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + * Gareth Hughes + */ + +/* Template for immediate mode vertices. + * + * Probably instantiate once for each vertex format used: + * - TINY_VERTICES + * - TEX0_VERTICES + * - TEX1_VERTICES + * - PTEX_VERTICES + * + * Have to handle TEX->PTEX transition somehow. + */ + +#define DBG 0 + + + +/* ============================================================= + * GL_POINTS + */ + +static void TAG(flush_point_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + if ( !v0->mask ) { + LOCAL_VARS; + DRAW_POINT( v0 ); + } +} + + +/* ============================================================= + * GL_LINES + */ + +static void TAG(flush_line_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_line_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + FLUSH_VERTEX = TAG(flush_line_1); + ACTIVE_VERTEX = IMM_VERTICES( 1 ); +} + +static void TAG(flush_line_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v1 = v0 - 1; + ACTIVE_VERTEX = IMM_VERTICES( 0 ); + FLUSH_VERTEX = TAG(flush_line_0); + if (FALLBACK_OR_CLIPPING) + CLIP_OR_DRAW_LINE( ctx, v1, v0 ); + else + DRAW_LINE( ctx, v1, v0 ); +} + + +/* ============================================================= + * GL_LINE_LOOP + */ + +static void TAG(flush_line_loop_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_line_loop_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_line_loop_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_line_loop_1); +} + +#define DRAW_LINELOOP_LINE( a, b ) \ + if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING) { \ + CLIP_OR_DRAW_LINE( ctx, a, b ); \ + } else if (EXTEND_PRIM( 1 )) { \ + EMIT_VERTEX( b ); \ + } else { \ + BEGIN_PRIM( GL_LINE_STRIP, 2 ); \ + EMIT_VERTEX( a ); \ + EMIT_VERTEX( b ); \ + } + +static void TAG(flush_line_loop_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v1 = v0 - 1; + ACTIVE_VERTEX = v1; + FLUSH_VERTEX = TAG(flush_line_loop_2); + DRAW_LINELOOP_LINE( v1, v0 ); +} + +static void TAG(flush_line_loop_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v1 = v0 + 1; + ACTIVE_VERTEX = v1; + FLUSH_VERTEX = TAG(flush_line_loop_1); + DRAW_LINELOOP_LINE( v1, v0 ); +} + +static void TAG(end_line_loop)( GLcontext *ctx ) +{ + LOCAL_VARS; + + if ( FLUSH_VERTEX != TAG(flush_line_loop_0) ) { + TNL_VERTEX *v1 = ACTIVE_VERTEX; + TNL_VERTEX *v0 = IMM_VERTICES( 0 ); + DRAW_LINELOOP_LINE( v1, v0 ); + } +} + + + +/* ============================================================= + * GL_LINE_STRIP + */ + +static void TAG(flush_line_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_line_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_line_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_line_strip_0b); +} + + +static void TAG(flush_line_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v1 = v0 - 1; + + ACTIVE_VERTEX = v1; + FLUSH_VERTEX = TAG(flush_line_strip_2); + + if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING) + CLIP_OR_DRAW_LINE( ctx, v1, v0 ); + else if (EXTEND_PRIM( 1 )) { + EMIT_VERTEX( v0 ); + } else { + BEGIN_PRIM( GL_LINE_STRIP, 2 ); + EMIT_VERTEX( v1 ); + EMIT_VERTEX( v0 ); + } +} + +static void TAG(flush_line_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v1 = v0 + 1; + + ACTIVE_VERTEX = v1; + FLUSH_VERTEX = TAG(flush_line_strip_1); + + if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING) + CLIP_OR_DRAW_LINE( ctx, v1, v0 ); + else if (EXTEND_PRIM( 1 )) { + EMIT_VERTEX( v0 ); + } else { + BEGIN_PRIM( GL_LINE_STRIP, 2 ); + EMIT_VERTEX( v1 ); + EMIT_VERTEX( v0 ); + } +} + + + +/* ============================================================= + * GL_TRIANGLES + */ + +static void TAG(flush_triangle_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_triangle_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_triangle_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" ); + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_triangle_1); + BEGIN_PRIM( GL_TRIANGLES, 0 ); +} + +static void TAG(flush_triangle_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" ); + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_triangle_2); +} + +static void TAG(flush_triangle_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v2 = v0 - 2; + TNL_VERTEX *v1 = v0 - 1; + + if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" ); + + ACTIVE_VERTEX = v2; + FLUSH_VERTEX = TAG(flush_triangle_0); + + /* nothing gained by trying to emit as hw primitives -- that + * happens normally in this case. + */ + if (FALLBACK_OR_CLIPPING) + CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 ); + else + DRAW_TRI( ctx, v2, v1, v0 ); +} + + + + +/* ============================================================= + * GL_TRIANGLE_STRIP + */ + +static void TAG(flush_tri_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_tri_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_tri_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_tri_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 1 ); + FLUSH_VERTEX = TAG(flush_tri_strip_1); +} + +static void TAG(flush_tri_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 2 ); + FLUSH_VERTEX = TAG(flush_tri_strip_2); +} + +#define DO_TRISTRIP_TRI( vert0, vert1 ) \ + if (!HAVE_TRI_STRIP || FALLBACK_OR_CLIPPING) { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + TAG(draw_tri)( ctx, v2, v1, v0 ); \ + } else if (EXTEND_PRIM( 1 )) { \ + EMIT_VERTEX( v0 ); \ + } else { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + BEGIN_PRIM( GL_TRIANGLE_STRIP, 3 ); \ + EMIT_VERTEX( v2 ); \ + EMIT_VERTEX( v1 ); \ + EMIT_VERTEX( v0 ); \ + } + +static void TAG(flush_tri_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + FLUSH_VERTEX = TAG(flush_tri_strip_3); + ACTIVE_VERTEX = IMM_VERTICES( 3 ); + DO_TRISTRIP_TRI( 0, 1 ); +} + +static void TAG(flush_tri_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + FLUSH_VERTEX = TAG(flush_tri_strip_4); + ACTIVE_VERTEX = IMM_VERTICES( 0 ); + DO_TRISTRIP_TRI( 1, 2 ); +} + +static void TAG(flush_tri_strip_4)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + FLUSH_VERTEX = TAG(flush_tri_strip_5); + ACTIVE_VERTEX = IMM_VERTICES( 1 ); + DO_TRISTRIP_TRI( 2, 3 ); +} + +static void TAG(flush_tri_strip_5)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + FLUSH_VERTEX = TAG(flush_tri_strip_2); + ACTIVE_VERTEX = IMM_VERTICES( 2 ); + DO_TRISTRIP_TRI( 0, 3 ); +} + + + +/* ============================================================= + * GL_TRIANGLE_FAN + */ + +static void TAG(flush_tri_fan_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_tri_fan_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_tri_fan_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_tri_fan_1); +} + +static void TAG(flush_tri_fan_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + ACTIVE_VERTEX = v0 + 1; + FLUSH_VERTEX = TAG(flush_tri_fan_2); +} + +#define DO_TRIFAN_TRI( vert0, vert1 ) \ + if (!HAVE_TRI_FAN || FALLBACK_OR_CLIPPING) { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + TAG(draw_tri)( ctx, v2, v1, v0 ); \ + } else if (EXTEND_PRIM( 1 )) { \ + EMIT_VERTEX( v0 ); \ + } else { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + BEGIN_PRIM( GL_TRIANGLE_FAN, 3 ); \ + EMIT_VERTEX( v2 ); \ + EMIT_VERTEX( v1 ); \ + EMIT_VERTEX( v0 ); \ + } + +static void TAG(flush_tri_fan_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 1 ); + FLUSH_VERTEX = TAG(flush_tri_fan_3 ); + DO_TRIFAN_TRI( 0, 1 ); +} + +static void TAG(flush_tri_fan_3)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 2 ); + FLUSH_VERTEX = TAG(flush_tri_fan_2 ); + DO_TRIFAN_TRI( 0, 2 ); +} + + + +/* ============================================================= + * GL_QUADS + */ + +static void TAG(flush_quad_3)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_quad_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_quad_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_quad_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_1); +} + +static void TAG(flush_quad_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_2); +} + +static void TAG(flush_quad_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_3); +} + +static void TAG(flush_quad_3)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v3 = v0 - 3; + TNL_VERTEX *v2 = v0 - 2; + TNL_VERTEX *v1 = v0 - 1; + + IMM_VERTEX( v0 ) = v3; + FLUSH_VERTEX = TAG(flush_quad_0); + + if (!HAVE_HW_QUADS || FALLBACK_OR_CLIPPING) { + CLIP_OR_DRAW_TRI( ctx, v3, v2, v0 ); + CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 ); + } else { + EXTEND_PRIM_NF( GL_QUADS, 4 ); + EMIT_VERTEX( v3 ); + EMIT_VERTEX( v2 ); + EMIT_VERTEX( v1 ); + EMIT_VERTEX( v0 ); + } +} + + + +/* ============================================================= + * GL_QUAD_STRIP + */ + +static void TAG(flush_quad_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_quad_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_quad_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_quad_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + IMM_VERTEX( v3 ) = v0; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_strip_1); +} + +static void TAG(flush_quad_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + IMM_VERTEX( v2 ) = v0; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_strip_2); +} + +static void TAG(flush_quad_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + + IMM_VERTEX( v1 ) = v0; + IMM_VERTEX( v0 ) = v0 + 1; + FLUSH_VERTEX = TAG(flush_quad_strip_3); +} + +static void TAG(flush_quad_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + TNL_VERTEX *v3 = IMM_VERTEX( v3 ); + TNL_VERTEX *v2 = IMM_VERTEX( v2 ); + TNL_VERTEX *v1 = IMM_VERTEX( v1 ); + + IMM_VERTEX( v0 ) = v3; + IMM_VERTEX( v2 ) = v0; + IMM_VERTEX( v3 ) = v1; + FLUSH_VERTEX = TAG(flush_quad_strip_2); + + if (FALLBACK_OR_CLIPPING) { + CLIP_OR_DRAW_TRI( ctx, v3, v2, v0 ); + CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 ); + } else { + DRAW_TRI( ctx, v3, v2, v0 ); + DRAW_TRI( ctx, v2, v1, v0 ); + } +} + + + +/* ============================================================= + * GL_POLYGON + */ + +static void TAG(flush_poly_2)( GLcontext *ctx, TNL_VERTEX *v0 ); +static void TAG(flush_poly_1)( GLcontext *ctx, TNL_VERTEX *v0 ); + +static void TAG(flush_poly_0)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 1 ); + FLUSH_VERTEX = TAG(flush_poly_1); +} + +static void TAG(flush_poly_1)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 2 ); + FLUSH_VERTEX = TAG(flush_poly_2); +} + +#define DO_POLY_TRI( vert0, vert1 ) \ + if (!HAVE_POLYGONS || FALLBACK_OR_CLIPPING) { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + TAG(draw_tri)( ctx, v1, v0, v2 ); \ + } else if (EXTEND_PRIM( 1 )) { \ + EMIT_VERTEX( v0 ); \ + } else { \ + TNL_VERTEX *v2 = IMM_VERTICES( vert0 ); \ + TNL_VERTEX *v1 = IMM_VERTICES( vert1 ); \ + BEGIN_PRIM( GL_POLYGON, 3 ); \ + EMIT_VERTEX( v2 ); \ + EMIT_VERTEX( v1 ); \ + EMIT_VERTEX( v0 ); \ + } + +static void TAG(flush_poly_2)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 1 ); + FLUSH_VERTEX = TAG(flush_poly_3); + DO_POLY_TRI( 0, 1 ); +} + +static void TAG(flush_poly_3)( GLcontext *ctx, TNL_VERTEX *v0 ) +{ + LOCAL_VARS; + ACTIVE_VERTEX = IMM_VERTICES( 2 ); + FLUSH_VERTEX = TAG(flush_poly_2); + DO_POLY_TRI( 0, 2 ); +} + + +void (*TAG(flush_tab)[GL_POLYGON+1])( GLcontext *, TNL_VERTEX * ) = +{ + TAG(flush_point), + TAG(flush_line_0), + TAG(flush_line_loop_0), + TAG(flush_line_strip_0), + TAG(flush_triangle_0), + TAG(flush_tri_strip_0), + TAG(flush_tri_fan_0), + TAG(flush_quad_0), + TAG(flush_quad_strip_0), + TAG(flush_poly_0), +}; + + +#ifndef PRESERVE_PRIM_DEFS +#undef LOCAL_VARS +#undef GET_INTERP_FUNC +#undef IMM_VERTEX +#undef IMM_VERTICES +#undef FLUSH_VERTEX +#endif +#undef PRESERVE_PRIM_DEFS +#undef EXTEND_PRIM +#undef EMIT_VERTEX +#undef EMIT_VERTEX_TRI +#undef EMIT_VERTEX_LINE +#undef EMIT_VERTEX_POINT +#undef TAG diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_tapi.h b/src/mesa/tnl_dd/imm/t_dd_imm_tapi.h new file mode 100644 index 00000000000..b82a9abebff --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_tapi.h @@ -0,0 +1,75 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Gareth Hughes + * Keith Whitwell + */ + +/* Template for immediate mode texture coordinate functions. + */ + +#ifndef DO_PROJ_TEX +#error "Need to define DO_PROJ_TEX" +#endif + + +/* ============================================================= + * Notify on calls to texture4f, to allow switch to projected texture + * vertex format: + */ + +static void TAG(TexCoord4f)( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) +{ + GET_CURRENT; + DO_PROJ_TEX; + TEXCOORD4( s, t, r, q ); +} + +static void TAG(TexCoord4fv)( const GLfloat *v ) +{ + GET_CURRENT; + DO_PROJ_TEX; + TEXCOORD4( v[0], v[1], v[2], v[3] ); +} + +static void TAG(MultiTexCoord4fARB)( GLenum target, GLfloat s, + GLfloat t, GLfloat r, GLfloat q ) +{ + GET_CURRENT; + DO_PROJ_TEX; + MULTI_TEXCOORD4( unit, s, t, r, q ); +} + +static void TAG(MultiTexCoord4fvARB)( GLenum target, const GLfloat *v ) +{ + GET_CURRENT; + DO_PROJ_TEX; + MULTI_TEXCOORD4( unit, v[0], v[1], v[2], v[3] ); +} + + + +#undef DO_PROJ_TEX +#undef TAG diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vapi.h b/src/mesa/tnl_dd/imm/t_dd_imm_vapi.h new file mode 100644 index 00000000000..95e93b1c839 --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_vapi.h @@ -0,0 +1,159 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Gareth Hughes + * Keith Whitwell + */ + +/* Template for immediate mode vertex functions. + */ + +#define DBG 0 + +#define VERTEX( ox, oy, oz, ow ) +do { + GET_CURRENT_VERTEX; + GLfloat w; + GLuint mask; + const GLfloat * const m = ctx->_ModelProjectMatrix.m; + + if (DO_FULL_MATRIX) { + VERTEX_CLIP(0) = m[0] * ox + m[4] * oy + m[8] * oz + m[12] * ow; + VERTEX_CLIP(1) = m[1] * ox + m[5] * oy + m[9] * oz + m[13] * ow; + VERTEX_CLIP(2) = m[2] * ox + m[6] * oy + m[10] * oz + m[14] * ow; + VERTEX_CLIP(3) = m[3] * ox + m[7] * oy + m[11] * oz + m[15] * ow; + w = VERTEX_CLIP(3); + } + else if (DO_NOROT_MATRIX) { + VERTEX_CLIP(0) = m[0] * ox + m[12] * ow; + VERTEX_CLIP(1) = m[5] * oy + m[13] * ow; + VERTEX_CLIP(2) = m[10] * oz + m[14] * ow; + VERTEX_CLIP(3) = ow; + w = ow; + } + else { + ASSERT (DO_IDENTITY_MATRIX); + VERTEX_CLIP(0) = ox; + VERTEX_CLIP(1) = oy; + VERTEX_CLIP(2) = oz; + VERTEX_CLIP(3) = ow; + w = ow; + } + + mask = 0; + if (DO_CLIP_TEST) { + if ( VERTEX_CLIP(0) > w ) mask |= CLIP_RIGHT_BIT; + if ( VERTEX_CLIP(0) < -w ) mask |= CLIP_LEFT_BIT; + if ( VERTEX_CLIP(1) > w ) mask |= CLIP_TOP_BIT; + if ( VERTEX_CLIP(1) < -w ) mask |= CLIP_BOTTOM_BIT; + if ( VERTEX_CLIP(2) > w ) mask |= CLIP_FAR_BIT; + if ( VERTEX_CLIP(2) < -w ) mask |= CLIP_NEAR_BIT; + VERTEX_MASK(v) = mask; + } + + if (!mask) { + if (HAVE_VERTEX_WIN) { + if (!HAVE_HW_VIEWPORT) { + const GLfloat *s = GET_VIEWPORT_MATRIX(); + if (HAVE_W && HAVE_HW_DIVIDE) { + VERTEX_WIN( 0 ) = s[0] * VERTEX_CLIP( 0 ) + s[12]; + VERTEX_WIN( 1 ) = s[5] * VERTEX_CLIP( 1 ) + s[13]; + VERTEX_WIN( 2 ) = s[10] * VERTEX_CLIP( 2 ) + s[14]; + VERTEX_WIN( 3 ) = w; + } + else { + const GLfloat oow = 1.0/w; /* possibly opt away */ + VERTEX_WIN( 0 ) = s[0] * VERTEX_CLIP( 0 ) * oow + s[12]; + VERTEX_WIN( 1 ) = s[5] * VERTEX_CLIP( 1 ) * oow + s[13]; + VERTEX_WIN( 2 ) = s[10] * VERTEX_CLIP( 2 ) * oow + s[14]; + if (HAVE_W) + VERTEX_WIN( 3 ) = oow; + } + } + else if (HAVE_W && HAVE_HW_DIVIDE) { + if (!VERTEX_WIN_IS_VERTEX_CLIP) { + VERTEX_WIN( 0 ) = VERTEX_CLIP( 0 ); + VERTEX_WIN( 1 ) = VERTEX_CLIP( 1 ); + VERTEX_WIN( 2 ) = VERTEX_CLIP( 2 ); + VERTEX_WIN( 3 ) = w; + } + } + else { + const GLfloat oow = 1.0/w; /* possibly opt away */ + VERTEX_WIN( 0 ) = VERTEX_CLIP( 0 ) * oow; + VERTEX_WIN( 1 ) = VERTEX_CLIP( 1 ) * oow; + VERTEX_WIN( 2 ) = VERTEX_CLIP( 2 ) * oow; + if (HAVE_W) + VERTEX_WIN( 3 ) = oow; + } + } + } else if (!FALLBACK_OR_CLIPPING) { + SET_CLIPPING(); /* transition to clipping */ + } + + COPY_VERTEX_FROM_CURRENT; + BUILD_PRIM_FROM_VERTEX; +} + +/* Let the compiler optimize away the constant operations: + */ +static void VTAG(Vertex2f)( GLfloat ox, GLfloat oy ) +{ + /* Cliptest on clip[2] could also be eliminated... + */ + VERTEX( ox, oy, 0, 1 ); +} + +static void VTAG(Vertex2fv)( const GLfloat *obj ) +{ + /* Cliptest on clip[2] could also be eliminated... + */ + VERTEX( obj[0], obj[1], 0, 1 ); +} + +static void VTAG(Vertex3f)( GLfloat ox, GLfloat oy, GLfloat oz ) +{ + VERTEX( ox, oy, oz, 1 ); +} + +static void VTAG(Vertex3fv)( const GLfloat *obj ) +{ + VERTEX( obj[0], obj[1], obj[2], 1 ); +} + +static void VTAG(Vertex4f)( GLfloat ox, GLfloat oy, GLfloat oz, GLfloat ow ) +{ + VERTEX( ox, oy, oz, ow ); +} + +static void VTAG(Vertex4fv)( const GLfloat *obj ) +{ + VERTEX( obj[0], obj[1], obj[2], obj[3] ); +} + + +#undef DO_FULL_MATRIX +#undef VTAG +#undef VERTEX diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vb.c b/src/mesa/tnl_dd/imm/t_dd_imm_vb.c new file mode 100644 index 00000000000..0c4462f556f --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_vb.c @@ -0,0 +1,204 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + +/* Template to build clipping routines to support t_dd_imm_primtmp.h. + * + * The TAG(draw_line) and TAG(draw_triangle) routines are called in + * clipping and fallback scenarios, and when the native hardware + * primitive (eg polygons) is unavailable. + */ + + +#define CLIP_DOTPROD(K, A, B, C, D) \ + (CLIP_X(K)*A + CLIP_Y(K)*B + \ + CLIP_Z(K)*C + CLIP_W(K)*D) + +#define POLY_CLIP( PLANE, A, B, C, D ) \ +do { \ + if (mask & PLANE) { \ + TNL_VERTEX **indata = inlist[in]; \ + TNL_VERTEX **outdata = inlist[in ^= 1]; \ + TNL_VERTEX *J = indata[0]; \ + GLfloat dpJ = CLIP_DOTPROD(J, A, B, C, D ); \ + GLuint outcount = 0; \ + GLuint i; \ + \ + indata[n] = indata[0]; /* prevent rotation of vertices */ \ + for (i = 1; i <= n; i++) { \ + TNL_VERTEX *I = indata[i]; \ + GLfloat dpI = CLIP_DOTPROD(idx, A, B, C, D ); \ + \ + if (!NEGATIVE(dpPrev)) { \ + outdata[outcount++] = J; \ + } \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + TNL_VERTEX *O = verts++; \ + outdata[outcount++] = O; \ + if (NEGATIVE(dpI)) { \ + /* Going out of bounds. Avoid division by zero as we \ + * know dp != dpPrev from DIFFERENT_SIGNS, above. \ + */ \ + GLfloat t = dpI / (dpI - dpJ); \ + INTERP( ctx, t, O, I, J ); \ + } else { \ + /* Coming back in. \ + */ \ + GLfloat t = dpJ / (dpJ - dpI); \ + INTERP( ctx, t, O, J, I ); \ + } \ + } \ + \ + J = I; \ + dpJ = dpI; \ + } \ + \ + if (outcount < 3) \ + return; \ + \ + nr = outcount; \ + } \ +} while (0) + + +#define LINE_CLIP(PLANE, A, B, C, D ) \ +do { \ + if (mask & PLANE) { \ + GLfloat dpI = CLIP_DOTPROD( I, A, B, C, D ); \ + GLfloat dpJ = CLIP_DOTPROD( J, A, B, C, D ); \ + \ + if (DIFFERENT_SIGNS(dpI, dpJ)) { \ + TNL_VERTEX *O = verts++; \ + if (NEGATIVE(dpJ)) { \ + GLfloat t = dpI / (dpI - dpJ); \ + INTERP( ctx, t, O, I, J ); \ + J = O; \ + } else { \ + GLfloat t = dpJ / (dpJ - dpI); \ + INTERP( ctx, t, O, J, I ); \ + I = O; \ + } \ + } \ + else if (NEGATIVE(dpI)) \ + return; \ + } \ +} while (0) + + + +/* Clip a line against the viewport and user clip planes. + */ +static void TAG(clip_draw_line)( GLcontext *ctx, + TNL_VERTEX *I, + TNL_VERTEX *J, + GLuint mask ) +{ + LOCAL_VARS; + GET_INTERP_FUNC; + TNL_VERTEX tmp[MAX_CLIPPED_VERTICES]; + TNL_VERTEX *verts = tmp; + TNL_VERTEX *pv = J; + + LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); + LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); + LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); + LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); + LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); + LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); + + if ((ctx->_TriangleCaps & DD_FLATSHADE) && J != pv) + COPY_PV( ctx, J, pv ); + + DRAW_LINE( I, J ); +} + + +/* Clip a triangle against the viewport and user clip planes. + */ +static void TAG(clip_draw_triangle)( GLcontext *ctx, + TNL_VERTEX *v0, + TNL_VERTEX *v1, + TNL_VERTEX *v2, + GLuint mask ) +{ + LOCAL_VARS; + GET_INTERP_FUNC; + TNL_VERTEX tmp[MAX_CLIPPED_VERTICES]; + TNL_VERTEX *verts = tmp; + TNL_VERTEX *(inlist[2][MAX_CLIPPED_VERTICES]); + TNL_VERTEX **out; + GLuint in = 0; + GLuint n = 3; + GLuint i; + + ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ + + POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); + POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); + POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); + POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); + POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); + POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); + + if ((ctx->_TriangleCaps & DD_FLATSHADE) && v2 != inlist[0]) + COPY_PV( ctx, inlist[0], v2 ); + + out = inlist[in]; + DRAW_POLYGON( out, n ); +} + + +static __inline void TAG(draw_triangle)( GLcontext *ctx, + TNL_VERTEX *v0, + TNL_VERTEX *v1, + TNL_VERTEX *v2 ) +{ + LOCAL_VARS; + GLubyte ormask = (v0->mask | v1->mask | v2->mask); + + if ( !ormask ) { + DRAW_TRI( v0, v1, v2 ); + } else if ( !(v0->mask & v1->mask & v2->mask) ) { + TAG(clip_draw_triangle)( ctx, v0, v1, v2, ormask ); + } +} + +static __inline void TAG(draw_line)( GLcontext *ctx, + TNL_VERTEX *v0, + TNL_VERTEX *v1 ) +{ + LOCAL_VARS; + GLubyte ormask = (v0->mask | v1->mask); + + if ( !ormask ) { + DRAW_LINE( v0, v1 ); + } else if ( !(v0->mask & v1->mask) ) { + TAG(clip_draw_line)( ctx, v0, v1, ormask ); + } +} + diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h b/src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h new file mode 100644 index 00000000000..2f76553cff9 --- /dev/null +++ b/src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h @@ -0,0 +1,268 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + +/* Template to build support for t_dd_imm_* tnl module using vertices + * as defined in t_dd_vertex.h. + * + * See t_dd_vbtmp.h for definitions of arguments to this file. + * Unfortunately it seems necessary to duplicate a lot of that code. + */ + +#ifndef LOCALVARS +#define LOCALVARS +#endif + + + +/* COPY_VERTEX_FROM_CURRENT in t_dd_imm_vapi.c + */ +static void TAG(emit_vfmt)( GLcontext *ctx, VERTEX *v ) +{ + LOCALVARS + ; + + /* This template assumes (like t_dd_vbtmp.h) that color is ubyte. + */ + if (DO_TEX0 || DO_TEX1 || !HAVE_TINY_VERTICES) + { + const GLubyte *col = GET_HARDWARE_COLOR(); + if (HAVE_RGBA_COLOR) { + v->v.ui[4] = *(GLuint *)&col; + } else { + v->v.color.blue = col[2]; + v->v.color.green = col[1]; + v->v.color.red = col[0]; + v->v.color.alpha = col[3]; + } + } + else { + if (HAVE_RGBA_COLOR) { + v->v.ui[3] = *(GLuint *)col; + } + else { + v->tv.color.blue = col[2]; + v->tv.color.green = col[1]; + v->tv.color.red = col[0]; + v->tv.color.alpha = col[3]; + } + } + + if (DO_TEX0) { + GLfloat *tc = ctx->Current.Texture[0]; + v->v.u0 = tc[0]; + v->v.v0 = tc[1]; + if (DO_PTEX) { + if (HAVE_PTEX_VERTICES) { + v->pv.q0 = tc[3]; + } + else { + float rhw = 1.0 / tc[3]; + v->v.w *= tc[3]; + v->v.u0 *= rhw; + v->v.v0 *= rhw; + } + } + } + if (DO_TEX1) { + GLfloat *tc = ctx->Current.Texture[1]; + if (DO_PTEX) { + v->pv.u1 = tc[0]; + v->pv.v1 = tc[1]; + v->pv.q1 = tc[3]; + } + else { + v->v.u1 = tc[0]; + v->v.v1 = tc[1]; + } + } + else if (DO_PTEX) { + *(GLuint *)&v->pv.q1 = 0; /* avoid culling on radeon */ + } + if (DO_TEX2) { + GLfloat *tc = ctx->Current.Texture[2]; + if (DO_PTEX) { + v->pv.u2 = tc[0]; + v->pv.v2 = tc[1]; + v->pv.q2 = tc[3]; + } + else { + v->v.u2 = tc[0]; + v->v.v2 = tc[1]; + } + } + if (DO_TEX3) { + GLfloat *tc = ctx->Current.Texture[3]; + if (DO_PTEX) { + v->pv.u3 = tc[0]; + v->pv.v3 = tc[1]; + v->pv.q3 = tc[3]; + } + else { + v->v.u3 = tc[0]; + v->v.v3 = tc[1]; + } + } +} + + + + +static void TAG(interp)( GLcontext *ctx, + GLfloat t, + TNL_VERTEX *dst, + TNL_VERTEX *in, + TNL_VERTEX *out ) +{ + LOCALVARS + const GLfloat *s = GET_VIEWPORT_MAT(); + GLfloat w; + + (void)s; + + if (HAVE_HW_DIVIDE) { + VIEWPORT_X( dst->v.v.x, dst->clip[0] ); + VIEWPORT_Y( dst->v.v.y, dst->clip[1] ); + VIEWPORT_Z( dst->v.v.z, dst->clip[2] ); + w = dstclip[3]; + } + else { + w = 1.0 / dst->clip[3]; + VIEWPORT_X( dst->v.v.x, dst->clip[0] * w ); + VIEWPORT_Y( dst->v.v.y, dst->clip[1] * w ); + VIEWPORT_Z( dst->v.v.z, dst->clip[2] * w ); + } + + if (HAVE_HW_DIVIDE || DO_TEX0) { + + dst->v.v.w = w; + + INTERP_UB( t, dst->v.ub4[4][0], out->v.ub4[4][0], in->v.ub4[4][0] ); + INTERP_UB( t, dst->v.ub4[4][1], out->v.ub4[4][1], in->v.ub4[4][1] ); + INTERP_UB( t, dst->v.ub4[4][2], out->v.ub4[4][2], in->v.ub4[4][2] ); + INTERP_UB( t, dst->v.ub4[4][3], out->v.ub4[4][3], in->v.ub4[4][3] ); + + if (DO_TEX0) { + if (DO_PTEX) { + if (HAVE_PTEX_VERTICES) { + INTERP_F( t, dst->v.pv.u0, out->v.pv.u0, in->v.pv.u0 ); + INTERP_F( t, dst->v.pv.v0, out->v.pv.v0, in->v.pv.v0 ); + INTERP_F( t, dst->v.pv.q0, out->v.pv.q0, in->v.pv.q0 ); + } else { + GLfloat wout = out->clip[3]; /* projected clip */ + GLfloat win = in->clip[3]; /* projected clip */ + GLfloat qout = out->v.pv.w / wout; + GLfloat qin = in->v.pv.w / win; + GLfloat qdst, rqdst; + + ASSERT( !HAVE_HW_DIVIDE ); /* assert win, wout projected clip */ + + INTERP_F( t, dst->v.v.u0, out->v.v.u0 * qout, in->v.v.u0 * qin ); + INTERP_F( t, dst->v.v.v0, out->v.v.v0 * qout, in->v.v.v0 * qin ); + INTERP_F( t, qdst, qout, qin ); + + rqdst = 1.0 / qdst; + dst->v.v.u0 *= rqdst; + dst->v.v.v0 *= rqdst; + dst->v.v.w *= rqdst; + } + } + else { + INTERP_F( t, dst->v.v.u0, out->v.v.u0, in->v.v.u0 ); + INTERP_F( t, dst->v.v.v0, out->v.v.v0, in->v.v.v0 ); + } + } + if (DO_TEX1) { + if (DO_PTEX) { + INTERP_F( t, dst->v.pv.u1, out->v.pv.u1, in->v.pv.u1 ); + INTERP_F( t, dst->v.pv.v1, out->v.pv.v1, in->v.pv.v1 ); + INTERP_F( t, dst->v.pv.q1, out->v.pv.q1, in->v.pv.q1 ); + } else { + INTERP_F( t, dst->v.v.u1, out->v.v.u1, in->v.v.u1 ); + INTERP_F( t, dst->v.v.v1, out->v.v.v1, in->v.v.v1 ); + } + } + else if (DO_PTEX) { + dst->v.pv.q0 = 0.0; /* must be a valid float on radeon */ + } + if (DO_TEX2) { + if (DO_PTEX) { + INTERP_F( t, dst->v.pv.u2, out->v.pv.u2, in->v.pv.u2 ); + INTERP_F( t, dst->v.pv.v2, out->v.pv.v2, in->v.pv.v2 ); + INTERP_F( t, dst->v.pv.q2, out->v.pv.q2, in->v.pv.q2 ); + } else { + INTERP_F( t, dst->v.v.u2, out->v.v.u2, in->v.v.u2 ); + INTERP_F( t, dst->v.v.v2, out->v.v.v2, in->v.v.v2 ); + } + } + if (DO_TEX3) { + if (DO_PTEX) { + INTERP_F( t, dst->v.pv.u3, out->v.pv.u3, in->v.pv.u3 ); + INTERP_F( t, dst->v.pv.v3, out->v.pv.v3, in->v.pv.v3 ); + INTERP_F( t, dst->v.pv.q3, out->v.pv.q3, in->v.pv.q3 ); + } else { + INTERP_F( t, dst->v.v.u3, out->v.v.u3, in->v.v.u3 ); + INTERP_F( t, dst->v.v.v3, out->v.v.v3, in->v.v.v3 ); + } + } + } else { + /* 4-dword vertex. Color is in v[3] and there is no oow coordinate. + */ + INTERP_UB( t, dst->v.ub4[3][0], out->v.ub4[3][0], in->v.ub4[3][0] ); + INTERP_UB( t, dst->v.ub4[3][1], out->v.ub4[3][1], in->v.ub4[3][1] ); + INTERP_UB( t, dst->v.ub4[3][2], out->v.ub4[3][2], in->v.ub4[3][2] ); + INTERP_UB( t, dst->v.ub4[3][3], out->v.ub4[3][3], in->v.ub4[3][3] ); + } +} + + +static __inline void TAG(copy_pv)( GLcontext *ctx, + TNL_VERTEX *dst, + TNL_VERTEX *src ) +{ + if (DO_TEX0 || DO_TEX1 || !HAVE_TINY_VERTICES) { + dst->v.v.ui[4] = src->v.v.ui[4]; + } + else { + dst->v.v.ui[3] = src->v.v.ui[3]; + } +} + + + +static void TAG(init)( void ) +{ + setup_tab[IND].emit = TAG(emit_vfmt); + setup_tab[IND].interp = TAG(interp_vfmt); +} + + +#undef IND +#undef TAG + + + diff --git a/src/mesa/tnl_dd/t_dd.c b/src/mesa/tnl_dd/t_dd.c new file mode 100644 index 00000000000..731da5c320d --- /dev/null +++ b/src/mesa/tnl_dd/t_dd.c @@ -0,0 +1,58 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + +static void copy_pv_rgba4_spec5( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLubyte *i810verts = (GLubyte *)imesa->verts; + GLuint shift = imesa->vertex_stride_shift; + i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift)); + i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift)); + dst->ui[4] = src->ui[4]; + dst->ui[5] = src->ui[5]; +} + +static void copy_pv_rgba4( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLubyte *i810verts = (GLubyte *)imesa->verts; + GLuint shift = imesa->vertex_stride_shift; + i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift)); + i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift)); + dst->ui[4] = src->ui[4]; +} + +static void copy_pv_rgba3( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + i810ContextPtr imesa = I810_CONTEXT( ctx ); + GLubyte *i810verts = (GLubyte *)imesa->verts; + GLuint shift = imesa->vertex_stride_shift; + i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift)); + i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift)); + dst->ui[3] = src->ui[3]; +} diff --git a/src/mesa/tnl_dd/t_dd_dmatmp.h b/src/mesa/tnl_dd/t_dd_dmatmp.h new file mode 100644 index 00000000000..d9f709389d1 --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_dmatmp.h @@ -0,0 +1,1105 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + + +/* 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. + * + * Produces code for both inline triangles and indexed triangles. + * 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) +#error "must have at least triangles to use render template" +#endif + +#if !HAVE_ELTS +#define ELTS_VARS +#define ALLOC_ELTS( nr ) +#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 + +#ifndef EMIT_TWO_ELTS +#define EMIT_TWO_ELTS( offset, elt0, elt1 ) \ +do { \ + EMIT_ELT( offset, elt0 ); \ + EMIT_ELT( offset+1, elt1 ); \ +} while (0) +#endif + +#ifndef FINISH +#define FINISH +#endif + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + + + +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 ) +{ + GLint i; + LOCAL_VARS; + ELTS_VARS; + + ALLOC_ELTS( nr ); + + for ( i = 0 ; i < nr ; i+=2, elts += 2 ) { + EMIT_TWO_ELTS( 0, elts[0], elts[1] ); + INCR_ELTS( 2 ); + } +} +#endif + + +/*********************************************************************** + * Render non-indexed primitives. + ***********************************************************************/ + + + +static void TAG(render_points_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_POINTS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + GLuint j, nr; + + INIT( GL_POINTS ); + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr ) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_lines_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINES) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + GLuint j, nr; + + INIT( GL_LINES ); + + /* Emit whole number of lines in total and in each buffer: + */ + count -= (count-start) & 1; + currentsz -= currentsz & 1; + dmasz -= dmasz & 1; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr ) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_line_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINE_STRIPS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + GLuint j, nr; + + NEW_PRIMITIVE(); /* always a new primitive */ + INIT( GL_LINE_STRIP ); + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j + 1 < count; j += nr - 1 ) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_line_loop_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINE_STRIPS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + GLuint j, nr; + + NEW_PRIMITIVE(); + INIT( GL_LINE_STRIP ); + + if (flags & PRIM_BEGIN) + j = start; + else + j = start + 1; + + /* Ensure last vertex won't wrap buffers: + */ + 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 (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 ); + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_triangles_verts)( GLcontext *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; + GLuint j, nr; + + INIT(GL_TRIANGLES); + + /* Emit whole number of tris in total. dmasz is already a multiple + * of 3. + */ + count -= (count-start)%3; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + FINISH; +} + + + +static void TAG(render_tri_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_TRI_STRIPS) { + LOCAL_VARS; + GLuint j, nr; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + 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); + currentsz -= (currentsz & 1); + + for (j = start ; j + 2 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_tri_fan_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_TRI_FANS) { + LOCAL_VARS; + GLuint j, nr; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + + NEW_PRIMITIVE(); + INIT(GL_TRIANGLE_FAN); + + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { + nr = MIN2( currentsz, count - j + 1 ); + EMIT_VERTS( ctx, start, 1 ); + EMIT_VERTS( ctx, j, nr - 1 ); + currentsz = dmasz; + } + + FINISH; + + } + else { + /* Could write code to emit these as indexed vertices (for the + * g400, for instance). + */ + VERT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_poly_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_POLYGONS) { + LOCAL_VARS; + GLuint j, nr; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + + NEW_PRIMITIVE(); + INIT(GL_POLYGON); + + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { + nr = MIN2( currentsz, count - j + 1 ); + EMIT_VERTS( ctx, start, 1 ); + EMIT_VERTS( ctx, j, nr - 1 ); + currentsz = dmasz; + } + + FINISH; + + } + else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) { + TAG(render_tri_fan_verts)( ctx, start, count, flags ); + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_quad_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + GLuint j, nr; + + if (HAVE_QUAD_STRIPS) { + LOCAL_VARS; + GLuint j, nr; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz; + + INIT(GL_QUAD_STRIP); + NEW_PRIMITIVE(); + + currentsz = GET_CURRENT_VB_MAX_VERTS(); + + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + dmasz -= (dmasz & 2); + currentsz -= (currentsz & 2); + + for (j = start ; j + 3 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + + FINISH; + + } else if (HAVE_TRI_STRIPS && (ctx->_TriangleCaps & DD_FLATSHADE)) { + if (TAG(emit_elt_verts)( ctx, start, count )) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint j, nr; + + /* Simulate flat-shaded quadstrips using indexed vertices: + */ + NEW_PRIMITIVE(); + ELT_INIT( GL_TRIANGLES ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 1; + count -= (count-start) & 1; + currentsz -= currentsz & 1; + + if (currentsz < 12) + currentsz = dmasz; + + currentsz = currentsz/6*2; + dmasz = dmasz/6*2; + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + if (nr >= 4) { + GLint quads = (nr/2)-1; + GLint i; + ELTS_VARS; + + NEW_PRIMITIVE(); + ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + + for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) { + EMIT_TWO_ELTS( 0, (i+0), (i+1) ); + EMIT_TWO_ELTS( 2, (i+2), (i+1) ); + EMIT_TWO_ELTS( 4, (i+3), (i+2) ); + INCR_ELTS( 6 ); + } + + NEW_PRIMITIVE(); + } + currentsz = dmasz; + } + + RELEASE_ELT_VERTS(); + } + else { + /* Vertices won't fit in a single buffer or elts not available, + * VERT_FALLBACK. + */ + VERT_FALLBACK( ctx, start, count, flags ); + } + } + else if (HAVE_TRI_STRIPS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS(); + int currentsz = GET_CURRENT_VB_MAX_VERTS(); + + /* Emit smooth-shaded quadstrips as tristrips: + */ + NEW_PRIMITIVE(); + INIT( GL_TRIANGLE_STRIP ); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 1; + 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 ); + currentsz = dmasz; + } + + FINISH; + + } else { + VERT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_quads_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_QUADS) { + LOCAL_VARS; + int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4; + int currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4; + GLuint j, nr; + + INIT(GL_QUADS); + + /* Emit whole number of quads in total. dmasz is already a multiple + * of 4. + */ + count -= (count-start)%4; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr) { + nr = MIN2( currentsz, count - j ); + EMIT_VERTS( ctx, j, nr ); + currentsz = dmasz; + } + FINISH; + } else if (TAG(emit_elt_verts)( ctx, start, count )) { + /* Hardware doesn't have a quad primitive type -- try to + * simulate it using indexed vertices and the triangle + * primitive: + */ + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint j, nr; + + NEW_PRIMITIVE(); + ELT_INIT( GL_TRIANGLES ); + currentsz = GET_CURRENT_VB_MAX_ELTS(); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 3; + count -= (count-start) & 3; + currentsz -= currentsz & 3; + + /* Adjust for rendering as triangles: + */ + currentsz = currentsz/6*4; + dmasz = dmasz/6*4; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr ) { + nr = MIN2( currentsz, count - j ); + if (nr >= 4) { + GLint quads = nr/4; + GLint i; + ELTS_VARS; + + NEW_PRIMITIVE(); + ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + + for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) { + EMIT_TWO_ELTS( 0, (i+0), (i+1) ); + EMIT_TWO_ELTS( 2, (i+3), (i+1) ); + EMIT_TWO_ELTS( 4, (i+2), (i+3) ); + INCR_ELTS( 6 ); + } + + NEW_PRIMITIVE(); + } + currentsz = dmasz; + } + + RELEASE_ELT_VERTS(); + } + else { + /* Vertices won't fit in a single buffer, fallback. + */ + VERT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_noop)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ +} + + + + +static render_func TAG(render_tab_verts)[GL_POLYGON+2] = +{ + TAG(render_points_verts), + TAG(render_lines_verts), + TAG(render_line_loop_verts), + TAG(render_line_strip_verts), + TAG(render_triangles_verts), + TAG(render_tri_strip_verts), + TAG(render_tri_fan_verts), + TAG(render_quads_verts), + TAG(render_quad_strip_verts), + TAG(render_poly_verts), + TAG(render_noop), +}; + + +/**************************************************************************** + * Render elts using hardware indexed verts * + ****************************************************************************/ + +#if (HAVE_ELTS) +static void TAG(render_points_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_POINTS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + GLuint j, nr; + + ELT_INIT( GL_POINTS ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr ) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + ELT_FALLBACK( ctx, start, count, flags ); + } +} + + + +static void TAG(render_lines_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINES) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + GLuint j, nr; + + ELT_INIT( GL_LINES ); + + /* Emit whole number of lines in total and in each buffer: + */ + count -= (count-start) & 1; + currentsz -= currentsz & 1; + dmasz -= dmasz & 1; + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr ) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + ELT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_line_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINE_STRIPS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + GLuint j, nr; + + NEW_PRIMITIVE(); /* always a new primitive */ + ELT_INIT( GL_LINE_STRIP ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j + 1 < count; j += nr - 1 ) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + /* TODO: Try to emit as indexed lines. + */ + ELT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_line_loop_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_LINE_STRIPS) { + LOCAL_VARS; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + GLuint j, nr; + + NEW_PRIMITIVE(); + ELT_INIT( GL_LINE_STRIP ); + + if (flags & PRIM_BEGIN) + j = start; + else + j = start + 1; + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + /* Ensure last vertex doesn't wrap: + */ + 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 (flags & PRIM_END) + TAG(emit_elts)( ctx, elts+start, 1 ); + + NEW_PRIMITIVE(); + } else { + /* TODO: Try to emit as indexed lines */ + ELT_FALLBACK( ctx, start, count, flags ); + } +} + + +/* For verts, we still eliminate the copy from main memory to dma + * buffers. For elts, this is probably no better (worse?) than the + * standard path. + */ +static void TAG(render_triangles_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3; + int currentsz; + GLuint j, nr; + + NEW_PRIMITIVE(); + ELT_INIT( GL_TRIANGLES ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + + /* Emit whole number of tris in total. dmasz is already a multiple + * of 3. + */ + count -= (count-start)%3; + currentsz -= currentsz%3; + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j < count; j += nr) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } +} + + + +static void TAG(render_tri_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_TRI_STRIPS) { + LOCAL_VARS; + GLuint j, nr; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + + NEW_PRIMITIVE(); + 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); + currentsz -= (currentsz & 1); + + for (j = start ; j + 2 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + /* TODO: try to emit as indexed triangles */ + ELT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_tri_fan_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_TRI_FANS) { + 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 ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { + nr = MIN2( currentsz, count - j + 1 ); + TAG(emit_elts)( ctx, elts+start, 1 ); + TAG(emit_elts)( ctx, elts+j, nr - 1 ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + /* TODO: try to emit as indexed triangles */ + ELT_FALLBACK( ctx, start, count, flags ); + } +} + + +static void TAG(render_poly_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_POLYGONS && 0) { + } else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) { + 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 ); + + currentsz = GET_CURRENT_VB_MAX_ELTS(); + if (currentsz < 8) { + NEW_BUFFER(); + currentsz = dmasz; + } + + for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { + nr = MIN2( currentsz, count - j + 1 ); + TAG(emit_elts)( ctx, elts+start, 1 ); + TAG(emit_elts)( ctx, elts+j, nr - 1 ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } else { + ELT_FALLBACK( ctx, start, count, flags ); + } +} + +static void TAG(render_quad_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_QUAD_STRIPS && 0) { + } + else if (HAVE_TRI_STRIPS) { + LOCAL_VARS; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint j, nr; + + NEW_PRIMITIVE(); + currentsz = GET_CURRENT_VB_MAX_ELTS(); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 1; + count -= (count-start) & 1; + currentsz -= currentsz & 1; + + if (currentsz < 12) + currentsz = dmasz; + + if (ctx->_TriangleCaps & DD_FLATSHADE) { + ELT_INIT( GL_TRIANGLES ); + + currentsz = currentsz/6*2; + dmasz = dmasz/6*2; + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + + if (nr >= 4) + { + GLint i; + GLint quads = (nr/2)-1; + ELTS_VARS; + + + NEW_PRIMITIVE(); + ALLOC_ELTS_NEW_PRIMITIVE( quads*6 ); + + for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) { + EMIT_TWO_ELTS( 0, elts[0], elts[1] ); + EMIT_TWO_ELTS( 2, elts[2], elts[1] ); + EMIT_TWO_ELTS( 4, elts[3], elts[2] ); + INCR_ELTS( 6 ); + } + + NEW_PRIMITIVE(); + } + + currentsz = dmasz; + } + } + else { + ELT_INIT( GL_TRIANGLE_STRIP ); + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + TAG(emit_elts)( ctx, elts+j, nr ); + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } + } +} + + +static void TAG(render_quads_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (HAVE_QUADS && 0) { + } else { + LOCAL_VARS; + GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts; + int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS(); + int currentsz; + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES ); + currentsz = GET_CURRENT_VB_MAX_ELTS(); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 3; + count -= (count-start) & 3; + currentsz -= currentsz & 3; + + /* Adjust for rendering as triangles: + */ + currentsz = currentsz/6*4; + dmasz = dmasz/6*4; + + if (currentsz < 8) + currentsz = dmasz; + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( currentsz, count - j ); + + if (nr >= 4) + { + GLint quads = nr/4; + GLint i; + ELTS_VARS; + NEW_PRIMITIVE(); + ALLOC_ELTS_NEW_PRIMITIVE( quads * 6 ); + + for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) { + EMIT_TWO_ELTS( 0, elts[0], elts[1] ); + EMIT_TWO_ELTS( 2, elts[3], elts[1] ); + EMIT_TWO_ELTS( 4, elts[2], elts[3] ); + INCR_ELTS( 6 ); + } + } + + NEW_PRIMITIVE(); + currentsz = dmasz; + } + } +} + + + +static render_func TAG(render_tab_elts)[GL_POLYGON+2] = +{ + TAG(render_points_elts), + TAG(render_lines_elts), + TAG(render_line_loop_elts), + TAG(render_line_strip_elts), + TAG(render_triangles_elts), + TAG(render_tri_strip_elts), + TAG(render_tri_fan_elts), + TAG(render_quads_elts), + TAG(render_quad_strip_elts), + TAG(render_poly_elts), + TAG(render_noop), +}; +#endif diff --git a/src/mesa/tnl_dd/t_dd_dmatmp2.h b/src/mesa/tnl_dd/t_dd_dmatmp2.h new file mode 100644 index 00000000000..3f58d24c952 --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_dmatmp2.h @@ -0,0 +1,949 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + + +/* 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. + * + */ + +#if !HAVE_TRIANGLES || !HAVE_POINTS || !HAVE_LINES +#error "must have points, lines & triangles to use render template" +#endif + +#if !HAVE_TRI_STRIPS || !HAVE_TRI_FANS +#error "must have tri strip and fans to use render template" +#endif + +#if !HAVE_LINE_STRIPS +#error "must have line strips to use render template" +#endif + +#if !HAVE_POLYGONS +#error "must have polygons to use render template" +#endif + +#if !HAVE_ELTS +#error "must have elts to use render template" +#endif + + +#ifndef EMIT_TWO_ELTS +#define EMIT_TWO_ELTS( dest, offset, elt0, elt1 ) \ +do { \ + (dest)[offset] = (elt0); \ + (dest)[offset+1] = (elt1); \ +} while (0) +#endif + + +/**********************************************************************/ +/* Render whole begin/end objects */ +/**********************************************************************/ + + +static ELT_TYPE *TAG(emit_elts)( GLcontext *ctx, + ELT_TYPE *dest, + GLuint *elts, GLuint nr ) +{ + GLint i; + LOCAL_VARS; + + for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) { + EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); + dest += 2; + } + if (i < nr) { + EMIT_ELT( dest, 0, elts[0] ); + dest += 1; + } + + return dest; +} + +static ELT_TYPE *TAG(emit_consecutive_elts)( GLcontext *ctx, + ELT_TYPE *dest, + GLuint start, GLuint nr ) +{ + GLint i; + LOCAL_VARS; + + for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) { + EMIT_TWO_ELTS( dest, 0, start, start+1 ); + dest += 2; + } + if (i < nr) { + EMIT_ELT( dest, 0, start ); + dest += 1; + } + + return dest; +} + +/*********************************************************************** + * Render non-indexed primitives. + ***********************************************************************/ + + + +static void TAG(render_points_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (start < count) { + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count ); + } +} + +static void TAG(render_lines_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + count -= (count-start) & 1; + + if (start+1 >= count) + return; + + if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) { + RESET_STIPPLE(); + AUTO_STIPPLE( GL_TRUE ); + } + + EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count ); + + if ((flags & PRIM_END) && ctx->Line.StippleFlag) + AUTO_STIPPLE( GL_FALSE ); +} + + +static void TAG(render_line_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (start+1 >= count) + return; + + if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) + RESET_STIPPLE(); + + + if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) + { + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + + ELT_INIT( GL_LINES, HW_LINES ); + + /* Emit whole number of lines in each full buffer. + */ + dmasz = dmasz/2; + + + for (j = start; j + 1 < count; j += nr - 1 ) { + ELT_TYPE *dest; + GLint i; + + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( (nr-1)*2 ); + + for ( i = j ; i+1 < j+nr ; i+=1 ) { + EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); + dest += 2; + } + + CLOSE_ELTS(); + } + } + else + EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count ); +} + + +static void TAG(render_line_loop_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint j, nr; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (flags & PRIM_BEGIN) { + j = start; + if (ctx->Line.StippleFlag) + RESET_STIPPLE( ); + } + else + j = start + 1; + + if (flags & PRIM_END) { + + if (start+1 >= count) + return; + + if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) { + int dmasz = GET_MAX_HW_ELTS(); + + ELT_INIT( GL_LINES, HW_LINES ); + + /* Emit whole number of lines in each full buffer. + */ + dmasz = dmasz/2; + + /* Ensure last vertex doesn't wrap: + */ + dmasz--; + + for (; j + 1 < count; ) { + GLint i; + ELT_TYPE *dest; + + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr*2 ); /* allocs room for 1 more line */ + + for ( i = 0 ; i < nr - 1 ; i+=1 ) { + EMIT_TWO_ELTS( dest, 0, (j+i), (j+i+1) ); + dest += 2; + } + + j += nr - 1; + + /* Emit 1 more line into space alloced above */ + if (j + 1 >= count) { + EMIT_TWO_ELTS( dest, 0, (j), (start) ); + dest += 2; + } + + CLOSE_ELTS(); + } + } + else + { + int dmasz = GET_MAX_HW_ELTS() - 1; + + ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); + + for ( ; j + 1 < count; ) { + nr = MIN2( dmasz, count - j ); + if (j + nr < count) { + ELT_TYPE *dest = ALLOC_ELTS( nr ); + dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr ); + j += nr - 1; + CLOSE_ELTS(); + } + else if (nr) { + ELT_TYPE *dest = ALLOC_ELTS( nr + 1 ); + dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr ); + dest = TAG(emit_consecutive_elts)( ctx, dest, start, 1 ); + j += nr; + CLOSE_ELTS(); + } + } + } + } else { + TAG(render_line_strip_verts)( ctx, j, count, flags ); + } +} + + +static void TAG(render_triangles_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + count -= (count-start)%3; + + if (start+2 >= count) { + return; + } + + /* need a PREFER_DISCRETE_ELT_PRIM here too.. + */ + EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count ); +} + + + +static void TAG(render_tri_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (start + 2 >= count) + return; + + if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES )) + { + int dmasz = GET_MAX_HW_ELTS(); + int parity = 0; + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + if (flags & PRIM_PARITY) + parity = 1; + + /* Emit even number of tris in each full buffer. + */ + dmasz = dmasz/3; + dmasz -= dmasz & 1; + + for (j = start; j + 2 < count; j += nr - 2 ) { + ELT_TYPE *dest; + GLint i; + + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( (nr-2)*3 ); + + for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) { + EMIT_ELT( dest, 0, (i+0+parity) ); + EMIT_ELT( dest, 1, (i+1-parity) ); + EMIT_ELT( dest, 2, (i+2) ); + dest += 3; + } + + CLOSE_ELTS(); + } + } + else if ((flags & PRIM_PARITY) == 0) + EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count ); + else if (HAVE_TRI_STRIP_1) + EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_1, start, count ); + else { + /* Emit the first triangle with elts, then the rest as a regular strip. + * TODO: Make this unlikely in t_imm_api.c + */ + ELT_TYPE *dest; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + dest = ALLOC_ELTS( 3 ); + EMIT_ELT( dest, 0, (start+1) ); + EMIT_ELT( dest, 1, (start+0) ); + EMIT_ELT( dest, 2, (start+2) ); + dest += 3; + CLOSE_ELTS(); + + start++; + if (start + 2 >= count) + return; + + EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, + count ); + } +} + +static void TAG(render_tri_fan_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (start+2 >= count) + return; + + if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES )) + { + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + dmasz = dmasz/3; + + for (j = start + 1; j + 1 < count; j += nr - 1 ) { + ELT_TYPE *dest; + GLint i; + + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( (nr-1)*3 ); + + for ( i = j ; i+1 < j+nr ; i++ ) { + EMIT_ELT( dest, 0, (start) ); + EMIT_ELT( dest, 1, (i) ); + EMIT_ELT( dest, 2, (i+1) ); + dest += 3; + } + + CLOSE_ELTS(); + } + } + else { + EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count ); + } +} + + +static void TAG(render_poly_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (start+2 >= count) + return; + + EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count ); +} + +static void TAG(render_quad_strip_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + count -= (count-start) & 1; + + if (start+3 >= count) + return; + + if (HAVE_QUAD_STRIPS) { + EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count ); + } + else if (ctx->_TriangleCaps & DD_FLATSHADE) { + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz = (dmasz/6)*2; + + for (j = start; j + 3 < count; j += nr - 2 ) { + ELT_TYPE *dest; + GLint quads, i; + + nr = MIN2( dmasz, count - j ); + quads = (nr/2)-1; + dest = ALLOC_ELTS( quads*6 ); + + for ( i = j ; i < j+quads*2 ; i+=2 ) { + EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); + EMIT_TWO_ELTS( dest, 2, (i+2), (i+1) ); + EMIT_TWO_ELTS( dest, 4, (i+3), (i+2) ); + dest += 6; + } + + CLOSE_ELTS(); + } + } + else { + EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count ); + } +} + + +static void TAG(render_quads_verts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + count -= (count-start)%4; + + if (start+3 >= count) + return; + + if (HAVE_QUADS) { + EMIT_PRIM( ctx, HW_QUADS, GL_QUADS, start, count ); + } + else { + /* Hardware doesn't have a quad primitive type -- simulate it + * using indexed vertices and the triangle primitive: + */ + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + /* Adjust for rendering as triangles: + */ + dmasz = (dmasz/6)*4; + + for (j = start; j < count; j += nr ) { + ELT_TYPE *dest; + GLint quads, i; + + nr = MIN2( dmasz, count - j ); + quads = nr/4; + dest = ALLOC_ELTS( quads*6 ); + + for ( i = j ; i < j+quads*4 ; i+=4 ) { + EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) ); + EMIT_TWO_ELTS( dest, 2, (i+3), (i+1) ); + EMIT_TWO_ELTS( dest, 4, (i+2), (i+3) ); + dest += 6; + } + + CLOSE_ELTS(); + } + } +} + +static void TAG(render_noop)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ +} + + + + +static render_func TAG(render_tab_verts)[GL_POLYGON+2] = +{ + TAG(render_points_verts), + TAG(render_lines_verts), + TAG(render_line_loop_verts), + TAG(render_line_strip_verts), + TAG(render_triangles_verts), + TAG(render_tri_strip_verts), + TAG(render_tri_fan_verts), + TAG(render_quads_verts), + TAG(render_quad_strip_verts), + TAG(render_poly_verts), + TAG(render_noop), +}; + + +/**************************************************************************** + * Render elts using hardware indexed verts * + ****************************************************************************/ + +static void TAG(render_points_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + ELT_TYPE *dest; + + ELT_INIT( GL_POINTS, HW_POINTS ); + + for (j = start; j < count; j += nr ) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } +} + + + +static void TAG(render_lines_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + ELT_TYPE *dest; + + if (start+1 >= count) + return; + + if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) { + RESET_STIPPLE(); + AUTO_STIPPLE( GL_TRUE ); + } + + ELT_INIT( GL_LINES, HW_LINES ); + + /* Emit whole number of lines in total and in each buffer: + */ + count -= (count-start) & 1; + dmasz -= dmasz & 1; + + for (j = start; j < count; j += nr ) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } + + if ((flags & PRIM_END) && ctx->Line.StippleFlag) + AUTO_STIPPLE( GL_FALSE ); +} + + +static void TAG(render_line_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + ELT_TYPE *dest; + + if (start+1 >= count) + return; + + ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); + + if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) + RESET_STIPPLE(); + + for (j = start; j + 1 < count; j += nr - 1 ) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } +} + + +static void TAG(render_line_loop_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + int dmasz = GET_MAX_HW_ELTS(); + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + ELT_TYPE *dest; + + if (0) fprintf(stderr, "%s\n", __FUNCTION__); + + if (flags & PRIM_BEGIN) + j = start; + else + j = start + 1; + + + if (flags & PRIM_END) { + if (start+1 >= count) + return; + } + else { + if (j+1 >= count) + return; + } + + ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP ); + + if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) + RESET_STIPPLE(); + + + /* Ensure last vertex doesn't wrap: + */ + dmasz--; + + for ( ; j + 1 < count; ) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr+1 ); /* Reserve possible space for last elt */ + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + j += nr - 1; + if (j + 1 >= count && (flags & PRIM_END)) { + dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); + } + CLOSE_ELTS(); + } +} + + +static void TAG(render_triangles_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint *elts = GET_MESA_ELTS(); + int dmasz = GET_MAX_HW_ELTS()/3*3; + GLuint j, nr; + ELT_TYPE *dest; + + if (start+2 >= count) + return; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + + /* Emit whole number of tris in total. dmasz is already a multiple + * of 3. + */ + count -= (count-start)%3; + + for (j = start; j < count; j += nr) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } +} + + + +static void TAG(render_tri_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint j, nr; + GLuint *elts = GET_MESA_ELTS(); + int dmasz = GET_MAX_HW_ELTS(); + ELT_TYPE *dest; + + if (start+2 >= count) + return; + + ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 ); + + /* Keep the same winding over multiple buffers: + */ + dmasz -= (dmasz & 1); + + for (j = start ; j + 2 < count; j += nr - 2 ) { + nr = MIN2( dmasz, count - j ); + + if (flags & PRIM_PARITY) { + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, 1 ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr-1 ); + nr--; flags &= ~PRIM_PARITY; + CLOSE_ELTS(); + } + else { + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } + } +} + +static void TAG(render_tri_fan_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + int dmasz = GET_MAX_HW_ELTS(); + ELT_TYPE *dest; + + if (start+2 >= count) + return; + + ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN ); + + for (j = start + 1 ; j + 1 < count; j += nr - 1 ) { + nr = MIN2( dmasz, count - j + 1 ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 ); + CLOSE_ELTS(); + } +} + + +static void TAG(render_poly_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + GLuint *elts = GET_MESA_ELTS(); + GLuint j, nr; + int dmasz = GET_MAX_HW_ELTS(); + ELT_TYPE *dest; + + if (start+2 >= count) + return; + + ELT_INIT( GL_POLYGON, HW_POLYGON ); + + for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) { + nr = MIN2( dmasz, count - j + 1 ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+start, 1 ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 ); + CLOSE_ELTS(); + } +} + +static void TAG(render_quad_strip_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (start+3 >= count) + return; + + if (HAVE_QUAD_STRIPS && 0) { + } + else { + LOCAL_VARS; + GLuint *elts = GET_MESA_ELTS(); + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + ELT_TYPE *dest; + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 1; + count -= (count-start) & 1; + + if (ctx->_TriangleCaps & DD_FLATSHADE) { + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + dmasz = dmasz/6*2; + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( dmasz, count - j ); + + if (nr >= 4) + { + GLint quads = (nr/2)-1; + ELT_TYPE *dest = ALLOC_ELTS( quads*6 ); + GLint i; + + for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) { + EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); + EMIT_TWO_ELTS( dest, 2, elts[2], elts[1] ); + EMIT_TWO_ELTS( dest, 4, elts[3], elts[2] ); + dest += 6; + } + + CLOSE_ELTS(); + } + } + } + else { + ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 ); + + for (j = start; j + 3 < count; j += nr - 2 ) { + nr = MIN2( dmasz, count - j ); + dest = ALLOC_ELTS( nr ); + dest = TAG(emit_elts)( ctx, dest, elts+j, nr ); + CLOSE_ELTS(); + } + } + } +} + + +static void TAG(render_quads_elts)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + if (start+3 >= count) + return; + + if (HAVE_QUADS && 0) { + } else { + LOCAL_VARS; + GLuint *elts = GET_MESA_ELTS(); + int dmasz = GET_MAX_HW_ELTS(); + GLuint j, nr; + + ELT_INIT( GL_TRIANGLES, HW_TRIANGLES ); + + /* Emit whole number of quads in total, and in each buffer. + */ + dmasz -= dmasz & 3; + count -= (count-start) & 3; + + /* Adjust for rendering as triangles: + */ + dmasz = dmasz/6*4; + + for (j = start; j + 3 < count; j += nr ) { + nr = MIN2( dmasz, count - j ); + + { + GLint quads = nr/4; + ELT_TYPE *dest = ALLOC_ELTS( quads * 6 ); + GLint i; + + for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) { + EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] ); + EMIT_TWO_ELTS( dest, 2, elts[3], elts[1] ); + EMIT_TWO_ELTS( dest, 4, elts[2], elts[3] ); + dest += 6; + } + + CLOSE_ELTS(); + } + } + } +} + + + +static render_func TAG(render_tab_elts)[GL_POLYGON+2] = +{ + TAG(render_points_elts), + TAG(render_lines_elts), + TAG(render_line_loop_elts), + TAG(render_line_strip_elts), + TAG(render_triangles_elts), + TAG(render_tri_strip_elts), + TAG(render_tri_fan_elts), + TAG(render_quads_elts), + TAG(render_quad_strip_elts), + TAG(render_poly_elts), + TAG(render_noop), +}; diff --git a/src/mesa/tnl_dd/t_dd_rendertmp.h b/src/mesa/tnl_dd/t_dd_rendertmp.h new file mode 100644 index 00000000000..fc00e76934b --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_rendertmp.h @@ -0,0 +1,437 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + + +#ifndef POSTFIX +#define POSTFIX +#endif + +#ifndef INIT +#define INIT(x) +#endif + +#ifndef NEED_EDGEFLAG_SETUP +#define NEED_EDGEFLAG_SETUP 0 +#define EDGEFLAG_GET(a) 0 +#define EDGEFLAG_SET(a,b) (void)b +#endif + +#ifndef RESET_STIPPLE +#define RESET_STIPPLE +#endif + +#ifndef RESET_OCCLUSION +#define RESET_OCCLUSION +#endif + +#ifndef TEST_PRIM_END +#define TEST_PRIM_END(flags) (flags & PRIM_END) +#define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN) +#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY) +#endif + +#ifndef ELT +#define ELT(x) x +#endif + +#ifndef RENDER_TAB_QUALIFIER +#define RENDER_TAB_QUALIFIER static +#endif + +static void TAG(render_points)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + LOCAL_VARS; + (void) flags; + + RESET_OCCLUSION; + INIT(GL_POINTS); + RENDER_POINTS( start, count ); + POSTFIX; +} + +static void TAG(render_lines)( GLcontext *ctx, + GLuint start, + GLuint count, + GLuint flags ) +{ + GLuint j; + LOCAL_VARS; + (void) flags; + + RESET_OCCLUSION; + INIT(GL_LINES); + for (j=start+1; j + */ + + +/* Template for building functions to plug into the driver interface + * of t_vb_render.c: + * ctx->Driver.QuadFunc + * ctx->Driver.TriangleFunc + * ctx->Driver.LineFunc + * ctx->Driver.PointsFunc + * + * DO_TWOSIDE: Plug back-color values from the VB into backfacing triangles, + * and restore vertices afterwards. + * DO_OFFSET: Calculate offset for triangles and adjust vertices. Restore + * vertices after rendering. + * DO_FLAT: For hardware without native flatshading, copy provoking colors + * into the other vertices. Restore after rendering. + * DO_UNFILLED: Decompose triangles to lines and points where appropriate. + * + * HAVE_RGBA: Vertices have rgba values (otherwise index values). + * HAVE_SPEC: Vertices have secondary rgba values. + * + * VERT_X(v): Alias for vertex x value. + * VERT_Y(v): Alias for vertex y value. + * VERT_Z(v): Alias for vertex z value. + * DEPTH_SCALE: Scale for offset. + * + * VERTEX: Hardware vertex type. + * GET_VERTEX(n): Retreive vertex with index n. + * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw. + * + * VERT_SET_RGBA: Assign vertex rgba from VB color. + * VERT_COPY_RGBA: Copy vertex rgba another vertex. + * VERT_SAVE_RGBA: Save vertex rgba to a local variable. + * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable. + * --> Similar for IND and SPEC. + * + * LOCAL_VARS(n): (At least) define local vars for save/restore rgba. + * + */ + +#if HAVE_RGBA +#define VERT_SET_IND( v, c ) (void) c +#define VERT_COPY_IND( v0, v1 ) +#define VERT_SAVE_IND( idx ) +#define VERT_RESTORE_IND( idx ) +#if HAVE_BACK_COLORS +#define VERT_SET_RGBA( v, c ) +#endif +#else +#define VERT_SET_RGBA( v, c ) (void) c +#define VERT_COPY_RGBA( v0, v1 ) +#define VERT_SAVE_RGBA( idx ) +#define VERT_RESTORE_RGBA( idx ) +#if HAVE_BACK_COLORS +#define VERT_SET_IND( v, c ) +#endif +#endif + +#if !HAVE_SPEC +#define VERT_SET_SPEC( v, c ) (void) c +#define VERT_COPY_SPEC( v0, v1 ) +#define VERT_SAVE_SPEC( idx ) +#define VERT_RESTORE_SPEC( idx ) +#if HAVE_BACK_COLORS +#define VERT_COPY_SPEC1( v ) +#endif +#else +#if HAVE_BACK_COLORS +#define VERT_SET_SPEC( v, c ) +#endif +#endif + +#if !HAVE_BACK_COLORS +#define VERT_COPY_SPEC1( v ) +#define VERT_COPY_IND1( v ) +#define VERT_COPY_RGBA1( v ) +#endif + +#ifndef INSANE_VERTICES +#define VERT_SET_Z(v,val) VERT_Z(v) = val +#define VERT_Z_ADD(v,val) VERT_Z(v) += val +#endif + +#if DO_TRI +static void TAG(triangle)( GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2 ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; + VERTEX *v[3]; + GLfloat offset; + GLfloat z[3]; + GLenum mode = GL_FILL; + GLuint facing; + LOCAL_VARS(3); + +/* fprintf(stderr, "%s\n", __FUNCTION__); */ + + v[0] = (VERTEX *)GET_VERTEX(e0); + v[1] = (VERTEX *)GET_VERTEX(e1); + v[2] = (VERTEX *)GET_VERTEX(e2); + + if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED) + { + GLfloat ex = VERT_X(v[0]) - VERT_X(v[2]); + GLfloat ey = VERT_Y(v[0]) - VERT_Y(v[2]); + GLfloat fx = VERT_X(v[1]) - VERT_X(v[2]); + GLfloat fy = VERT_Y(v[1]) - VERT_Y(v[2]); + GLfloat cc = ex*fy - ey*fx; + + if (DO_TWOSIDE || DO_UNFILLED) + { + facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit; + + if (DO_UNFILLED) { + if (facing) { + mode = ctx->Polygon.BackMode; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode != GL_FRONT) { + return; + } + } else { + mode = ctx->Polygon.FrontMode; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode != GL_BACK) { + return; + } + } + } + + if (DO_TWOSIDE && facing == 1) + { + if (HAVE_RGBA) { + if (HAVE_BACK_COLORS) { + if (!DO_FLAT) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_COPY_RGBA1( v[0] ); + VERT_COPY_RGBA1( v[1] ); + } + VERT_SAVE_RGBA( 2 ); + VERT_COPY_RGBA1( v[2] ); + if (HAVE_SPEC) { + if (!DO_FLAT) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_COPY_SPEC1( v[0] ); + VERT_COPY_SPEC1( v[1] ); + } + VERT_SAVE_SPEC( 2 ); + VERT_COPY_SPEC1( v[2] ); + } + } + else { + GLchan (*vbcolor)[4] = VB->ColorPtr[1]->Ptr; + ASSERT(VB->ColorPtr[1]->Type == CHAN_TYPE); + ASSERT(VB->ColorPtr[1]->StrideB == 4*sizeof(GLchan)); + (void) vbcolor; + + if (!DO_FLAT) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_SET_RGBA( v[0], vbcolor[e0] ); + VERT_SET_RGBA( v[1], vbcolor[e1] ); + } + VERT_SAVE_RGBA( 2 ); + VERT_SET_RGBA( v[2], vbcolor[e2] ); + + if (HAVE_SPEC && VB->SecondaryColorPtr[1]) { + GLchan (*vbspec)[4] = VB->SecondaryColorPtr[1]->Ptr; + + if (!DO_FLAT) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_SET_SPEC( v[0], vbspec[e0] ); + VERT_SET_SPEC( v[1], vbspec[e1] ); + } + VERT_SAVE_SPEC( 2 ); + VERT_SET_SPEC( v[2], vbspec[e2] ); + } + } + } + else { + GLuint *vbindex = VB->IndexPtr[1]->data; + if (!DO_FLAT) { + VERT_SET_IND( v[0], vbindex[e0] ); + VERT_SET_IND( v[1], vbindex[e1] ); + } + VERT_SET_IND( v[2], vbindex[e2] ); + } + } + } + + + if (DO_OFFSET) + { + offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; + z[0] = VERT_Z(v[0]); + z[1] = VERT_Z(v[1]); + z[2] = VERT_Z(v[2]); + if (cc * cc > 1e-16) { + GLfloat ic = 1.0 / cc; + GLfloat ez = z[0] - z[2]; + GLfloat fz = z[1] - z[2]; + GLfloat a = ey*fz - ez*fy; + GLfloat b = ez*fx - ex*fz; + GLfloat ac = a * ic; + GLfloat bc = b * ic; + if ( ac < 0.0f ) ac = -ac; + if ( bc < 0.0f ) bc = -bc; + offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor; + } + offset *= ctx->MRD; + } + } + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_COPY_RGBA( v[0], v[2] ); + VERT_COPY_RGBA( v[1], v[2] ); + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_COPY_SPEC( v[0], v[2] ); + VERT_COPY_SPEC( v[1], v[2] ); + } + } + else { + VERT_SAVE_IND( 0 ); + VERT_SAVE_IND( 1 ); + VERT_COPY_IND( v[0], v[2] ); + VERT_COPY_IND( v[1], v[2] ); + } + } + + if (mode == GL_POINT) { + if (DO_OFFSET && ctx->Polygon.OffsetPoint) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + } + UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 ); + } else if (mode == GL_LINE) { + if (DO_OFFSET && ctx->Polygon.OffsetLine) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + } + UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 ); + } else { + if (DO_OFFSET && ctx->Polygon.OffsetFill) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + } + if (DO_UNFILLED) + RASTERIZE( GL_TRIANGLES ); + TRI( v[0], v[1], v[2] ); + } + + if (DO_OFFSET) + { + VERT_SET_Z(v[0], z[0]); + VERT_SET_Z(v[1], z[1]); + VERT_SET_Z(v[2], z[2]); + } + + if (DO_TWOSIDE && facing == 1) + { + if (HAVE_RGBA) { + if (!DO_FLAT) { + VERT_RESTORE_RGBA( 0 ); + VERT_RESTORE_RGBA( 1 ); + } + VERT_RESTORE_RGBA( 2 ); + if (HAVE_SPEC) { + if (!DO_FLAT) { + VERT_RESTORE_SPEC( 0 ); + VERT_RESTORE_SPEC( 1 ); + } + VERT_RESTORE_SPEC( 2 ); + } + } + else { + GLuint *vbindex = VB->IndexPtr[0]->data; + if (!DO_FLAT) { + VERT_SET_IND( v[0], vbindex[e0] ); + VERT_SET_IND( v[1], vbindex[e1] ); + } + VERT_SET_IND( v[2], vbindex[e2] ); + } + } + + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_RESTORE_RGBA( 0 ); + VERT_RESTORE_RGBA( 1 ); + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_RESTORE_SPEC( 0 ); + VERT_RESTORE_SPEC( 1 ); + } + } + else { + VERT_RESTORE_IND( 0 ); + VERT_RESTORE_IND( 1 ); + } + } +} +#endif + +#if DO_QUAD +#if DO_FULL_QUAD +static void TAG(quad)( GLcontext *ctx, + GLuint e0, GLuint e1, GLuint e2, GLuint e3 ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; + VERTEX *v[4]; + GLfloat offset; + GLfloat z[4]; + GLenum mode = GL_FILL; + GLuint facing; + LOCAL_VARS(4); + + v[0] = (VERTEX *)GET_VERTEX(e0); + v[1] = (VERTEX *)GET_VERTEX(e1); + v[2] = (VERTEX *)GET_VERTEX(e2); + v[3] = (VERTEX *)GET_VERTEX(e3); + + if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED) + { + GLfloat ex = VERT_X(v[2]) - VERT_X(v[0]); + GLfloat ey = VERT_Y(v[2]) - VERT_Y(v[0]); + GLfloat fx = VERT_X(v[3]) - VERT_X(v[1]); + GLfloat fy = VERT_Y(v[3]) - VERT_Y(v[1]); + GLfloat cc = ex*fy - ey*fx; + + if (DO_TWOSIDE || DO_UNFILLED) + { + facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit; + + if (DO_UNFILLED) { + if (facing) { + mode = ctx->Polygon.BackMode; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode != GL_FRONT) { + return; + } + } else { + mode = ctx->Polygon.FrontMode; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode != GL_BACK) { + return; + } + } + } + + if (DO_TWOSIDE && facing == 1) + { + if (HAVE_RGBA) { + GLchan (*vbcolor)[4] = VB->ColorPtr[1]->Ptr; + (void)vbcolor; + + if (HAVE_BACK_COLORS) { + if (!DO_FLAT) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_SAVE_RGBA( 2 ); + VERT_COPY_RGBA1( v[0] ); + VERT_COPY_RGBA1( v[1] ); + VERT_COPY_RGBA1( v[2] ); + } + VERT_SAVE_RGBA( 3 ); + VERT_COPY_RGBA1( v[3] ); + if (HAVE_SPEC) { + if (!DO_FLAT) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_SAVE_SPEC( 2 ); + VERT_COPY_SPEC1( v[0] ); + VERT_COPY_SPEC1( v[1] ); + VERT_COPY_SPEC1( v[2] ); + } + VERT_SAVE_SPEC( 3 ); + VERT_COPY_SPEC1( v[3] ); + } + } + else { + if (!DO_FLAT) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_SAVE_RGBA( 2 ); + VERT_SET_RGBA( v[0], vbcolor[e0] ); + VERT_SET_RGBA( v[1], vbcolor[e1] ); + VERT_SET_RGBA( v[2], vbcolor[e2] ); + } + VERT_SAVE_RGBA( 3 ); + VERT_SET_RGBA( v[3], vbcolor[e3] ); + + if (HAVE_SPEC && VB->SecondaryColorPtr[1]) { + GLchan (*vbspec)[4] = VB->SecondaryColorPtr[1]->Ptr; + ASSERT(VB->SecondaryColorPtr[1]->StrideB==4*sizeof(GLchan)); + + if (!DO_FLAT) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_SAVE_SPEC( 2 ); + VERT_SET_SPEC( v[0], vbspec[e0] ); + VERT_SET_SPEC( v[1], vbspec[e1] ); + VERT_SET_SPEC( v[2], vbspec[e2] ); + } + VERT_SAVE_SPEC( 3 ); + VERT_SET_SPEC( v[3], vbspec[e3] ); + } + } + } + else { + GLuint *vbindex = VB->IndexPtr[1]->data; + if (!DO_FLAT) { + VERT_SET_IND( v[0], vbindex[e0] ); + VERT_SET_IND( v[1], vbindex[e1] ); + VERT_SET_IND( v[2], vbindex[e2] ); + } + VERT_SET_IND( v[3], vbindex[e3] ); + } + } + } + + + if (DO_OFFSET) + { + offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE; + z[0] = VERT_Z(v[0]); + z[1] = VERT_Z(v[1]); + z[2] = VERT_Z(v[2]); + z[3] = VERT_Z(v[3]); + if (cc * cc > 1e-16) { + GLfloat ez = z[2] - z[0]; + GLfloat fz = z[3] - z[1]; + GLfloat a = ey*fz - ez*fy; + GLfloat b = ez*fx - ex*fz; + GLfloat ic = 1.0 / cc; + GLfloat ac = a * ic; + GLfloat bc = b * ic; + if ( ac < 0.0f ) ac = -ac; + if ( bc < 0.0f ) bc = -bc; + offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor; + } + offset *= ctx->MRD; + } + } + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_SAVE_RGBA( 0 ); + VERT_SAVE_RGBA( 1 ); + VERT_SAVE_RGBA( 2 ); + VERT_COPY_RGBA( v[0], v[3] ); + VERT_COPY_RGBA( v[1], v[3] ); + VERT_COPY_RGBA( v[2], v[3] ); + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_SAVE_SPEC( 0 ); + VERT_SAVE_SPEC( 1 ); + VERT_SAVE_SPEC( 2 ); + VERT_COPY_SPEC( v[0], v[3] ); + VERT_COPY_SPEC( v[1], v[3] ); + VERT_COPY_SPEC( v[2], v[3] ); + } + } + else { + VERT_SAVE_IND( 0 ); + VERT_SAVE_IND( 1 ); + VERT_SAVE_IND( 2 ); + VERT_COPY_IND( v[0], v[3] ); + VERT_COPY_IND( v[1], v[3] ); + VERT_COPY_IND( v[2], v[3] ); + } + } + + if (mode == GL_POINT) { + if (( DO_OFFSET) && ctx->Polygon.OffsetPoint) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + VERT_Z_ADD(v[3], offset); + } + UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 ); + } else if (mode == GL_LINE) { + if (DO_OFFSET && ctx->Polygon.OffsetLine) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + VERT_Z_ADD(v[3], offset); + } + UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 ); + } else { + if (DO_OFFSET && ctx->Polygon.OffsetFill) { + VERT_Z_ADD(v[0], offset); + VERT_Z_ADD(v[1], offset); + VERT_Z_ADD(v[2], offset); + VERT_Z_ADD(v[3], offset); + } + RASTERIZE( GL_TRIANGLES ); + QUAD( (v[0]), (v[1]), (v[2]), (v[3]) ); + } + + if (DO_OFFSET) + { + VERT_SET_Z(v[0], z[0]); + VERT_SET_Z(v[1], z[1]); + VERT_SET_Z(v[2], z[2]); + VERT_SET_Z(v[3], z[3]); + } + + if (DO_TWOSIDE && facing == 1) + { + if (HAVE_RGBA) { + if (!DO_FLAT) { + VERT_RESTORE_RGBA( 0 ); + VERT_RESTORE_RGBA( 1 ); + VERT_RESTORE_RGBA( 2 ); + } + VERT_RESTORE_RGBA( 3 ); + if (HAVE_SPEC) { + if (!DO_FLAT) { + VERT_RESTORE_SPEC( 0 ); + VERT_RESTORE_SPEC( 1 ); + VERT_RESTORE_SPEC( 2 ); + } + VERT_RESTORE_SPEC( 3 ); + } + } + else { + GLuint *vbindex = VB->IndexPtr[0]->data; + if (!DO_FLAT) { + VERT_SET_IND( v[0], vbindex[e0] ); + VERT_SET_IND( v[1], vbindex[e1] ); + VERT_SET_IND( v[2], vbindex[e2] ); + } + VERT_SET_IND( v[3], vbindex[e3] ); + } + } + + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_RESTORE_RGBA( 0 ); + VERT_RESTORE_RGBA( 1 ); + VERT_RESTORE_RGBA( 2 ); + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_RESTORE_SPEC( 0 ); + VERT_RESTORE_SPEC( 1 ); + VERT_RESTORE_SPEC( 2 ); + } + } + else { + VERT_RESTORE_IND( 0 ); + VERT_RESTORE_IND( 1 ); + VERT_RESTORE_IND( 2 ); + } + } +} +#else +static void TAG(quad)( GLcontext *ctx, GLuint e0, + GLuint e1, GLuint e2, GLuint e3 ) +{ + if (DO_UNFILLED) { + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte ef1 = VB->EdgeFlag[e1]; + GLubyte ef3 = VB->EdgeFlag[e3]; + VB->EdgeFlag[e1] = 0; + TAG(triangle)( ctx, e0, e1, e3 ); + VB->EdgeFlag[e1] = ef1; + VB->EdgeFlag[e3] = 0; + TAG(triangle)( ctx, e1, e2, e3 ); + VB->EdgeFlag[e3] = ef3; + } else { + TAG(triangle)( ctx, e0, e1, e3 ); + TAG(triangle)( ctx, e1, e2, e3 ); + } +} +#endif +#endif + +#if DO_LINE +static void TAG(line)( GLcontext *ctx, GLuint e0, GLuint e1 ) +{ + TNLvertexbuffer *VB = &TNL_CONTEXT(ctx)->vb; + VERTEX *v[2]; + LOCAL_VARS(2); + + v[0] = (VERTEX *)GET_VERTEX(e0); + v[1] = (VERTEX *)GET_VERTEX(e1); + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_SAVE_RGBA( 0 ); + VERT_COPY_RGBA( v[0], v[1] ); + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_SAVE_SPEC( 0 ); + VERT_COPY_SPEC( v[0], v[1] ); + } + } + else { + VERT_SAVE_IND( 0 ); + VERT_COPY_IND( v[0], v[1] ); + } + } + + LINE( v[0], v[1] ); + + if (DO_FLAT) { + if (HAVE_RGBA) { + VERT_RESTORE_RGBA( 0 ); + + if (HAVE_SPEC && VB->SecondaryColorPtr[0]) { + VERT_RESTORE_SPEC( 0 ); + } + } + else { + VERT_RESTORE_IND( 0 ); + } + } +} +#endif + +#if DO_POINTS +static void TAG(points)( GLcontext *ctx, GLuint first, GLuint last ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb; + int i; + LOCAL_VARS(1); + + if (VB->Elts == 0) { + for ( i = first ; i < last ; i++ ) { + if ( VB->ClipMask[i] == 0 ) { + VERTEX *v = (VERTEX *)GET_VERTEX(i); + POINT( v ); + } + } + } else { + for ( i = first ; i < last ; i++ ) { + GLuint e = VB->Elts[i]; + if ( VB->ClipMask[e] == 0 ) { + VERTEX *v = (VERTEX *)GET_VERTEX(e); + POINT( v ); + } + } + } +} +#endif + +static void TAG(init)( void ) +{ +#if DO_QUAD + TAB[IND].quad = TAG(quad); +#endif +#if DO_TRI + TAB[IND].triangle = TAG(triangle); +#endif +#if DO_LINE + TAB[IND].line = TAG(line); +#endif +#if DO_POINTS + TAB[IND].points = TAG(points); +#endif +} + +#undef IND +#undef TAG + +#if HAVE_RGBA +#undef VERT_SET_IND +#undef VERT_COPY_IND +#undef VERT_SAVE_IND +#undef VERT_RESTORE_IND +#if HAVE_BACK_COLORS +#undef VERT_SET_RGBA +#endif +#else +#undef VERT_SET_RGBA +#undef VERT_COPY_RGBA +#undef VERT_SAVE_RGBA +#undef VERT_RESTORE_RGBA +#if HAVE_BACK_COLORS +#undef VERT_SET_IND +#endif +#endif + +#if !HAVE_SPEC +#undef VERT_SET_SPEC +#undef VERT_COPY_SPEC +#undef VERT_SAVE_SPEC +#undef VERT_RESTORE_SPEC +#if HAVE_BACK_COLORS +#undef VERT_COPY_SPEC1 +#endif +#else +#if HAVE_BACK_COLORS +#undef VERT_SET_SPEC +#endif +#endif + +#if !HAVE_BACK_COLORS +#undef VERT_COPY_SPEC1 +#undef VERT_COPY_IND1 +#undef VERT_COPY_RGBA1 +#endif + +#ifndef INSANE_VERTICES +#undef VERT_SET_Z +#undef VERT_Z_ADD +#endif diff --git a/src/mesa/tnl_dd/t_dd_unfilled.h b/src/mesa/tnl_dd/t_dd_unfilled.h new file mode 100644 index 00000000000..46415ea5f68 --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_unfilled.h @@ -0,0 +1,212 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + +#if HAVE_RGBA +#define VERT_SET_IND( v, c ) +#define VERT_COPY_IND( v0, v1 ) +#define VERT_SAVE_IND( idx ) +#define VERT_RESTORE_IND( idx ) +#endif + +#if !HAVE_SPEC +#define VERT_SET_SPEC( v, c ) +#define VERT_COPY_SPEC( v0, v1 ) +#define VERT_SAVE_SPEC( idx ) +#define VERT_RESTORE_SPEC( idx ) +#endif + +static void TAG(unfilled_tri)( GLcontext *ctx, + GLenum mode, + GLuint e0, GLuint e1, GLuint e2 ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte *ef = VB->EdgeFlag; + VERTEX *v[3]; + LOCAL_VARS(3); + + v[0] = (VERTEX *)GET_VERTEX(e0); + v[1] = (VERTEX *)GET_VERTEX(e1); + v[2] = (VERTEX *)GET_VERTEX(e2); + + if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) { + if (HAVE_RGBA) { + VERT_SAVE_RGBA(0); + VERT_SAVE_RGBA(1); + VERT_COPY_RGBA(v[0], v[2]); + VERT_COPY_RGBA(v[1], v[2]); + + if (HAVE_SPEC) { + VERT_SAVE_SPEC(0); + VERT_SAVE_SPEC(1); + VERT_COPY_SPEC(v[0], v[2]); + VERT_COPY_SPEC(v[1], v[2]); + } + } else { + VERT_SAVE_IND(0); + VERT_SAVE_IND(1); + VERT_COPY_IND(v[0], v[2]); + VERT_COPY_IND(v[1], v[2]); + } + } + +/* fprintf(stderr, "%s %s %d %d %d\n", __FUNCTION__, */ +/* _mesa_lookup_enum_by_nr( mode ), */ +/* ef[e0], ef[e1], ef[e2]); */ + + if (mode == GL_POINT) { + RASTERIZE(GL_POINTS); + if (ef[e0]) POINT( v[0] ); + if (ef[e1]) POINT( v[1] ); + if (ef[e2]) POINT( v[2] ); + } + else { + RASTERIZE(GL_LINES); + if (RENDER_PRIMITIVE == GL_POLYGON) { + if (ef[e2]) LINE( v[2], v[0] ); + if (ef[e0]) LINE( v[0], v[1] ); + if (ef[e1]) LINE( v[1], v[2] ); + } + else { + if (ef[e0]) LINE( v[0], v[1] ); + if (ef[e1]) LINE( v[1], v[2] ); + if (ef[e2]) LINE( v[2], v[0] ); + } + } + + if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) { + if (HAVE_RGBA) { + VERT_RESTORE_RGBA(0); + VERT_RESTORE_RGBA(1); + + if (HAVE_SPEC) { + VERT_RESTORE_SPEC(0); + VERT_RESTORE_SPEC(1); + } + } else { + VERT_RESTORE_IND(0); + VERT_RESTORE_IND(1); + } + } +} + + +static void TAG(unfilled_quad)( GLcontext *ctx, + GLenum mode, + GLuint e0, GLuint e1, + GLuint e2, GLuint e3 ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte *ef = VB->EdgeFlag; + VERTEX *v[4]; + LOCAL_VARS(4); + + v[0] = (VERTEX *)GET_VERTEX(e0); + v[1] = (VERTEX *)GET_VERTEX(e1); + v[2] = (VERTEX *)GET_VERTEX(e2); + v[3] = (VERTEX *)GET_VERTEX(e3); + + /* Hardware flatshading breaks down here. If the hardware doesn't + * support flatshading, this will already have been done: + */ + if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) { + if (HAVE_RGBA) { + VERT_SAVE_RGBA(0); + VERT_SAVE_RGBA(1); + VERT_SAVE_RGBA(2); + VERT_COPY_RGBA(v[0], v[3]); + VERT_COPY_RGBA(v[1], v[3]); + VERT_COPY_RGBA(v[2], v[3]); + + if (HAVE_SPEC) { + VERT_SAVE_SPEC(0); + VERT_SAVE_SPEC(1); + VERT_SAVE_SPEC(2); + VERT_COPY_SPEC(v[0], v[3]); + VERT_COPY_SPEC(v[1], v[3]); + VERT_COPY_SPEC(v[2], v[3]); + } + } else { + VERT_SAVE_IND(0); + VERT_SAVE_IND(1); + VERT_SAVE_IND(2); + VERT_COPY_IND(v[0], v[3]); + VERT_COPY_IND(v[1], v[3]); + VERT_COPY_IND(v[2], v[3]); + } + } + + if (mode == GL_POINT) { + RASTERIZE(GL_POINTS); + if (ef[e0]) POINT( v[0] ); + if (ef[e1]) POINT( v[1] ); + if (ef[e2]) POINT( v[2] ); + if (ef[e3]) POINT( v[3] ); + } + else { + RASTERIZE(GL_LINES); + if (ef[e0]) LINE( v[0], v[1] ); + if (ef[e1]) LINE( v[1], v[2] ); + if (ef[e2]) LINE( v[2], v[3] ); + if (ef[e3]) LINE( v[3], v[0] ); + } + + if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) { + if (HAVE_RGBA) { + VERT_RESTORE_RGBA(0); + VERT_RESTORE_RGBA(1); + VERT_RESTORE_RGBA(2); + + if (HAVE_SPEC) { + VERT_RESTORE_SPEC(0); + VERT_RESTORE_SPEC(1); + VERT_RESTORE_SPEC(2); + } + } else { + VERT_RESTORE_IND(0); + VERT_RESTORE_IND(1); + VERT_RESTORE_IND(2); + } + } +} + + +#if HAVE_RGBA +#undef VERT_SET_IND +#undef VERT_COPY_IND +#undef VERT_SAVE_IND +#undef VERT_RESTORE_IND +#endif + +#if !HAVE_SPEC +#undef VERT_SET_SPEC +#undef VERT_COPY_SPEC +#undef VERT_SAVE_SPEC +#undef VERT_RESTORE_SPEC +#endif + +#undef TAG diff --git a/src/mesa/tnl_dd/t_dd_vb.c b/src/mesa/tnl_dd/t_dd_vb.c new file mode 100644 index 00000000000..4a742bcbbee --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_vb.c @@ -0,0 +1,392 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ +#include "math/m_translate.h" + +#if (HAVE_HW_VIEWPORT) +#define UNVIEWPORT_VARS +#define UNVIEWPORT_X(x) x +#define UNVIEWPORT_Y(x) x +#define UNVIEWPORT_Z(x) x +#endif + +#ifndef LOCALVARS +#define LOCALVARS +#endif + +#ifndef CHECK_HW_DIVIDE +#define CHECK_HW_DIVIDE 1 +#endif + +/* These don't need to be duplicated, but there's currently nowhere + * really convenient to put them. Need to build some actual .o files in + * this directory? + */ +static void copy_pv_rgba4_spec5( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + LOCALVARS + GLubyte *verts = GET_VERTEX_STORE(); + GLuint shift = GET_VERTEX_STRIDE_SHIFT(); + GLuint *dst = (GLuint *)(verts + (edst << shift)); + GLuint *src = (GLuint *)(verts + (esrc << shift)); + dst[4] = src[4]; + dst[5] = src[5]; +} + +static void copy_pv_rgba4( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + LOCALVARS + GLubyte *verts = GET_VERTEX_STORE(); + GLuint shift = GET_VERTEX_STRIDE_SHIFT(); + GLuint *dst = (GLuint *)(verts + (edst << shift)); + GLuint *src = (GLuint *)(verts + (esrc << shift)); + dst[4] = src[4]; +} + +static void copy_pv_rgba3( GLcontext *ctx, GLuint edst, GLuint esrc ) +{ + LOCALVARS + GLubyte *verts = GET_VERTEX_STORE(); + GLuint shift = GET_VERTEX_STRIDE_SHIFT(); + GLuint *dst = (GLuint *)(verts + (edst << shift)); + GLuint *src = (GLuint *)(verts + (esrc << shift)); + dst[3] = src[3]; +} + + +void TAG(translate_vertex)(GLcontext *ctx, + const VERTEX *src, + SWvertex *dst) +{ + LOCALVARS + GLuint format = GET_VERTEX_FORMAT(); + GLfloat *s = ctx->Viewport._WindowMap.m; + UNVIEWPORT_VARS; + + if (format == TINY_VERTEX_FORMAT) { + if (HAVE_HW_VIEWPORT) { + dst->win[0] = s[0] * src->v.x + s[12]; + dst->win[1] = s[5] * src->v.y + s[13]; + dst->win[2] = s[10] * src->v.z + s[14]; + dst->win[3] = 1.0; + } else { + dst->win[0] = UNVIEWPORT_X( src->v.x ); + dst->win[1] = UNVIEWPORT_Y( src->v.y ); + dst->win[2] = UNVIEWPORT_Z( src->v.z ); + dst->win[3] = 1.0; + } + + dst->color[0] = src->tv.color.red; + dst->color[1] = src->tv.color.green; + dst->color[2] = src->tv.color.blue; + dst->color[3] = src->tv.color.alpha; + } + else { + if (HAVE_HW_VIEWPORT) { + if (HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) { + GLfloat oow = 1.0 / src->v.w; + dst->win[0] = s[0] * src->v.x * oow + s[12]; + dst->win[1] = s[5] * src->v.y * oow + s[13]; + dst->win[2] = s[10] * src->v.z * oow + s[14]; + dst->win[3] = oow; + } else { + dst->win[0] = s[0] * src->v.x + s[12]; + dst->win[1] = s[5] * src->v.y + s[13]; + dst->win[2] = s[10] * src->v.z + s[14]; + dst->win[3] = src->v.w; + } + } else { + dst->win[0] = UNVIEWPORT_X( src->v.x ); + dst->win[1] = UNVIEWPORT_Y( src->v.y ); + dst->win[2] = UNVIEWPORT_Z( src->v.z ); + dst->win[3] = src->v.w; + } + + dst->color[0] = src->v.color.red; + dst->color[1] = src->v.color.green; + dst->color[2] = src->v.color.blue; + dst->color[3] = src->v.color.alpha; + + dst->specular[0] = src->v.specular.red; + dst->specular[1] = src->v.specular.green; + dst->specular[2] = src->v.specular.blue; + + dst->fog = src->v.specular.alpha/255.0; + + if (HAVE_PTEX_VERTICES && + ((HAVE_TEX2_VERTICES && format == PROJ_TEX3_VERTEX_FORMAT) || + (format == PROJ_TEX1_VERTEX_FORMAT))) { + + dst->texcoord[0][0] = src->pv.u0; + dst->texcoord[0][1] = src->pv.v0; + dst->texcoord[0][3] = src->pv.q0; + + dst->texcoord[1][0] = src->pv.u1; + dst->texcoord[1][1] = src->pv.v1; + dst->texcoord[1][3] = src->pv.q1; + + if (HAVE_TEX2_VERTICES) { + dst->texcoord[2][0] = src->pv.u2; + dst->texcoord[2][1] = src->pv.v2; + dst->texcoord[2][3] = src->pv.q2; + } + + if (HAVE_TEX3_VERTICES) { + dst->texcoord[3][0] = src->pv.u3; + dst->texcoord[3][1] = src->pv.v3; + dst->texcoord[3][3] = src->pv.q3; + } + } + else { + dst->texcoord[0][0] = src->v.u0; + dst->texcoord[0][1] = src->v.v0; + dst->texcoord[0][3] = 1.0; + + dst->texcoord[1][0] = src->v.u1; + dst->texcoord[1][1] = src->v.v1; + dst->texcoord[1][3] = 1.0; + + if (HAVE_TEX2_VERTICES) { + dst->texcoord[2][0] = src->v.u2; + dst->texcoord[2][1] = src->v.v2; + dst->texcoord[2][3] = 1.0; + } + + if (HAVE_TEX3_VERTICES) { + dst->texcoord[3][0] = src->v.u3; + dst->texcoord[3][1] = src->v.v3; + dst->texcoord[3][3] = 1.0; + } + } + } + + dst->pointSize = ctx->Point._Size; +} + + + +void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v ) +{ + LOCALVARS + GLuint format = GET_VERTEX_FORMAT(); + + fprintf(stderr, "(%x) ", format); + + switch (format) { +#if HAVE_TINY_VERTICES + case TINY_VERTEX_FORMAT: + fprintf(stderr, "xyz %.4f,%.4f,%.4f rgba %x:%x:%x:%x\n", + v->v.x, v->v.y, v->v.z, + v->tv.color.red, + v->tv.color.green, + v->tv.color.blue, + v->tv.color.alpha); + break; +#endif +#if HAVE_NOTEX_VERTICES + case NOTEX_VERTEX_FORMAT: + fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x spec %x:%x:%x:%x\n", + v->v.x, v->v.y, v->v.z, v->v.w, + v->v.color.red, + v->v.color.green, + v->v.color.blue, + v->v.color.alpha, + v->v.specular.red, + v->v.specular.green, + v->v.specular.blue, + v->v.specular.alpha); + break; +#endif +#if HAVE_TEX0_VERTICES + case TEX0_VERTEX_FORMAT: + fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f\n", + v->v.x, v->v.y, v->v.z, v->v.w, + v->v.color.red, + v->v.color.green, + v->v.color.blue, + v->v.color.alpha, + v->v.u0, + v->v.v0); + break; +#endif +#if HAVE_TEX1_VERTICES + case TEX1_VERTEX_FORMAT: + fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f st %.4f,%.4f\n", + v->v.x, v->v.y, v->v.z, v->v.w, + v->v.color.red, + v->v.color.green, + v->v.color.blue, + v->v.color.alpha, + v->v.u0, + v->v.v0, + v->v.u1, + v->v.u2); + break; +#endif +#if HAVE_PTEX_VERTICES + case PROJ_TEX1_VERTEX_FORMAT: + fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x stq %.4f,%.4f,%.4f stq %.4f,%.4f,%.4f\n", + v->v.x, v->v.y, v->v.z, v->v.w, + v->v.color.red, + v->v.color.green, + v->v.color.blue, + v->v.color.alpha, + v->pv.u0, + v->pv.v0, + v->pv.q0, + v->pv.u1, + v->pv.v1, + v->pv.q1); + break; +#endif + default: + fprintf(stderr, "???\n"); + break; + } + + fprintf(stderr, "\n"); +} + +static void do_import( struct vertex_buffer *VB, + struct gl_client_array *to, + struct gl_client_array *from ) +{ + GLuint count = VB->Count; + + if (!to->Ptr) { + to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLubyte), 32 ); + to->Type = GL_UNSIGNED_BYTE; + } + + /* No need to transform the same value 3000 times. + */ + if (!from->StrideB) { + to->StrideB = 0; + count = 1; + } + else + to->StrideB = 4 * sizeof(GLubyte); + + _math_trans_4ub( (GLubyte (*)[4]) to->Ptr, + from->Ptr, + from->StrideB, + from->Type, + from->Size, + 0, + count); +} + +#ifndef IMPORT_QUALIFIER +#define IMPORT_QUALIFIER static +#endif + +IMPORT_QUALIFIER void TAG(import_float_colors)( GLcontext *ctx ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + struct gl_client_array *to = GET_UBYTE_COLOR_STORE(); + do_import( VB, to, VB->ColorPtr[0] ); + VB->ColorPtr[0] = to; +} + +IMPORT_QUALIFIER void TAG(import_float_spec_colors)( GLcontext *ctx ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + struct gl_client_array *to = GET_UBYTE_SPEC_COLOR_STORE(); + do_import( VB, to, VB->SecondaryColorPtr[0] ); + VB->SecondaryColorPtr[0] = to; +} + +/* Interpolate the elements of the VB not included in typical hardware + * vertices. + * + * NOTE: All these arrays are guarenteed by tnl to be writeable and + * have good stride. + */ +#ifndef INTERP_QUALIFIER +#define INTERP_QUALIFIER static +#endif + +#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx]) + + +INTERP_QUALIFIER void TAG(interp_extras)( GLcontext *ctx, + GLfloat t, + GLuint dst, GLuint out, GLuint in, + GLboolean force_boundary ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + if (VB->ColorPtr[1]) { + INTERP_4CHAN( t, + GET_COLOR(VB->ColorPtr[1], dst), + GET_COLOR(VB->ColorPtr[1], out), + GET_COLOR(VB->ColorPtr[1], in) ); + + if (VB->SecondaryColorPtr[1]) { + INTERP_3CHAN( t, + GET_COLOR(VB->SecondaryColorPtr[1], dst), + GET_COLOR(VB->SecondaryColorPtr[1], out), + GET_COLOR(VB->SecondaryColorPtr[1], in) ); + } + } + + if (VB->EdgeFlag) { + VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary; + } + + INTERP_VERTEX(ctx, t, dst, out, in, force_boundary); +} + +INTERP_QUALIFIER void TAG(copy_pv_extras)( GLcontext *ctx, + GLuint dst, GLuint src ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + if (VB->ColorPtr[1]) { + COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst), + GET_COLOR(VB->ColorPtr[1], src) ); + + if (VB->SecondaryColorPtr[1]) { + COPY_CHAN4( GET_COLOR(VB->SecondaryColorPtr[1], dst), + GET_COLOR(VB->SecondaryColorPtr[1], src) ); + } + } + + COPY_PV_VERTEX(ctx, dst, src); +} + + +#undef INTERP_QUALIFIER +#undef IMPORT_QUALIFIER +#undef GET_COLOR + +#undef IND +#undef TAG diff --git a/src/mesa/tnl_dd/t_dd_vbtmp.h b/src/mesa/tnl_dd/t_dd_vbtmp.h new file mode 100644 index 00000000000..5aad0b56222 --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_vbtmp.h @@ -0,0 +1,834 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.0.1 + * + * Copyright (C) 1999-2003 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + + +/* Unlike the other templates here, this assumes quite a bit about the + * underlying hardware. Specifically it assumes a d3d-like vertex + * format, with a layout more or less constrained to look like the + * following: + * + * union { + * struct { + * float x, y, z, w; + * struct { char r, g, b, a; } color; + * struct { char r, g, b, fog; } spec; + * float u0, v0; + * float u1, v1; + * float u2, v2; + * float u3, v3; + * } v; + * struct { + * float x, y, z, w; + * struct { char r, g, b, a; } color; + * struct { char r, g, b, fog; } spec; + * float u0, v0, q0; + * float u1, v1, q1; + * float u2, v2, q2; + * float u3, v3, q3; + * } pv; + * struct { + * float x, y, z; + * struct { char r, g, b, a; } color; + * } tv; + * float f[16]; + * unsigned int ui[16]; + * unsigned char ub4[4][16]; + * } + * + + * VERTEX: hw vertex type as above + * VERTEX_COLOR: hw color struct type in VERTEX + * + * DO_XYZW: Emit xyz and maybe w coordinates. + * DO_RGBA: Emit color. + * DO_SPEC: Emit specular color. + * DO_FOG: Emit fog coordinate in specular alpha. + * DO_TEX0: Emit tex0 u,v coordinates. + * DO_TEX1: Emit tex1 u,v coordinates. + * DO_TEX2: Emit tex2 u,v coordinates. + * DO_TEX3: Emit tex3 u,v coordinates. + * DO_PTEX: Emit tex0,1,2,3 q coordinates where possible. + * + * HAVE_RGBA_COLOR: Hardware takes color in rgba order (else bgra). + * + * HAVE_HW_VIEWPORT: Hardware performs viewport transform. + * HAVE_HW_DIVIDE: Hardware performs perspective divide. + * + * HAVE_TINY_VERTICES: Hardware understands v.tv format. + * HAVE_PTEX_VERTICES: Hardware understands v.pv format. + * HAVE_NOTEX_VERTICES: Hardware understands v.v format with texcount 0. + * + * Additionally, this template assumes it is emitting *transformed* + * vertices; the modifications to emit untransformed vertices (ie. to + * t&l hardware) are probably too great to cooexist with the code + * already in this file. + * + * NOTE: The PTEX vertex format always includes TEX0 and TEX1, even if + * only TEX0 is enabled, in order to maintain a vertex size which is + * an exact number of quadwords. + */ + +#if (HAVE_HW_VIEWPORT) +#define VIEWPORT_X(dst,x) dst = x +#define VIEWPORT_Y(dst,y) dst = y +#define VIEWPORT_Z(dst,z) dst = z +#else +#define VIEWPORT_X(dst,x) dst = s[0] * x + s[12] +#define VIEWPORT_Y(dst,y) dst = s[5] * y + s[13] +#define VIEWPORT_Z(dst,z) dst = s[10] * z + s[14] +#endif + +#if (HAVE_HW_DIVIDE && !HAVE_PTEX_VERTICES) +#error "can't cope with this combination" +#endif + +#ifndef LOCALVARS +#define LOCALVARS +#endif + +#ifndef CHECK_HW_DIVIDE +#define CHECK_HW_DIVIDE 1 +#endif + +#if (HAVE_HW_DIVIDE || DO_SPEC || DO_TEX0 || DO_FOG || !HAVE_TINY_VERTICES) + +static void TAG(emit)( GLcontext *ctx, + GLuint start, GLuint end, + void *dest, + GLuint stride ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLfloat (*tc0)[4], (*tc1)[4], (*fog)[4]; + GLfloat (*tc2)[4], (*tc3)[4]; + GLubyte (*col)[4], (*spec)[4]; + GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride; + GLuint tc2_stride, tc3_stride; + GLuint tc0_size, tc1_size; + GLuint tc2_size, tc3_size; + GLfloat (*coord)[4]; + GLuint coord_stride; + VERTEX *v = (VERTEX *)dest; + const GLfloat *s = GET_VIEWPORT_MAT(); + const GLubyte *mask = VB->ClipMask; + int i; + +/* fprintf(stderr, "%s(big) importable %d %d..%d\n", */ +/* __FUNCTION__, VB->importable_data, start, end); */ + + if (HAVE_HW_VIEWPORT && HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) { + (void) s; + coord = VB->ClipPtr->data; + coord_stride = VB->ClipPtr->stride; + } + else { + coord = VB->NdcPtr->data; + coord_stride = VB->NdcPtr->stride; + } + + if (DO_TEX3) { + const GLuint t3 = GET_TEXSOURCE(3); + tc3 = VB->TexCoordPtr[t3]->data; + tc3_stride = VB->TexCoordPtr[t3]->stride; + if (DO_PTEX) + tc3_size = VB->TexCoordPtr[t3]->size; + } + + if (DO_TEX2) { + const GLuint t2 = GET_TEXSOURCE(2); + tc2 = VB->TexCoordPtr[t2]->data; + tc2_stride = VB->TexCoordPtr[t2]->stride; + if (DO_PTEX) + tc2_size = VB->TexCoordPtr[t2]->size; + } + + if (DO_TEX1) { + const GLuint t1 = GET_TEXSOURCE(1); + tc1 = VB->TexCoordPtr[t1]->data; + tc1_stride = VB->TexCoordPtr[t1]->stride; + if (DO_PTEX) + tc1_size = VB->TexCoordPtr[t1]->size; + } + + if (DO_TEX0) { + const GLuint t0 = GET_TEXSOURCE(0); + tc0_stride = VB->TexCoordPtr[t0]->stride; + tc0 = VB->TexCoordPtr[t0]->data; + if (DO_PTEX) + tc0_size = VB->TexCoordPtr[t0]->size; + } + + if (DO_RGBA) { + if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) + IMPORT_FLOAT_COLORS( ctx ); + col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr; + col_stride = VB->ColorPtr[0]->StrideB; + } + + if (DO_SPEC) { + if (VB->SecondaryColorPtr[0]) { + if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE) + IMPORT_FLOAT_SPEC_COLORS( ctx ); + spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr; + spec_stride = VB->SecondaryColorPtr[0]->StrideB; + } else { + GLubyte tmp[4]; + spec = &tmp; + spec_stride = 0; + } + } + + if (DO_FOG) { + if (VB->FogCoordPtr) { + fog = VB->FogCoordPtr->data; + fog_stride = VB->FogCoordPtr->stride; + } + else { + static GLfloat tmp[4] = {0, 0, 0, 0}; + fog = &tmp; + fog_stride = 0; + } + } + + if (VB->importable_data || (DO_SPEC && !spec_stride) || (DO_FOG && !fog_stride)) { + /* May have nonstandard strides: + */ + if (start) { + coord = (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride); + if (DO_TEX0) + tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride); + if (DO_TEX1) + tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride); + if (DO_TEX2) + tc2 = (GLfloat (*)[4])((GLubyte *)tc2 + start * tc2_stride); + if (DO_TEX3) + tc3 = (GLfloat (*)[4])((GLubyte *)tc3 + start * tc3_stride); + if (DO_RGBA) + STRIDE_4UB(col, start * col_stride); + if (DO_SPEC) + STRIDE_4UB(spec, start * spec_stride); + if (DO_FOG) + /*STRIDE_F(fog, start * fog_stride);*/ + fog = (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride); + } + + for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) { + if (DO_XYZW) { + if (HAVE_HW_VIEWPORT || mask[i] == 0) { + VIEWPORT_X(v->v.x, coord[0][0]); + VIEWPORT_Y(v->v.y, coord[0][1]); + VIEWPORT_Z(v->v.z, coord[0][2]); + v->v.w = coord[0][3]; + } +/* fprintf(stderr, "vert %d: %.2f %.2f %.2f %.2f\n", */ +/* i, v->v.x, v->v.y, v->v.z, v->v.w); */ + coord = (GLfloat (*)[4])((GLubyte *)coord + coord_stride); + } + if (DO_RGBA) { + if (HAVE_RGBA_COLOR) { + *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[0]); + STRIDE_4UB(col, col_stride); + } else { + v->v.color.blue = col[0][2]; + v->v.color.green = col[0][1]; + v->v.color.red = col[0][0]; + v->v.color.alpha = col[0][3]; + STRIDE_4UB(col, col_stride); + } + } + if (DO_SPEC) { + v->v.specular.red = spec[0][0]; + v->v.specular.green = spec[0][1]; + v->v.specular.blue = spec[0][2]; + STRIDE_4UB(spec, spec_stride); + } + if (DO_FOG) { + v->v.specular.alpha = fog[0][0] * 255.0; + /*STRIDE_F(fog, fog_stride);*/ + fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride); + } + if (DO_TEX0) { + v->v.u0 = tc0[0][0]; + v->v.v0 = tc0[0][1]; + if (DO_PTEX) { + if (HAVE_PTEX_VERTICES) { + if (tc0_size == 4) + v->pv.q0 = tc0[0][3]; + else + v->pv.q0 = 1.0; + } + else if (tc0_size == 4) { + float rhw = 1.0 / tc0[0][3]; + v->v.w *= tc0[0][3]; + v->v.u0 *= rhw; + v->v.v0 *= rhw; + } + } + tc0 = (GLfloat (*)[4])((GLubyte *)tc0 + tc0_stride); + } + if (DO_TEX1) { + if (DO_PTEX) { + v->pv.u1 = tc1[0][0]; + v->pv.v1 = tc1[0][1]; + if (tc1_size == 4) + v->pv.q1 = tc1[0][3]; + else + v->pv.q1 = 1.0; + } + else { + v->v.u1 = tc1[0][0]; + v->v.v1 = tc1[0][1]; + } + tc1 = (GLfloat (*)[4])((GLubyte *)tc1 + tc1_stride); + } + else if (DO_PTEX) { + *(GLuint *)&v->pv.q1 = 0; /* avoid culling on radeon */ + } + if (DO_TEX2) { + if (DO_PTEX) { + v->pv.u2 = tc2[0][0]; + v->pv.v2 = tc2[0][1]; + if (tc2_size == 4) + v->pv.q2 = tc2[0][3]; + else + v->pv.q2 = 1.0; + } + else { + v->v.u2 = tc2[0][0]; + v->v.v2 = tc2[0][1]; + } + tc2 = (GLfloat (*)[4])((GLubyte *)tc2 + tc2_stride); + } + if (DO_TEX3) { + if (DO_PTEX) { + v->pv.u3 = tc3[0][0]; + v->pv.v3 = tc3[0][1]; + if (tc3_size == 4) + v->pv.q3 = tc3[0][3]; + else + v->pv.q3 = 1.0; + } + else { + v->v.u3 = tc3[0][0]; + v->v.v3 = tc3[0][1]; + } + tc3 = (GLfloat (*)[4])((GLubyte *)tc3 + tc3_stride); + } + } + } + else { + for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) { + if (DO_XYZW) { + if (HAVE_HW_VIEWPORT || mask[i] == 0) { + VIEWPORT_X(v->v.x, coord[i][0]); + VIEWPORT_Y(v->v.y, coord[i][1]); + VIEWPORT_Z(v->v.z, coord[i][2]); + v->v.w = coord[i][3]; + } + } + if (DO_RGBA) { + if (HAVE_RGBA_COLOR) { + *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[i]); + } + else { + v->v.color.blue = col[i][2]; + v->v.color.green = col[i][1]; + v->v.color.red = col[i][0]; + v->v.color.alpha = col[i][3]; + } + } + if (DO_SPEC) { + v->v.specular.red = spec[i][0]; + v->v.specular.green = spec[i][1]; + v->v.specular.blue = spec[i][2]; + } + if (DO_FOG) { + v->v.specular.alpha = fog[i][0] * 255.0; + } + if (DO_TEX0) { + v->v.u0 = tc0[i][0]; + v->v.v0 = tc0[i][1]; + if (DO_PTEX) { + if (HAVE_PTEX_VERTICES) { + if (tc0_size == 4) + v->pv.q0 = tc0[i][3]; + else + v->pv.q0 = 1.0; + + v->pv.q1 = 0; /* radeon */ + } + else if (tc0_size == 4) { + float rhw = 1.0 / tc0[i][3]; + v->v.w *= tc0[i][3]; + v->v.u0 *= rhw; + v->v.v0 *= rhw; + } + } + } + if (DO_TEX1) { + if (DO_PTEX) { + v->pv.u1 = tc1[i][0]; + v->pv.v1 = tc1[i][1]; + if (tc1_size == 4) + v->pv.q1 = tc1[i][3]; + else + v->pv.q1 = 1.0; + } + else { + v->v.u1 = tc1[i][0]; + v->v.v1 = tc1[i][1]; + } + } + } + } +} +#else +#if DO_XYZW + +#if HAVE_HW_DIVIDE +#error "cannot use tiny vertices with hw perspective divide" +#endif + +static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end, + void *dest, GLuint stride ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte (*col)[4]; + GLuint col_stride; + GLfloat (*coord)[4] = VB->NdcPtr->data; + GLuint coord_stride = VB->NdcPtr->stride; + GLfloat *v = (GLfloat *)dest; + const GLubyte *mask = VB->ClipMask; + const GLfloat *s = GET_VIEWPORT_MAT(); + int i; + + (void) s; + + ASSERT(stride == 4); + + if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) + IMPORT_FLOAT_COLORS( ctx ); + + col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr; + col_stride = VB->ColorPtr[0]->StrideB; + ASSERT(VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE); + +/* fprintf(stderr, "%s(small) importable %x\n", */ +/* __FUNCTION__, VB->importable_data); */ + + /* Pack what's left into a 4-dword vertex. Color is in a different + * place, and there is no 'w' coordinate. + */ + if (VB->importable_data) { + if (start) { + coord = (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride); + STRIDE_4UB(col, start * col_stride); + } + + for (i=start; i < end; i++, v+=4) { + if (HAVE_HW_VIEWPORT || mask[i] == 0) { + VIEWPORT_X(v[0], coord[0][0]); + VIEWPORT_Y(v[1], coord[0][1]); + VIEWPORT_Z(v[2], coord[0][2]); + } + coord = (GLfloat (*)[4])((GLubyte *)coord + coord_stride); + if (DO_RGBA) { + if (HAVE_RGBA_COLOR) { + *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)col); + } + else { + VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3]; + c->blue = col[0][2]; + c->green = col[0][1]; + c->red = col[0][0]; + c->alpha = col[0][3]; + } + STRIDE_4UB( col, col_stride ); + } +/* fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n", */ +/* i, v[0], v[1], v[2], *(int *)&v[3]); */ + } + } + else { + for (i=start; i < end; i++, v+=4) { + if (HAVE_HW_VIEWPORT || mask[i] == 0) { + VIEWPORT_X(v[0], coord[i][0]); + VIEWPORT_Y(v[1], coord[i][1]); + VIEWPORT_Z(v[2], coord[i][2]); + } + if (DO_RGBA) { + if (HAVE_RGBA_COLOR) { + *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)&col[i]); + } + else { + VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3]; + c->blue = col[i][2]; + c->green = col[i][1]; + c->red = col[i][0]; + c->alpha = col[i][3]; + } + } +/* fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n", */ +/* i, v[0], v[1], v[2], *(int *)&v[3]); */ + + } + } +} +#else +static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end, + void *dest, GLuint stride ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte (*col)[4]; + GLuint col_stride; + GLfloat *v = (GLfloat *)dest; + int i; + + if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) + IMPORT_FLOAT_COLORS( ctx ); + + col = VB->ColorPtr[0]->Ptr; + col_stride = VB->ColorPtr[0]->StrideB; + + if (start) + STRIDE_4UB(col, col_stride * start); + + /* Need to figure out where color is: + */ + if (GET_VERTEX_FORMAT() == TINY_VERTEX_FORMAT) + v += 3; + else + v += 4; + + for (i=start; i < end; i++, STRIDE_F(v, stride)) { + if (HAVE_RGBA_COLOR) { + *(GLuint *)v = LE32_TO_CPU(*(GLuint *)col[0]); + } + else { + VERTEX_COLOR *c = (VERTEX_COLOR *)v; + c->blue = col[0][2]; + c->green = col[0][1]; + c->red = col[0][0]; + c->alpha = col[0][3]; + } + STRIDE_4UB( col, col_stride ); + } +} +#endif /* emit */ +#endif /* emit */ + +#if (DO_XYZW) && (DO_RGBA) + + +#if (HAVE_PTEX_VERTICES) +static GLboolean TAG(check_tex_sizes)( GLcontext *ctx ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + /* Force 'missing' texcoords to something valid. + */ + if (DO_TEX3 && VB->TexCoordPtr[2] == 0) + VB->TexCoordPtr[2] = VB->TexCoordPtr[3]; + + if (DO_TEX2 && VB->TexCoordPtr[1] == 0) + VB->TexCoordPtr[1] = VB->TexCoordPtr[2]; + + if (DO_TEX1 && VB->TexCoordPtr[0] == 0) + VB->TexCoordPtr[0] = VB->TexCoordPtr[1]; + + if (DO_PTEX) + return GL_TRUE; + + if ((DO_TEX3 && VB->TexCoordPtr[GET_TEXSOURCE(3)]->size == 4) || + (DO_TEX2 && VB->TexCoordPtr[GET_TEXSOURCE(2)]->size == 4) || + (DO_TEX1 && VB->TexCoordPtr[GET_TEXSOURCE(1)]->size == 4) || + (DO_TEX0 && VB->TexCoordPtr[GET_TEXSOURCE(0)]->size == 4)) + return GL_FALSE; + + return GL_TRUE; +} +#else +static GLboolean TAG(check_tex_sizes)( GLcontext *ctx ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + + /* Force 'missing' texcoords to something valid. + */ + if (DO_TEX3 && VB->TexCoordPtr[2] == 0) + VB->TexCoordPtr[2] = VB->TexCoordPtr[3]; + + if (DO_TEX2 && VB->TexCoordPtr[1] == 0) + VB->TexCoordPtr[1] = VB->TexCoordPtr[2]; + + if (DO_TEX1 && VB->TexCoordPtr[0] == 0) + VB->TexCoordPtr[0] = VB->TexCoordPtr[1]; + + if (DO_PTEX) + return GL_TRUE; + + /* No hardware support for projective texture. Can fake it for + * TEX0 only. + */ + if ((DO_TEX3 && VB->TexCoordPtr[GET_TEXSOURCE(3)]->size == 4) || + (DO_TEX2 && VB->TexCoordPtr[GET_TEXSOURCE(2)]->size == 4) || + (DO_TEX1 && VB->TexCoordPtr[GET_TEXSOURCE(1)]->size == 4)) { + PTEX_FALLBACK(); + return GL_FALSE; + } + + if (DO_TEX0 && VB->TexCoordPtr[GET_TEXSOURCE(0)]->size == 4) { + if (DO_TEX1 || DO_TEX2 || DO_TEX3) { + PTEX_FALLBACK(); + } + return GL_FALSE; + } + + return GL_TRUE; +} +#endif /* ptex */ + + +static void TAG(interp)( GLcontext *ctx, + GLfloat t, + GLuint edst, GLuint eout, GLuint ein, + GLboolean force_boundary ) +{ + LOCALVARS + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + GLubyte *ddverts = GET_VERTEX_STORE(); + GLuint shift = GET_VERTEX_STRIDE_SHIFT(); + const GLfloat *dstclip = VB->ClipPtr->data[edst]; + GLfloat w; + const GLfloat *s = GET_VIEWPORT_MAT(); + + VERTEX *dst = (VERTEX *)(ddverts + (edst << shift)); + VERTEX *in = (VERTEX *)(ddverts + (ein << shift)); + VERTEX *out = (VERTEX *)(ddverts + (eout << shift)); + + (void)s; + + if (HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) { + VIEWPORT_X( dst->v.x, dstclip[0] ); + VIEWPORT_Y( dst->v.y, dstclip[1] ); + VIEWPORT_Z( dst->v.z, dstclip[2] ); + w = dstclip[3]; + } + else { + w = 1.0 / dstclip[3]; + VIEWPORT_X( dst->v.x, dstclip[0] * w ); + VIEWPORT_Y( dst->v.y, dstclip[1] * w ); + VIEWPORT_Z( dst->v.z, dstclip[2] * w ); + } + + if ((HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) || + DO_FOG || DO_SPEC || DO_TEX0 || DO_TEX1 || + DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES) { + + dst->v.w = w; + + INTERP_UB( t, dst->ub4[4][0], out->ub4[4][0], in->ub4[4][0] ); + INTERP_UB( t, dst->ub4[4][1], out->ub4[4][1], in->ub4[4][1] ); + INTERP_UB( t, dst->ub4[4][2], out->ub4[4][2], in->ub4[4][2] ); + INTERP_UB( t, dst->ub4[4][3], out->ub4[4][3], in->ub4[4][3] ); + + if (DO_SPEC) { + INTERP_UB( t, dst->v.specular.red, out->v.specular.red, in->v.specular.red ); + INTERP_UB( t, dst->v.specular.green, out->v.specular.green, in->v.specular.green ); + INTERP_UB( t, dst->v.specular.blue, out->v.specular.blue, in->v.specular.blue ); + } + if (DO_FOG) { + INTERP_UB( t, dst->v.specular.alpha, out->v.specular.alpha, in->v.specular.alpha ); + } + if (DO_TEX0) { + if (DO_PTEX) { + if (HAVE_PTEX_VERTICES) { + INTERP_F( t, dst->pv.u0, out->pv.u0, in->pv.u0 ); + INTERP_F( t, dst->pv.v0, out->pv.v0, in->pv.v0 ); + INTERP_F( t, dst->pv.q0, out->pv.q0, in->pv.q0 ); + } else { + GLfloat wout = VB->NdcPtr->data[eout][3]; + GLfloat win = VB->NdcPtr->data[ein][3]; + GLfloat qout = out->pv.w / wout; + GLfloat qin = in->pv.w / win; + GLfloat qdst, rqdst; + + ASSERT( !HAVE_HW_DIVIDE ); + + INTERP_F( t, dst->v.u0, out->v.u0 * qout, in->v.u0 * qin ); + INTERP_F( t, dst->v.v0, out->v.v0 * qout, in->v.v0 * qin ); + INTERP_F( t, qdst, qout, qin ); + + rqdst = 1.0 / qdst; + dst->v.u0 *= rqdst; + dst->v.v0 *= rqdst; + dst->v.w *= rqdst; + } + } + else { + INTERP_F( t, dst->v.u0, out->v.u0, in->v.u0 ); + INTERP_F( t, dst->v.v0, out->v.v0, in->v.v0 ); + } + } + if (DO_TEX1) { + if (DO_PTEX) { + INTERP_F( t, dst->pv.u1, out->pv.u1, in->pv.u1 ); + INTERP_F( t, dst->pv.v1, out->pv.v1, in->pv.v1 ); + INTERP_F( t, dst->pv.q1, out->pv.q1, in->pv.q1 ); + } else { + INTERP_F( t, dst->v.u1, out->v.u1, in->v.u1 ); + INTERP_F( t, dst->v.v1, out->v.v1, in->v.v1 ); + } + } + else if (DO_PTEX) { + dst->pv.q1 = 0.0; /* must be a valid float on radeon */ + } + if (DO_TEX2) { + if (DO_PTEX) { + INTERP_F( t, dst->pv.u2, out->pv.u2, in->pv.u2 ); + INTERP_F( t, dst->pv.v2, out->pv.v2, in->pv.v2 ); + INTERP_F( t, dst->pv.q2, out->pv.q2, in->pv.q2 ); + } else { + INTERP_F( t, dst->v.u2, out->v.u2, in->v.u2 ); + INTERP_F( t, dst->v.v2, out->v.v2, in->v.v2 ); + } + } + if (DO_TEX3) { + if (DO_PTEX) { + INTERP_F( t, dst->pv.u3, out->pv.u3, in->pv.u3 ); + INTERP_F( t, dst->pv.v3, out->pv.v3, in->pv.v3 ); + INTERP_F( t, dst->pv.q3, out->pv.q3, in->pv.q3 ); + } else { + INTERP_F( t, dst->v.u3, out->v.u3, in->v.u3 ); + INTERP_F( t, dst->v.v3, out->v.v3, in->v.v3 ); + } + } + } else { + /* 4-dword vertex. Color is in v[3] and there is no oow coordinate. + */ + INTERP_UB( t, dst->ub4[3][0], out->ub4[3][0], in->ub4[3][0] ); + INTERP_UB( t, dst->ub4[3][1], out->ub4[3][1], in->ub4[3][1] ); + INTERP_UB( t, dst->ub4[3][2], out->ub4[3][2], in->ub4[3][2] ); + INTERP_UB( t, dst->ub4[3][3], out->ub4[3][3], in->ub4[3][3] ); + } +} + +#endif /* rgba && xyzw */ + + +static void TAG(init)( void ) +{ + setup_tab[IND].emit = TAG(emit); + +#if (DO_XYZW && DO_RGBA) + setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes); + setup_tab[IND].interp = TAG(interp); +#endif + + if (DO_SPEC) + setup_tab[IND].copy_pv = copy_pv_rgba4_spec5; + else if (HAVE_HW_DIVIDE || DO_SPEC || DO_FOG || DO_TEX0 || DO_TEX1 || + DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES) + setup_tab[IND].copy_pv = copy_pv_rgba4; + else + setup_tab[IND].copy_pv = copy_pv_rgba3; + + if (DO_TEX3) { + if (DO_PTEX) { + ASSERT(HAVE_PTEX_VERTICES); + setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 18; + setup_tab[IND].vertex_stride_shift = 7; + } + else { + setup_tab[IND].vertex_format = TEX3_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 14; + setup_tab[IND].vertex_stride_shift = 6; + } + } + else if (DO_TEX2) { + if (DO_PTEX) { + ASSERT(HAVE_PTEX_VERTICES); + setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 18; + setup_tab[IND].vertex_stride_shift = 7; + } + else { + setup_tab[IND].vertex_format = TEX2_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 12; + setup_tab[IND].vertex_stride_shift = 6; + } + } + else if (DO_TEX1) { + if (DO_PTEX) { + ASSERT(HAVE_PTEX_VERTICES); + setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 12; + setup_tab[IND].vertex_stride_shift = 6; + } + else { + setup_tab[IND].vertex_format = TEX1_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 10; + setup_tab[IND].vertex_stride_shift = 6; + } + } + else if (DO_TEX0) { + if (DO_PTEX && HAVE_PTEX_VERTICES) { + setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 12; + setup_tab[IND].vertex_stride_shift = 6; + } else { + setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 8; + setup_tab[IND].vertex_stride_shift = 5; + } + } + else if (!HAVE_HW_DIVIDE && !DO_SPEC && !DO_FOG && HAVE_TINY_VERTICES) { + setup_tab[IND].vertex_format = TINY_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 4; + setup_tab[IND].vertex_stride_shift = 4; + } else if (HAVE_NOTEX_VERTICES) { + setup_tab[IND].vertex_format = NOTEX_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 6; + setup_tab[IND].vertex_stride_shift = 5; + } else { + setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT; + setup_tab[IND].vertex_size = 8; + setup_tab[IND].vertex_stride_shift = 5; + } + + assert(setup_tab[IND].vertex_size * 4 <= + 1 << setup_tab[IND].vertex_stride_shift); +} + + +#undef IND +#undef TAG diff --git a/src/mesa/tnl_dd/t_dd_vertex.h b/src/mesa/tnl_dd/t_dd_vertex.h new file mode 100644 index 00000000000..d45dd09fbd7 --- /dev/null +++ b/src/mesa/tnl_dd/t_dd_vertex.h @@ -0,0 +1,78 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.0.3 + * + * Copyright (C) 1999-2002 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * 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. + * + * Authors: + * Keith Whitwell + */ + +typedef struct { + GLfloat x, y, z, w; +} TAG(_coord_t); + +#ifdef COLOR_IS_RGBA +typedef struct { +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN + GLubyte alpha, blue, green, red; +#else + GLubyte red, green, blue, alpha; +#endif +} TAG(_color_t); +#else +typedef struct { +#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN + GLubyte alpha, red, green, blue; +#else + GLubyte blue, green, red, alpha; +#endif +} TAG(_color_t); +#endif + +typedef union { + struct { + GLfloat x, y, z, w; + TAG(_color_t) color; + TAG(_color_t) specular; + GLfloat u0, v0; + GLfloat u1, v1; + GLfloat u2, v2; + GLfloat u3, v3; + } v; + struct { + GLfloat x, y, z, w; + TAG(_color_t) color; + TAG(_color_t) specular; + GLfloat u0, v0, q0; + GLfloat u1, v1, q1; + GLfloat u2, v2, q2; + GLfloat u3, v3, q3; + } pv; + struct { + GLfloat x, y, z; + TAG(_color_t) color; + } tv; + GLfloat f[24]; + GLuint ui[24]; + GLubyte ub4[24][4]; +} TAG(Vertex), *TAG(VertexPtr); + -- cgit v1.2.3