diff options
author | Felix Kuehling <[email protected]> | 2005-01-16 01:28:26 +0000 |
---|---|---|
committer | Felix Kuehling <[email protected]> | 2005-01-16 01:28:26 +0000 |
commit | ad360a81bdc9076cc09f9241176116efdbba43e4 (patch) | |
tree | d6e5077f995b32803e0840422885d65178ff8d8e /src/mesa/drivers/dri/savage/savagerender.c | |
parent | ca710a0a7f0ae7e637e3e73cc4edac0a81f6fe1c (diff) |
Added a fast path for emitting unclipped primitives directly to a
vertex buffer. ELTS are not supported yet (missing functionality in
the DRM). You need at least Savage DRM version 2.1.3, which fixes a
bug that screwed up triangle fans and strips.
Moved the texture normalization stage to savagerender.c.
Diffstat (limited to 'src/mesa/drivers/dri/savage/savagerender.c')
-rw-r--r-- | src/mesa/drivers/dri/savage/savagerender.c | 356 |
1 files changed, 356 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/savage/savagerender.c b/src/mesa/drivers/dri/savage/savagerender.c new file mode 100644 index 00000000000..50ec9eac685 --- /dev/null +++ b/src/mesa/drivers/dri/savage/savagerender.c @@ -0,0 +1,356 @@ +/* + * Copyright 2005 Felix Kuehling + * 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, 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 FELIX KUEHLING 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. + */ + +/* + * Render unclipped vertex buffers by emitting vertices directly to + * dma buffers. Use strip/fan hardware primitives where possible. + * Simulate missing primitives with indexed vertices. + */ +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" + +#include "tnl/t_context.h" + +#include "savagecontext.h" +#include "savagetris.h" +#include "savagestate.h" +#include "savageioctl.h" + +/* + * Standard render tab for Savage4 and smooth shading on Savage3D + */ +#define HAVE_POINTS 0 +#define HAVE_LINES 0 +#define HAVE_LINE_STRIPS 0 +#define HAVE_TRIANGLES 1 +#define HAVE_TRI_STRIPS 1 +#define HAVE_TRI_STRIP_1 0 +#define HAVE_TRI_FANS 1 +#define HAVE_POLYGONS 0 +#define HAVE_QUADS 0 +#define HAVE_QUAD_STRIPS 0 + +#define HAVE_ELTS 0 /* for now */ + +#define LOCAL_VARS savageContextPtr imesa = SAVAGE_CONTEXT(ctx) +#define INIT( prim ) do { \ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ + savageFlushVertices(imesa); \ + switch (prim) { \ + case GL_TRIANGLES: imesa->HwPrim = SAVAGE_PRIM_TRILIST; break; \ + case GL_TRIANGLE_STRIP: imesa->HwPrim = SAVAGE_PRIM_TRISTRIP; break; \ + case GL_TRIANGLE_FAN: imesa->HwPrim = SAVAGE_PRIM_TRIFAN; break; \ + } \ +} while (0) +#define FLUSH() savageFlushVertices(imesa) +#define GET_CURRENT_VB_MAX_VERTS() \ + ((imesa->bufferSize/4 - imesa->vtxBuf->used) / imesa->HwVertexSize) +#define GET_SUBSEQUENT_VB_MAX_VERTS() \ + (imesa->bufferSize/4 / imesa->HwVertexSize) + +#define ALLOC_VERTS( nr ) \ + savageAllocVtxBuf( imesa, (nr) * imesa->HwVertexSize ) +#define EMIT_VERTS( ctx, j, nr, buf ) \ + _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf ) + +#define TAG(x) savage_##x +#include "tnl_dd/t_dd_dmatmp.h" + +/* + * On Savage3D triangle fans and strips are broken with flat + * shading. With triangles it wants the color for flat shading in the + * first vertex! So we make another template instance which uses + * triangles only (with reordered vertices: SAVAGE_PRIM_TRILIST_201). + * The reordering is done by the DRM. + */ +#undef HAVE_TRI_STRIPS +#undef HAVE_TRI_FANS +#define HAVE_TRI_STRIPS 0 +#define HAVE_TRI_FANS 0 + +#undef INIT +#define INIT( prim ) do { \ + if (0) fprintf(stderr, "%s\n", __FUNCTION__); \ + savageFlushVertices(imesa); \ + imesa->HwPrim = SAVAGE_PRIM_TRILIST_201; \ +} while(0) + +#undef TAG +#define TAG(x) savage_flat_##x##_s3d +#include "tnl_dd/t_dd_dmatmp.h" + + +/**********************************************************************/ +/* Render pipeline stage */ +/**********************************************************************/ + +static GLboolean savage_run_render( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + savageContextPtr imesa = SAVAGE_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + tnl_render_func *tab; + GLboolean valid; + GLuint i; + + if (imesa->savageScreen->chipset < S3_SAVAGE4 && + (ctx->_TriangleCaps & DD_FLATSHADE)) { + tab = savage_flat_render_tab_verts_s3d; + valid = savage_flat_validate_render_s3d( ctx, VB ); + } else { + tab = savage_render_tab_verts; + valid = savage_validate_render( ctx, VB ); + } + + /* Don't handle clipping or indexed vertices or vertex manipulations. + */ + if (imesa->RenderIndex != 0 || !valid) { + return GL_TRUE; + } + + tnl->Driver.Render.Start( ctx ); + /* Check RenderIndex again. The ptexHack is detected late in RenderStart. + * Also check for fallbacks detected late. + */ + if (imesa->RenderIndex != 0 || imesa->Fallback != 0) { + return GL_TRUE; + } + + /* setup for hardware culling */ + imesa->raster_primitive = GL_TRIANGLES; + imesa->new_state |= SAVAGE_NEW_CULL; + savageDDUpdateHwState(ctx); + + for (i = 0 ; i < VB->PrimitiveCount ; i++) + { + GLuint prim = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + if (length) + tab[prim & PRIM_MODE_MASK]( ctx, start, start+length, prim); + } + + tnl->Driver.Render.Finish( ctx ); + + return GL_FALSE; /* finished the pipe */ +} + +static void savage_check_render( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + __DRIscreenPrivate *driScrnPriv = + SAVAGE_CONTEXT(ctx)->savageScreen->driScrnPriv; + stage->inputs = TNL_CONTEXT(ctx)->render_inputs; + /* This hack will go away when we depend on 2.2.x for ELTS. */ + if (driScrnPriv->drmMinor <= 1 && driScrnPriv->drmPatch < 3) { + static GLboolean firstTime = GL_TRUE; + stage->active = GL_FALSE; + if (firstTime) { + fprintf (stderr, + "*** Disabling fast path because your DRM version is buggy.\n" + "*** You need at least Savage DRM version 2.1.3.\n"); + firstTime = GL_FALSE; + } + } +} + +static void dtr( struct tnl_pipeline_stage *stage ) +{ + (void)stage; +} + +const struct tnl_pipeline_stage _savage_render_stage = +{ + "savage render", + (_DD_NEW_SEPARATE_SPECULAR | + _NEW_TEXTURE| + _NEW_FOG| + _NEW_RENDERMODE), /* re-check (new inputs) */ + 0, /* re-run (always runs) */ + GL_TRUE, /* active */ + 0, 0, /* inputs (set in check_render), outputs */ + 0, 0, /* changed_inputs, private */ + dtr, /* destructor */ + savage_check_render, /* check - initially set to alloc data */ + savage_run_render /* run */ +}; + + +/**********************************************************************/ +/* Pipeline stage for texture coordinate normalization */ +/**********************************************************************/ +struct texnorm_stage_data { + GLvector4f texcoord[MAX_TEXTURE_UNITS]; +}; + +#define TEXNORM_STAGE_DATA(stage) ((struct texnorm_stage_data *)stage->privatePtr) + + +static GLboolean run_texnorm_stage( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage); + savageContextPtr imesa = SAVAGE_CONTEXT(ctx); + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + GLuint i; + + if (imesa->Fallback) + return GL_TRUE; + + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { + if (!(stage->inputs & stage->changed_inputs & VERT_BIT_TEX(i)) || + VB->TexCoordPtr[i]->size == 4) + /* Never try to normalize homogenous tex coords! */ + continue; + + GLuint reallyEnabled = ctx->Texture.Unit[i]._ReallyEnabled; + struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; + GLboolean normalizeS = (texObj->WrapS == GL_REPEAT); + GLboolean normalizeT = (reallyEnabled & TEXTURE_2D_BIT) && + (texObj->WrapT == GL_REPEAT); + GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data; + GLint instride = VB->TexCoordPtr[i]->stride; + GLfloat (*out)[4] = store->texcoord[i].data; + GLint j; + + if (normalizeS && normalizeT) { + /* take first texcoords as rough estimate of mean value */ + GLfloat correctionS = -floor(in[0]+0.5); + GLfloat correctionT = -floor(in[1]+0.5); + for (j = 0; j < VB->Count; ++j) { + out[j][0] = in[0] + correctionS; + out[j][1] = in[1] + correctionT; + in = (GLfloat *)((GLubyte *)in + instride); + } + } else if (normalizeS) { + /* take first texcoords as rough estimate of mean value */ + GLfloat correctionS = -floor(in[0]+0.5); + if (reallyEnabled & TEXTURE_2D_BIT) { + for (j = 0; j < VB->Count; ++j) { + out[j][0] = in[0] + correctionS; + out[j][1] = in[1]; + in = (GLfloat *)((GLubyte *)in + instride); + } + } else { + for (j = 0; j < VB->Count; ++j) { + out[j][0] = in[0] + correctionS; + in = (GLfloat *)((GLubyte *)in + instride); + } + } + } else if (normalizeT) { + /* take first texcoords as rough estimate of mean value */ + GLfloat correctionT = -floor(in[1]+0.5); + for (j = 0; j < VB->Count; ++j) { + out[j][0] = in[0]; + out[j][1] = in[1] + correctionT; + in = (GLfloat *)((GLubyte *)in + instride); + } + } + + if (normalizeS || normalizeT) + VB->AttribPtr[VERT_ATTRIB_TEX0+i] = VB->TexCoordPtr[i] = &store->texcoord[i]; + } + + return GL_TRUE; +} + +/* Called the first time stage->run() is invoked. + */ +static GLboolean alloc_texnorm_data( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; + struct texnorm_stage_data *store; + GLuint i; + + stage->privatePtr = CALLOC(sizeof(*store)); + store = TEXNORM_STAGE_DATA(stage); + if (!store) + return GL_FALSE; + + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) + _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); + + /* Now run the stage. + */ + stage->run = run_texnorm_stage; + return stage->run( ctx, stage ); +} + +static void check_texnorm( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + GLuint flags = 0; + + if (((ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) && + (ctx->Texture.Unit[0]._Current->WrapS == GL_REPEAT)) || + ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) && + (ctx->Texture.Unit[0]._Current->WrapT == GL_REPEAT))) + flags |= VERT_BIT_TEX0; + + if (((ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) && + (ctx->Texture.Unit[1]._Current->WrapS == GL_REPEAT)) || + ((ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT) && + (ctx->Texture.Unit[1]._Current->WrapT == GL_REPEAT))) + flags |= VERT_BIT_TEX1; + + stage->inputs = flags; + stage->outputs = flags; + stage->active = (flags != 0); +} + +static void free_texnorm_data( struct tnl_pipeline_stage *stage ) +{ + struct texnorm_stage_data *store = TEXNORM_STAGE_DATA(stage); + GLuint i; + + if (store) { + for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) + if (store->texcoord[i].data) + _mesa_vector4f_free( &store->texcoord[i] ); + FREE( store ); + stage->privatePtr = 0; + } +} + +const struct tnl_pipeline_stage _savage_texnorm_stage = +{ + "savage texture coordinate normalization stage", /* name */ + _NEW_TEXTURE, /* check_state */ + _NEW_TEXTURE, /* run_state */ + GL_TRUE, /* active? */ + 0, /* inputs */ + 0, /* outputs */ + 0, /* changed_inputs */ + NULL, /* private data */ + free_texnorm_data, /* destructor */ + check_texnorm, /* check */ + alloc_texnorm_data, /* run -- initially set to init */ +}; |