summaryrefslogtreecommitdiff
path: root/xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c
diff options
context:
space:
mode:
Diffstat (limited to 'xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c')
-rw-r--r--xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c498
1 files changed, 498 insertions, 0 deletions
diff --git a/xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c
new file mode 100644
index 000000000..a5cb9b6bc
--- /dev/null
+++ b/xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c
@@ -0,0 +1,498 @@
+/* -*- mode: c; c-basic-offset: 3 -*-
+ *
+ * Copyright 2000 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
+ * 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 (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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS 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.
+ */
+/* $XFree86$ */
+
+/*
+ * Original rewrite:
+ * Gareth Hughes <gareth@valinux.com>, 29 Sep - 1 Oct 2000
+ *
+ * Authors:
+ * Gareth Hughes <gareth@valinux.com>
+ * Brian Paul <brianp@valinux.com>
+ * Keith Whitwell <keithw@valinux.com>
+ *
+ */
+
+#include "tdfx_context.h"
+#include "tdfx_vb.h"
+
+#include "stages.h"
+#include "mem.h"
+
+
+#define COORD \
+do { \
+ v->v.x = winCoord[0] + xoffset; \
+ v->v.y = winCoord[1] + yoffset; \
+ v->v.z = winCoord[2]; \
+ v->v.rhw = w; \
+} while (0)
+
+
+/* The assembly is slower...
+ */
+#if 0 && defined(USE_X86_ASM)
+#define COL \
+do { \
+ __asm__ ( \
+ "movl (%%edx),%%eax \n" \
+ "bswap %%eax \n" \
+ "rorl $8,%%eax \n" \
+ "movl %%eax,16(%%edi) \n" \
+ : \
+ : "d" (color), "D" (v) \
+ : "%eax" ); \
+} while (0)
+#else
+#define COL \
+do { \
+ v->v.color.blue = color[2]; \
+ v->v.color.green = color[1]; \
+ v->v.color.red = color[0]; \
+ v->v.color.alpha = color[3]; \
+} while (0)
+#endif
+
+
+#define TEX0 \
+do { \
+ v->v.tu0 = tc0[i][0] * sScale0 * w; \
+ v->v.tv0 = tc0[i][1] * tScale0 * w; \
+} while (0)
+
+#define TEX1 \
+do { \
+ v->v.tu1 = tc1[i][0] * sScale1 * w; \
+ v->v.tv1 = tc1[i][1] * tScale1 * w; \
+} while (0)
+
+
+#define TEX0_4 \
+ if ( VB->TexCoordPtr[0]->size == 4 ) { \
+ GLfloat (*tc)[4] = VB->TexCoordPtr[0]->data; \
+ winCoord = VB->Win.data[start]; \
+ v = &(TDFX_DRIVER_DATA(VB)->verts[start]); \
+ for ( i = start ; i < end ; i++, v++, winCoord+=4 ) { \
+ v->v.tq0 = tc[i][3] * winCoord[3]; \
+ } \
+ }
+
+#define TEX1_4 \
+ if ( VB->TexCoordPtr[1]->size == 4 ) { \
+ GLfloat (*tc)[4] = VB->TexCoordPtr[1]->data; \
+ winCoord = VB->Win.data[start]; \
+ v = &(TDFX_DRIVER_DATA(VB)->verts[start]); \
+ for ( i = start ; i < end ; i++, v++, winCoord+=4 ) { \
+ v->v.tq1 = tc[i][3] * winCoord[3]; \
+ } \
+ }
+
+
+#define FOG
+
+
+#define NOP
+
+
+
+#define SETUPFUNC(name,win,col,tex0,tex1,tex0_4,tex1_4,fog) \
+static void name( struct vertex_buffer *VB, GLuint start, GLuint end ) \
+{ \
+ tdfxContextPtr fxMesa = TDFX_CONTEXT(VB->ctx); \
+ tdfxVertexPtr v; \
+ const GLfloat *winCoord; \
+ GLfloat (*tc0)[4]; \
+ GLfloat (*tc1)[4]; \
+ const GLfloat xoffset = fxMesa->x_offset + TRI_X_OFFSET; \
+ const GLfloat yoffset = fxMesa->y_delta + TRI_Y_OFFSET; \
+ const GLfloat sScale0 = fxMesa->sScale0; \
+ const GLfloat tScale0 = fxMesa->tScale0; \
+ const GLfloat sScale1 = fxMesa->sScale1; \
+ const GLfloat tScale1 = fxMesa->tScale1; \
+ const GLubyte *color; \
+ int i; \
+ \
+ (void) xoffset; (void) yoffset; \
+ (void) sScale0; (void) tScale0; \
+ (void) sScale1; (void) tScale1; \
+ \
+ if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
+ gl_import_client_data( VB, VB->ctx->RenderFlags, \
+ (VB->ClipOrMask \
+ ? VEC_WRITABLE|VEC_GOOD_STRIDE \
+ : VEC_GOOD_STRIDE)); \
+ \
+ tc0 = VB->TexCoordPtr[fxMesa->tmu_source[0]]->data; \
+ tc1 = VB->TexCoordPtr[fxMesa->tmu_source[1]]->data; \
+ color = VB->Color[0]->data[start]; \
+ winCoord = VB->Win.data[start]; \
+ \
+ v = &(TDFX_DRIVER_DATA(VB)->verts[start]); \
+ \
+ if ( VB->ClipOrMask == 0 ) { \
+ for ( i = start ; i < end ; i++, v++, color+=4, winCoord+=4 ) { \
+ const GLfloat w = winCoord[3]; \
+ (void) w; \
+ win; \
+ col; \
+ fog; \
+ tex0; \
+ tex1; \
+ } \
+ } else { \
+ for ( i = start ; i < end ; i++, v++, color+=4, winCoord+=4 ) { \
+ if ( VB->ClipMask[i] == 0 ) { \
+ const GLfloat w = winCoord[3]; \
+ (void) w; \
+ win; \
+ fog; \
+ tex0; \
+ tex1; \
+ } \
+ col; \
+ } \
+ } \
+ tex0_4; \
+ tex1_4; \
+}
+
+
+SETUPFUNC(rs_wt0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, NOP)
+SETUPFUNC(rs_wt0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP)
+SETUPFUNC(rs_wft0, COORD, NOP, TEX0, NOP, TEX0_4, NOP, FOG)
+SETUPFUNC(rs_wft0t1, COORD, NOP, TEX0, TEX1, TEX0_4, TEX1_4, FOG)
+SETUPFUNC(rs_wg, COORD, COL, NOP, NOP, NOP, NOP, NOP)
+SETUPFUNC(rs_wgt0, COORD, COL, TEX0, NOP, TEX0_4, NOP, NOP)
+SETUPFUNC(rs_wgt0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP)
+SETUPFUNC(rs_wgf, COORD, COL, NOP, NOP, NOP, NOP, FOG)
+SETUPFUNC(rs_wgft0, COORD, COL, TEX0, NOP, TEX0_4, NOP, FOG)
+SETUPFUNC(rs_wgft0t1, COORD, COL, TEX0, TEX1, TEX0_4, TEX1_4, FOG)
+
+SETUPFUNC(rs_t0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, NOP)
+SETUPFUNC(rs_t0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, NOP)
+SETUPFUNC(rs_f, NOP, NOP, NOP, NOP, NOP, NOP, FOG)
+SETUPFUNC(rs_ft0, NOP, NOP, TEX0, NOP, TEX0_4, NOP, FOG)
+SETUPFUNC(rs_ft0t1, NOP, NOP, TEX0, TEX1, TEX0_4, TEX1_4, FOG)
+SETUPFUNC(rs_g, NOP, COL, NOP, NOP, NOP, NOP, NOP)
+SETUPFUNC(rs_gt0, NOP, COL, TEX0, NOP, TEX0_4, NOP, NOP)
+SETUPFUNC(rs_gt0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, NOP)
+SETUPFUNC(rs_gf, NOP, COL, NOP, NOP, NOP, NOP, FOG)
+SETUPFUNC(rs_gft0, NOP, COL, TEX0, NOP, TEX0_4, NOP, FOG)
+SETUPFUNC(rs_gft0t1, NOP, COL, TEX0, TEX1, TEX0_4, TEX1_4, FOG)
+
+
+
+static void rs_invalid( struct vertex_buffer *VB, GLuint start, GLuint end )
+{
+ fprintf( stderr, "tdfxRasterSetup(): invalid setup function\n" );
+}
+
+typedef void (*setupFunc)( struct vertex_buffer *, GLuint, GLuint );
+
+static setupFunc setup_func[0x40];
+
+
+void tdfxDDSetupInit( void )
+{
+ int i;
+
+ for (i = 0; i < Elements(setup_func); i++)
+ setup_func[i] = rs_invalid;
+
+ /* Functions to build vertices from scratch */
+ setup_func[TDFX_WIN_BIT|TDFX_TEX0_BIT] = rs_wt0;
+ setup_func[TDFX_WIN_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_wt0t1;
+ setup_func[TDFX_WIN_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT] = rs_wft0;
+ setup_func[TDFX_WIN_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_wft0t1;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT] = rs_wg;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT|TDFX_TEX0_BIT] = rs_wgt0;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_wgt0t1;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT|TDFX_FOG_BIT] = rs_wgf;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT] = rs_wgft0;
+ setup_func[TDFX_WIN_BIT|TDFX_RGBA_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_wgft0t1;
+
+ /* Repair functions */
+ setup_func[TDFX_TEX0_BIT] = rs_t0;
+ setup_func[TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_t0t1;
+ setup_func[TDFX_FOG_BIT] = rs_f;
+ setup_func[TDFX_FOG_BIT|TDFX_TEX0_BIT] = rs_ft0;
+ setup_func[TDFX_FOG_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_ft0t1;
+ setup_func[TDFX_RGBA_BIT] = rs_g;
+ setup_func[TDFX_RGBA_BIT|TDFX_TEX0_BIT] = rs_gt0;
+ setup_func[TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_gt0t1;
+ setup_func[TDFX_RGBA_BIT|TDFX_FOG_BIT] = rs_gf;
+ setup_func[TDFX_RGBA_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT] = rs_gft0;
+ setup_func[TDFX_RGBA_BIT|TDFX_FOG_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT] = rs_gft0t1;
+}
+
+
+void tdfxPrintSetupFlags( char *msg, GLuint flags )
+{
+ fprintf( stderr, "%s: 0x%x %s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & TDFX_WIN_BIT) ? " xyzw," : "",
+ (flags & TDFX_RGBA_BIT) ? " rgba," : "",
+ (flags & TDFX_FOG_BIT) ? " fog," : "",
+ (flags & TDFX_TEX0_BIT) ? " tex-0," : "",
+ (flags & TDFX_TEX1_BIT) ? " tex-1," : "" );
+}
+
+
+/* ================================================================
+ * Raster Setup
+ */
+
+void tdfxDDChooseRasterSetupFunc( GLcontext *ctx )
+{
+ tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
+ int index = TDFX_WIN_BIT | TDFX_RGBA_BIT;
+ int vertexFormat = fxMesa->vertexFormat;
+
+ fxMesa->vertsize = 8;
+ fxMesa->tmu_source[0] = 0;
+ fxMesa->tmu_source[1] = 1;
+ fxMesa->tex_dest[0] = TDFX_TEX0_BIT;
+ fxMesa->tex_dest[1] = TDFX_TEX1_BIT;
+ fxMesa->vertexFormat = TDFX_LAYOUT_SINGLE;
+
+ if ( ctx->Texture.ReallyEnabled & ENABLE_TEX0 ) {
+ index |= TDFX_TEX0_BIT;
+ }
+
+ if ( ctx->Texture.ReallyEnabled & ENABLE_TEX1 ) {
+ if ( ctx->Texture.ReallyEnabled & ENABLE_TEX0 ) {
+ fxMesa->vertexFormat = TDFX_LAYOUT_MULTI;
+ fxMesa->vertsize = 10;
+ index |= TDFX_TEX1_BIT;
+ } else {
+ /* Just a funny way of doing single texturing.
+ */
+ fxMesa->tmu_source[0] = 1;
+ fxMesa->tex_dest[1] = TDFX_TEX0_BIT;
+ index |= TDFX_TEX0_BIT;
+ }
+ }
+
+ if (ctx->Texture.ReallyEnabled & (ENABLE_TEX0 | ENABLE_TEX1)) {
+ if ((ctx->VB->TexCoordPtr[0] && ctx->VB->TexCoordPtr[0]->size == 4) ||
+ (ctx->VB->TexCoordPtr[1] && ctx->VB->TexCoordPtr[1]->size == 4)) {
+ fxMesa->vertexFormat = TDFX_LAYOUT_PROJECT;
+ }
+ }
+
+ if ( ctx->Fog.Enabled )
+ index |= TDFX_FOG_BIT;
+
+ fxMesa->SetupIndex = index;
+ ctx->Driver.RasterSetup = setup_func[index];
+
+ if ( fxMesa->vertexFormat != vertexFormat ) {
+ fxMesa->dirty |= TDFX_UPLOAD_VERTEX_LAYOUT;
+ }
+
+ if (0) {
+ tdfxPrintSetupFlags( "full setup function", index );
+ fprintf(stderr, "full setup function %p\n", ctx->Driver.RasterSetup);
+ }
+}
+
+/* Check to see if vertices need repairing.
+ */
+void tdfxDDCheckPartialRasterSetup( GLcontext *ctx,
+ struct gl_pipeline_stage *d )
+{
+ tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
+ int tmp = fxMesa->SetupDone;
+
+ d->type = 0;
+ fxMesa->SetupDone = 0; /* cleared if we return */
+
+ if ( (ctx->Array.Summary & VERT_OBJ_ANY) == 0 )
+ return;
+ if ( ctx->IndirectTriangles )
+ return;
+
+ fxMesa->SetupDone = tmp;
+}
+
+/* Repair existing precalculated vertices with new data.
+ */
+void tdfxDDPartialRasterSetup( struct vertex_buffer *VB )
+{
+ tdfxContextPtr fxMesa = TDFX_CONTEXT( VB->ctx );
+ GLuint new = VB->pipeline->new_outputs;
+ GLuint available = VB->pipeline->outputs;
+ GLuint index = 0;
+
+ if ( new & VERT_WIN ) {
+ new = available;
+ index |= TDFX_WIN_BIT | TDFX_FOG_BIT;
+ }
+
+ if ( new & VERT_RGBA )
+ index |= TDFX_RGBA_BIT;
+
+ if ( new & VERT_TEX0_ANY )
+ index |= TDFX_TEX0_BIT;
+
+ if ( new & VERT_TEX1_ANY )
+ index |= fxMesa->tex_dest[1];
+
+ if ( new & VERT_FOG_COORD )
+ index |= TDFX_FOG_BIT;
+
+ fxMesa->SetupDone &= ~index;
+ index &= fxMesa->SetupIndex;
+ fxMesa->SetupDone |= index;
+
+ if ( 0 )
+ tdfxPrintSetupFlags( "partial setup function", index );
+
+ if ( index )
+ setup_func[index]( VB, VB->Start, VB->Count );
+}
+
+void tdfxDDDoRasterSetup( struct vertex_buffer *VB )
+{
+ GLcontext *ctx = VB->ctx;
+
+ if ( VB->Type == VB_CVA_PRECALC ) {
+ tdfxDDPartialRasterSetup( VB );
+ } else if ( ctx->Driver.RasterSetup ) {
+ ctx->Driver.RasterSetup( VB, VB->CopyStart, VB->Count );
+ }
+}
+
+
+/* ================================================================
+ * Device-specific Vertex Buffers
+ */
+
+void tdfxDDResizeVB( struct vertex_buffer *VB, GLuint size )
+{
+ tdfxVertexBufferPtr fxVB = TDFX_DRIVER_DATA(VB);
+
+ while ( fxVB->size < size )
+ fxVB->size *= 2;
+
+ ALIGN_FREE( fxVB->vert_store );
+ fxVB->vert_store = ALIGN_MALLOC( sizeof(tdfxVertex) * fxVB->size, 32 );
+ if ( !fxVB->vert_store ) {
+ fprintf( stderr, "Cannot allocate vertex store! Exiting...\n" );
+ exit( 1 );
+ }
+
+ fxVB->verts = (tdfxVertexPtr)fxVB->vert_store;
+
+ gl_vector1ui_free( &fxVB->clipped_elements );
+ gl_vector1ui_alloc( &fxVB->clipped_elements,
+ VEC_WRITABLE, fxVB->size, 32 );
+ if ( !fxVB->clipped_elements.start ) {
+ fprintf( stderr, "Cannot allocate clipped elements! Exiting...\n" );
+ exit( 1 );
+ }
+
+ ALIGN_FREE( VB->ClipMask );
+ VB->ClipMask = (GLubyte *)ALIGN_MALLOC( sizeof(GLubyte) * fxVB->size, 32 );
+ if ( !VB->ClipMask ) {
+ fprintf( stderr, "Cannot allocate clipmask! Exiting...\n" );
+ exit( 1 );
+ }
+}
+
+void tdfxDDResizeElts( struct vertex_buffer *VB, GLuint size )
+{
+#if 0
+ tdfxVertexBufferPtr fxVB = TDFX_DRIVER_DATA(VB);
+
+ FREE(fxVB->elts);
+
+ while (fxVB->elt_size < size)
+ fxVB->elt_size *= 2;
+
+ FREE(fxVB->elts);
+ fxVB->elts = MALLOC( sizeof(tdfxVertex *) * fxVB->elt_size );
+ if ( !fxVB->elts ) {
+ fprintf( stderr, "Cannot allocate vertex indirection! Exiting...\n" );
+ exit( 1 );
+ }
+#endif
+}
+
+void tdfxDDRegisterVB( struct vertex_buffer *VB )
+{
+ tdfxVertexBufferPtr fxVB;
+
+ fxVB = (tdfxVertexBufferPtr) CALLOC( sizeof(*fxVB) );
+
+ fxVB->elt_size = fxVB->size = VB->Size * 2;
+ fxVB->vert_store = ALIGN_MALLOC( sizeof(tdfxVertex) * fxVB->size, 32 );
+ if ( !fxVB->vert_store ) {
+ fprintf( stderr, "Cannot allocate vertex store! Exiting...\n" );
+ exit( 1 );
+ }
+
+ fxVB->verts = (tdfxVertexPtr)fxVB->vert_store;
+
+#if 0
+ fxVB->elts = MALLOC( sizeof(tdfxVertex *) * fxVB->elt_size );
+ if ( !fxVB->elts ) {
+ fprintf( stderr, "Cannot allocate vertex indirection! Exiting...\n" );
+ exit( 1 );
+ }
+#endif
+
+ gl_vector1ui_alloc( &fxVB->clipped_elements,
+ VEC_WRITABLE, fxVB->size, 32 );
+ if ( !fxVB->clipped_elements.start ) {
+ fprintf( stderr, "Cannot allocate clipped elements! Exiting...\n" );
+ exit( 1 );
+ }
+
+
+ ALIGN_FREE( VB->ClipMask );
+ VB->ClipMask = (GLubyte *)ALIGN_MALLOC( sizeof(GLubyte) * fxVB->size, 32 );
+ if ( !VB->ClipMask ) {
+ fprintf( stderr, "Cannot allocate clipmask! Exiting...\n" );
+ exit( 1 );
+ }
+
+ VB->driver_data = fxVB;
+}
+
+void tdfxDDUnregisterVB( struct vertex_buffer *VB )
+{
+ tdfxVertexBufferPtr fxVB = TDFX_DRIVER_DATA(VB);
+
+ if ( fxVB ) {
+ if ( fxVB->vert_store ) ALIGN_FREE( fxVB->vert_store );
+ if ( fxVB->elts ) ALIGN_FREE( fxVB->elts );
+ gl_vector1ui_free( &fxVB->clipped_elements );
+ FREE( fxVB );
+ VB->driver_data = NULL;
+ }
+}