summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/savage/savagerender.c
diff options
context:
space:
mode:
authorFelix Kuehling <fxkuehl@gmx.de>2005-01-16 01:28:26 +0000
committerFelix Kuehling <fxkuehl@gmx.de>2005-01-16 01:28:26 +0000
commitad360a81bdc9076cc09f9241176116efdbba43e4 (patch)
treed6e5077f995b32803e0840422885d65178ff8d8e /src/mesa/drivers/dri/savage/savagerender.c
parentca710a0a7f0ae7e637e3e73cc4edac0a81f6fe1c (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.c356
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 0000000000..50ec9eac68
--- /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 */
+};