diff options
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c')
-rw-r--r-- | xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c | 1456 |
1 files changed, 890 insertions, 566 deletions
diff --git a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c index 414dc072d..6d84f5c9c 100644 --- a/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c +++ b/xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c @@ -1,638 +1,961 @@ /* $XFree86$ */ +/************************************************************************** + +Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and + Tungsten Graphics Inc., Cedar Park, Texas. + +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 +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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. + +**************************************************************************/ + /* - * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. - * - * 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 - * on the rights to use, copy, modify, merge, publish, distribute, sub - * license, 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 (including the next - * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS 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 <gareth@valinux.com> + * Keith Whitwell <keith@tungstengraphics.com> + * */ +#include "radeon_context.h" +#include "radeon_state.h" +#include "radeon_ioctl.h" +#include "radeon_tex.h" +#include "radeon_tcl.h" +#include "radeon_vtxfmt.h" - -#include "glheader.h" #include "api_noop.h" -#include "colormac.h" +#include "api_arrayelt.h" #include "context.h" -#include "light.h" -#include "macros.h" #include "mem.h" #include "mmath.h" #include "mtypes.h" -#include "simple_list.h" +#include "enums.h" +#include "glapi.h" +#include "colormac.h" +#include "light.h" +#include "state.h" #include "vtxfmt.h" -#include "math/m_xform.h" #include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_array_api.h" -#include "radeon_context.h" -#include "radeon_ioctl.h" -#include "radeon_vb.h" -#include "radeon_vtxfmt.h" - - -struct radeon_imm_vertex { - /* The immediate mode vertex cache. - */ - radeonTnlVertex vertices[8]; - - /* Current vertices out of the cache. This makes the state machine - * a lot simpler, and avoids the need to swap lots of function - * pointers around. - */ - radeonTnlVertex *v0; - radeonTnlVertex *v1; - radeonTnlVertex *v2; - radeonTnlVertex *v3; - - radeon_flush_func *flush_tab; - - void (*save_vertex)( GLcontext *ctx, radeonTnlVertex *v ); - void (*flush_vertex)( GLcontext *ctx, radeonTnlVertex *v ); - - radeon_interp_func interp; +struct radeon_vb vb; - GLuint prim; - GLuint format; +static void radeonFlushVertices( GLcontext *, GLuint ); - GLvertexformat vtxfmt; -}; +static void count_func( const char *name, struct dynfn *l ) +{ + int i = 0; + struct dynfn *f; + foreach (f, l) i++; + if (i) fprintf(stderr, "%s: %d\n", name, i ); +} +static void count_funcs( radeonContextPtr rmesa ) +{ + count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f ); + count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv ); + count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f ); + count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv ); + count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub ); + count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv ); + count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub ); + count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv ); + count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f ); + count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv ); + count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f ); + count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv ); + count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f ); + count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv ); + count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f ); + count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv ); + count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f ); + count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv ); + count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); +} -#define VERTEX radeonVertex -#define TNL_VERTEX radeonTnlVertex +void radeon_copy_to_current( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); -#define LINTERP( T, A, B ) ((A) + (T) * ((B) - (A))) + assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT); + assert(vb.context == ctx); -#define INTERP_RGBA( t, out, a, b ) \ -do { \ - GLint i; \ - for ( i = 0 ; i < 4 ; i++ ) { \ - GLfloat fa = UBYTE_TO_FLOAT( a[i] ); \ - GLfloat fb = UBYTE_TO_FLOAT( b[i] ); \ - GLfloat fo = LINTERP( t, fa, fb ); \ - UNCLAMPED_FLOAT_TO_UBYTE( out[i], fo ); \ - } \ -} while (0) + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_N0) { + ctx->Current.Normal[0] = vb.normalptr[0]; + ctx->Current.Normal[1] = vb.normalptr[1]; + ctx->Current.Normal[2] = vb.normalptr[2]; + } + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKCOLOR) { + ctx->Current.Color[0] = UBYTE_TO_FLOAT( vb.ubytecolorptr[0] ); + ctx->Current.Color[1] = UBYTE_TO_FLOAT( vb.ubytecolorptr[1] ); + ctx->Current.Color[2] = UBYTE_TO_FLOAT( vb.ubytecolorptr[2] ); + ctx->Current.Color[3] = UBYTE_TO_FLOAT( vb.ubytecolorptr[3] ); + } + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPCOLOR) { + ctx->Current.Color[0] = vb.floatcolorptr[0]; + ctx->Current.Color[1] = vb.floatcolorptr[1]; + ctx->Current.Color[2] = vb.floatcolorptr[2]; + } + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPALPHA) + ctx->Current.Color[3] = vb.floatcolorptr[3]; + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKSPEC) { + ctx->Current.SecondaryColor[0] = UBYTE_TO_FLOAT( vb.ubytespecptr[0] ); + ctx->Current.SecondaryColor[1] = UBYTE_TO_FLOAT( vb.ubytespecptr[1] ); + ctx->Current.SecondaryColor[2] = UBYTE_TO_FLOAT( vb.ubytespecptr[2] ); + } + + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST0) { + ctx->Current.Texcoord[0][0] = vb.texcoordptr[0][0]; + ctx->Current.Texcoord[0][1] = vb.texcoordptr[0][1]; + ctx->Current.Texcoord[0][2] = 0.0F; + ctx->Current.Texcoord[0][3] = 1.0F; + } + if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST1) { + ctx->Current.Texcoord[1][0] = vb.texcoordptr[1][0]; + ctx->Current.Texcoord[1][1] = vb.texcoordptr[1][1]; + ctx->Current.Texcoord[1][2] = 0.0F; + ctx->Current.Texcoord[1][3] = 1.0F; + } -/* ================================================================ - * Color functions: Always update ctx->Current.* - */ + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} -/* ================================================================ - * Material functions: - */ +static GLboolean discreet_gl_prim[GL_POLYGON+1] = { + 1, /* 0 points */ + 1, /* 1 lines */ + 0, /* 2 line_strip */ + 0, /* 3 line_loop */ + 1, /* 4 tris */ + 0, /* 5 tri_fan */ + 0, /* 6 tri_strip */ + 1, /* 7 quads */ + 0, /* 8 quadstrip */ + 0, /* 9 poly */ +}; -static __inline void radeon_recalc_base_color( GLcontext *ctx ) +static void flush_prims( radeonContextPtr rmesa ) { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - struct gl_light *light; - - COPY_3V( rmesa->state.light.base_color, ctx->Light._BaseColor[0] ); - foreach ( light, &ctx->Light.EnabledList ) { - ACC_3V( rmesa->state.light.base_color, light->_MatAmbient[0] ); + int i,j; + struct radeon_dma_region tmp = rmesa->dma.current; + + tmp.buf->refcount++; + tmp.aos_size = vb.vertex_size; + tmp.aos_stride = vb.vertex_size; + tmp.aos_start = GET_START(&tmp); + + rmesa->dma.current.ptr = rmesa->dma.current.start += + (vb.initial_counter - vb.counter) * vb.vertex_size * 4; + + rmesa->tcl.vertex_format = rmesa->vb.vertex_format; + rmesa->tcl.aos_components[0] = &tmp; + rmesa->tcl.nr_aos_components = 1; + rmesa->dma.flush = 0; + + /* Optimize the primitive list: + */ + if (rmesa->vb.nrprims > 1) { + for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) { + int pj = rmesa->vb.primlist[j].prim & 0xf; + int pi = rmesa->vb.primlist[i].prim & 0xf; + + if (pj == pi && discreet_gl_prim[pj] && + rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) { + rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end; + } + else { + j++; + if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i]; + } + } + rmesa->vb.nrprims = j+1; } - - UNCLAMPED_FLOAT_TO_UBYTE( rmesa->state.light.base_alpha, - ctx->Light.Material[0].Diffuse[3] ); -} - -/* ================================================================ - * Normal functions: - */ - -struct radeon_norm_tab { - void (*normal3f_multi)( GLfloat x, GLfloat y, GLfloat z ); - void (*normal3fv_multi)( const GLfloat *v ); - void (*normal3f_single)( GLfloat x, GLfloat y, GLfloat z ); - void (*normal3fv_single)( const GLfloat *v ); -}; - -static struct radeon_norm_tab norm_tab[0x4]; + for (i = 0 ; i < rmesa->vb.nrprims; i++) { + if (RADEON_DEBUG & DEBUG_PRIMS) + fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i, + _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim & + PRIM_MODE_MASK ), + rmesa->vb.primlist[i].start, + rmesa->vb.primlist[i].end); + + radeonEmitPrimitive( vb.context, + rmesa->vb.primlist[i].start, + rmesa->vb.primlist[i].end, + rmesa->vb.primlist[i].prim ); + } + rmesa->vb.nrprims = 0; + radeonReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ ); +} -#define HAVE_HW_LIGHTING 0 -#define GET_CURRENT_VERTEX \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ - radeonTnlVertexPtr v = rmesa->imm.v0 +static void start_prim( radeonContextPtr rmesa, GLuint mode ) +{ + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); -#define CURRENT_NORMAL rmesa->state.current.normal -#define BASE_COLOR rmesa->state.light.base_color -#define BASE_ALPHA rmesa->state.light.base_alpha + rmesa->vb.primlist[rmesa->vb.nrprims].start = vb.initial_counter - vb.counter; + rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode; +} -#define VERT_COLOR( COMP ) v->color[COMP] +static void note_last_prim( radeonContextPtr rmesa, GLuint flags ) +{ + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags; + rmesa->vb.primlist[rmesa->vb.nrprims].end = vb.initial_counter - vb.counter; -#define IND (0) -#define TAG(x) radeon_##x -#define PRESERVE_NORMAL_DEFS -#include "tnl_dd/t_dd_imm_napi.h" + if (++(rmesa->vb.nrprims) == RADEON_MAX_PRIMS) + flush_prims( rmesa ); + } +} -#define IND (NORM_RESCALE) -#define TAG(x) radeon_##x##_rescale -#define PRESERVE_NORMAL_DEFS -#include "tnl_dd/t_dd_imm_napi.h" -#define IND (NORM_NORMALIZE) -#define TAG(x) radeon_##x##_normalize -#include "tnl_dd/t_dd_imm_napi.h" +static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst ) +{ + GLuint i; + GLfloat *src = (GLfloat *)(rmesa->dma.current.address + + rmesa->dma.current.ptr + + (rmesa->vb.primlist[rmesa->vb.nrprims].start + n) * + vb.vertex_size * 4); + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n); -static void radeon_init_norm_funcs( void ) -{ - radeon_init_norm(); - radeon_init_norm_rescale(); - radeon_init_norm_normalize(); + for (i = 0 ; i < vb.vertex_size; i++) { + dst[i] = src[i]; + } } -static void radeon_choose_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +/* NOTE: This actually reads the copied vertices back from uncached + * memory. Could also use the counter/notify mechanism to populate + * tmp on the fly as vertices are generated. + */ +static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[15] ) { - GET_CURRENT_CONTEXT(ctx); - GLuint index; - - if ( ctx->Light.Enabled ) { - if ( ctx->Transform.Normalize ) { - index = NORM_NORMALIZE; - } - else if ( !ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0 ) { - index = NORM_RESCALE; - } - else { - index = 0; - } - - if ( ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev ) { - ctx->Exec->Normal3f = norm_tab[index].normal3f_single; + GLuint ovf, i; + GLuint nr = (vb.initial_counter - vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start; + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr); + + switch( rmesa->vb.prim[0] ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_TRIANGLES: + ovf = nr%3; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_QUADS: + ovf = nr&3; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + copy_vertex( rmesa, nr-1, tmp[0] ); + return 1; + case GL_LINE_LOOP: + case GL_TRIANGLE_FAN: + case GL_POLYGON: + if (nr == 0) + return 0; + else if (nr == 1) { + copy_vertex( rmesa, 0, tmp[0] ); + return 1; } else { - ctx->Exec->Normal3f = norm_tab[index].normal3f_multi; + copy_vertex( rmesa, 0, tmp[0] ); + copy_vertex( rmesa, nr-1, tmp[1] ); + return 2; } - } else { - ctx->Exec->Normal3f = _mesa_noop_Normal3f; + case GL_TRIANGLE_STRIP: + ovf = MIN2( nr-1, 2 ); + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + case GL_QUAD_STRIP: + ovf = MIN2( nr-1, 2 ); + if (nr > 2) ovf += nr&1; + for (i = 0 ; i < ovf ; i++) + copy_vertex( rmesa, nr-ovf+i, tmp[i] ); + return i; + default: + assert(0); + return 0; } - - glNormal3f( x, y, z ); } -static void radeon_choose_Normal3fv( const GLfloat *v ) +static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller ) { - GET_CURRENT_CONTEXT(ctx); - GLuint index; + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( ctx->Light.Enabled ) { - if ( ctx->Transform.Normalize ) { - index = NORM_NORMALIZE; - } - else if ( !ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0 ) { - index = NORM_RESCALE; - } - else { - index = 0; - } + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); - if ( ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev ) { - ctx->Exec->Normal3fv = norm_tab[index].normal3fv_single; - } else { - ctx->Exec->Normal3fv = norm_tab[index].normal3fv_multi; - } - } else { - ctx->Exec->Normal3fv = _mesa_noop_Normal3fv; - } + if (ctx->Driver.NeedFlush) + radeonFlushVertices( ctx, ctx->Driver.NeedFlush ); - glNormal3fv( v ); -} + if (ctx->NewState) + _mesa_update_state( ctx ); /* clear state so fell_back sticks */ + _tnl_wakeup_exec( ctx ); + assert( rmesa->dma.flush == 0 ); + rmesa->vb.fell_back = GL_TRUE; + rmesa->vb.installed = GL_FALSE; + vb.context = 0; +} -/* ================================================================ - * Texture functions: - */ +static void VFMT_FALLBACK( const char *caller ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat tmp[3][15]; + GLuint i, prim; + GLuint ind = rmesa->vb.vertex_format; + GLuint nrverts; + GLfloat alpha = 1.0; -#define GET_CURRENT \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) + if (RADEON_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT)) + fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); -#define NUM_TEXTURE_UNITS RADEON_MAX_TEXTURE_UNITS -#define DO_PROJ_TEX + if (rmesa->vb.prim[0] == GL_POLYGON+1) { + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); + return; + } -#define CURRENT_TEXTURE( unit ) rmesa->state.current.texture[unit] + /* Copy vertices out of dma: + */ + nrverts = copy_dma_verts( rmesa, tmp ); -#define TAG(x) radeon_##x -#include "tnl_dd/t_dd_imm_tapi.h" + /* Finish the prim at this point: + */ + note_last_prim( rmesa, 0 ); + flush_prims( rmesa ); + /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl. + */ + prim = rmesa->vb.prim[0]; + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + _tnl_wakeup_exec( ctx ); + assert(rmesa->dma.flush == 0); + rmesa->vb.fell_back = GL_TRUE; + rmesa->vb.installed = GL_FALSE; + vb.context = 0; + glBegin( prim ); + + if (rmesa->vb.installed_color_3f_sz == 4) + alpha = ctx->Current.Color[3]; -/* ================================================================ - * Vertex functions: - */ + /* Replay saved vertices + */ + for (i = 0 ; i < nrverts; i++) { + GLuint offset = 3; + if (ind & RADEON_CP_VC_FRMT_N0) { + glNormal3fv( &tmp[i][offset] ); + offset += 3; + } -#define GET_CURRENT_VERTEX \ - GET_CURRENT_CONTEXT(ctx); \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \ - radeonTnlVertexPtr v = rmesa->imm.v0 + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) { + glColor4ubv( (GLubyte *)&tmp[i][offset] ); + offset++; + } + else if (ind & RADEON_CP_VC_FRMT_FPALPHA) { + glColor4fv( &tmp[i][offset] ); + offset+=4; + } + else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + glColor3fv( &tmp[i][offset] ); + offset+=3; + } -#define CURRENT_VERTEX v->obj -#define SAVE_VERTEX rmesa->imm.save_vertex( ctx, v ) + if (ind & RADEON_CP_VC_FRMT_PKSPEC) { + _glapi_Dispatch->SecondaryColor3ubvEXT( (GLubyte *)&tmp[i][offset] ); + offset++; + } -#define TAG(x) radeon_##x -#include "tnl_dd/t_dd_imm_vapi.h" + if (ind & RADEON_CP_VC_FRMT_ST0) { + glTexCoord2fv( &tmp[i][offset] ); + offset += 2; + } + if (ind & RADEON_CP_VC_FRMT_ST1) { + glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] ); + offset += 2; + } + glVertex3fv( &tmp[i][0] ); + } + /* Replay current vertex + */ + if (ind & RADEON_CP_VC_FRMT_N0) + glNormal3fv( vb.normalptr ); + + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) + glColor4ubv( vb.ubytecolorptr ); + else if (ind & RADEON_CP_VC_FRMT_FPALPHA) + glColor4fv( vb.floatcolorptr ); + else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0) + glColor4f( vb.floatcolorptr[0], + vb.floatcolorptr[1], + vb.floatcolorptr[2], + alpha ); + else + glColor3fv( vb.floatcolorptr ); + } + if (ind & RADEON_CP_VC_FRMT_PKSPEC) + _glapi_Dispatch->SecondaryColor3ubvEXT( vb.ubytespecptr ); -struct radeon_vert_tab { - void (*save_vertex)( GLcontext *ctx, radeonTnlVertexPtr v ); - void (*interpolate_vertex)( GLfloat t, - radeonTnlVertex *O, - const radeonTnlVertex *I, - const radeonTnlVertex *J ); -}; + if (ind & RADEON_CP_VC_FRMT_ST0) + glTexCoord2fv( vb.texcoordptr[0] ); -static struct radeon_vert_tab vert_tab[0xf]; + if (ind & RADEON_CP_VC_FRMT_ST1) + glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, vb.texcoordptr[1] ); +} -#define VTX_NORMAL 0x0 -#define VTX_RGBA 0x1 -#define VTX_SPEC 0x2 -#define VTX_TEX0 0x4 -#define VTX_TEX1 0x8 -#define LOCAL_VARS \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) -#define CURRENT_COLOR rmesa->state.current.color -#define CURRENT_SPECULAR rmesa->state.current.specular +static void wrap_buffer( void ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLfloat tmp[3][15]; + GLuint i, nrverts; -#define CURRENT_NORMAL( COMP ) rmesa->state.current.normal[COMP] -#define CURRENT_TEXTURE( U, COMP ) rmesa->state.current.texture[U][COMP] + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS)) + fprintf(stderr, "%s %d\n", __FUNCTION__, vb.initial_counter - vb.counter); -#define FLUSH_VERTEX rmesa->imm.flush_vertex( ctx, v ); + /* Don't deal with parity. + */ + if ((((vb.initial_counter - vb.counter) - + rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) { + vb.counter++; + vb.initial_counter++; + return; + } + /* Copy vertices out of dma: + */ + nrverts = copy_dma_verts( rmesa, tmp ); -#define IND (VTX_NORMAL) -#define TAG(x) radeon_##x##_NORMAL -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%d vertices to copy\n", nrverts); + -#define IND (VTX_NORMAL|VTX_TEX0) -#define TAG(x) radeon_##x##_NORMAL_TEX0 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Finish the prim at this point: + */ + note_last_prim( rmesa, 0 ); + flush_prims( rmesa ); -#define IND (VTX_NORMAL|VTX_TEX0|VTX_TEX1) -#define TAG(x) radeon_##x##_NORMAL_TEX0_TEX1 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Get new buffer + */ + radeonRefillCurrentDmaRegion( rmesa ); -#define IND (VTX_RGBA) -#define TAG(x) radeon_##x##_RGBA -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + /* Reset counter, dmaptr + */ + vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address); + vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / + (vb.vertex_size * 4); + vb.counter--; + vb.initial_counter = vb.counter; + vb.notify = wrap_buffer; -#define IND (VTX_RGBA|VTX_TEX0) -#define TAG(x) radeon_##x##_RGBA_TEX0 -#define PRESERVE_VERTEX_DEFS -#include "tnl_dd/t_dd_imm_vertex.h" + rmesa->dma.flush = flush_prims; + start_prim( rmesa, rmesa->vb.prim[0] ); -#define IND (VTX_RGBA|VTX_TEX1) -#define TAG(x) radeon_##x##_RGBA_TEX0_TEX1 -#include "tnl_dd/t_dd_imm_vertex.h" + /* Reemit saved vertices + */ + for (i = 0 ; i < nrverts; i++) { + if (RADEON_DEBUG & DEBUG_VERTS) { + int j; + fprintf(stderr, "re-emit vertex %d to %p\n", i, vb.dmaptr); + if (RADEON_DEBUG & DEBUG_VERBOSE) + for (j = 0 ; j < vb.vertex_size; j++) + fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); + } -static void radeon_init_vert_funcs( void ) -{ - radeon_init_vert_NORMAL(); - radeon_init_vert_NORMAL_TEX0(); - radeon_init_vert_NORMAL_TEX0_TEX1(); - radeon_init_vert_RGBA(); - radeon_init_vert_RGBA_TEX0(); - radeon_init_vert_RGBA_TEX0_TEX1(); + memcpy( vb.dmaptr, tmp[i], vb.vertex_size * 4 ); + vb.dmaptr += vb.vertex_size; + vb.counter--; + } } +static GLboolean check_vtx_fmt( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + GLuint ind = RADEON_CP_VC_FRMT_Z; + if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag) + return GL_FALSE; + if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) + ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT ); + + /* Make all this event-driven: + */ + if (ctx->Light.Enabled) { + ind |= RADEON_CP_VC_FRMT_N0; + + /* TODO: make this data driven: If we receive only ubytes, send + * color as ubytes. Also check if converting (with free + * checking for overflow) is cheaper than sending floats + * directly. + */ + if (ctx->Light.ColorMaterialEnabled) { + ind |= RADEON_CP_VC_FRMT_FPCOLOR; + if (ctx->Color.AlphaEnabled) { + ind |= RADEON_CP_VC_FRMT_FPALPHA; + } + } + } + else { + /* TODO: make this data driven? + */ + ind |= RADEON_CP_VC_FRMT_PKCOLOR; + + if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) { + ind |= RADEON_CP_VC_FRMT_PKSPEC; + } + } + if (ctx->Texture.Unit[0]._ReallyEnabled) { + if (ctx->Texture.Unit[0].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[0]) { + ind |= RADEON_CP_VC_FRMT_N0; + } + } else { + if (ctx->Current.Texcoord[0][2] != 0.0F || + ctx->Current.Texcoord[0][3] != 1.0) { + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s: rq0\n", __FUNCTION__); + return GL_FALSE; + } + ind |= RADEON_CP_VC_FRMT_ST0; + } + } -#define LOCAL_VARS \ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx) + if (ctx->Texture.Unit[1]._ReallyEnabled) { + if (ctx->Texture.Unit[1].TexGenEnabled) { + if (rmesa->TexGenNeedNormals[1]) { + ind |= RADEON_CP_VC_FRMT_N0; + } + } else { + if (ctx->Current.Texcoord[1][2] != 0.0F || + ctx->Current.Texcoord[1][3] != 1.0) { + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS)) + fprintf(stderr, "%s: rq1\n", __FUNCTION__); + return GL_FALSE; + } + ind |= RADEON_CP_VC_FRMT_ST1; + } + } -#define GET_INTERP_FUNC \ - radeon_interp_func interp = rmesa->imm.interp + if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_STATE)) + fprintf(stderr, "%s: format: 0x%x\n", __FUNCTION__, ind ); -#define FLUSH_VERTEX rmesa->imm.flush_vertex + RADEON_NEWPRIM(rmesa); + rmesa->vb.vertex_format = ind; + vb.vertex_size = 3; + rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive; -#define IMM_VERTEX( V ) rmesa->imm.V -#define IMM_VERTICES( n ) rmesa->imm.vertices[n] + vb.normalptr = ctx->Current.Normal; + vb.ubytecolorptr = 0; + vb.floatcolorptr = ctx->Current.Color; + vb.texcoordptr[0] = ctx->Current.Texcoord[0]; + vb.texcoordptr[1] = ctx->Current.Texcoord[1]; + + /* Run through and initialize the vertex components in the order + * the hardware understands: + */ + if (ind & RADEON_CP_VC_FRMT_N0) { + vb.normalptr = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 3; + vb.normalptr[0] = ctx->Current.Normal[0]; + vb.normalptr[1] = ctx->Current.Normal[1]; + vb.normalptr[2] = ctx->Current.Normal[2]; + } + if (ind & RADEON_CP_VC_FRMT_PKCOLOR) { + vb.ubytecolorptr = &vb.vertex[vb.vertex_size].ub4[0]; + vb.vertex_size += 1; + UNCLAMPED_FLOAT_TO_RGBA_CHAN( vb.ubytecolorptr, ctx->Current.Color ); + } -/* TINY_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 16, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->color); \ - vb += 4; \ -} while (0) + if (ind & RADEON_CP_VC_FRMT_FPCOLOR) { + assert(!(ind & RADEON_CP_VC_FRMT_PKCOLOR)); + vb.floatcolorptr = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 3; + vb.floatcolorptr[0] = ctx->Current.Color[0]; + vb.floatcolorptr[1] = ctx->Current.Color[1]; + vb.floatcolorptr[2] = ctx->Current.Color[2]; + + if (ind & RADEON_CP_VC_FRMT_FPALPHA) { + vb.vertex_size += 1; + vb.floatcolorptr[3] = ctx->Current.Color[3]; + } + } + + if (ind & RADEON_CP_VC_FRMT_PKSPEC) { + vb.ubytespecptr = &vb.vertex[vb.vertex_size].ub4[0]; + vb.vertex_size += 1; + UNCLAMPED_FLOAT_TO_RGB_CHAN( vb.ubytespecptr, + ctx->Current.SecondaryColor ); + } -#define TAG(x) radeon_##x##_tiny -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" + if (ind & RADEON_CP_VC_FRMT_ST0) { + vb.texcoordptr[0] = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 2; + vb.texcoordptr[0][0] = ctx->Current.Texcoord[0][0]; + vb.texcoordptr[0][1] = ctx->Current.Texcoord[0][1]; + } + + if (ind & RADEON_CP_VC_FRMT_ST1) { + vb.texcoordptr[1] = &vb.vertex[vb.vertex_size].f; + vb.vertex_size += 2; + vb.texcoordptr[1][0] = ctx->Current.Texcoord[1][0]; + vb.texcoordptr[1][1] = ctx->Current.Texcoord[1][1]; + } + + if (rmesa->vb.installed_vertex_format != rmesa->vb.vertex_format) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall on vertex_format change\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + rmesa->vb.installed_vertex_format = rmesa->vb.vertex_format; + } + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s -- success\n", __FUNCTION__); + + return GL_TRUE; +} -/* NOTEX_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 24, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb += 6; \ -} while (0) -#define TAG(x) radeon_##x##_notex -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" +void radeonVtxfmtInvalidate( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + rmesa->vb.recheck = GL_TRUE; + rmesa->vb.fell_back = GL_FALSE; +} -/* TEX0_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 32, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb[6] = *(GLuint *)&(v->texture[0][0]); \ - vb[7] = *(GLuint *)&(v->texture[0][1]); \ - vb += 8; \ -} while (0) -#define TAG(x) radeon_##x##_tex0 -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" +static void radeonNewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); +} -/* TEX1_VERTEX_FORMAT: - */ -#define GET_VERTEX_SPACE( n ) radeonAllocDmaLow( rmesa, n * 40, __FUNCTION__ ) - -#define EMIT_VERTEX( vb, v ) \ -do { \ - vb[0] = *(GLuint *)&(v->clip[0]); \ - vb[1] = *(GLuint *)&(v->clip[1]); \ - vb[2] = *(GLuint *)&(v->clip[2]); \ - vb[3] = *(GLuint *)&(v->clip[3]); \ - vb[4] = *(GLuint *)&(v->color); \ - vb[5] = *(GLuint *)&(v->specular); \ - vb[6] = *(GLuint *)&(v->texture[0][0]); \ - vb[7] = *(GLuint *)&(v->texture[0][1]); \ - vb[8] = *(GLuint *)&(v->texture[1][0]); \ - vb[9] = *(GLuint *)&(v->texture[1][1]); \ - vb += 10; \ -} while (0) +static void radeonVtxfmtValidate( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); -#define TAG(x) radeon_##x##_tex1 -#define PRESERVE_PRIM_DEFS -#include "tnl_dd/t_dd_imm_primtmp.h" + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + if (ctx->Driver.NeedFlush) + ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); + rmesa->vb.recheck = GL_FALSE; + if (check_vtx_fmt( ctx )) { + if (!rmesa->vb.installed) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall (new install)\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + ctx->Driver.FlushVertices = radeonFlushVertices; + ctx->Driver.NewList = radeonNewList; + rmesa->vb.installed = GL_TRUE; + vb.context = ctx; + } + else if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: already installed", __FUNCTION__); + } + else { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: failed\n", __FUNCTION__); + + if (rmesa->vb.installed) { + if (rmesa->dma.flush) + rmesa->dma.flush( rmesa ); + _tnl_wakeup_exec( ctx ); + rmesa->vb.installed = GL_FALSE; + vb.context = 0; + } + } +} -/* Bzzt: Material changes are lost on fallback. +/* Materials: */ -static void radeon_Materialfv( GLenum face, GLenum pname, +static void radeon_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) { - GET_CURRENT_CONTEXT(ctx); + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + VFMT_FALLBACK( __FUNCTION__ ); + glMaterialfv( face, pname, params ); + return; + } _mesa_noop_Materialfv( face, pname, params ); - radeon_recalc_base_color( ctx ); + radeonUpdateMaterial( vb.context ); } - - - -/* ================================================================ - * Fallback functions: +/* Begin/End */ - -static void radeon_do_fallback( GLcontext *ctx ) +static void radeon_Begin( GLenum mode ) { + GLcontext *ctx = vb.context; radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - struct radeon_current_state *current = &rmesa->state.current; + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks - * and revive internal state that depended on those callbacks: - */ - _tnl_wakeup_exec( ctx ); + if (mode > GL_POLYGON) { + _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); + return; + } - /* Replay enough vertices that the current primitive is continued - * correctly: - */ - if ( rmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) { - glBegin( rmesa->imm.prim ); - /*rmesa->fire_on_fallback( ctx );*/ + if (rmesa->vb.prim[0] != GL_POLYGON+1) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); + return; } + + if (ctx->NewState) + _mesa_update_state( ctx ); - /* Replay the current, partially complete vertex: - */ - if ( current->texture[0][3] == 1.0 ) { - glMultiTexCoord3fvARB( GL_TEXTURE0_ARB, current->texture[0] ); - } else { - glMultiTexCoord4fvARB( GL_TEXTURE0_ARB, current->texture[0] ); + if (rmesa->NewGLState) + radeonValidateState( ctx ); + + if (rmesa->vb.recheck) + radeonVtxfmtValidate( ctx ); + + if (!rmesa->vb.installed) { + glBegin( mode ); + return; } - if ( current->texture[1][3] == 1.0 ) { - glMultiTexCoord3fvARB( GL_TEXTURE1_ARB, current->texture[1] ); - } else { - glMultiTexCoord4fvARB( GL_TEXTURE1_ARB, current->texture[1] ); + + if (rmesa->dma.flush && vb.counter < 12) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__); + flush_prims( rmesa ); } - /* FIXME: Secondary color, fog coord... + /* Need to arrange to save vertices here? Or always copy from dma (yuk)? */ + if (!rmesa->dma.flush) { + if (rmesa->dma.current.ptr + 12*vb.vertex_size*4 > + rmesa->dma.current.end) { + RADEON_NEWPRIM( rmesa ); + radeonRefillCurrentDmaRegion( rmesa ); + } - if ( ctx->Light.Enabled ) { - glColor4fv( ctx->Current.Color ); /* Catch ColorMaterial */ - glNormal3fv( current->normal ); - } else { - glColor4ubv( current->color ); + vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr); + vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / + (vb.vertex_size * 4); + vb.counter--; + vb.initial_counter = vb.counter; + vb.notify = wrap_buffer; + rmesa->dma.flush = flush_prims; + vb.context->Driver.NeedFlush |= FLUSH_STORED_VERTICES; } + + + rmesa->vb.prim[0] = mode; + start_prim( rmesa, mode | PRIM_BEGIN ); } -#define PRE_LOOPBACK( FUNC ) do { \ - GET_CURRENT_CONTEXT(ctx); \ - radeon_do_fallback( ctx ); \ -} while (0) -#define TAG(x) radeon_fallback_##x -#include "vtxfmt_tmp.h" +static void radeon_End( void ) +{ + GLcontext *ctx = vb.context; + radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); + if (rmesa->vb.prim[0] == GL_POLYGON+1) { + _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); + return; + } + + note_last_prim( rmesa, PRIM_END ); + rmesa->vb.prim[0] = GL_POLYGON+1; +} + + +/* Fallback on difficult entrypoints: + */ +#define PRE_LOOPBACK( FUNC ) \ +do { \ + if (RADEON_DEBUG & DEBUG_VFMT) \ + fprintf(stderr, "%s\n", __FUNCTION__); \ + VFMT_FALLBACK( __FUNCTION__ ); \ +} while (0) +#define TAG(x) radeon_fallback_##x +#include "vtxfmt_tmp.h" -static void radeon_Begin( GLenum prim ) +static GLboolean radeonNotifyBegin( GLcontext *ctx, GLenum p ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - if ( prim > GL_POLYGON ) { - _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); - return; - } - if ( rmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); - return; - } + assert(!rmesa->vb.installed); - ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES | - FLUSH_UPDATE_CURRENT); + if (ctx->NewState) + _mesa_update_state( ctx ); + if (rmesa->NewGLState) + radeonValidateState( ctx ); - radeonChooseVertexState( ctx ); + if (ctx->Driver.NeedFlush) + ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); + if (rmesa->vb.recheck) + radeonVtxfmtValidate( ctx ); - rmesa->imm.prim = prim; - rmesa->imm.v0 = &rmesa->imm.vertices[0]; + if (!rmesa->vb.installed) { + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s -- failed\n", __FUNCTION__); + return GL_FALSE; + } - rmesa->imm.save_vertex = radeon_save_vertex_RGBA; - rmesa->imm.flush_vertex = rmesa->imm.flush_tab[prim]; + radeon_Begin( p ); + return GL_TRUE; } -static void radeon_End( void ) +static void radeonFlushVertices( GLcontext *ctx, GLuint flags ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); - if ( rmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END ) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); - return; - } + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "%s\n", __FUNCTION__); - rmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; + assert(rmesa->vb.installed); + assert(vb.context == ctx); - ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES | - FLUSH_UPDATE_CURRENT); -} + if (flags & FLUSH_UPDATE_CURRENT) { + radeon_copy_to_current( ctx ); + if (RADEON_DEBUG & DEBUG_VFMT) + fprintf(stderr, "reinstall on update_current\n"); + _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt ); + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; + } + if (flags & FLUSH_STORED_VERTICES) { + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + assert (rmesa->dma.flush == 0 || + rmesa->dma.flush == flush_prims); + if (rmesa->dma.flush == flush_prims) + flush_prims( RADEON_CONTEXT( ctx ) ); + ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; + } +} +/* At this point, don't expect very many versions of each function to + * be generated, so not concerned about freeing them? + */ -void radeonInitTnlModule( GLcontext *ctx ) +void radeonVtxfmtInit( GLcontext *ctx ) { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - GLvertexformat *vfmt = &(rmesa->imm.vtxfmt); - - return; - - radeon_init_norm_funcs(); - radeon_init_vert_funcs(); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + GLvertexformat *vfmt = &(rmesa->vb.vtxfmt); MEMSET( vfmt, 0, sizeof(GLvertexformat) ); - /* Handled fully in supported states: + /* Hook in chooser functions for codegen, etc: */ - vfmt->ArrayElement = NULL; /* FIXME: ... */ - vfmt->Color3f = radeon_choose_Color3f; - vfmt->Color3fv = radeon_choose_Color3fv; - vfmt->Color3ub = radeon_choose_Color3ub; - vfmt->Color3ubv = radeon_choose_Color3ubv; - vfmt->Color4f = radeon_choose_Color4f; - vfmt->Color4fv = radeon_choose_Color4fv; - vfmt->Color4ub = radeon_choose_Color4ub; - vfmt->Color4ubv = radeon_choose_Color4ubv; - vfmt->FogCoordfvEXT = radeon_FogCoordfvEXT; - vfmt->FogCoordfEXT = radeon_FogCoordfEXT; - vfmt->Materialfv = radeon_Materialfv; - vfmt->MultiTexCoord1fARB = radeon_MultiTexCoord1fARB; - vfmt->MultiTexCoord1fvARB = radeon_MultiTexCoord1fvARB; - vfmt->MultiTexCoord2fARB = radeon_MultiTexCoord2fARB; - vfmt->MultiTexCoord2fvARB = radeon_MultiTexCoord2fvARB; - vfmt->MultiTexCoord3fARB = radeon_MultiTexCoord3fARB; - vfmt->MultiTexCoord3fvARB = radeon_MultiTexCoord3fvARB; - vfmt->MultiTexCoord4fARB = radeon_MultiTexCoord4fARB; - vfmt->MultiTexCoord4fvARB = radeon_MultiTexCoord4fvARB; - vfmt->Normal3f = radeon_choose_Normal3f; - vfmt->Normal3fv = radeon_choose_Normal3fv; - vfmt->SecondaryColor3ubEXT = radeon_SecondaryColor3ubEXT; - vfmt->SecondaryColor3ubvEXT = radeon_SecondaryColor3ubvEXT; - vfmt->SecondaryColor3fEXT = radeon_SecondaryColor3fEXT; - vfmt->SecondaryColor3fvEXT = radeon_SecondaryColor3fvEXT; - vfmt->TexCoord1f = radeon_TexCoord1f; - vfmt->TexCoord1fv = radeon_TexCoord1fv; - vfmt->TexCoord2f = radeon_TexCoord2f; - vfmt->TexCoord2fv = radeon_TexCoord2fv; - vfmt->TexCoord3f = radeon_TexCoord3f; - vfmt->TexCoord3fv = radeon_TexCoord3fv; - vfmt->TexCoord4f = radeon_TexCoord4f; - vfmt->TexCoord4fv = radeon_TexCoord4fv; - vfmt->Vertex2f = radeon_Vertex2f; - vfmt->Vertex2fv = radeon_Vertex2fv; - vfmt->Vertex3f = radeon_Vertex3f; - vfmt->Vertex3fv = radeon_Vertex3fv; - vfmt->Vertex4f = radeon_Vertex4f; - vfmt->Vertex4fv = radeon_Vertex4fv; + radeonVtxfmtInitChoosers( vfmt ); + /* Handled fully in supported states, but no codegen: + */ + vfmt->Materialfv = radeon_Materialfv; + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ vfmt->Begin = radeon_Begin; vfmt->End = radeon_End; - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ - - vfmt->DrawArrays = NULL; - vfmt->DrawElements = NULL; - vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */ + /* Fallback for performance reasons: (Fix with cva/elt path here and + * dmatmp2.h style primitive-merging) + * + * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow + * a driver-hook. + */ + vfmt->DrawArrays = radeon_fallback_DrawArrays; + vfmt->DrawElements = radeon_fallback_DrawElements; + vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements; /* Not active in supported states; just keep ctx->Current uptodate: */ + vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT; + vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT; vfmt->EdgeFlag = _mesa_noop_EdgeFlag; vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv; vfmt->Indexi = _mesa_noop_Indexi; @@ -640,10 +963,6 @@ void radeonInitTnlModule( GLcontext *ctx ) /* Active but unsupported -- fallback if we receive these: - * - * All of these fallbacks can be fixed with additional code, except - * CallList, unless we build a play_immediate_noop() command which - * turns an immediate back into glBegin/glEnd commands... */ vfmt->CallList = radeon_fallback_CallList; vfmt->EvalCoord1f = radeon_fallback_EvalCoord1f; @@ -654,132 +973,137 @@ void radeonInitTnlModule( GLcontext *ctx ) vfmt->EvalMesh2 = radeon_fallback_EvalMesh2; vfmt->EvalPoint1 = radeon_fallback_EvalPoint1; vfmt->EvalPoint2 = radeon_fallback_EvalPoint2; - - - rmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; - - /* THIS IS A HACK! - */ - _mesa_install_exec_vtxfmt( ctx, vfmt ); + vfmt->TexCoord3f = radeon_fallback_TexCoord3f; + vfmt->TexCoord3fv = radeon_fallback_TexCoord3fv; + vfmt->TexCoord4f = radeon_fallback_TexCoord4f; + vfmt->TexCoord4fv = radeon_fallback_TexCoord4fv; + vfmt->MultiTexCoord3fARB = radeon_fallback_MultiTexCoord3fARB; + vfmt->MultiTexCoord3fvARB = radeon_fallback_MultiTexCoord3fvARB; + vfmt->MultiTexCoord4fARB = radeon_fallback_MultiTexCoord4fARB; + vfmt->MultiTexCoord4fvARB = radeon_fallback_MultiTexCoord4fvARB; + vfmt->Vertex4f = radeon_fallback_Vertex4f; + vfmt->Vertex4fv = radeon_fallback_Vertex4fv; + + (void)radeon_fallback_vtxfmt; + + TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin; + + vb.context = ctx; + rmesa->vb.enabled = 1; + rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive; + rmesa->vb.primflags = 0; + + make_empty_list( &rmesa->vb.dfn_cache.Vertex2f ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex3f ); + make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv ); + make_empty_list( &rmesa->vb.dfn_cache.Color4ub ); + make_empty_list( &rmesa->vb.dfn_cache.Color4ubv ); + make_empty_list( &rmesa->vb.dfn_cache.Color3ub ); + make_empty_list( &rmesa->vb.dfn_cache.Color3ubv ); + make_empty_list( &rmesa->vb.dfn_cache.Color4f ); + make_empty_list( &rmesa->vb.dfn_cache.Color4fv ); + make_empty_list( &rmesa->vb.dfn_cache.Color3f ); + make_empty_list( &rmesa->vb.dfn_cache.Color3fv ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + make_empty_list( &rmesa->vb.dfn_cache.Normal3f ); + make_empty_list( &rmesa->vb.dfn_cache.Normal3fv ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f ); + make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); + + radeonInitCodegen( &rmesa->vb.codegen ); } - - - - - -#if 0 - - - -static void radeon_Begin( GLenum prim ) +static void free_funcs( struct dynfn *l ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - radeon_prim *tab = &radeon_prim_tab[(int)prim]; - - if ( prim > GL_POLYGON ) { - gl_error( ctx, GL_INVALID_ENUM, "glBegin" ); - return; - } - - if ( rmesa->prim != PRIM_OUTSIDE_BEGIN_END ) { - gl_error( ctx, GL_INVALID_OPERATION, "glBegin" ); - return; - } - - if ( tab->fire_on_vertex ) { - rmesa->fire_on_vertex = tab->fire_on_vertex; - rmesa->fire_on_end = tab->fire_on_end; - rmesa->fire_on_fallback = tab->fire_on_fallback; - rmesa->vert = &(rmesa->cache[0]); - rmesa->prim = prim; - ctx->Driver.NeedFlush |= (FLUSH_INSIDE_BEGIN_END | - FLUSH_STORED_VERTICES); - } else { - radeon_fallback_vtxfmt( ctx ); + struct dynfn *f, *tmp; + foreach_s (f, tmp, l) { + remove_from_list( f ); + ALIGN_FREE( f->code ); + FREE( f ); } } -static void radeon_End( void ) +void radeonVtxfmtUnbindContext( GLcontext *ctx ) { - GET_CURRENT_CONTEXT(ctx); - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - if ( rmesa->prim == PRIM_OUTSIDE_BEGIN_END ) { - gl_error( ctx, GL_INVALID_OPERATION, "glEnd" ); - return; + if (RADEON_CONTEXT(ctx)->vb.installed) { + assert(vb.context == ctx); + VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ ); } - rmesa->fire_on_end( ctx ); - rmesa->prim = PRIM_OUTSIDE_BEGIN_END; - - ctx->Exec->Vertex3fv = radeon_noop_Vertex3fv; - ctx->Exec->Vertex3f = radeon_noop_Vertex3f; - ctx->Exec->Vertex2f = radeon_noop_Vertex2f; - - ctx->Driver.NeedFlush &= ~(FLUSH_INSIDE_BEGIN_END | - FLUSH_STORED_VERTICES); + TNL_CONTEXT(ctx)->Driver.NotifyBegin = 0; } - - -static GLboolean radeon_flush_vtxfmt( GLcontext *ctx, GLuint flags ) +void radeonVtxfmtMakeCurrent( GLcontext *ctx ) { - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - - if ( fxMesa->prim != PRIM_OUTSIDE_BEGIN_END ) - return GL_FALSE; - - /* Outside begin/end. All vertices will already be flushed, just - * update ctx->Current. - */ - if ( flags & FLUSH_UPDATE_CURRENT ) { - radeonClipVertexPtr v = &(RADEON_CONTEXT(ctx)->Current); - COPY_2FV( ctx->Current.Texcoord[0], v->texcoord[0] ); - COPY_2FV( ctx->Current.Texcoord[1], v->texcoord[1] ); - if ( rmesa->accel_light == ACCEL_LIGHT ) { - COPY_3FV( ctx->Current.Normal, v->normal ); - } else { - ctx->Current.Color[RCOMP] = UBYTE_TO_CHAN( v->v.color.red ); - ctx->Current.Color[GCOMP] = UBYTE_TO_CHAN( v->v.color.green ); - ctx->Current.Color[BCOMP] = UBYTE_TO_CHAN( v->v.color.blue ); - ctx->Current.Color[ACOMP] = UBYTE_TO_CHAN( v->v.color.alpha ); + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + +#if defined(THREADS) + static GLboolean ThreadSafe = GL_FALSE; /* In thread-safe mode? */ + if (!ThreadSafe) { + static unsigned long knownID; + static GLboolean firstCall = GL_TRUE; + if (firstCall) { + knownID = _glthread_GetID(); + firstCall = GL_FALSE; + } + else if (knownID != _glthread_GetID()) { + ThreadSafe = GL_TRUE; - if ( ctx->Light.ColorMaterialEnabled ) - _mesa_update_color_material( ctx, ctx->Current.Color ); + if (RADEON_DEBUG & (DEBUG_DRI|DEBUG_VFMT)) + fprintf(stderr, "**** Multithread situation!\n"); } } + if (ThreadSafe) + return; +#endif - /* Could clear this flag and set it from each 'choose' function, - * maybe, but there isn't much of a penalty for leaving it set: - */ - ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT; - return GL_TRUE; + if (rmesa->vb.enabled) { + TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin; + } } -void radeon_update_lighting( GLcontext *ctx ) -{ - radeonContextPtr rmesa = RADEON_CONTEXT(ctx); - if ( !ctx->Light.Enabled ) { - rmesa->accel_light = ACCEL_NO_LIGHT; - } - else if ( !ctx->Light._NeedVertices && !ctx->Light.Model.TwoSide ) { - rmesa->accel_light = ACCEL_LIGHT; - radeon_recalc_basecolor( ctx ); - } - else { - radeon->accel_light = 0; - } +void radeonVtxfmtDestroy( GLcontext *ctx ) +{ + radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); + + count_funcs( rmesa ); + free_funcs( &rmesa->vb.dfn_cache.Vertex2f ); + free_funcs( &rmesa->vb.dfn_cache.Vertex2fv ); + free_funcs( &rmesa->vb.dfn_cache.Vertex3f ); + free_funcs( &rmesa->vb.dfn_cache.Vertex3fv ); + free_funcs( &rmesa->vb.dfn_cache.Color4ub ); + free_funcs( &rmesa->vb.dfn_cache.Color4ubv ); + free_funcs( &rmesa->vb.dfn_cache.Color3ub ); + free_funcs( &rmesa->vb.dfn_cache.Color3ubv ); + free_funcs( &rmesa->vb.dfn_cache.Color4f ); + free_funcs( &rmesa->vb.dfn_cache.Color4fv ); + free_funcs( &rmesa->vb.dfn_cache.Color3f ); + free_funcs( &rmesa->vb.dfn_cache.Color3fv ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT ); + free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT ); + free_funcs( &rmesa->vb.dfn_cache.Normal3f ); + free_funcs( &rmesa->vb.dfn_cache.Normal3fv ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord2f ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord1f ); + free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB ); + free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB ); } - -/* How to fallback: - * - install default vertex format - * - call glBegin - * - revive stalled vertices (may be reordered). - * - re-issue call that caused fallback. - */ -#endif |