summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/s3v
diff options
context:
space:
mode:
authorAdam Jackson <ajax@freedesktop.org>2004-12-16 19:26:23 +0000
committerAdam Jackson <ajax@freedesktop.org>2004-12-16 19:26:23 +0000
commitc403bcb8a7be437976d5adce41189fff1e7f690f (patch)
treefcd53d612d1725eb2609c49031e04da54a52370b /src/mesa/drivers/dri/s3v
parent8662c5d98febd8efaf5f8ee47d34c7fcfd597ce3 (diff)
Import s3virge and trident drivers. Not functional yet; no Makefile, no DRI-aware DDX.
Diffstat (limited to 'src/mesa/drivers/dri/s3v')
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_context.c258
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_context.h443
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_dd.c107
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_inithw.c79
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_lock.c62
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_lock.h103
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_macros.h233
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_regs.h367
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_render.c251
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_screen.c96
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_screen.h36
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_span.c308
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_state.c885
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tex.c560
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tex.h26
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_texmem.c583
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_texstate.c303
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tris.c850
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tris.h11
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_tritmp.h899
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_vb.c341
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_vb.h39
-rw-r--r--src/mesa/drivers/dri/s3v/s3v_xmesa.c326
-rw-r--r--src/mesa/drivers/dri/s3v/s3virgetri.h383
24 files changed, 7549 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/s3v/s3v_context.c b/src/mesa/drivers/dri/s3v/s3v_context.c
new file mode 100644
index 0000000000..4e199a68cd
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_context.c
@@ -0,0 +1,258 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "context.h"
+#include "simple_list.h"
+#include "mem.h"
+#include "matrix.h"
+#include "extensions.h"
+#if defined(USE_X86_ASM)
+#include "X86/common_x86_asm.h"
+#endif
+#include "simple_list.h"
+#include "mem.h"
+#include "mm.h"
+
+
+#include "s3v_vb.h"
+#include "s3v_tris.h"
+
+#if 0
+extern const struct gl_pipeline_stage _s3v_render_stage;
+
+static const struct gl_pipeline_stage *s3v_pipeline[] = {
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ /* REMOVE: point attenuation stage */
+#if 1
+ &_s3v_render_stage, /* ADD: unclipped rastersetup-to-dma */
+#endif
+ &_tnl_render_stage,
+ 0,
+};
+#endif
+
+GLboolean s3vCreateContext( Display *dpy, const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate)
+{
+ GLcontext *ctx, *shareCtx;
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ s3vContextPtr vmesa;
+ s3vScreenPtr s3vScrn;
+ S3VSAREAPtr saPriv=(S3VSAREAPtr)(((char*)sPriv->pSAREA)+
+ sizeof(XF86DRISAREARec));
+
+ DEBUG_WHERE(("*** s3vCreateContext ***\n"));
+
+ vmesa = (s3vContextPtr) CALLOC( sizeof(*vmesa) );
+ if ( !vmesa ) return GL_FALSE;
+
+ /* Allocate the Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((s3vContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+
+ vmesa->glCtx = _mesa_create_context(glVisual, shareCtx, vmesa, GL_TRUE);
+ if (!vmesa->glCtx) {
+ FREE(vmesa);
+ return GL_FALSE;
+ }
+
+ vmesa->display = dpy;
+
+ vmesa->driContext = driContextPriv;
+ vmesa->driScreen = sPriv;
+ vmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */
+
+ vmesa->hHWContext = driContextPriv->hHWContext;
+ vmesa->driHwLock = &sPriv->pSAREA->lock;
+ vmesa->driFd = sPriv->fd;
+ vmesa->sarea = saPriv;
+
+ s3vScrn = vmesa->s3vScreen = (s3vScreenPtr)(sPriv->private);
+
+ ctx = vmesa->glCtx;
+
+ ctx->Const.MaxTextureLevels = 11; /* it is (11-1) -> 1024 * 1024 FIXME */
+
+ ctx->Const.MaxTextureUnits = 1; /* FIXME: or 2 ? */
+
+ /* No wide points.
+ */
+ ctx->Const.MinPointSize = 1.0;
+ ctx->Const.MinPointSizeAA = 1.0;
+ ctx->Const.MaxPointSize = 1.0;
+ ctx->Const.MaxPointSizeAA = 1.0;
+
+ /* No wide lines.
+ */
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 1.0;
+ ctx->Const.MaxLineWidthAA = 1.0;
+ ctx->Const.LineWidthGranularity = 1.0;
+
+ vmesa->texHeap = mmInit( 0, vmesa->s3vScreen->textureSize );
+ DEBUG(("vmesa->s3vScreen->textureSize = 0x%x\n",
+ vmesa->s3vScreen->textureSize));
+
+ /* NOTE */
+ /* mmInit(offset, size); */
+
+ /* allocates a structure like this:
+
+ struct mem_block_t {
+ struct mem_block_t *next;
+ struct mem_block_t *heap;
+ int ofs,size;
+ int align;
+ int free:1;
+ int reserved:1;
+ };
+
+ */
+
+ make_empty_list(&vmesa->TexObjList);
+ make_empty_list(&vmesa->SwappedOut);
+
+ vmesa->CurrentTexObj[0] = 0;
+ vmesa->CurrentTexObj[1] = 0; /* FIXME */
+
+ vmesa->RenderIndex = ~0;
+
+ /* Initialize the software rasterizer and helper modules.
+ */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+
+ /* Install the customized pipeline:
+ */
+#if 0
+ _tnl_destroy_pipeline( ctx );
+ _tnl_install_pipeline( ctx, s3v_pipeline );
+#endif
+ /* Configure swrast to match hardware characteristics:
+ */
+#if 0
+ _swrast_allow_pixel_fog( ctx, GL_FALSE );
+ _swrast_allow_vertex_fog( ctx, GL_TRUE );
+#endif
+ vmesa->_3d_mode = 0;
+
+ /* 3D lines / gouraud tris */
+ vmesa->CMD = ( AUTO_EXEC_ON | HW_CLIP_ON | DEST_COL_1555
+ | FOG_OFF | ALPHA_OFF | Z_OFF | Z_UPDATE_OFF
+ | Z_LESS | TEX_WRAP_ON | TEX_MODULATE | LINEAR
+ | TEX_COL_ARGB1555 | CMD_3D );
+
+ vmesa->_alpha[0] = vmesa->_alpha[1] = ALPHA_OFF;
+ vmesa->alpha_cmd = vmesa->_alpha[0];
+ vmesa->_tri[0] = DO_GOURAUD_TRI;
+ vmesa->_tri[1] = DO_TEX_LIT_TRI;
+ vmesa->prim_cmd = vmesa->_tri[0];
+
+ /* printf("first vmesa->CMD = 0x%x\n", vmesa->CMD); */
+
+ vmesa->TexOffset = vmesa->s3vScreen->texOffset;
+
+ s3vInitVB( ctx );
+ s3vInitExtensions( ctx );
+ s3vInitDriverFuncs( ctx );
+ s3vInitStateFuncs( ctx );
+ s3vInitSpanFuncs( ctx );
+ s3vInitTextureFuncs( ctx );
+ s3vInitTriFuncs( ctx );
+ s3vInitState( vmesa );
+
+ driContextPriv->driverPrivate = (void *)vmesa;
+
+ /* HACK */
+ vmesa->bufSize = S3V_DMA_BUF_SZ;
+
+ DEBUG(("vmesa->bufSize = %i\n", vmesa->bufSize));
+ DEBUG(("vmesa->bufCount = %i\n", vmesa->bufCount));
+
+
+ /* dma init */
+ DEBUG_BUFS(("GET_FIRST_DMA\n"));
+
+ vmesa->_bufNum = 0;
+
+ GET_FIRST_DMA(vmesa->driFd, vmesa->hHWContext,
+ 1, &(vmesa->bufIndex[0]), &(vmesa->bufSize),
+ &vmesa->_buf[0], &vmesa->bufCount, s3vScrn);
+
+ GET_FIRST_DMA(vmesa->driFd, vmesa->hHWContext,
+ 1, &(vmesa->bufIndex[1]), &(vmesa->bufSize),
+ &vmesa->_buf[1], &vmesa->bufCount, s3vScrn);
+
+ vmesa->buf = vmesa->_buf[vmesa->_bufNum];
+
+/*
+ vmesa->CMD = (AUTO_EXEC_ON | HW_CLIP_ON | DEST_COL_1555
+ | FOG_OFF | ALPHA_OFF | Z_OFF | Z_UPDATE_OFF
+ | DO_GOURAUD_TRI | CMD_3D);
+
+ vmesa->TexOffset = vmesa->s3vScreen->texOffset;
+*/
+
+/* ... but we should support only 15 bit in virge (out of 8/15/24)... */
+
+ DEBUG(("glVisual->depthBits = %i\n", glVisual->depthBits));
+
+ switch (glVisual->depthBits) {
+ case 8:
+ break;
+
+ case 15:
+ case 16:
+ vmesa->depth_scale = 1.0f / 0xffff;
+ break;
+ case 24:
+ vmesa->depth_scale = 1.0f / 0xffffff;
+ break;
+ default:
+ break;
+ }
+
+ vmesa->cull_zero = 0.0f;
+
+ vmesa->DepthSize = glVisual->depthBits;
+ vmesa->Flags = S3V_FRONT_BUFFER;
+ vmesa->Flags |= (glVisual->doubleBufferMode ? S3V_BACK_BUFFER : 0);
+ vmesa->Flags |= (vmesa->DepthSize > 0 ? S3V_DEPTH_BUFFER : 0);
+
+ vmesa->EnabledFlags = S3V_FRONT_BUFFER;
+ vmesa->EnabledFlags |= (glVisual->doubleBufferMode ? S3V_BACK_BUFFER : 0);
+
+
+ if (vmesa->Flags & S3V_BACK_BUFFER) {
+ vmesa->readOffset = vmesa->drawOffset = vmesa->s3vScreen->backOffset;
+ } else {
+ vmesa->readOffset = vmesa->drawOffset = 0;
+ }
+
+ s3vInitHW( vmesa );
+
+ driContextPriv->driverPrivate = (void *)vmesa;
+
+ return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_context.h b/src/mesa/drivers/dri/s3v/s3v_context.h
new file mode 100644
index 0000000000..79cd6feb5a
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_context.h
@@ -0,0 +1,443 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef _S3V_CONTEXT_H_
+#define _S3V_CONTEXT_H_
+
+#include "dri_util.h"
+
+#include "s3v_dri.h"
+#include "s3v_regs.h"
+#include "s3v_macros.h"
+#include "s3v_screen.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "drm.h"
+#include "mm.h"
+
+/* Flags for context */
+#define S3V_FRONT_BUFFER 0x00000001
+#define S3V_BACK_BUFFER 0x00000002
+#define S3V_DEPTH_BUFFER 0x00000004
+
+ /* FIXME: check */
+#define S3V_MAX_TEXTURE_SIZE 2048
+
+/* These are the minimum requirements and should probably be increased */
+#define MAX_MODELVIEW_STACK 16
+#define MAX_PROJECTION_STACK 2
+#define MAX_TEXTURE_STACK 2
+
+extern void s3vDDUpdateHWState(GLcontext *ctx);
+extern s3vScreenPtr s3vCreateScreen(__DRIscreenPrivate *sPriv);
+extern void s3vDestroyScreen(__DRIscreenPrivate *sPriv);
+extern GLboolean s3vCreateContext( Display *dpy,
+ const __GLcontextModes *glVisual,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+
+#define S3V_UPLOAD_ALL 0xffffffff
+/* #define S3V_UPLOAD_CLIPRECTS 0x00000002 */
+#define S3V_UPLOAD_ALPHA 0x00000004
+#define S3V_UPLOAD_BLEND 0x00000008
+#define S3V_UPLOAD_DEPTH 0x00000010
+#define S3V_UPLOAD_VIEWPORT 0x00000020
+#define S3V_UPLOAD_SHADE 0x00000040
+#define S3V_UPLOAD_CLIP 0x00000080
+#define S3V_UPLOAD_MASKS 0x00000100
+#define S3V_UPLOAD_WINDOW 0x00000200 /* defunct */
+#define S3V_UPLOAD_GEOMETRY 0x00000400
+#define S3V_UPLOAD_POLYGON 0x00000800
+#define S3V_UPLOAD_DITHER 0x00001000
+#define S3V_UPLOAD_LOGICOP 0x00002000
+#define S3V_UPLOAD_FOG 0x00004000
+#define S3V_UPLOAD_LIGHT 0x00008000
+#define S3V_UPLOAD_CONTEXT 0x00010000
+#define S3V_UPLOAD_TEX0 0x00020000
+#define S3V_UPLOAD_STIPPLE 0x00040000
+#define S3V_UPLOAD_TRANSFORM 0x00080000
+#define S3V_UPLOAD_LINEMODE 0x00100000
+#define S3V_UPLOAD_POINTMODE 0x00200000
+#define S3V_UPLOAD_TRIMODE 0x00400000
+
+#define S3V_NEW_CLIP 0x00000001
+#define S3V_NEW_WINDOW 0x00000002
+#define S3V_NEW_CONTEXT 0x00000004
+#define S3V_NEW_TEXTURE 0x00000008 /* defunct */
+#define S3V_NEW_ALPHA 0x00000010
+#define S3V_NEW_DEPTH 0x00000020
+#define S3V_NEW_MASKS 0x00000040
+#define S3V_NEW_POLYGON 0x00000080
+#define S3V_NEW_CULL 0x00000100
+#define S3V_NEW_LOGICOP 0x00000200
+#define S3V_NEW_FOG 0x00000400
+#define S3V_NEW_LIGHT 0x00000800
+#define S3V_NEW_STIPPLE 0x00001000
+#define S3V_NEW_ALL 0xffffffff
+
+#define S3V_FALLBACK_TRI 0x00000001
+#define S3V_FALLBACK_TEXTURE 0x00000002
+
+struct s3v_context;
+typedef struct s3v_context s3vContextRec;
+typedef struct s3v_context *s3vContextPtr;
+typedef struct s3v_texture_object_t *s3vTextureObjectPtr;
+
+#define VALID_S3V_TEXTURE_OBJECT(tobj) (tobj)
+
+#define S3V_TEX_MAXLEVELS 12
+
+/* For shared texture space managment, these texture objects may also
+ * be used as proxies for regions of texture memory containing other
+ * client's textures. Such proxy textures (not to be confused with GL
+ * proxy textures) are subject to the same LRU aging we use for our
+ * own private textures, and thus we have a mechanism where we can
+ * fairly decide between kicking out our own textures and those of
+ * other clients.
+ *
+ * Non-local texture objects have a valid MemBlock to describe the
+ * region managed by the other client, and can be identified by
+ * 't->globj == 0'
+ */
+struct s3v_texture_object_t {
+ struct s3v_texture_object_t *next, *prev;
+
+ GLuint age;
+ struct gl_texture_object *globj;
+
+ int Pitch;
+ int Height;
+ int WidthLog2;
+ int texelBytes;
+ int totalSize;
+ int bound;
+
+ PMemBlock MemBlock;
+ GLuint BufAddr;
+
+ GLuint min_level;
+ GLuint max_level;
+ GLuint dirty_images;
+
+ GLint firstLevel, lastLevel; /* upload tObj->Image[first .. lastLevel] */
+
+ struct {
+ const struct gl_texture_image *image;
+ int offset; /* into BufAddr */
+ int height;
+ int internalFormat;
+ } image[S3V_TEX_MAXLEVELS];
+
+ CARD32 TextureCMD;
+
+ CARD32 TextureColorMode;
+ CARD32 TextureFilterMode;
+ CARD32 TextureBorderColor;
+ CARD32 TextureWrap;
+ CARD32 TextureMipSize;
+
+ CARD32 TextureBaseAddr[S3V_TEX_MAXLEVELS];
+ CARD32 TextureFormat;
+ CARD32 TextureReadMode;
+};
+
+#define S3V_NO_PALETTE 0x0
+#define S3V_USE_PALETTE 0x1
+#define S3V_UPDATE_PALETTE 0x2
+#define S3V_FALLBACK_PALETTE 0x4
+
+void s3vUpdateTextureState( GLcontext *ctx );
+
+void s3vDestroyTexObj( s3vContextPtr vmesa, s3vTextureObjectPtr t);
+void s3vUploadTexImages( s3vContextPtr vmesa, s3vTextureObjectPtr t );
+
+void s3vResetGlobalLRU( s3vContextPtr vmesa );
+void s3vTexturesGone( s3vContextPtr vmesa,
+ GLuint start, GLuint end,
+ GLuint in_use );
+
+void s3vEmitHwState( s3vContextPtr vmesa );
+void s3vGetLock( s3vContextPtr vmesa, GLuint flags );
+void s3vInitExtensions( GLcontext *ctx );
+void s3vInitDriverFuncs( GLcontext *ctx );
+void s3vInitSpanFuncs( GLcontext *ctx );
+void s3vInitState( s3vContextPtr vmesa );
+void s3vInitHW( s3vContextPtr vmesa );
+void s3vInitStateFuncs( GLcontext *ctx );
+void s3vInitTextureFuncs( GLcontext *ctx );
+void s3vInitTriFuncs( GLcontext *ctx );
+
+void s3vUpdateWindow( GLcontext *ctx );
+void s3vUpdateViewportOffset( GLcontext *ctx );
+
+void s3vPrintLocalLRU( s3vContextPtr vmesa );
+void s3vPrintGlobalLRU( s3vContextPtr vmesa );
+
+extern void s3vFallback( s3vContextPtr vmesa, GLuint bit, GLboolean mode );
+#define FALLBACK( imesa, bit, mode ) s3vFallback( imesa, bit, mode )
+
+/* Use the templated vertex formats. Only one of these is used in s3v.
+ */
+#define TAG(x) s3v##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+typedef void (*s3v_quad_func)( s3vContextPtr,
+ const s3vVertex *,
+ const s3vVertex *,
+ const s3vVertex *,
+ const s3vVertex * );
+typedef void (*s3v_tri_func)( s3vContextPtr,
+ const s3vVertex *,
+ const s3vVertex *,
+ const s3vVertex * );
+typedef void (*s3v_line_func)( s3vContextPtr,
+ const s3vVertex *,
+ const s3vVertex * );
+typedef void (*s3v_point_func)( s3vContextPtr,
+ const s3vVertex * );
+
+
+/* static void s3v_lines_emit(GLcontext *ctx, GLuint start, GLuint end); */
+typedef void (*emit_func)( GLcontext *, GLuint, GLuint);
+
+struct s3v_context {
+ GLcontext *glCtx; /* Mesa context */
+
+ __DRIcontextPrivate *driContext;
+ __DRIscreenPrivate *driScreen;
+ __DRIdrawablePrivate *driDrawable;
+
+ GLuint new_gl_state;
+ GLuint new_state;
+ GLuint dirty;
+
+ S3VSAREAPtr sarea;
+
+ /* Temporaries for translating away float colors
+ */
+ struct gl_client_array UbyteColor;
+ struct gl_client_array UbyteSecondaryColor;
+
+ /* Mirrors of some DRI state
+ */
+ Display *display; /* X server display */
+
+ drmContext hHWContext;
+ drmLock *driHwLock;
+ int driFd;
+
+ GLuint numClipRects; /* Cliprects for the draw buffer */
+ XF86DRIClipRectPtr pClipRects;
+
+ CARD32* buf; /* FIXME */
+ CARD32* _buf[2];
+ int _bufNum;
+ int bufIndex[2];
+ int bufSize;
+ int bufCount;
+
+ s3vScreenPtr s3vScreen; /* Screen private DRI data */
+
+ int drawOffset;
+ int readOffset;
+
+ s3v_point_func draw_point;
+ s3v_line_func draw_line;
+ s3v_tri_func draw_tri;
+ s3v_quad_func draw_quad;
+
+ GLuint Fallback;
+ GLuint RenderIndex;
+ GLuint SetupNewInputs;
+ GLuint SetupIndex;
+
+ GLuint vertex_format;
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ char *verts;
+
+ GLfloat hw_viewport[16];
+ GLuint hw_primitive;
+ GLenum render_primitive;
+
+ GLfloat depth_scale;
+
+ s3vTextureObjectPtr CurrentTexObj[2];
+ struct s3v_texture_object_t TexObjList;
+ struct s3v_texture_object_t SwappedOut;
+ GLenum TexEnvImageFmt[2];
+
+ memHeap_t *texHeap;
+
+ int lastSwap;
+ int texAge;
+ int ctxAge;
+ int dirtyAge;
+ int lastStamp;
+
+ /* max was here: don't touch */
+
+ unsigned int S3V_REG[S3V_REGS_NUM];
+
+ CARD32 texMode;
+ CARD32 alphaMode;
+ CARD32 lightMode;
+
+ CARD32 SrcBase;
+ CARD32 DestBase;
+ CARD32 DestBlit;
+ CARD32 ScissorLR;
+ CARD32 ScissorTB;
+ CARD32 ScissorWH; /* SubScissorWH */ /* RectWH */
+ CARD32 FrontStride;
+ CARD32 BackStride;
+ CARD32 SrcStride;
+ CARD32 DestStride;
+ CARD32 SrcXY;
+ CARD32 DestXY;
+
+ CARD32 ClearColor;
+ CARD32 Color;
+ CARD32 DitherMode;
+ CARD32 ClearDepth;
+
+ CARD32 TextureBorderColor;
+ CARD32 TexOffset;
+ CARD32 TexStride;
+
+ CARD32 CMD;
+ CARD32 prim_cmd;
+ CARD32 _tri[2]; /* 0 = gouraud; 1 = tex (lit or unlit) */
+ CARD32 alpha_cmd; /* actual alpha cmd */
+ CARD32 _alpha[2];
+ CARD32 _alpha_tex; /* tex alpha type */
+ /* (3d_mode) 0 = 3d line/gourad tri; 1 = 3d tex tri */
+ CARD32 _3d_mode;
+
+ GLfloat backface_sign;
+ GLfloat cull_zero;
+
+ int restore_primitive;
+
+/* *** 2check *** */
+
+ CARD32 FogMode;
+ CARD32 AreaStippleMode;
+ CARD32 LBReadFormat;
+ CARD32 LBWriteFormat;
+ CARD32 LineMode;
+ CARD32 PointMode;
+ CARD32 TriangleMode;
+ CARD32 AntialiasMode;
+ GLfloat ViewportScaleX;
+ GLfloat ViewportScaleY;
+ GLfloat ViewportScaleZ;
+ GLfloat ViewportOffsetX;
+ GLfloat ViewportOffsetY;
+ GLfloat ViewportOffsetZ;
+ int MatrixMode;
+ int DepthMode;
+ int TransformMode;
+ int LBReadMode;
+ int FBReadMode;
+ int FBWindowBase;
+ int LBWindowBase;
+ int ColorDDAMode;
+ int GeometryMode;
+ int AlphaTestMode;
+ int AlphaBlendMode;
+ int AB_FBReadMode;
+ int AB_FBReadMode_Save;
+ int DeltaMode;
+ int ColorMaterialMode;
+ int FBHardwareWriteMask;
+ int MaterialMode;
+ int NormalizeMode;
+ int LightingMode;
+ int Light0Mode;
+ int Light1Mode;
+ int Light2Mode;
+ int Light3Mode;
+ int Light4Mode;
+ int Light5Mode;
+ int Light6Mode;
+ int Light7Mode;
+ int Light8Mode;
+ int Light9Mode;
+ int Light10Mode;
+ int Light11Mode;
+ int Light12Mode;
+ int Light13Mode;
+ int Light14Mode;
+ int Light15Mode;
+ int LogicalOpMode;
+ int ScissorMode;
+ int ScissorMaxXY;
+ int ScissorMinXY;
+ int Window; /* GID part probably should be in draw priv */
+ int WindowOrigin;
+ int x, y, w, h; /* Probably should be in drawable priv */
+ int FrameCount; /* Probably should be in drawable priv */
+ int NotClipped; /* Probably should be in drawable priv */
+ int WindowChanged; /* Probably should be in drawabl... */
+ int Flags;
+ int EnabledFlags;
+ int DepthSize;
+ int Begin;
+ GLenum ErrorValue;
+ int Texture1DEnabled;
+ int Texture2DEnabled;
+
+ float ModelView[16];
+ float Proj[16];
+ float ModelViewProj[16];
+ float Texture[16];
+
+ float ModelViewStack[(MAX_MODELVIEW_STACK-1)*16];
+ int ModelViewCount;
+ float ProjStack[(MAX_PROJECTION_STACK-1)*16];
+ int ProjCount;
+ float TextureStack[(MAX_TEXTURE_STACK-1)*16];
+ int TextureCount;
+};
+
+#define S3VIRGEPACKCOLOR555( r, g, b, a ) \
+ ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
+ ((a) ? 0x8000 : 0))
+
+#define S3VIRGEPACKCOLOR565( r, g, b ) \
+ ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define S3VIRGEPACKCOLOR888( r, g, b ) \
+ (((r) << 16) | ((g) << 8) | (b))
+
+#define S3VIRGEPACKCOLOR8888( r, g, b, a ) \
+ (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+#define S3VIRGEPACKCOLOR4444( r, g, b, a ) \
+ ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+static __inline GLuint s3vPackColor( GLuint cpp,
+ GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a )
+{
+ unsigned int ret;
+ DEBUG(("cpp = %i, r=0x%x, g=0x%x, b=0x%x, a=0x%x\n", cpp, r, g, b, a));
+
+ switch ( cpp ) {
+ case 2:
+ ret = S3VIRGEPACKCOLOR555( r, g, b, a );
+ DEBUG(("ret = 0x%x\n", ret));
+ return ret;
+ case 4:
+ return PACK_COLOR_8888( a, r, g, b );
+ default:
+ return 0;
+ }
+}
+
+#define S3V_CONTEXT(ctx) ((s3vContextPtr)(ctx->DriverCtx))
+
+#endif /* _S3V_CONTEXT_H_ */
diff --git a/src/mesa/drivers/dri/s3v/s3v_dd.c b/src/mesa/drivers/dri/s3v/s3v_dd.c
new file mode 100644
index 0000000000..683ae3412a
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_dd.c
@@ -0,0 +1,107 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+#include "s3v_vb.h"
+#include "s3v_lock.h"
+#if defined(USE_X86_ASM)
+#include "X86/common_x86_asm.h"
+#endif
+
+#include "context.h"
+#include "swrast/swrast.h"
+
+#define S3V_DATE "20020207"
+
+
+/* Return the width and height of the current color buffer.
+ */
+static void s3vDDGetBufferSize( GLframebuffer *buffer,
+ GLuint *width, GLuint *height )
+{
+ GET_CURRENT_CONTEXT(ctx);
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+/* S3VHW_LOCK( vmesa ); */
+ *width = vmesa->driDrawable->w;
+ *height = vmesa->driDrawable->h;
+/* S3VHW_UNLOCK( vmesa ); */
+}
+
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *s3vDDGetString( GLcontext *ctx, GLenum name )
+{
+ static char buffer[128];
+
+ switch ( name ) {
+ case GL_VENDOR:
+ return (GLubyte *)"Max Lingua (ladybug)";
+
+ case GL_RENDERER:
+ sprintf( buffer, "Mesa DRI S3 Virge " S3V_DATE );
+
+ /* Append any CPU-specific information.
+ */
+#ifdef USE_X86_ASM
+ if ( _mesa_x86_cpu_features ) {
+ strncat( buffer, " x86", 4 );
+
+}
+#ifdef USE_MMX_ASM
+ if ( cpu_has_mmx ) {
+ strncat( buffer, "/MMX", 4 );
+ }
+#endif
+#ifdef USE_3DNOW_ASM
+ if ( cpu_has_3dnow ) {
+ strncat( buffer, "/3DNow!", 7 );
+ }
+#endif
+#ifdef USE_SSE_ASM
+ if ( cpu_has_xmm ) {
+ strncat( buffer, "/SSE", 4 );
+ }
+#endif
+#endif
+ return (GLubyte *)buffer;
+
+ default:
+ return NULL;
+ }
+}
+
+/* Enable the extensions supported by this driver.
+ */
+void s3vInitExtensions( GLcontext *ctx )
+{
+ /* None... */
+}
+
+/* Initialize the driver's misc functions.
+ */
+void s3vInitDriverFuncs( GLcontext *ctx )
+{
+ ctx->Driver.GetBufferSize = s3vDDGetBufferSize;
+ ctx->Driver.GetString = s3vDDGetString;
+
+ ctx->Driver.Error = NULL;
+
+ /* Pixel path fallbacks
+ */
+ ctx->Driver.Accum = _swrast_Accum;
+ ctx->Driver.Bitmap = _swrast_Bitmap;
+ ctx->Driver.CopyPixels = _swrast_CopyPixels;
+ ctx->Driver.DrawPixels = _swrast_DrawPixels;
+ ctx->Driver.ReadPixels = _swrast_ReadPixels;
+ ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+
+ /* Swrast hooks for imaging extensions:
+ */
+ ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+ ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+ ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+ ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_inithw.c b/src/mesa/drivers/dri/s3v/s3v_inithw.c
new file mode 100644
index 0000000000..bdc9effb79
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_inithw.c
@@ -0,0 +1,79 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <sys/ioctl.h>
+
+#include "s3v_context.h"
+
+void s3vInitHW( s3vContextPtr vmesa )
+{
+ int i;
+ static short _reset = 1;
+
+ DEBUG(("vmesa->driDrawable = %p\n", vmesa->driDrawable));
+ DEBUG(("stride = %i\n",
+ vmesa->driScreen->fbWidth*vmesa->s3vScreen->cpp));
+ DEBUG(("frontOffset = 0x%x\n", vmesa->s3vScreen->frontOffset));
+ DEBUG(("backOffset = 0x%x\n", vmesa->s3vScreen->backOffset));
+ DEBUG(("depthOffset = 0x%x\n", vmesa->s3vScreen->depthOffset));
+ DEBUG(("textureOffset = 0x%x\n", vmesa->s3vScreen->texOffset));
+
+/* if (_reset) { */
+/* ioctl(vmesa->driFd, 0x4a); */
+ ioctl(vmesa->driFd, 0x41); /* reset */
+ _reset = 0;
+/* ioctl(vmesa->driFd, 0x4c); */
+/* } */
+
+ /* FIXME */
+ switch (vmesa->s3vScreen->cpp) {
+ case 2:
+ break;
+ case 4:
+ break;
+ }
+
+ /* FIXME for stencil, gid, etc */
+ switch (vmesa->DepthSize) {
+ case 15:
+ case 16:
+ break;
+ case 24:
+ break;
+ case 32:
+ break;
+ }
+
+ vmesa->FogMode = 1;
+ vmesa->ClearDepth = 0xffff;
+ vmesa->x = 0;
+ vmesa->y = 0;
+ vmesa->w = 0;
+ vmesa->h = 0;
+ vmesa->FrameCount = 0;
+ vmesa->MatrixMode = GL_MODELVIEW;
+ vmesa->ModelViewCount = 0;
+ vmesa->ProjCount = 0;
+ vmesa->TextureCount = 0;
+
+
+ /* FIXME: do we need the following? */
+
+ for (i = 0; i < 16; i++)
+ if (i % 5 == 0)
+ vmesa->ModelView[i] =
+ vmesa->Proj[i] =
+ vmesa->ModelViewProj[i] =
+ vmesa->Texture[i] = 1.0;
+ else
+ vmesa->ModelView[i] =
+ vmesa->Proj[i] =
+ vmesa->ModelViewProj[i] =
+ vmesa->Texture[i] = 0.0;
+
+ vmesa->LBWindowBase = vmesa->driScreen->fbWidth *
+ (vmesa->driScreen->fbHeight - 1);
+ vmesa->FBWindowBase = vmesa->driScreen->fbWidth *
+ (vmesa->driScreen->fbHeight - 1);
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_lock.c b/src/mesa/drivers/dri/s3v/s3v_lock.c
new file mode 100644
index 0000000000..52bb87ecec
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_lock.c
@@ -0,0 +1,62 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+
+#if DEBUG_LOCKING
+char *prevLockFile = NULL;
+int prevLockLine = 0;
+#endif
+
+
+/* Update the hardware state. This is called if another context has
+ * grabbed the hardware lock, which includes the X server. This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects. Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void s3vGetLock( s3vContextPtr vmesa, GLuint flags )
+{
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+/* __DRIscreenPrivate *sPriv = vmesa->driScreen; */
+
+ printf("s3vGetLock <- ***\n");
+
+ drmGetLock( vmesa->driFd, vmesa->hHWContext, flags );
+
+ /* The window might have moved, so we might need to get new clip
+ * rects.
+ *
+ * NOTE: This releases and regrabs the hw lock to allow the X server
+ * to respond to the DRI protocol request for new drawable info.
+ * Since the hardware state depends on having the latest drawable
+ * clip rects, all state checking must be done _after_ this call.
+ */
+ /* DRI_VALIDATE_DRAWABLE_INFO( vmesa->display, sPriv, dPriv ); */
+
+ if ( vmesa->lastStamp != dPriv->lastStamp ) {
+ vmesa->lastStamp = dPriv->lastStamp;
+ vmesa->new_state |= S3V_NEW_WINDOW | S3V_NEW_CLIP;
+ }
+
+ vmesa->numClipRects = dPriv->numClipRects;
+ vmesa->pClipRects = dPriv->pClipRects;
+
+#if 0
+ vmesa->dirty = ~0;
+
+ if ( sarea->ctxOwner != vmesa->hHWContext ) {
+ sarea->ctxOwner = vmesa->hHWContext;
+ vmesa->dirty = S3V_UPLOAD_ALL;
+ }
+
+ for ( i = 0 ; i < vmesa->lastTexHeap ; i++ ) {
+ if ( sarea->texAge[i] != vmesa->lastTexAge[i] ) {
+ s3vAgeTextures( vmesa, i );
+ }
+ }
+#endif
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_lock.h b/src/mesa/drivers/dri/s3v/s3v_lock.h
new file mode 100644
index 0000000000..f1bb2a9bf2
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_lock.h
@@ -0,0 +1,103 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef __S3V_LOCK_H__
+#define __S3V_LOCK_H__
+
+#include <sys/ioctl.h>
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void s3vGetLock( s3vContextPtr vmesa, GLuint flags );
+
+/* Turn DEBUG_LOCKING on to find locking conflicts.
+ */
+#define DEBUG_LOCKING 0
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK() \
+ do { \
+ prevLockFile = (__FILE__); \
+ prevLockLine = (__LINE__); \
+ } while (0)
+
+#define DEBUG_RESET() \
+ do { \
+ prevLockFile = 0; \
+ prevLockLine = 0; \
+ } while (0)
+
+#define DEBUG_CHECK_LOCK() \
+ do { \
+ if ( prevLockFile ) { \
+ fprintf( stderr, \
+ "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
+ prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
+ exit(1); \
+ } \
+ } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+/*
+ * !!! We may want to separate locks from locks with validation. This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( vmesa ) \
+ do { \
+ char __ret = 0; \
+ DEBUG_CHECK_LOCK(); \
+ DRM_CAS( vmesa->driHwLock, vmesa->hHWContext, \
+ (DRM_LOCK_HELD | vmesa->hHWContext), __ret ); \
+ if ( __ret ) \
+ s3vGetLock( vmesa, 0 ); \
+ DEBUG_LOCK(); \
+ } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( vmesa ) \
+ do { \
+ DRM_UNLOCK( vmesa->driFd, \
+ vmesa->driHwLock, \
+ vmesa->hHWContext ); \
+ DEBUG_RESET(); \
+ } while (0)
+
+#endif
+
+#define S3VHW_LOCK( vmesa ) \
+ DRM_UNLOCK(vmesa->driFd, vmesa->driHwLock, vmesa->hHWContext); \
+ DRM_SPINLOCK(&vmesa->driScreen->pSAREA->drawable_lock, \
+ vmesa->driScreen->drawLockID); \
+ /* VALIDATE_DRAWABLE_INFO_NO_LOCK(vmesa); */
+
+#define S3VHW_UNLOCK( vmesa ) \
+ DRM_SPINUNLOCK(&vmesa->driScreen->pSAREA->drawable_lock, \
+ vmesa->driScreen->drawLockID); \
+ /* VALIDATE_DRAWABLE_INFO_NO_LOCK_POST(vmesa); */
+
+#define S3V_SIMPLE_LOCK( vmesa ) \
+ ioctl(vmesa->driFd, 0x4a)
+
+#define S3V_SIMPLE_FLUSH_LOCK( vmesa ) \
+ ioctl(vmesa->driFd, 0x4b)
+
+#define S3V_SIMPLE_UNLOCK( vmesa ) \
+ ioctl(vmesa->driFd, 0x4c)
+
+#endif /* __S3V_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/s3v/s3v_macros.h b/src/mesa/drivers/dri/s3v/s3v_macros.h
new file mode 100644
index 0000000000..b54d506788
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_macros.h
@@ -0,0 +1,233 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef _S3V_MACROS_H_
+#define _S3V_MACROS_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+/**************/
+/* DRI macros */
+/**************/
+
+#define GENERIC_DEBUG 0
+#define FLOW_DEBUG 0
+#define DMABUFS_DEBUG 0
+
+/* Note: The argument to DEBUG*() _must_ be enclosed in parenthesis */
+
+#if (GENERIC_DEBUG || FLOW_DEBUG || DMABUFS_DEBUG)
+ #include <stdio.h>
+#endif
+
+#if GENERIC_DEBUG
+ #define DEBUG(str) printf str
+#else
+ #define DEBUG(str)
+#endif
+
+#if FLOW_DEBUG
+ #define DEBUG_WHERE(str) printf str
+#else
+ #define DEBUG_WHERE(str)
+#endif
+
+#if DMABUFS_DEBUG
+ #define DEBUG_BUFS(str) printf str
+#else
+ #define DEBUG_BUFS(str)
+#endif
+
+
+#if 0
+#define S3V_DMA_SEND_FLAGS DRM_DMA_PRIORITY
+#define S3V_DMA_SEND_FLAGS DRM_DMA_BLOCK
+#else
+#define S3V_DMA_SEND_FLAGS 0
+#endif
+
+#if 0
+#define S3V_DMA_GET_FLAGS \
+ (DRM_DMA_SMALLER_OK | DRM_DMA_LARGER_OK | DRM_DMA_WAIT)
+#else
+#define S3V_DMA_GET_FLAGS DRM_DMA_WAIT
+#endif
+
+
+#define DMAOUT_CHECK(reg,len) \
+do { \
+ DEBUG(("DMAOUT_CHECK: reg = 0x%x\n", S3V_##reg##_REG)); \
+ DEBUG_BUFS(("DMAOUT_CHECK (was): ")); \
+ DEBUG_BUFS(("vmesa->bufCount=%i of vmesa->bufSize=%i\n", \
+ vmesa->bufCount, vmesa->bufSize)); \
+ /* FIXME: > or >= */ \
+ if (vmesa->bufCount+(len+1) >= vmesa->bufSize) \
+ DMAFLUSH(); \
+\
+ vmesa->bufCount += (len+1); \
+ DEBUG_BUFS(("DMAOUT_CHECK (is): vmesa->bufCount=%i len=%i, reg=%x\n", \
+ vmesa->bufCount, len, S3V_##reg##_REG)); \
+ DMAOUT( ((len & 0xffff) | ((S3V_##reg##_REG & 0xfffc) << 14)) ); \
+} while (0)
+
+#define DMAOUT(val) \
+do { \
+ *(vmesa->buf++)=val; \
+ DEBUG_BUFS(("DMAOUT: val=0x%x\n", (unsigned int)val)); \
+} while(0)
+
+#define DMAFINISH() \
+do { \
+ /* NOTE: it does nothing - it just prints some summary infos */ \
+ DEBUG(("DMAFINISH: vmesa->bufCount=%i\n", vmesa->bufCount)); \
+ DEBUG(("buf: index=%i; addr=%p\n", vmesa->bufIndex[vmesa->_bufNum], \
+ vmesa->s3vScreen->bufs->list[vmesa->bufIndex[vmesa->_bufNum]].address)); \
+} while(0)
+
+#define DMAFLUSH() \
+do { \
+ if (vmesa->bufCount) { \
+ SEND_DMA(vmesa->driFd, vmesa->hHWContext, 1, \
+ &vmesa->bufIndex[vmesa->_bufNum], &vmesa->bufCount); \
+/*
+ GET_DMA(vmesa->driFd, vmesa->hHWContext, 1, \
+ &vmesa->bufIndex, &vmesa->bufSize); \
+*/ \
+ vmesa->_bufNum = !(vmesa->_bufNum); \
+ vmesa->buf = vmesa->_buf[vmesa->_bufNum]; \
+/*
+ vmesa->buf = \
+ vmesa->s3vScreen->bufs->list[vmesa->bufIndex].address; \
+*/ \
+ vmesa->bufCount = 0; \
+ } \
+} while (0)
+
+#define CMDCHANGE() \
+do { \
+ DMAOUT_CHECK(3DTRI_CMDSET, 1); /* FIXME: TRI/LINE */ \
+ DMAOUT(vmesa->CMD); \
+ DMAFINISH(); \
+} while (0)
+
+#ifdef DONT_SEND_DMA
+#define GET_DMA(fd, hHWCtx, n, idx, size)
+#define SEND_DMA(fd, hHWCtx,n, idx, cnt)
+#else
+#define GET_DMA(fd, hHWCtx, n, idx, size) \
+do { \
+ drmDMAReq dma; \
+ int retcode, i; \
+\
+ DEBUG(("GET_DMA: ")); \
+ DEBUG(("req_count=%i; req_list[#0]=%i; req_size[#0]=%i\n", \
+ n, (idx)[n-1], (size)[n-1])); \
+\
+ dma.context = (hHWCtx); \
+ dma.send_count = 0; \
+ dma.send_list = NULL; \
+ dma.send_sizes = NULL; \
+ dma.flags = S3V_DMA_GET_FLAGS; \
+ dma.request_count = (n); \
+ dma.request_size = S3V_DMA_BUF_SZ; \
+ dma.request_list = (idx); \
+ dma.request_sizes = (size); \
+\
+ do { \
+ if ((retcode = drmDMA((fd), &dma))) { \
+ DEBUG_BUFS(("drmDMA (get) returned %d\n", retcode)); \
+ } \
+} while (!(dma).granted_count); \
+\
+ for (i = 0; i < (n); i++) { \
+ DEBUG(("Got buffer %i (index #%i)\n", (idx)[i], i)); \
+ DEBUG(("of %i bytes (%i words) size\n", \
+ (size)[i], (size)[i] >>2)); \
+ /* Convert from bytes to words */ \
+ (size)[i] >>= 2; \
+ } \
+} while (0)
+
+#define SEND_DMA(fd, hHWCtx, n, idx, cnt) \
+do { \
+ drmDMAReq dma; \
+ int retcode, i; \
+\
+ DEBUG(("SEND_DMA: ")); \
+ DEBUG(("send_count=%i; send_list[#0]=%i; send_sizes[#0]=%i\n", \
+ n, (idx)[n-1], (cnt)[n-1])); \
+\
+ for (i = 0; i < (n); i++) { \
+ /* Convert from words to bytes */ \
+ (cnt)[i] <<= 2; \
+ } \
+\
+ dma.context = (hHWCtx); \
+ dma.send_count = (n); \
+ dma.send_list = (idx); \
+ dma.send_sizes = (cnt); \
+ dma.flags = S3V_DMA_SEND_FLAGS; \
+ dma.request_count = 0; \
+ dma.request_size = 0; \
+ dma.request_list = NULL; \
+ dma.request_sizes = NULL; \
+\
+ if ((retcode = drmDMA((fd), &dma))) { \
+ DEBUG_BUFS(("drmDMA (send) returned %d\n", retcode)); \
+ } \
+\
+ for (i = 0; i < (n); i++) { \
+ DEBUG(("Sent buffer %i (index #%i)\n", (idx)[i], i)); \
+ DEBUG(("of %i bytes (%i words) size\n", \
+ (cnt)[i], (cnt)[i] >>2)); \
+ (cnt)[i] = 0; \
+ } \
+} while (0)
+#endif /* DONT_SEND_DMA */
+
+#define GET_FIRST_DMA(fd, hHWCtx, n, idx, size, buf, cnt, vPriv) \
+do { \
+ int i; \
+ DEBUG_BUFS(("GET_FIRST_DMA\n")); \
+ DEBUG_BUFS(("n=%i idx=%i size=%i\n", n, *idx, *size)); \
+ DEBUG_BUFS(("going to GET_DMA\n")); \
+ GET_DMA(fd, hHWCtx, n, idx, size); \
+ DEBUG_BUFS(("coming from GET_DMA\n")); \
+ DEBUG_BUFS(("n=%i idx=%i size=%i\n", n, (idx)[0], (size)[0])); \
+ for (i = 0; i < (n); i++) { \
+ DEBUG_BUFS(("buf #%i @%p\n", \
+ i, (vPriv)->bufs->list[(idx)[i]].address)); \
+ (buf)[i] = (vPriv)->bufs->list[(idx)[i]].address; \
+ (cnt)[i] = 0; \
+ } \
+ DEBUG(("GOING HOME\n")); \
+} while (0)
+
+#endif
+
+/**************************/
+/* generic, global macros */
+/**************************/
+
+#define CALC_LOG2(l2,s) \
+do { \
+ int __s = s; \
+ l2 = 0; \
+ while (__s > 1) { ++l2; __s >>= 1; } \
+} while (0)
+
+#define PrimType_Null 0x00000000
+#define PrimType_Points 0x10000000
+#define PrimType_Lines 0x20000000
+#define PrimType_LineLoop 0x30000000
+#define PrimType_LineStrip 0x40000000
+#define PrimType_Triangles 0x50000000
+#define PrimType_TriangleStrip 0x60000000
+#define PrimType_TriangleFan 0x70000000
+#define PrimType_Quads 0x80000000
+#define PrimType_QuadStrip 0x90000000
+#define PrimType_Polygon 0xa0000000
+#define PrimType_Mask 0xf0000000
+
+#endif /* _S3V_MACROS_H_ */
diff --git a/src/mesa/drivers/dri/s3v/s3v_regs.h b/src/mesa/drivers/dri/s3v/s3v_regs.h
new file mode 100644
index 0000000000..26a7c54af5
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_regs.h
@@ -0,0 +1,367 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef _S3V_REG_H
+#define _S3V_REG_H
+
+#define S3V_REGS_NUM 256
+
+/************
+ * DMA REGS *
+ ************/
+
+#define S3V_DMA_ID 0
+#define S3V_DMA_REG 0x8590
+#define S3V_DMA_WRITEP_ID 1
+#define S3V_DMA_WRITEP_REG 0x8594
+#define S3V_DMA_READP_ID 2
+#define S3V_DMA_READP_REG 0x8598
+#define S3V_DMA_ENABLE_ID 3
+#define S3V_DMA_ENABLE_REG 0x859C
+#define S3V_DMA_UPDATE_ID 4
+#define S3V_DMA_UPDATE_REG 0x10000
+
+/***************
+ * STATUS REGS *
+ ***************/
+
+#define S3V_STAT_ID 10
+#define S3V_STAT_REG 0x8504
+#define S3V_STAT_VSYNC_ID 11
+#define S3V_STAT_VSYNC_REG 0x8505
+#define S3V_STAT_3D_DONE_ID 12
+#define S3V_STAT_3D_DONE_REG 0x8506
+#define S3V_STAT_FIFO_OVER_ID 13
+#define S3V_STAT_FIFO_OVER_REG 0x8508
+#define S3V_STAT_FIFO_EMPTY_ID 14
+#define S3V_STAT_FIFO_EMPTY_REG 0x850C
+#define S3V_STAT_HDMA_DONE_ID 15
+#define S3V_STAT_HDMA_DONE_REG 0x8514
+#define S3V_STAT_CDMA_DONE_ID 16
+#define S3V_STAT_CDMA_DONE_REG 0x8524
+#define S3V_STAT_3D_FIFO_EMPTY_ID 17
+#define S3V_STAT_3D_FIFO_EMPTY_REG 0x8544
+#define S3V_STAT_LPB_ID 18
+#define S3V_STAT_LPB_REG 0x8584
+#define S3V_STAT_3D_BUSY_ID 19
+#define S3V_STAT_3D_BUSY_REG 0x8704
+
+/***********
+ * 2D REGS *
+ ***********/
+
+#define S3V_BITBLT_ID 30
+#define S3V_BITBLT_REG 0xA400
+#define S3V_BITBLT_SRC_BASE_ID 31
+#define S3V_BITBLT_SRC_BASE_REG 0xA4D4
+#define S3V_BITBLT_DEST_BASE_ID 32
+#define S3V_BITBLT_DEST_BASE_REG 0xA4D8
+#define S3V_BITBLT_CLIP_L_R_ID 33
+#define S3V_BITBLT_CLIP_L_R_REG 0xA4DC
+#define S3V_BITBLT_CLIP_T_B_ID 34
+#define S3V_BITBLT_CLIP_T_B_REG 0xA4E0
+#define S3V_BITBLT_DEST_SRC_STRIDE_ID 35
+#define S3V_BITBLT_DEST_SRC_STRIDE_REG 0xA4E4
+#define S3V_BITBLT_MONO_PAT0_ID 36
+#define S3V_BITBLT_MONO_PAT0_REG 0xA4E8
+#define S3V_BITBLT_MONO_PAT1_ID 37
+#define S3V_BITBLT_MONO_PAT1_REG 0xA4EC
+#define S3V_BITBLT_PAT_BG_COLOR_ID 38
+#define S3V_BITBLT_PAT_BG_COLOR_REG 0xA4F0
+#define S3V_BITBLT_PAT_FG_COLOR_ID 39
+#define S3V_BITBLT_PAT_FG_COLOR_REG 0xA4F4
+#define S3V_BITBLT_CMDSET_ID 40
+#define S3V_BITBLT_CMDSET_REG 0xA500
+#define S3V_BITBLT_WIDTH_HEIGHT_ID 41
+#define S3V_BITBLT_WIDTH_HEIGHT_REG 0xA504
+#define S3V_BITBLT_SRC_X_Y_ID 42
+#define S3V_BITBLT_SRC_X_Y_REG 0xA508
+#define S3V_BITBLT_DEST_X_Y_ID 43
+#define S3V_BITBLT_DEST_X_Y_REG 0xA50C
+#define S3V_2DLINE_ID 44
+#define S3V_2DLINE_REG 0xA800
+#define S3V_2DPOLY_ID 45
+#define S3V_2DPOLY_REG 0xAC00
+
+/***************
+ * 3DLINE REGS *
+ ***************/
+/* base regs */
+#define S3V_3DLINE_ID 50
+#define S3V_3DLINE_REG 0xB000
+#define S3V_3DLINE_Z_BASE_ID 51
+#define S3V_3DLINE_Z_BASE_REG 0xB0D4
+#define S3V_3DLINE_SRC_BASE_ID 52 /* it is the same reg */
+#define S3V_3DLINE_SRC_BASE_REG 0xB0D4
+#define S3V_3DLINE_DEST_BASE_ID 53
+#define S3V_3DLINE_DEST_BASE_REG 0xB0D8
+#define S3V_3DLINE_CLIP_L_R_ID 54
+#define S3V_3DLINE_CLIP_L_R_REG 0xB0DC
+#define S3V_3DLINE_CLIP_T_B_ID 55
+#define S3V_3DLINE_CLIP_T_B_REG 0xB0E0
+#define S3V_3DLINE_DEST_SRC_STRIDE_ID 56
+#define S3V_3DLINE_DEST_SRC_STRIDE_REG 0xB0E4
+#define S3V_3DLINE_Z_STRIDE_ID 57
+#define S3V_3DLINE_Z_STRIDE_REG 0xB0E8
+#define S3V_3DLINE_TEX_BASE_ID 58
+#define S3V_3DLINE_TEX_BASE_REG 0xB0EC
+#define S3V_3DLINE_TEX_B_COLOR_ID 59
+#define S3V_3DLINE_TEX_B_COLOR_REG 0xB0F0
+#define S3V_3DLINE_FOG_COLOR_ID 60
+#define S3V_3DLINE_FOG_COLOR_REG 0xB0F4
+#define S3V_3DLINE_COLOR0_ID 61
+#define S3V_3DLINE_COLOR0_REG 0xB0F8
+#define S3V_3DLINE_COLOR1_ID 62
+#define S3V_3DLINE_COLOR1_REG 0xB0FC
+#define S3V_3DLINE_CMDSET_ID 63
+#define S3V_3DLINE_CMDSET_REG 0xB100 /* special */
+/* tex regs */
+/* FIXME: shouldn't it be a 1D tex for lines? */
+#define S3V_3DLINE_BASEV_ID 64
+#define S3V_3DLINE_BASEV_REG 0xB104
+#define S3V_3DLINE_BASEU_ID 65
+#define S3V_3DLINE_BASEU_REG 0xB108
+#define S3V_3DLINE_WXD_ID 66
+#define S3V_3DLINE_WXD_REG 0xB10C
+#define S3V_3DLINE_WYD_ID 67
+#define S3V_3DLINE_WYD_REG 0xB110
+#define S3V_3DLINE_WSTART_ID 68
+#define S3V_3DLINE_WSTART_REG 0xB114
+#define S3V_3DLINE_DXD_ID 69
+#define S3V_3DLINE_DXD_REG 0xB118
+#define S3V_3DLINE_VXD_ID 70
+#define S3V_3DLINE_VXD_REG 0xB11C
+#define S3V_3DLINE_UXD_ID 71
+#define S3V_3DLINE_UXD_REG 0xB120
+#define S3V_3DLINE_DYD_ID 72
+#define S3V_3DLINE_DYD_REG 0xB124
+#define S3V_3DLINE_VYD_ID 73
+#define S3V_3DLINE_VYD_REG 0xB128
+#define S3V_3DLINE_UYD_ID 74
+#define S3V_3DLINE_UYD_REG 0xB12C
+#define S3V_3DLINE_DSTART_ID 75
+#define S3V_3DLINE_DSTART_REG 0xB130
+#define S3V_3DLINE_VSTART_ID 76
+#define S3V_3DLINE_VSTART_REG 0xB134
+#define S3V_3DLINE_USTART_ID 77
+#define S3V_3DLINE_USTART_REG 0xB138
+/* gourad regs */
+#define S3V_3DLINE_GBD_ID 78
+#define S3V_3DLINE_GBD_REG 0xB144
+#define S3V_3DLINE_ARD_ID 79
+#define S3V_3DLINE_ARD_REG 0xB148
+#define S3V_3DLINE_GS_BS_ID 80
+#define S3V_3DLINE_GS_BS_REG 0xB14C
+#define S3V_3DLINE_AS_RS_ID 81
+#define S3V_3DLINE_AS_RS_REG 0xB150
+/* vertex regs */
+#define S3V_3DLINE_DZ_ID 82
+#define S3V_3DLINE_DZ_REG 0xB158
+#define S3V_3DLINE_ZSTART_ID 83
+#define S3V_3DLINE_ZSTART_REG 0xB15C
+#define S3V_3DLINE_XEND0_END1_ID 84
+#define S3V_3DLINE_XEND0_END1_REG 0xB16C
+#define S3V_3DLINE_DX_ID 85
+#define S3V_3DLINE_DX_REG 0xB170
+#define S3V_3DLINE_XSTART_ID 86
+#define S3V_3DLINE_XSTART_REG 0xB174
+#define S3V_3DLINE_YSTART_ID 87
+#define S3V_3DLINE_YSTART_REG 0xB178
+#define S3V_3DLINE_YCNT_ID 88
+#define S3V_3DLINE_YCNT_REG 0xB17C
+
+/**************
+ * 3DTRI REGS *
+ **************/
+/* base regs */
+#define S3V_3DTRI_ID 100
+#define S3V_3DTRI_REG 0xB400
+#define S3V_3DTRI_Z_BASE_ID 101
+#define S3V_3DTRI_Z_BASE_REG 0xB4D4
+#define S3V_3DTRI_SRC_BASE_ID 102 /* it is the same reg */
+#define S3V_3DTRI_SRC_BASE_REG 0xB4D4
+#define S3V_3DTRI_DEST_BASE_ID 103
+#define S3V_3DTRI_DEST_BASE_REG 0xB4D8
+#define S3V_3DTRI_CLIP_L_R_ID 104
+#define S3V_3DTRI_CLIP_L_R_REG 0xB4DC
+#define S3V_3DTRI_CLIP_T_B_ID 105
+#define S3V_3DTRI_CLIP_T_B_REG 0xB4E0
+#define S3V_3DTRI_DEST_SRC_STRIDE_ID 106
+#define S3V_3DTRI_DEST_SRC_STRIDE_REG 0xB4E4
+#define S3V_3DTRI_Z_STRIDE_ID 107
+#define S3V_3DTRI_Z_STRIDE_REG 0xB4E8
+#define S3V_3DTRI_TEX_BASE_ID 108
+#define S3V_3DTRI_TEX_BASE_REG 0xB4EC
+#define S3V_3DTRI_TEX_B_COLOR_ID 109
+#define S3V_3DTRI_TEX_B_COLOR_REG 0xB4F0
+#define S3V_3DTRI_FOG_COLOR_ID 110
+#define S3V_3DTRI_FOG_COLOR_REG 0xB4F4
+#define S3V_3DTRI_COLOR0_ID 111
+#define S3V_3DTRI_COLOR0_REG 0xB4F8
+#define S3V_3DTRI_COLOR1_ID 112
+#define S3V_3DTRI_COLOR1_REG 0xB4FC
+#define S3V_3DTRI_CMDSET_ID 113 /* special */
+#define S3V_3DTRI_CMDSET_REG 0xB500
+/* tex regs */
+#define S3V_3DTRI_BASEV_ID 114
+#define S3V_3DTRI_BASEV_REG 0xB504
+#define S3V_3DTRI_BASEU_ID 115
+#define S3V_3DTRI_BASEU_REG 0xB508
+#define S3V_3DTRI_WXD_ID 116
+#define S3V_3DTRI_WXD_REG 0xB50C
+#define S3V_3DTRI_WYD_ID 117
+#define S3V_3DTRI_WYD_REG 0xB510
+#define S3V_3DTRI_WSTART_ID 118
+#define S3V_3DTRI_WSTART_REG 0xB514
+#define S3V_3DTRI_DXD_ID 119
+#define S3V_3DTRI_DXD_REG 0xB518
+#define S3V_3DTRI_VXD_ID 120
+#define S3V_3DTRI_VXD_REG 0xB51C
+#define S3V_3DTRI_UXD_ID 121
+#define S3V_3DTRI_UXD_REG 0xB520
+#define S3V_3DTRI_DYD_ID 122
+#define S3V_3DTRI_DYD_REG 0xB524
+#define S3V_3DTRI_VYD_ID 123
+#define S3V_3DTRI_VYD_REG 0xB528
+#define S3V_3DTRI_UYD_ID 124
+#define S3V_3DTRI_UYD_REG 0xB52C
+#define S3V_3DTRI_DSTART_ID 125
+#define S3V_3DTRI_DSTART_REG 0xB530
+#define S3V_3DTRI_VSTART_ID 126
+#define S3V_3DTRI_VSTART_REG 0xB534
+#define S3V_3DTRI_USTART_ID 127
+#define S3V_3DTRI_USTART_REG 0xB538
+/* gourad regs */
+#define S3V_3DTRI_GBX_ID 128
+#define S3V_3DTRI_GBX_REG 0xB53C
+#define S3V_3DTRI_ARX_ID 129
+#define S3V_3DTRI_ARX_REG 0xB540
+#define S3V_3DTRI_GBY_ID 130
+#define S3V_3DTRI_GBY_REG 0xB544
+#define S3V_3DTRI_ARY_ID 131
+#define S3V_3DTRI_ARY_REG 0xB548
+#define S3V_3DTRI_GS_BS_ID 132
+#define S3V_3DTRI_GS_BS_REG 0xB54C
+#define S3V_3DTRI_AS_RS_ID 133
+#define S3V_3DTRI_AS_RS_REG 0xB550
+/* vertex regs */
+#define S3V_3DTRI_ZXD_ID 134
+#define S3V_3DTRI_ZXD_REG 0xB554
+#define S3V_3DTRI_ZYD_ID 135
+#define S3V_3DTRI_ZYD_REG 0xB558
+#define S3V_3DTRI_ZSTART_ID 136
+#define S3V_3DTRI_ZSTART_REG 0xB55C
+#define S3V_3DTRI_TXDELTA12_ID 137
+#define S3V_3DTRI_TXDELTA12_REG 0xB560
+#define S3V_3DTRI_TXEND12_ID 138
+#define S3V_3DTRI_TXEND12_REG 0xB564
+#define S3V_3DTRI_TXDELTA01_ID 139
+#define S3V_3DTRI_TXDELTA01_REG 0xB568
+#define S3V_3DTRI_TXEND01_ID 140
+#define S3V_3DTRI_TXEND01_REG 0xB56C
+#define S3V_3DTRI_TXDELTA02_ID 141
+#define S3V_3DTRI_TXDELTA02_REG 0xB570
+#define S3V_3DTRI_TXSTART02_ID 142
+#define S3V_3DTRI_TXSTART02_REG 0xB574
+#define S3V_3DTRI_TYS_ID 143
+#define S3V_3DTRI_TYS_REG 0xB578
+#define S3V_3DTRI_TY01_Y12_ID 144
+#define S3V_3DTRI_TY01_Y12_REG 0xB57C
+
+/* COMMANDS (to 0xB100 [lines] or 0xB500 [tris]) */
+
+/* Auto execute */
+#define AUTO_EXEC_MASK 0x00000001
+#define AUTO_EXEC_OFF (0x0)
+#define AUTO_EXEC_ON (0x1)
+/* HW clipping */
+#define HW_CLIP_MASK 0x00000002
+#define HW_CLIP_OFF (0x0 << 1)
+#define HW_CLIP_ON (0x1 << 1)
+/* Destination color */
+#define DEST_COL_MASK 0x0000001c
+#define DEST_COL_PAL (0x0 << 2) /* 8 bpp - palettized */
+#define DEST_COL_1555 (0x1 << 2) /* 16 bpp - ZRGB */
+#define DEST_COL_888 (0x2 << 2) /* 24 bpp - RGB */
+/* Texture color */
+#define TEX_COL_MASK 0x000000e0
+#define TEX_COL_ARGB8888 (0x0 << 5) /* 32 bpp - ARGB */
+#define TEX_COL_ARGB4444 (0x1 << 5) /* 16 bpp - ARGB */
+#define TEX_COL_ARGB1555 (0x2 << 5) /* 16 bpp - ARGB */
+#define TEX_COL_ALPHA4 (0x3 << 5) /* 8 bpp - ALPHA4 */
+#define TEX_COL_BLEND4_LOW (0x4 << 5) /* 4 bpp - BLEND4 low nibble */
+#define TEX_COL_BLEND4_HIGH (0x5 << 5) /* 4 bpp - BLEND4 high nibble */
+#define TEX_COL_PAL (0x6 << 5) /* 8 bpp - palettized */
+#define TEX_COL_YUV (0x7 << 5) /* 16 bpp - YUV */
+/* Mipmap level */
+#define MIP_MASK 0x00000f00
+#define MIPMAP_LEVEL(s) (s << 8) /* 8 -> 11 bits */
+/* Texture filtering */
+#define TEX_FILTER_MASK 0x00007000
+#define MIP_NEAREST (0x0 << 12)
+#define LINEAR_MIP_NEAREST (0x1 << 12)
+#define MIP_LINEAR (0x2 << 12)
+#define LINEAR_MIP_LINEAR (0x3 << 12)
+#define NEAREST (0x4 << 12)
+#define FAST_BILINEAR (0x5 << 12)
+#define LINEAR (0x6 << 12)
+/* Texture blending */
+#define TEX_BLEND_MAKS 0x00018000
+#define TEX_REFLECT (0x0 << 15)
+#define TEX_MODULATE (0x1 << 15)
+#define TEX_DECAL (0x2 << 15)
+/* Fog */
+#define FOG_MASK 0x00020000
+#define FOG_OFF (0x0 << 17)
+#define FOG_ON (0x1 << 17)
+/* Alpha blending */
+#define ALPHA_BLEND_MASK 0x000c0000
+#define ALPHA_OFF (0x0 << 18) | (0x0 << 19)
+#define ALPHA_TEX (0x2 << 18)
+#define ALPHA_SRC (0x3 << 18)
+/* Depth compare mode */
+#define Z_MODE_MASK 0x00700000
+#define Z_NEVER (0x0 << 20)
+#define Z_GREATER (0x1 << 20)
+#define Z_EQUAL (0x2 << 20)
+#define Z_GEQUAL (0x3 << 20)
+#define Z_LESS (0x4 << 20)
+#define Z_NOTEQUAL (0x5 << 20)
+#define Z_LEQUAL (0x6 << 20)
+#define Z_ALWAYS (0x7 << 20)
+/* Depth update */
+#define Z_UPDATE_MASK 0x00800000
+#define Z_UPDATE_OFF (0x0 << 23) /* disable z update */
+#define Z_UPDATE_ON (0x1 << 23)
+/* Depth buffering mode */
+#define Z_BUFFER_MASK 0x03000000
+#define Z_BUFFER (0x0 << 24) | (0x0 << 25)
+#define Z_MUX_BUF (0x1 << 24) | (0x0 << 25)
+#define Z_MUX_DRAW (0x2 << 24)
+#define Z_OFF (0x3 << 24) /* no z buffering */
+/* Texture wrapping */
+#define TEX_WRAP_MASK 0x04000000
+#define TEX_WRAP_OFF (0x0 << 26)
+#define TEX_WRAP_ON (0x1 << 26)
+/* 3d command */
+#define DO_MASK 0x78000000
+#define DO_GOURAUD_TRI (0x0 << 27)
+#define DO_TEX_LIT_TRI_OLD (0x1 << 27)
+#define DO_TEX_UNLIT_TRI_OLD (0x2 << 27)
+#define DO_TEX_LIT_TRI (0x5 << 27)
+#define DO_TEX_UNLIT_TRI (0x6 << 27)
+#define DO_3D_LINE (0x8 << 27)
+#define DO_NOP (0xf << 27) /* turn on autoexec */
+/* status */
+#define CMD_MASK 0x80000000
+#define CMD_2D (0x0 << 31) /* execute a 2d cmd */
+#define CMD_3D (0x1 << 31) /* execute a 3d cmd */
+
+/* global masks */
+#define TEX_MASK ( TEX_COL_MASK | TEX_WRAP_MASK | MIP_MASK \
+ | TEX_FILTER_MASK | TEX_BLEND_MAKS \
+ | TEX_WRAP_MASK )
+#define Z_MASK ( Z_MODE_MASK | Z_UPDATE_MASK | Z_BUFFER_MASK )
+
+#endif /* _S3V_REG_H */
diff --git a/src/mesa/drivers/dri/s3v/s3v_render.c b/src/mesa/drivers/dri/s3v/s3v_render.c
new file mode 100644
index 0000000000..3da9f763a3
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_render.c
@@ -0,0 +1,251 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "macros.h"
+#include "mem.h"
+#include "mtypes.h"
+#include "mmath.h"
+
+#include "tnl/t_context.h"
+
+#include "s3v_context.h"
+#include "s3v_tris.h"
+#include "s3v_vb.h"
+
+
+#define HAVE_POINTS 0
+#define HAVE_LINES 0
+#define HAVE_LINE_STRIPS 0
+#define HAVE_TRIANGLES 0
+#define HAVE_TRI_STRIPS 0
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS 0
+#define HAVE_QUADS 0
+#define HAVE_QUAD_STRIPS 0
+#define HAVE_POLYGONS 0
+
+#define HAVE_ELTS 0
+
+static void VERT_FALLBACK( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+/* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
+ int _flags;
+
+ DEBUG(("VERT_FALLBACK: flags & PRIM_MODE_MASK = %i\n",
+ flags & PRIM_MODE_MASK));
+ DEBUG(("VERT_FALLBACK: flags=%i PRIM_MODE_MASK=%i\n",
+ flags, PRIM_MODE_MASK));
+#if 0
+ tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
+#endif
+ tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
+
+ _flags = flags & PRIM_MODE_MASK;
+
+ tnl->Driver.Render.PrimTabVerts[_flags]( ctx, start, count, flags );
+ S3V_CONTEXT(ctx)->SetupNewInputs = VERT_CLIP;
+}
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ PrimType_Points,
+ PrimType_Lines,
+ PrimType_LineLoop,
+ PrimType_LineStrip,
+ PrimType_Triangles,
+ PrimType_TriangleStrip,
+ PrimType_TriangleFan,
+ PrimType_Quads,
+ PrimType_QuadStrip,
+ PrimType_Polygon
+};
+
+static __inline void s3vStartPrimitive( s3vContextPtr vmesa, GLenum prim )
+{
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+
+ int _hw_prim = hw_prim[prim];
+
+ DEBUG(("s3vStartPrimitive (new #%i) ", prim));
+
+ if (_hw_prim != vmesa->restore_primitive) {
+
+ if (prim == 4) { /* TRI */
+ DEBUG(("switching to tri\n"));
+ vmesa->prim_cmd = vmesa->_tri[vmesa->_3d_mode];
+ vmesa->alpha_cmd = vmesa->_alpha[vmesa->_3d_mode];
+ DMAOUT_CHECK(3DTRI_Z_BASE, 12);
+ } else if (prim == 1) { /* LINE */
+ DEBUG(("switching to line\n"));
+ vmesa->prim_cmd = DO_3D_LINE;
+ vmesa->alpha_cmd = vmesa->_alpha[0];
+ DMAOUT_CHECK(3DLINE_Z_BASE, 12);
+ } else {
+ DEBUG(("Never mind the bollocks!\n"));
+ }
+
+ DMAOUT(vmesa->s3vScreen->depthOffset & 0x003FFFF8);
+ DMAOUT(vmesa->DestBase);
+ /* DMAOUT(vmesa->ScissorLR); */
+ /* DMAOUT(vmesa->ScissorTB); */
+ DMAOUT( (0 << 16) | (dPriv->w-1) );
+ DMAOUT( (0 << 16) | (dPriv->h-1) );
+ DMAOUT( (vmesa->SrcStride << 16) | vmesa->TexStride );
+ DMAOUT(vmesa->SrcStride);
+ DMAOUT(vmesa->TexOffset);
+ DMAOUT(vmesa->TextureBorderColor);
+ DMAOUT(0); /* FOG */
+ DMAOUT(0);
+ DMAOUT(0);
+ DMAOUT(vmesa->CMD | vmesa->prim_cmd | vmesa->alpha_cmd);
+ DMAFINISH();
+ }
+
+ vmesa->restore_primitive = _hw_prim;
+}
+
+static __inline void s3vEndPrimitive( s3vContextPtr vmesa )
+{
+/* GLcontext *ctx = vmesa->glCtx; */
+ DEBUG(("s3vEndPrimitive\n"));
+}
+
+#define LOCAL_VARS s3vContextPtr vmesa = S3V_CONTEXT(ctx)
+#define INIT( prim ) s3vStartPrimitive( vmesa, prim )
+#define FINISH s3vEndPrimitive( vmesa )
+#define NEW_PRIMITIVE() (void) vmesa
+#define NEW_BUFFER() (void) vmesa
+#define FIRE_VERTICES() (void) vmesa
+#define GET_CURRENT_VB_MAX_VERTS() \
+ (vmesa->bufSize - vmesa->bufCount) / 2
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+ S3V_DMA_BUF_SZ / 2
+#define EMIT_VERTS( ctx, j, nr ) \
+do { \
+ printf("Alas, emit...\n"); \
+ /* s3v_emit(ctx, j, (j)+(nr)) */ \
+ /* we don't need emit on s3v */ \
+} while (0)
+
+#define TAG(x) s3v_##x
+
+#include "tnl_dd/t_dd_dmatmp.h"
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+static GLboolean s3v_run_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i, length, flags = 0;
+ render_func *tab;
+
+ DEBUG(("s3v_run_render\n"));
+
+ /* FIXME: hw clip */
+ if (VB->ClipOrMask || vmesa->RenderIndex != 0) {
+ DEBUG(("*** CLIPPED in render ***\n"));
+#if 1
+ return GL_TRUE; /* don't handle clipping here */
+#endif
+ }
+
+
+ /* We don't do elts */
+ if (VB->Elts)
+ return GL_TRUE;
+
+ tab = TAG(render_tab_verts);
+
+ tnl->Driver.Render.Start( ctx );
+
+ for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+ {
+ flags = VB->Primitive[i];
+ length = VB->PrimitiveLength[i];
+
+ DEBUG(("s3v_run_render (loop=%i) (lenght=%i)\n", i, length));
+
+ if (length) {
+ tnl->Driver.Render.BuildVertices( ctx, i, i+length,
+ ~0 /*stage->inputs*/);
+ tnl->Driver.Render.PrimTabVerts[flags & PRIM_MODE_MASK]
+ ( ctx, i, i + length, flags );
+ vmesa->SetupNewInputs = VERT_CLIP;
+ }
+ }
+
+ tnl->Driver.Render.Finish( ctx );
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+static void s3v_check_render( GLcontext *ctx,
+ struct gl_pipeline_stage *stage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ GLuint inputs = VERT_CLIP | VERT_RGBA;
+
+ DEBUG(("s3v_check_render\n"));
+
+ if (ctx->RenderMode == GL_RENDER) {
+
+ if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+ DEBUG(("DD_SEPARATE_SPECULAR\n"));
+ inputs |= VERT_SPEC_RGB;
+ }
+
+ if (ctx->Texture.Unit[0]._ReallyEnabled) {
+ DEBUG(("ctx->Texture.Unit[0]._ReallyEnabled\n"));
+ inputs |= VERT_TEX(0);
+ }
+
+ if (ctx->Texture.Unit[1]._ReallyEnabled) {
+ DEBUG(("ctx->Texture.Unit[1]._ReallyEnabled\n"));
+ inputs |= VERT_TEX(1);
+ }
+
+ if (ctx->Fog.Enabled) {
+ DEBUG(("ctx->Fog.Enabled\n"));
+ inputs |= VERT_FOG_COORD;
+ }
+ }
+
+ stage->inputs = inputs;
+ vmesa->SetupNewInputs = inputs;
+}
+
+
+static void dtr( struct gl_pipeline_stage *stage )
+{
+ (void)stage;
+}
+
+
+const struct gl_pipeline_stage _s3v_render_stage =
+{
+ "s3v 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 */
+ s3v_check_render, /* check - initially set to alloc data */
+ s3v_run_render /* run */
+};
diff --git a/src/mesa/drivers/dri/s3v/s3v_screen.c b/src/mesa/drivers/dri/s3v/s3v_screen.c
new file mode 100644
index 0000000000..e558d5b4f3
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_screen.c
@@ -0,0 +1,96 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+#include "s3v_vb.h"
+#include "s3v_dri.h"
+
+#include "mem.h"
+
+s3vScreenPtr s3vCreateScreen( __DRIscreenPrivate *sPriv )
+{
+ s3vScreenPtr s3vScreen;
+ S3VDRIPtr vDRIPriv = (S3VDRIPtr)sPriv->pDevPriv;
+
+/* int i; */
+
+ DEBUG(("s3vCreateScreen\n"));
+ DEBUG(("sPriv->pDevPriv at %p\n", sPriv->pDevPriv));
+ DEBUG(("size = %i\n", sizeof(*vDRIPriv)));
+
+ /* Allocate the private area */
+ s3vScreen = (s3vScreenPtr) CALLOC( sizeof(*s3vScreen) );
+ if ( !s3vScreen ) return NULL;
+
+ s3vScreen->regionCount = 4; /* Magic number. Can we fix this? */
+
+ s3vScreen->regions = Xmalloc(s3vScreen->regionCount *
+ sizeof(s3vRegion));
+ DEBUG(("sPriv->fd = %i\nvDRIPriv->dmaBufHandle = %x\n",
+ sPriv->fd, vDRIPriv->dmaBufHandle));
+
+ DEBUG(("vDRIPriv->dmaBufSize=%i\nvDRIPriv->dmaBuf=%p\n",
+ vDRIPriv->dmaBufSize, vDRIPriv->dmaBuf));
+
+
+ /* Get the list of dma buffers */
+ s3vScreen->bufs = drmMapBufs(sPriv->fd);
+
+ if (!s3vScreen->bufs) {
+ DEBUG(("Helter/skelter with drmMapBufs\n"));
+ return GL_FALSE;
+ }
+
+ s3vScreen->textureSize = vDRIPriv->texSize;
+ s3vScreen->logTextureGranularity = vDRIPriv->logTextureGranularity;
+ s3vScreen->cpp = vDRIPriv->cpp;
+ s3vScreen->frontOffset = vDRIPriv->frontOffset;
+ s3vScreen->frontPitch = vDRIPriv->frontPitch;
+ s3vScreen->backOffset = vDRIPriv->backOffset;
+ s3vScreen->backPitch = vDRIPriv->frontPitch; /* FIXME: check */
+ s3vScreen->depthOffset = vDRIPriv->depthOffset;
+ s3vScreen->depthPitch = vDRIPriv->frontPitch;
+ s3vScreen->texOffset = vDRIPriv->texOffset;
+
+ s3vScreen->driScreen = sPriv;
+
+ DEBUG(("vDRIPriv->width =%i; vDRIPriv->deviceID =%x\n", vDRIPriv->width,
+ vDRIPriv->deviceID));
+ DEBUG(("vDRIPriv->mem =%i\n", vDRIPriv->mem));
+ DEBUG(("vDRIPriv->fbOffset =%i\n", vDRIPriv->fbOffset));
+ DEBUG((" ps3vDRI->fbStride =%i\n", vDRIPriv->fbStride));
+ DEBUG(("s3vScreen->cpp = %i\n", s3vScreen->cpp));
+ DEBUG(("s3vScreen->backOffset = %x\n", s3vScreen->backOffset));
+ DEBUG(("s3vScreen->depthOffset = %x\n", s3vScreen->depthOffset));
+ DEBUG(("s3vScreen->texOffset = %x\n", s3vScreen->texOffset));
+ DEBUG(("I will return from s3vCreateScreen now\n"));
+
+ DEBUG(("s3vScreen->bufs = 0x%x\n", s3vScreen->bufs));
+ return s3vScreen;
+}
+
+/* Destroy the device specific screen private data struct.
+ */
+void s3vDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+ s3vScreenPtr s3vScreen = (s3vScreenPtr)sPriv->private;
+
+ DEBUG(("s3vDestroyScreen\n"));
+
+ /* First, unmap the dma buffers */
+/*
+ drmUnmapBufs( s3vScreen->bufs );
+*/
+ /* Next, unmap all the regions */
+/* while (s3vScreen->regionCount > 0) {
+
+ (void)drmUnmap(s3vScreen->regions[s3vScreen->regionCount].map,
+ s3vScreen->regions[s3vScreen->regionCount].size);
+ s3vScreen->regionCount--;
+
+ }
+ FREE(s3vScreen->regions); */
+ if (s3vScreen)
+ FREE(s3vScreen);
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_screen.h b/src/mesa/drivers/dri/s3v/s3v_screen.h
new file mode 100644
index 0000000000..6bba29a7fa
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_screen.h
@@ -0,0 +1,36 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+typedef struct _s3vRegion {
+ drmHandle handle;
+ drmSize size;
+ drmAddress map;
+} s3vRegion, *s3vRegionPtr;
+
+typedef struct {
+
+ int regionCount; /* Count of register regions */
+ s3vRegion *regions; /* Vector of mapped region info */
+
+ drmBufMapPtr bufs; /* Map of DMA buffers */
+
+ __DRIscreenPrivate *driScreen; /* Back pointer to DRI screen */
+
+ int cpp;
+ int frontPitch;
+ int frontOffset;
+
+ int backPitch;
+ int backOffset;
+ int backX;
+ int backY;
+
+ int depthOffset;
+ int depthPitch;
+
+ int texOffset;
+ int textureOffset;
+ int textureSize;
+ int logTextureGranularity;
+} s3vScreenRec, *s3vScreenPtr;
diff --git a/src/mesa/drivers/dri/s3v/s3v_span.c b/src/mesa/drivers/dri/s3v/s3v_span.c
new file mode 100644
index 0000000000..d8210f684b
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_span.c
@@ -0,0 +1,308 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+#include "s3v_lock.h"
+
+#include "swrast/swrast.h"
+
+#define _SPANLOCK 1
+#define DBG 0
+
+#define LOCAL_VARS \
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx); \
+ s3vScreenPtr s3vscrn = vmesa->s3vScreen; \
+ __DRIscreenPrivate *sPriv = vmesa->driScreen; \
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
+ GLuint pitch = ( (vmesa->Flags & S3V_BACK_BUFFER) ? \
+ ((dPriv->w+31)&~31) * s3vscrn->cpp \
+ : sPriv->fbWidth * s3vscrn->cpp); \
+ GLuint height = dPriv->h; \
+ char *buf = ( (vmesa->Flags & S3V_BACK_BUFFER) ? \
+ (char *)(sPriv->pFB + vmesa->drawOffset) \
+ : (char *)(sPriv->pFB + vmesa->drawOffset \
+ + dPriv->x * s3vscrn->cpp + dPriv->y * pitch) ); \
+ char *read_buf = ( (vmesa->Flags & S3V_BACK_BUFFER) ? \
+ (char *)(sPriv->pFB + vmesa->drawOffset) \
+ : (char *)(sPriv->pFB + vmesa->drawOffset \
+ + dPriv->x * s3vscrn->cpp + dPriv->y * pitch) ); \
+ GLuint p; \
+ (void) read_buf; (void) buf; (void) p; (void) pitch
+
+/* FIXME! Depth/Stencil read/writes don't work ! */
+#define LOCAL_DEPTH_VARS \
+ s3vScreenPtr s3vscrn = vmesa->s3vScreen; \
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
+ __DRIscreenPrivate *sPriv = vmesa->driScreen; \
+ GLuint pitch = s3vscrn->depthPitch; \
+ GLuint height = dPriv->h; \
+ char *buf = (char *)(sPriv->pFB + \
+ s3vscrn->depthOffset); /* + \
+ dPriv->x * s3vscrn->cpp + \
+ dPriv->y * pitch)*/ \
+ (void) pitch
+
+#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
+
+
+#define CLIPPIXEL( _x, _y ) \
+ ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
+ if ( _y < miny || _y >= maxy ) { \
+ _n1 = 0, _x1 = x; \
+ } else { \
+ _n1 = _n; \
+ _x1 = _x; \
+ if ( _x1 < minx ) \
+ _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+ if ( _x1 + _n1 >= maxx ) \
+ n1 -= (_x1 + n1 - maxx); \
+ }
+
+#define Y_FLIP( _y ) (height - _y - 1)
+
+#if _SPANLOCK /* OK, we lock */
+
+#define HW_LOCK() \
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx); \
+ (void) vmesa; \
+ DMAFLUSH(); \
+ S3V_SIMPLE_FLUSH_LOCK(vmesa);
+#define HW_UNLOCK() S3V_SIMPLE_UNLOCK(vmesa);
+
+#else /* plz, don't lock */
+
+#define HW_LOCK() \
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx); \
+ (void) vmesa; \
+ DMAFLUSH();
+#define HW_UNLOCK()
+
+#endif
+
+#define HW_CLIPLOOP() \
+ do { \
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable; \
+ int _nc = dPriv->numClipRects; \
+ \
+ while ( _nc-- ) { \
+ int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
+ int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
+ int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
+ int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+#define HW_ENDCLIPLOOP() \
+ } \
+ } while (0)
+
+
+/* ================================================================
+ * Color buffer
+ */
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#define INIT_MONO_PIXEL(p, color) \
+ p = S3VIRGEPACKCOLOR555( color[0], color[1], color[2], color[3] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+do { \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 7) | \
+ (((int)g & 0xf8) << 2) | \
+ (((int)b & 0xf8) >> 3)); \
+ DEBUG(("buf=0x%x drawOffset=0x%x dPriv->x=%i s3vscrn->cpp=%i dPriv->y=%i pitch=%i\n", \
+ sPriv->pFB, vmesa->drawOffset, dPriv->x, s3vscrn->cpp, dPriv->y, pitch)); \
+ DEBUG(("dPriv->w = %i\n", dPriv->w)); \
+} while(0)
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+ do { \
+ GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
+ rgba[0] = (p >> 7) & 0xf8; \
+ rgba[1] = (p >> 2) & 0xf8; \
+ rgba[2] = (p << 3) & 0xf8; \
+ rgba[3] = 0xff; /*
+ if ( rgba[0] & 0x08 ) rgba[0] |= 0x07; \
+ if ( rgba[1] & 0x04 ) rgba[1] |= 0x03; \
+ if ( rgba[2] & 0x08 ) rgba[2] |= 0x07; */ \
+ } while (0)
+
+#define TAG(x) s3v##x##_RGB555
+#include "spantmp.h"
+
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+ p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a ) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
+ (g << 8) | \
+ (r << 16) | \
+ (a << 24) )
+
+#define WRITE_PIXEL( _x, _y, p ) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y ) \
+do { \
+ GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
+ rgba[0] = (p >> 16) & 0xff; \
+ rgba[1] = (p >> 8) & 0xff; \
+ rgba[2] = (p >> 0) & 0xff; \
+ rgba[3] = (p >> 24) & 0xff; \
+} while (0)
+
+#define TAG(x) s3v##x##_ARGB8888
+#include "spantmp.h"
+
+
+/* 16 bit depthbuffer functions.
+ */
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLushort *)(buf + _x*2 + _y*dPriv->w*2) = d
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLushort *)(buf + _x*2 + _y*dPriv->w*2);
+
+#define TAG(x) s3v##x##_16
+#include "depthtmp.h"
+
+
+
+
+/* 32 bit depthbuffer functions.
+ */
+#if 0
+#define WRITE_DEPTH( _x, _y, d ) \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = d;
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint *)(buf + _x*4 + _y*pitch);
+
+#define TAG(x) s3v##x##_32
+#include "depthtmp.h"
+#endif
+
+
+/* 24/8 bit interleaved depth/stencil functions
+ */
+#if 0
+#define WRITE_DEPTH( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \
+ tmp &= 0xff; \
+ tmp |= (d) & 0xffffff00; \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \
+}
+
+#define READ_DEPTH( d, _x, _y ) \
+ d = *(GLuint *)(buf + _x*4 + _y*pitch) & ~0xff
+
+
+#define TAG(x) s3v##x##_24_8
+#include "depthtmp.h"
+
+#define WRITE_STENCIL( _x, _y, d ) { \
+ GLuint tmp = *(GLuint *)(buf + _x*4 + _y*pitch); \
+ tmp &= 0xffffff00; \
+ tmp |= d & 0xff; \
+ *(GLuint *)(buf + _x*4 + _y*pitch) = tmp; \
+}
+
+#define READ_STENCIL( d, _x, _y ) \
+ d = *(GLuint *)(buf + _x*4 + _y*pitch) & 0xff
+
+#define TAG(x) s3v##x##_24_8
+#include "stenciltmp.h"
+
+#endif
+
+static void s3vSetReadBuffer( GLcontext *ctx,
+ GLframebuffer *colorBuffer,
+ GLenum mode )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ switch ( mode ) {
+ case GL_FRONT_LEFT:
+ vmesa->readOffset = 0;
+ break;
+ case GL_BACK_LEFT:
+ vmesa->readOffset = vmesa->driScreen->fbHeight * vmesa->driScreen->fbWidth * vmesa->s3vScreen->cpp;
+ break;
+ }
+}
+
+
+void s3vInitSpanFuncs( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+ swdd->SetReadBuffer = s3vSetReadBuffer;
+
+ switch ( vmesa->s3vScreen->cpp ) {
+ case 2:
+ swdd->WriteRGBASpan = s3vWriteRGBASpan_RGB555;
+ swdd->WriteRGBSpan = s3vWriteRGBSpan_RGB555;
+ swdd->WriteMonoRGBASpan = s3vWriteMonoRGBASpan_RGB555;
+ swdd->WriteRGBAPixels = s3vWriteRGBAPixels_RGB555;
+ swdd->WriteMonoRGBAPixels = s3vWriteMonoRGBAPixels_RGB555;
+ swdd->ReadRGBASpan = s3vReadRGBASpan_RGB555;
+ swdd->ReadRGBAPixels = s3vReadRGBAPixels_RGB555;
+ break;
+
+ case 4:
+ swdd->WriteRGBASpan = s3vWriteRGBASpan_ARGB8888;
+ swdd->WriteRGBSpan = s3vWriteRGBSpan_ARGB8888;
+ swdd->WriteMonoRGBASpan = s3vWriteMonoRGBASpan_ARGB8888;
+ swdd->WriteRGBAPixels = s3vWriteRGBAPixels_ARGB8888;
+ swdd->WriteMonoRGBAPixels = s3vWriteMonoRGBAPixels_ARGB8888;
+#if 1
+ swdd->ReadRGBASpan = s3vReadRGBASpan_ARGB8888;
+#else
+ swdd->ReadRGBASpan = s3vReadRGBASpan8888;
+#endif
+ swdd->ReadRGBAPixels = s3vReadRGBAPixels_ARGB8888;
+ break;
+
+ default:
+ break;
+ }
+
+ switch ( vmesa->glCtx->Visual.depthBits ) {
+ case 15:
+ case 16:
+ swdd->ReadDepthSpan = s3vReadDepthSpan_16;
+ swdd->WriteDepthSpan = s3vWriteDepthSpan_16;
+ swdd->ReadDepthPixels = s3vReadDepthPixels_16;
+ swdd->WriteDepthPixels = s3vWriteDepthPixels_16;
+ break;
+
+#if 0
+ case 24:
+ swdd->ReadDepthSpan = s3vReadDepthSpan_24_8;
+ swdd->WriteDepthSpan = s3vWriteDepthSpan_24_8;
+ swdd->ReadDepthPixels = s3vReadDepthPixels_24_8;
+ swdd->WriteDepthPixels = s3vWriteDepthPixels_24_8;
+
+ swdd->ReadStencilSpan = s3vReadStencilSpan_24_8;
+ swdd->WriteStencilSpan = s3vWriteStencilSpan_24_8;
+ swdd->ReadStencilPixels = s3vReadStencilPixels_24_8;
+ swdd->WriteStencilPixels = s3vWriteStencilPixels_24_8;
+ break;
+#endif
+
+ default:
+ break;
+ }
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_state.c b/src/mesa/drivers/dri/s3v/s3v_state.c
new file mode 100644
index 0000000000..66f15dbbbd
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_state.c
@@ -0,0 +1,885 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <X11/Xlibint.h>
+#include "s3v_context.h"
+#include "s3v_macros.h"
+#include "macros.h"
+#include "s3v_dri.h"
+#include "colormac.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+
+/* #define DEBUG(str) printf str */
+#define ENABLELIGHTING 0
+
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void s3vUpdateAlphaMode( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ CARD32 cmd = vmesa->CMD;
+ cmd &= ~ALPHA_BLEND_MASK;
+
+ if ( ctx->Color.BlendEnabled ) {
+ DEBUG(("ctx->Color.AlphaEnabled = 1"));
+ vmesa->_alpha[0] = ALPHA_SRC;
+ vmesa->_alpha[1] = vmesa->_alpha_tex; /* FIXME: not all tex modes
+ support alpha */
+ } else {
+ DEBUG(("ctx->Color.AlphaEnabled = 0"));
+ vmesa->_alpha[0] = vmesa->_alpha[1] = ALPHA_OFF;
+ }
+#if 1
+ if ((cmd & DO_MASK) & DO_3D_LINE) { /* we are drawing 3d lines */
+ /* which don't support tex */
+ cmd |= vmesa->_alpha[0];
+ } else {
+ cmd |= vmesa->_alpha[vmesa->_3d_mode];
+ }
+
+ vmesa->CMD = cmd; /* FIXME: enough? */
+#else
+ vmesa->restore_primitive = -1;
+#endif
+
+}
+
+static void s3vDDAlphaFunc( GLcontext *ctx, GLenum func, GLchan ref )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ DEBUG(("s3vDDAlphaFunc\n"));
+
+ vmesa->new_state |= S3V_NEW_ALPHA;
+}
+
+static void s3vDDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ DEBUG(("s3vDDBlendFunc\n"));
+
+ vmesa->new_state |= S3V_NEW_ALPHA;
+}
+
+/* ================================================================
+ * Buffer clear
+ */
+
+static void s3vDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint cx, GLint cy, GLint cw, GLint ch )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ unsigned int _stride;
+
+ vmesa->restore_primitive = -1;
+
+ /* Update and emit any new state. We need to do this here to catch
+ * changes to the masks.
+ * FIXME: Just update the masks?
+ */
+
+ if ( vmesa->new_state )
+ s3vDDUpdateHWState( ctx );
+
+/* s3vUpdateMasks( ctx ); */
+/* s3vUpdateClipping( ctx ); */
+/* s3vEmitHwState( vmesa ); */
+
+
+#if 1 /* soft (0)/hw (1)*/
+
+ DEBUG(("*** s3vDDClear ***\n"));
+
+ DMAOUT_CHECK(BITBLT_SRC_BASE, 15);
+ DMAOUT(vmesa->SrcBase);
+ DMAOUT(vmesa->DestBlit);
+ DMAOUT( vmesa->ScissorLR );
+ DMAOUT( vmesa->ScissorTB );
+ DMAOUT( (vmesa->SrcStride << 16) | vmesa->SrcStride ); /* FIXME: unify */
+ DMAOUT( (~(0)) ); /* masks */
+ DMAOUT( (~(0)) );
+ DMAOUT(0);
+ DMAOUT(vmesa->ClearColor);
+ DMAOUT(0);
+ DMAOUT(0);
+ /* FIXME */
+ DMAOUT(0x16000122 | 0x5 | (0xF0 << 17)); /* black magic to me */
+ DMAOUT(vmesa->ScissorWH);
+ DMAOUT(vmesa->SrcXY);
+ DMAOUT(vmesa->DestXY);
+ DMAFINISH();
+
+ if (mask & DD_DEPTH_BIT) { /* depth */
+ DEBUG(("DD_DEPTH_BIT\n"));
+
+ _stride = ((cw+31)&~31) * 2;
+
+ DMAOUT_CHECK(BITBLT_SRC_BASE, 15);
+ DMAOUT(0);
+ DMAOUT(vmesa->s3vScreen->depthOffset);
+ DMAOUT( (0 << 16) | cw );
+ DMAOUT( (0 << 16) | ch );
+ DMAOUT( (vmesa->SrcStride << 16) | vmesa->DestStride );
+ DMAOUT( (~(0)) ); /* masks */
+ DMAOUT( (~(0)) );
+ DMAOUT(0);
+ DMAOUT(vmesa->ClearDepth); /* 0x7FFF */
+ /* FIXME */
+ DMAOUT(0);
+ DMAOUT(0);
+ DMAOUT(0x16000122 | 0x5 | (0xF0 << 17));
+ DMAOUT( ((cw-1) << 16) | (ch-1) );
+ DMAOUT(0);
+ DMAOUT( (0 << 16) | 0 );
+ DMAFINISH();
+
+ DEBUG(("vmesa->ClearDepth = 0x%x\n", vmesa->ClearDepth));
+ mask &= ~DD_DEPTH_BIT;
+ }
+
+ if (!vmesa->NotClipped) {
+ DEBUG(("vmesa->NotClipped\n")); /* yes */
+ }
+
+ if (!(vmesa->EnabledFlags & S3V_BACK_BUFFER)) {
+ DEBUG(("!S3V_BACK_BUFFER -> flush\n"));
+ DMAFLUSH();
+ }
+/*
+ if ( mask )
+ DEBUG(("still masked ;3(\n")); */ /* yes */
+#else
+ _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+#endif
+}
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void s3vUpdateZMode( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ CARD32 cmd = vmesa->CMD;
+
+ DEBUG(("Depth.Test = %i\n", ctx->Depth.Test));
+ DEBUG(("CMD was = 0x%x ", cmd));
+
+/* printf("depth --- CMD was = 0x%x \n", cmd); */
+
+ cmd &= ~Z_MASK; /* 0xfc0fffff; */
+ /* Z_BUFFER */ /* 000 mode */ /* Z_UPDATE_OFF */
+
+ if (!ctx->Depth.Test)
+ cmd |= Z_OFF;
+
+ if ( ctx->Depth.Mask )
+ cmd |= Z_UPDATE_ON;
+
+ switch ( ctx->Depth.Func ) {
+ case GL_NEVER:
+ cmd |= Z_NEVER;
+ break;
+ case GL_ALWAYS:
+ cmd |= Z_ALWAYS;
+ break;
+ case GL_LESS:
+ cmd |= Z_LESS;
+ break;
+ case GL_LEQUAL:
+ cmd |= Z_LEQUAL;
+ break;
+ case GL_EQUAL:
+ cmd |= Z_EQUAL;
+ break;
+ case GL_GEQUAL:
+ cmd |= Z_GEQUAL;
+ break;
+ case GL_GREATER:
+ cmd |= Z_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ cmd |= Z_NOTEQUAL;
+ break;
+ }
+
+ DEBUG(("CMD is 0x%x\n", cmd));
+
+ vmesa->dirty |= S3V_UPLOAD_DEPTH;
+ vmesa->CMD = cmd;
+}
+
+static void s3vDDDepthFunc( GLcontext *ctx, GLenum func )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+/* FLUSH_BATCH( vmesa ); */
+ DEBUG(("s3vDDDepthFunc\n"));
+ vmesa->new_state |= S3V_NEW_DEPTH;
+}
+
+static void s3vDDDepthMask( GLcontext *ctx, GLboolean flag )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ /* FLUSH_BATCH( vmesa ); */
+ DEBUG(("s3vDDDepthMask\n"));
+ vmesa->new_state |= S3V_NEW_DEPTH;
+}
+
+static void s3vDDClearDepth( GLcontext *ctx, GLclampd d )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ switch ( vmesa->DepthSize ) {
+ case 15:
+ case 16:
+ vmesa->ClearDepth = d * 0x0000ffff; /* 65536 */
+ DEBUG(("GLclampd d = %f\n", d));
+ DEBUG(("ctx->Depth.Clear = %f\n", ctx->Depth.Clear));
+ DEBUG(("(They should be the same)\n"));
+ break;
+ case 24:
+ vmesa->ClearDepth = d * 0x00ffffff;
+ break;
+ case 32:
+ vmesa->ClearDepth = d * 0xffffffff;
+ break;
+ }
+}
+
+static void s3vDDFinish( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ DMAFLUSH();
+}
+
+static void s3vDDFlush( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ DMAFLUSH();
+}
+
+/* =============================================================
+ * Fog
+ */
+
+static void s3vUpdateFogAttrib( GLcontext *ctx )
+{
+/* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
+
+ if (ctx->Fog.Enabled) {
+ } else {
+ }
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ break;
+ case GL_EXP:
+ break;
+ case GL_EXP2:
+ break;
+ }
+}
+
+static void s3vDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ vmesa->new_state |= S3V_NEW_FOG;
+}
+
+/* =============================================================
+ * Lines
+ */
+static void s3vDDLineWidth( GLcontext *ctx, GLfloat width )
+{
+ /* FIXME: on virge you only have one size of 3d lines *
+ * if we wanted more, we should start using tris instead *
+ * but virge has problem with some tris when all of the *
+ * vertices stay on a line */
+}
+
+/* =============================================================
+ * Points
+ */
+static void s3vDDPointSize( GLcontext *ctx, GLfloat size )
+{
+ /* FIXME: we use 3d line to fake points. So same limitations
+ * as above apply */
+}
+
+/* =============================================================
+ * Polygon
+ */
+
+static void s3vUpdatePolygon( GLcontext *ctx )
+{
+ /* FIXME: I don't think we could do much here */
+
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ vmesa->dirty |= S3V_UPLOAD_POLYGON;
+}
+
+/* =============================================================
+ * Clipping
+ */
+
+static void s3vUpdateClipping( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+
+ int x0,y0,x1,y1;
+
+ DEBUG((">>> s3vUpdateClipping <<<\n"));
+/*
+ if ( vmesa->driDrawable ) {
+ DEBUG(("s3vUpdateClipping\n"));
+*/
+ if (vmesa->EnabledFlags & S3V_BACK_BUFFER) {
+ DEBUG(("S3V_BACK_BUFFER\n"));
+
+ x0 = 0;
+ y0 = 0;
+ x1 = dPriv->w - 1;
+ y1 = dPriv->h - 1;
+
+ vmesa->SrcBase = 0;
+ vmesa->DestBase = vmesa->s3vScreen->backOffset;
+ vmesa->DestBlit = vmesa->DestBase;
+ vmesa->ScissorLR = ( (0 << 16) | (dPriv->w-1) );
+ vmesa->ScissorTB = ( (0 << 16) | (dPriv->h-1) );
+/*
+ vmesa->ScissorLR = ( (x0 << 16) | x1 );
+ vmesa->ScissorTB = ( (y0 << 16) | y1 );
+*/
+ vmesa->SrcStride = ( ((dPriv->w+31)&~31) * vmesa->s3vScreen->cpp );
+ vmesa->DestStride = vmesa->driScreen->fbWidth*vmesa->s3vScreen->cpp;
+ vmesa->ScissorWH = ( (dPriv->w << 16) | dPriv->h );
+ vmesa->SrcXY = 0;
+/* vmesa->DestXY = ( (dPriv->x << 16) | dPriv->y ); */
+ vmesa->DestXY = ( (0 << 16) | 0 );
+ } else {
+ DEBUG(("S3V_FRONT_BUFFER\n"));
+
+ x0 = dPriv->x;
+ y0 = dPriv->y;
+ x1 = x0 + dPriv->w - 1;
+ y1 = y0 + dPriv->h - 1;
+
+ vmesa->SrcBase = 0;
+ vmesa->DestBase = 0;
+ vmesa->ScissorLR = ( (x0 << 16) | x1 );
+ vmesa->ScissorTB = ( (y0 << 16) | y1 );
+ vmesa->DestStride = vmesa->driScreen->fbWidth*vmesa->s3vScreen->cpp;
+ vmesa->SrcStride = vmesa->DestStride;
+ vmesa->DestBase = (y0 * vmesa->DestStride)
+ + x0*vmesa->s3vScreen->cpp;
+ vmesa->DestBlit = 0;
+ vmesa->ScissorWH = ( (x1 << 16) | y1 );
+ vmesa->SrcXY = 0;
+ vmesa->DestXY = ( (0 << 16) | 0 );
+/* vmesa->DestXY = ( (dPriv->x << 16) | dPriv->y ); */
+ }
+
+ DEBUG(("x0=%i y0=%i x1=%i y1=%i\n", x0, y0, x1, y1));
+ DEBUG(("stride=%i rectWH=0x%x\n\n", vmesa->DestStride, vmesa->ScissorWH));
+
+ /* FIXME: how could we use the following info? */
+ /* if (ctx->Scissor.Enabled) {} */
+
+ vmesa->dirty |= S3V_UPLOAD_CLIP;
+/* } */
+}
+
+static void s3vDDScissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ DEBUG((">>> s3vDDScissor <<<"));
+ /* FLUSH_BATCH( vmesa ); */
+ vmesa->new_state |= S3V_NEW_CLIP;
+}
+
+/* =============================================================
+ * Culling
+ */
+
+static void s3vUpdateCull( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ GLfloat backface_sign = 1;
+
+ DEBUG(("s3vUpdateCull\n"));
+ /* FIXME: GL_FRONT_AND_BACK */
+
+ switch ( ctx->Polygon.CullFaceMode ) {
+ case GL_BACK:
+ if (ctx->Polygon.FrontFace == GL_CCW)
+ backface_sign = -1;
+ break;
+
+ case GL_FRONT:
+ if (ctx->Polygon.FrontFace != GL_CCW)
+ backface_sign = -1;
+ break;
+
+ default:
+ break;
+ }
+
+ vmesa->backface_sign = backface_sign;
+ vmesa->dirty |= S3V_UPLOAD_GEOMETRY;
+}
+
+
+static void s3vDDCullFace( GLcontext *ctx, GLenum mode )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ /* FLUSH_BATCH( vmesa ); */
+ vmesa->new_state |= S3V_NEW_CULL;
+}
+
+static void s3vDDFrontFace( GLcontext *ctx, GLenum mode )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ /* FLUSH_BATCH( vmesa ); */
+ vmesa->new_state |= S3V_NEW_CULL;
+}
+
+/* =============================================================
+ * Masks
+ */
+
+static void s3vUpdateMasks( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ GLuint mask = s3vPackColor( vmesa->s3vScreen->cpp,
+ ctx->Color.ColorMask[RCOMP],
+ ctx->Color.ColorMask[GCOMP],
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] );
+
+ if (vmesa->s3vScreen->cpp == 2) mask |= mask << 16;
+
+ /* FIXME: can we do something in virge? */
+}
+/*
+static void s3vDDColorMask( GLcontext *ctx, GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a)
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ FLUSH_BATCH( vmesa );
+ vmesa->new_state |= S3V_NEW_MASKS;
+}
+*/
+/* =============================================================
+ * Rendering attributes
+ */
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void s3vDDClearColor( GLcontext *ctx, const GLchan color[4])
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ DEBUG(("*** s3vDDClearColor\n"));
+
+ vmesa->ClearColor = s3vPackColor( 2, /* vmesa->s3vScreen->cpp, */
+ color[0], color[1], color[2], color[3] );
+
+#if 0
+ if (vmesa->s3vScreen->cpp == 2) vmesa->ClearColor |= vmesa->ClearColor<<16;
+#endif
+}
+
+static void s3vDDSetDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ int found = GL_TRUE;
+
+ DEBUG(("*** s3vDDSetDrawBuffer ***\n"));
+
+ /* FLUSH_BATCH( vmesa ); */
+
+ switch ( mode ) {
+ case GL_FRONT_LEFT:
+ vmesa->drawOffset = vmesa->s3vScreen->frontOffset;
+ break;
+ case GL_BACK_LEFT:
+ vmesa->drawOffset = vmesa->s3vScreen->backOffset;
+ /* vmesa->driScreen->fbHeight *
+ * vmesa->driScreen->fbWidth *
+ * vmesa->s3vScreen->cpp; */
+ break;
+ default:
+ found = GL_FALSE;
+ break;
+ }
+
+ DEBUG(("vmesa->drawOffset = 0x%x\n", vmesa->drawOffset));
+/* return GL_TRUE; */
+}
+
+/* =============================================================
+ * Window position and viewport transformation
+ */
+
+void s3vUpdateWindow( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+ GLfloat xoffset = (GLfloat)dPriv->x;
+ GLfloat yoffset =
+ vmesa->driScreen->fbHeight - (GLfloat)dPriv->y - dPriv->h;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+ GLfloat sx = v[MAT_SX];
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat sy = v[MAT_SY];
+ GLfloat ty = v[MAT_TY] + yoffset;
+ GLfloat sz = v[MAT_SZ] * vmesa->depth_scale;
+ GLfloat tz = v[MAT_TZ] * vmesa->depth_scale;
+
+ vmesa->dirty |= S3V_UPLOAD_VIEWPORT;
+
+ vmesa->ViewportScaleX = sx;
+ vmesa->ViewportScaleY = sy;
+ vmesa->ViewportScaleZ = sz;
+ vmesa->ViewportOffsetX = tx;
+ vmesa->ViewportOffsetY = ty;
+ vmesa->ViewportOffsetZ = tz;
+}
+
+
+/*
+static void s3vDDViewport( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height )
+{
+ s3vUpdateWindow( ctx );
+}
+
+static void s3vDDDepthRange( GLcontext *ctx, GLclampd nearval,
+ GLclampd farval )
+{
+ s3vUpdateWindow( ctx );
+}
+*/
+void s3vUpdateViewportOffset( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+ GLfloat xoffset = (GLfloat)dPriv->x;
+ GLfloat yoffset =
+ vmesa->driScreen->fbHeight - (GLfloat)dPriv->y - dPriv->h;
+ const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+ GLfloat tx = v[MAT_TX] + xoffset;
+ GLfloat ty = v[MAT_TY] + yoffset;
+
+ DEBUG(("*** s3vUpdateViewportOffset ***\n"));
+
+ if ( vmesa->ViewportOffsetX != tx ||
+ vmesa->ViewportOffsetY != ty )
+ {
+ vmesa->ViewportOffsetX = tx;
+ vmesa->ViewportOffsetY = ty;
+
+ vmesa->new_state |= S3V_NEW_WINDOW;
+ }
+
+/* vmesa->new_state |= S3V_NEW_CLIP; */
+}
+
+/* =============================================================
+ * State enable/disable
+ */
+
+static void s3vDDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ switch ( cap ) {
+ case GL_ALPHA_TEST:
+ case GL_BLEND:
+ vmesa->new_state |= S3V_NEW_ALPHA;
+ DEBUG(("s3vDDEnable: GL_BLEND\n"));
+ break;
+
+ case GL_CULL_FACE:
+ vmesa->new_state |= S3V_NEW_CULL;
+ DEBUG(("s3vDDEnable: GL_CULL_FACE\n"));
+ break;
+
+ case GL_DEPTH_TEST:
+ vmesa->new_state |= S3V_NEW_DEPTH;
+ DEBUG(("s3vDDEnable: GL_DEPTH\n"));
+ break;
+#if 0
+ case GL_FOG:
+ vmesa->new_state |= S3V_NEW_FOG;
+ break;
+#endif
+
+ case GL_SCISSOR_TEST:
+ vmesa->new_state |= S3V_NEW_CLIP;
+ break;
+
+ case GL_TEXTURE_2D:
+ DEBUG(("*** GL_TEXTURE_2D: %i\n", state));
+ vmesa->_3d_mode = state;
+ vmesa->restore_primitive = -1;
+ break;
+
+ default:
+ return;
+ }
+}
+
+/* =============================================================
+ * State initialization, management
+ */
+
+
+/*
+ * Load the current context's state into the hardware.
+ *
+ * NOTE: Be VERY careful about ensuring the context state is marked for
+ * upload, the only place it shouldn't be uploaded is when the setup
+ * state has changed in ReducedPrimitiveChange as this comes right after
+ * a state update.
+ *
+ * Blits of any type should always upload the context and masks after
+ * they are done.
+ */
+void s3vEmitHwState( s3vContextPtr vmesa )
+{
+ if (!vmesa->driDrawable) return;
+ if (!vmesa->dirty) return;
+
+ DEBUG(("**********************\n"));
+ DEBUG(("*** s3vEmitHwState ***\n"));
+ DEBUG(("**********************\n"));
+
+ if (vmesa->dirty & S3V_UPLOAD_VIEWPORT) {
+ vmesa->dirty &= ~S3V_UPLOAD_VIEWPORT;
+ DEBUG(("S3V_UPLOAD_VIEWPORT\n"));
+ }
+
+ if ( (vmesa->dirty & S3V_UPLOAD_POINTMODE) ||
+ (vmesa->dirty & S3V_UPLOAD_LINEMODE) ||
+ (vmesa->dirty & S3V_UPLOAD_TRIMODE) ) {
+
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_POINTMODE) {
+ vmesa->dirty &= ~S3V_UPLOAD_POINTMODE;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_LINEMODE) {
+ vmesa->dirty &= ~S3V_UPLOAD_LINEMODE;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_TRIMODE) {
+ vmesa->dirty &= ~S3V_UPLOAD_TRIMODE;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_FOG) {
+ GLchan c[3], col;
+ UNCLAMPED_FLOAT_TO_RGB_CHAN( c, vmesa->glCtx->Fog.Color );
+ DEBUG(("uploading ** FOG **\n"));
+ col = s3vPackColor(2, c[0], c[1], c[2], 0);
+ vmesa->dirty &= ~S3V_UPLOAD_FOG;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_DITHER) {
+ vmesa->dirty &= ~S3V_UPLOAD_DITHER;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_LOGICOP) {
+ vmesa->dirty &= ~S3V_UPLOAD_LOGICOP;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_CLIP) {
+ vmesa->dirty &= ~S3V_UPLOAD_CLIP;
+ DEBUG(("S3V_UPLOAD_CLIP\n"));
+ DEBUG(("vmesa->ScissorLR: %i\n", vmesa->ScissorLR));
+ DEBUG(("vmesa->ScissorTB: %i\n", vmesa->ScissorTB));
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_MASKS) {
+ vmesa->dirty &= ~S3V_UPLOAD_MASKS;
+ DEBUG(("S3V_UPLOAD_BLEND\n"));
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_ALPHA) {
+ vmesa->dirty &= ~S3V_UPLOAD_ALPHA;
+ DEBUG(("S3V_UPLOAD_ALPHA\n"));
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_SHADE) {
+ vmesa->dirty &= ~S3V_UPLOAD_SHADE;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_POLYGON) {
+ vmesa->dirty &= ~S3V_UPLOAD_POLYGON;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_DEPTH) {
+ vmesa->dirty &= ~S3V_UPLOAD_DEPTH;
+ DEBUG(("S3V_UPLOAD_DEPTH: DepthMode = 0x%x08\n", vmesa->DepthMode));
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_GEOMETRY) {
+ vmesa->dirty &= ~S3V_UPLOAD_GEOMETRY;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_TRANSFORM) {
+ vmesa->dirty &= ~S3V_UPLOAD_TRANSFORM;
+ }
+
+ if (vmesa->dirty & S3V_UPLOAD_TEX0) {
+ s3vTextureObjectPtr curTex = vmesa->CurrentTexObj[0];
+ vmesa->dirty &= ~S3V_UPLOAD_TEX0;
+ DEBUG(("S3V_UPLOAD_TEX0\n"));
+ if (curTex) {
+ DEBUG(("S3V_UPLOAD_TEX0: curTex\n"));
+ } else {
+ DEBUG(("S3V_UPLOAD_TEX0: !curTex\n"));
+ }
+ }
+}
+
+void s3vDDUpdateHWState( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ int new_state = vmesa->new_state;
+
+ /* s3vUpdateClipping( ctx ); */
+
+ if ( new_state )
+ {
+
+ vmesa->new_state = 0;
+
+ /* Update the various parts of the context's state.
+ */
+ if ( new_state & S3V_NEW_ALPHA )
+ s3vUpdateAlphaMode( ctx );
+
+ if ( new_state & S3V_NEW_DEPTH )
+ s3vUpdateZMode( ctx );
+
+ if ( new_state & S3V_NEW_FOG )
+ s3vUpdateFogAttrib( ctx );
+
+ if ( new_state & S3V_NEW_CLIP )
+ {
+ DEBUG(("---> going to s3vUpdateClipping\n"));
+ s3vUpdateClipping( ctx );
+ }
+
+ if ( new_state & S3V_NEW_POLYGON )
+ s3vUpdatePolygon( ctx );
+
+ if ( new_state & S3V_NEW_CULL )
+ s3vUpdateCull( ctx );
+
+ if ( new_state & S3V_NEW_MASKS )
+ s3vUpdateMasks( ctx );
+
+ if ( new_state & S3V_NEW_WINDOW )
+ s3vUpdateWindow( ctx );
+/*
+ if ( new_state & S3_NEW_TEXTURE )
+ s3vUpdateTextureState( ctx );
+*/
+ CMDCHANGE();
+ }
+
+ /* HACK ! */
+ s3vEmitHwState( vmesa );
+}
+
+
+static void s3vDDUpdateState( GLcontext *ctx, GLuint new_state )
+{
+ _swrast_InvalidateState( ctx, new_state );
+ _swsetup_InvalidateState( ctx, new_state );
+ _ac_InvalidateState( ctx, new_state );
+ _tnl_InvalidateState( ctx, new_state );
+ S3V_CONTEXT(ctx)->new_gl_state |= new_state;
+}
+
+
+/* Initialize the context's hardware state.
+ */
+void s3vInitState( s3vContextPtr vmesa )
+{
+ vmesa->new_state = 0;
+}
+
+/* Initialize the driver's state functions.
+ */
+void s3vInitStateFuncs( GLcontext *ctx )
+{
+ ctx->Driver.UpdateState = s3vDDUpdateState;
+
+ ctx->Driver.Clear = s3vDDClear;
+ ctx->Driver.ClearIndex = NULL;
+ ctx->Driver.ClearColor = s3vDDClearColor;
+ ctx->Driver.SetDrawBuffer = s3vDDSetDrawBuffer;
+
+ ctx->Driver.IndexMask = NULL;
+ ctx->Driver.ColorMask = NULL; /* s3vDDColorMask; */ /* FIXME */
+
+ ctx->Driver.AlphaFunc = s3vDDAlphaFunc; /* FIXME */
+ ctx->Driver.BlendEquation = NULL; /* s3vDDBlendEquation; */
+ ctx->Driver.BlendFunc = s3vDDBlendFunc; /* FIXME */
+ ctx->Driver.BlendFuncSeparate = NULL; /* s3vDDBlendFuncSeparate; */
+ ctx->Driver.ClearDepth = s3vDDClearDepth;
+ ctx->Driver.CullFace = s3vDDCullFace;
+ ctx->Driver.FrontFace = s3vDDFrontFace;
+ ctx->Driver.DepthFunc = s3vDDDepthFunc; /* FIXME */
+ ctx->Driver.DepthMask = s3vDDDepthMask; /* FIXME */
+ ctx->Driver.DepthRange = NULL; /* s3vDDDepthRange; */
+ ctx->Driver.Enable = s3vDDEnable; /* FIXME */
+ ctx->Driver.Finish = s3vDDFinish;
+ ctx->Driver.Flush = s3vDDFlush;
+#if 1
+ ctx->Driver.Fogfv = NULL; /* s3vDDFogfv; */
+#endif
+ ctx->Driver.Hint = NULL;
+ ctx->Driver.LineWidth = NULL; /* s3vDDLineWidth; */
+ ctx->Driver.LineStipple = NULL; /* s3vDDLineStipple; */
+#if ENABLELIGHTING
+ ctx->Driver.Lightfv = NULL; /* s3vDDLightfv; */
+
+ ctx->Driver.LightModelfv = NULL; /* s3vDDLightModelfv; */
+#endif
+ ctx->Driver.LogicOpcode = NULL; /* s3vDDLogicalOpcode; */
+ ctx->Driver.PointSize = NULL; /* s3vDDPointSize; */
+ ctx->Driver.PolygonMode = NULL; /* s3vDDPolygonMode; */
+ ctx->Driver.PolygonStipple = NULL; /* s3vDDPolygonStipple; */
+ ctx->Driver.Scissor = s3vDDScissor; /* ScissorLR / ScissorTB */
+ ctx->Driver.ShadeModel = NULL; /* s3vDDShadeModel; */
+ ctx->Driver.ClearStencil = NULL;
+ ctx->Driver.StencilFunc = NULL;
+ ctx->Driver.StencilMask = NULL;
+ ctx->Driver.StencilOp = NULL;
+ ctx->Driver.Viewport = NULL; /* s3vDDViewport; */
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_tex.c b/src/mesa/drivers/dri/s3v/s3v_tex.c
new file mode 100644
index 0000000000..80564101ec
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_tex.c
@@ -0,0 +1,560 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "mem.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "swrast/swrast.h"
+
+#include "mm.h"
+#include "mmath.h"
+#include "s3v_context.h"
+#include "s3v_tex.h"
+
+
+extern void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
+extern void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
+
+/*
+static GLuint s3vComputeLodBias(GLfloat bias)
+{
+#if TEX_DEBUG_ON
+ DEBUG_TEX(("*** s3vComputeLodBias ***\n"));
+#endif
+ return bias;
+}
+*/
+
+static void s3vSetTexWrapping(s3vContextPtr vmesa,
+ s3vTextureObjectPtr t,
+ GLenum wraps, GLenum wrapt)
+{
+ CARD32 t0 = t->TextureCMD;
+ CARD32 cmd = vmesa->CMD;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vSetTexWrapping: #%i ***\n", ++times));
+#endif
+
+
+ t0 &= ~TEX_WRAP_MASK;
+ cmd &= ~TEX_WRAP_MASK;
+
+ if ((wraps != GL_CLAMP) || (wrapt != GL_CLAMP)) {
+ DEBUG(("TEX_WRAP_ON\n"));
+ t0 |= TEX_WRAP_ON;
+ cmd |= TEX_WRAP_ON;
+ }
+
+ cmd |= TEX_WRAP_ON; /* FIXME: broken if off */
+ t->TextureCMD = t0;
+ vmesa->CMD = cmd;
+}
+
+
+static void s3vSetTexFilter(s3vContextPtr vmesa,
+ s3vTextureObjectPtr t,
+ GLenum minf, GLenum magf)
+{
+ CARD32 t0 = t->TextureCMD;
+ CARD32 cmd = vmesa->CMD;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vSetTexFilter: #%i ***\n", ++times));
+#endif
+
+ t0 &= ~TEX_FILTER_MASK;
+ cmd &= ~TEX_FILTER_MASK;
+
+ switch (minf) {
+ case GL_NEAREST:
+ DEBUG(("GL_NEAREST\n"));
+ t0 |= NEAREST;
+ cmd |= NEAREST;
+ break;
+ case GL_LINEAR:
+ DEBUG(("GL_LINEAR\n"));
+ t0 |= LINEAR;
+ cmd |= LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ DEBUG(("GL_MIPMAP_NEAREST\n"));
+ t0 |= MIP_NEAREST;
+ cmd |= MIP_NEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ DEBUG(("GL_LINEAR_MIPMAP_NEAREST\n"));
+ t0 |= LINEAR_MIP_NEAREST;
+ cmd |= LINEAR_MIP_NEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ DEBUG(("GL_NEAREST_MIPMAP_LINEAR\n"));
+ t0 |= MIP_LINEAR;
+ cmd |= MIP_LINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ DEBUG(("GL_LINEAR_MIPMAP_LINEAR\n"));
+ t0 |= LINEAR_MIP_LINEAR;
+ cmd |= LINEAR_MIP_LINEAR;
+ break;
+ default:
+ break;
+ }
+ /* FIXME: bilinear? */
+
+#if 0
+ switch (magf) {
+ case GL_NEAREST:
+ break;
+ case GL_LINEAR:
+ break;
+ default:
+ break;
+ }
+#endif
+
+ t->TextureCMD = t0;
+
+ DEBUG(("CMD was = 0x%x\n", vmesa->CMD));
+ DEBUG(("CMD is = 0x%x\n", cmd));
+
+ vmesa->CMD = cmd;
+ /* CMDCHANGE(); */
+}
+
+
+static void s3vSetTexBorderColor(s3vContextPtr vmesa,
+ s3vTextureObjectPtr t,
+ GLubyte color[4])
+{
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vSetTexBorderColor: #%i ***\n", ++times));
+#endif
+
+ /*FIXME: it should depend on tex col format */
+ /* switch(t0 ... t->TextureColorMode) */
+
+ /* case TEX_COL_ARGB1555: */
+ t->TextureBorderColor =
+ S3VIRGEPACKCOLOR555(color[0], color[1], color[2], color[3]);
+
+ DEBUG(("TextureBorderColor = 0x%x\n", t->TextureBorderColor));
+
+ vmesa->TextureBorderColor = t->TextureBorderColor;
+}
+
+static void s3vTexParameter( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexParameter: #%i ***\n", ++times));
+#endif
+
+ if (!t) return;
+
+ /* Can't do the update now as we don't know whether to flush
+ * vertices or not. Setting vmesa->new_state means that
+ * s3vUpdateTextureState() will be called before any triangles are
+ * rendered. If a statechange has occurred, it will be detected at
+ * that point, and buffered vertices flushed.
+ */
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ case GL_TEXTURE_MAG_FILTER:
+ s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ case GL_TEXTURE_WRAP_T:
+ s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ s3vSetTexBorderColor( vmesa, t, tObj->BorderColor );
+ break;
+
+ case GL_TEXTURE_BASE_LEVEL:
+ case GL_TEXTURE_MAX_LEVEL:
+ case GL_TEXTURE_MIN_LOD:
+ case GL_TEXTURE_MAX_LOD:
+ /* This isn't the most efficient solution but there doesn't appear to
+ * be a nice alternative for Virge. Since there's no LOD clamping,
+ * we just have to rely on loading the right subset of mipmap levels
+ * to simulate a clamped LOD.
+ */
+ s3vSwapOutTexObj( vmesa, t );
+ break;
+
+ default:
+ return;
+ }
+
+ if (t == vmesa->CurrentTexObj[0])
+ vmesa->dirty |= S3V_UPLOAD_TEX0;
+
+#if 0
+ if (t == vmesa->CurrentTexObj[1]) {
+ vmesa->dirty |= S3V_UPLOAD_TEX1;
+ }
+#endif
+}
+
+
+static void s3vTexEnv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *param )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ GLuint unit = ctx->Texture.CurrentUnit;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexEnv: #%i ***\n", ++times));
+#endif
+
+ /* Only one env color. Need a fallback if env colors are different
+ * and texture setup references env color in both units.
+ */
+ switch (pname) {
+ case GL_TEXTURE_ENV_COLOR: {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ GLfloat *fc = texUnit->EnvColor;
+ GLuint r, g, b, a, col;
+ CLAMPED_FLOAT_TO_UBYTE(r, fc[0]);
+ CLAMPED_FLOAT_TO_UBYTE(g, fc[1]);
+ CLAMPED_FLOAT_TO_UBYTE(b, fc[2]);
+ CLAMPED_FLOAT_TO_UBYTE(a, fc[3]);
+
+ col = ((a << 24) |
+ (r << 16) |
+ (g << 8) |
+ (b << 0));
+
+ break;
+ }
+ case GL_TEXTURE_ENV_MODE:
+ vmesa->TexEnvImageFmt[unit] = 0; /* force recalc of env state */
+ break;
+ case GL_TEXTURE_LOD_BIAS_EXT: {
+/*
+ struct gl_texture_object *tObj =
+ ctx->Texture.Unit[unit]._Current;
+
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
+*/
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void s3vTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *pack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexImage1D: #%i ***\n", ++times));
+#endif
+
+#if 1
+ if (t) {
+#if _TEXFLUSH
+ DMAFLUSH();
+#endif
+ s3vSwapOutTexObj( vmesa, t );
+/*
+ s3vDestroyTexObj( vmesa, t );
+ texObj->DriverData = 0;
+*/
+ }
+#endif
+ _mesa_store_teximage1d( ctx, target, level, internalFormat,
+ width, border, format, type,
+ pixels, pack, texObj, texImage );
+}
+
+static void s3vTexSubImage1D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLsizei width,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *pack,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexSubImage1D: #%i ***\n", ++times));
+#endif
+
+#if 1
+ if (t) {
+#if _TEXFLUSH
+ DMAFLUSH();
+#endif
+ s3vSwapOutTexObj( vmesa, t );
+/*
+ s3vDestroyTexObj( vmesa, t );
+ texObj->DriverData = 0;
+*/
+ }
+#endif
+ _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+ format, type, pixels, pack, texObj,
+ texImage);
+}
+
+static void s3vTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+ GLint internalFormat,
+ GLint width, GLint height, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
+
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexImage2D: #%i ***\n", ++times));
+#endif
+
+#if 1
+ if (t) {
+#if _TEXFLUSH
+ DMAFLUSH();
+#endif
+ s3vSwapOutTexObj( vmesa, t );
+/*
+ s3vDestroyTexObj( vmesa, t );
+ texObj->DriverData = 0;
+*/
+ }
+#endif
+ _mesa_store_teximage2d( ctx, target, level, internalFormat,
+ width, height, border, format, type,
+ pixels, packing, texObj, texImage );
+}
+
+static void s3vTexSubImage2D( GLcontext *ctx,
+ GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing,
+ struct gl_texture_object *texObj,
+ struct gl_texture_image *texImage )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) texObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexSubImage2D: #%i ***\n", ++times));
+#endif
+
+#if 1
+ if (t) {
+#if _TEXFLUSH
+ DMAFLUSH();
+#endif
+ s3vSwapOutTexObj( vmesa, t );
+/*
+ s3vDestroyTexObj( vmesa, t );
+ texObj->DriverData = 0;
+*/
+ }
+#endif
+ _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+ height, format, type, pixels, packing, texObj,
+ texImage);
+}
+
+
+static void s3vBindTexture( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
+ CARD32 cmd = vmesa->CMD;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vBindTexture: #%i ***\n", ++times));
+#endif
+
+ if (!t) {
+/*
+ GLfloat bias = ctx->Texture.Unit[ctx->Texture.CurrentUnit].LodBias;
+*/
+ t = CALLOC_STRUCT(s3v_texture_object_t);
+
+ /* Initialize non-image-dependent parts of the state:
+ */
+ t->globj = tObj;
+#if 0
+ if (target == GL_TEXTURE_2D) {
+ } else
+ if (target == GL_TEXTURE_1D) {
+ }
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+ t->TextureFormat = (TF_LittleEndian |
+#else
+ t->TextureFormat = (TF_BigEndian |
+#endif
+#endif
+ t->dirty_images = ~0;
+
+ tObj->DriverData = t;
+ make_empty_list( t );
+#if 0
+ s3vSetTexWrapping( vmesa, t, tObj->WrapS, tObj->WrapT );
+ s3vSetTexFilter( vmesa, t, tObj->MinFilter, tObj->MagFilter );
+ s3vSetTexBorderColor( vmesa, t, tObj->BorderColor );
+#endif
+ }
+
+ if (!ctx->Texture._ReallyEnabled) {
+ DEBUG_TEX(("!ctx->Texture._ReallyEnabled\n"));
+ return;
+ }
+
+ cmd = vmesa->CMD & ~MIP_MASK;
+ vmesa->dirty |= S3V_UPLOAD_TEX0;
+ vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel];
+ vmesa->TexStride = t->Pitch;
+ cmd |= MIPMAP_LEVEL(t->WidthLog2);
+ vmesa->CMD = cmd;
+ vmesa->restore_primitive = -1;
+#if 0
+ printf("t->TextureBaseAddr[0] = 0x%x\n", t->TextureBaseAddr[0]);
+ printf("t->TextureBaseAddr[1] = 0x%x\n", t->TextureBaseAddr[1]);
+ printf("t->TextureBaseAddr[2] = 0x%x\n", t->TextureBaseAddr[2]);
+#endif
+}
+
+
+static void s3vDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
+{
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vDeleteTexture: #%i ***\n", ++times));
+#endif
+
+ if (t) {
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+
+#if _TEXFLUSH
+ if (vmesa) {
+ DMAFLUSH();
+ }
+#endif
+
+ s3vDestroyTexObj( vmesa, t );
+ tObj->DriverData = 0;
+
+ }
+}
+
+static GLboolean s3vIsTextureResident( GLcontext *ctx,
+ struct gl_texture_object *tObj )
+{
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vIsTextureResident: #%i ***\n", ++times));
+#endif
+
+ return (t && t->MemBlock);
+}
+
+static void s3vInitTextureObjects( GLcontext *ctx )
+{
+ /* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
+ struct gl_texture_object *texObj;
+ GLuint tmp = ctx->Texture.CurrentUnit;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vInitTextureObjects: #%i ***\n", ++times));
+#endif
+
+#if 1
+ ctx->Texture.CurrentUnit = 0;
+
+ texObj = ctx->Texture.Unit[0].Current1D;
+ s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
+
+ texObj = ctx->Texture.Unit[0].Current2D;
+ s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
+#endif
+
+#if 0
+ ctx->Texture.CurrentUnit = 1;
+
+ texObj = ctx->Texture.Unit[1].Current1D;
+ s3vBindTexture( ctx, GL_TEXTURE_1D, texObj );
+
+ texObj = ctx->Texture.Unit[1].Current2D;
+ s3vBindTexture( ctx, GL_TEXTURE_2D, texObj );
+#endif
+
+ ctx->Texture.CurrentUnit = tmp;
+}
+
+
+void s3vInitTextureFuncs( GLcontext *ctx )
+{
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vInitTextureFuncs: #%i ***\n", ++times));
+#endif
+
+ ctx->Driver.TexEnv = s3vTexEnv;
+ ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
+ ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+ ctx->Driver.TexImage2D = s3vTexImage2D;
+ ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+ ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
+ ctx->Driver.TexSubImage2D = s3vTexSubImage2D;
+ ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+ ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+ ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+ ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+ ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+ ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+ ctx->Driver.BindTexture = s3vBindTexture;
+ ctx->Driver.DeleteTexture = s3vDeleteTexture;
+ ctx->Driver.TexParameter = s3vTexParameter;
+ ctx->Driver.UpdateTexturePalette = 0;
+ ctx->Driver.IsTextureResident = s3vIsTextureResident;
+ ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+ s3vInitTextureObjects( ctx );
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_tex.h b/src/mesa/drivers/dri/s3v/s3v_tex.h
new file mode 100644
index 0000000000..0bbe267d77
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_tex.h
@@ -0,0 +1,26 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef _S3V_TEX_H
+#define _S3V_TEX_H
+
+#define TEX_DEBUG_ON 0
+
+#if TEX_DEBUG_ON
+ #define DEBUG_TEX(str) printf str
+#else
+ #define DEBUG_TEX(str) /* str */
+#endif
+
+#define _TEXFLUSH 1 /* flush before uploading */
+#define _TEXLOCK 1 /* lock before writing new texures to card mem */
+ /* if you turn it on you will gain stability and image
+ quality, but you will loose performance (~10%) */
+#define _TEXFALLBACK 0 /* fallback to software for -big- textures (slow) */
+ /* turning this off, you will lose some tex (e.g. mountains
+ on tuxracer) but you will increase average playability */
+
+#define _TEXALIGN 0x00000007
+
+#endif
diff --git a/src/mesa/drivers/dri/s3v/s3v_texmem.c b/src/mesa/drivers/dri/s3v/s3v_texmem.c
new file mode 100644
index 0000000000..ab2e67d182
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_texmem.c
@@ -0,0 +1,583 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "enums.h"
+
+#include "mm.h"
+#include "mem.h"
+#include "s3v_context.h"
+#include "s3v_lock.h"
+#include "s3v_tex.h"
+
+void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t);
+void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t );
+
+
+void s3vDestroyTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
+{
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vDestroyTexObj: #%i ***\n", ++times));
+#endif
+
+ if (!t) return;
+
+/* FIXME: useful? */
+#if _TEXFLUSH
+ if (vmesa)
+ DMAFLUSH();
+#endif
+
+ /* This is sad - need to sync *in case* we upload a texture
+ * to this newly free memory...
+ */
+ if (t->MemBlock) {
+ mmFreeMem(t->MemBlock);
+ t->MemBlock = 0;
+
+ if (vmesa && t->age > vmesa->dirtyAge)
+ vmesa->dirtyAge = t->age;
+ }
+
+ if (t->globj)
+ t->globj->DriverData = NULL;
+
+ if (vmesa) {
+ if (vmesa->CurrentTexObj[0] == t) {
+ vmesa->CurrentTexObj[0] = 0;
+ vmesa->dirty &= ~S3V_UPLOAD_TEX0;
+ }
+
+#if 0
+ if (vmesa->CurrentTexObj[1] == t) {
+ vmesa->CurrentTexObj[1] = 0;
+ vmesa->dirty &= ~S3V_UPLOAD_TEX1;
+ }
+#endif
+ }
+
+ remove_from_list(t);
+ FREE(t);
+}
+
+
+void s3vSwapOutTexObj(s3vContextPtr vmesa, s3vTextureObjectPtr t)
+{
+/* int i; */
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vSwapOutTexObj: #%i ***\n", ++times));
+#endif
+
+ if (t->MemBlock) {
+
+ mmFreeMem(t->MemBlock);
+ t->MemBlock = 0;
+
+ if (t->age > vmesa->dirtyAge)
+ vmesa->dirtyAge = t->age;
+
+ t->dirty_images = ~0;
+ move_to_tail(&(vmesa->SwappedOut), t);
+ }
+}
+
+
+/* Upload an image from mesa's internal copy.
+ */
+
+static void s3vUploadTexLevel( s3vContextPtr vmesa, s3vTextureObjectPtr t,
+ int level )
+{
+ __DRIscreenPrivate *sPriv = vmesa->driScreen;
+ const struct gl_texture_image *image = t->image[level].image;
+ int i,j;
+ int l2d;
+ /* int offset = 0; */
+ int words;
+ CARD32* dest;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+#endif
+ if ( !image ) return;
+ if (image->Data == 0) return;
+
+ DEBUG_TEX(("*** s3vUploadTexLevel: #%i ***\n", ++times));
+ DEBUG_TEX(("level = %i\n", level));
+
+ l2d = 5; /* 32bits per texel == 1<<5 */
+/*
+ if (level == 0)
+ ;
+*/
+ DEBUG_TEX(("t->image[%i].offset = 0x%x\n",
+ level, t->image[level].offset));
+
+ t->TextureBaseAddr[level] = (CARD32)(t->BufAddr + t->image[level].offset
+ + _TEXALIGN) & (CARD32)(~_TEXALIGN);
+ dest = (CARD32*)(sPriv->pFB + t->TextureBaseAddr[level]);
+
+ DEBUG_TEX(("sPriv->pFB = 0x%x\n", sPriv->pFB));
+ DEBUG_TEX(("dest = 0x%x\n", dest));
+ DEBUG_TEX(("dest - sPriv->pFB = 0x%x\n", ((int)dest - (int)sPriv->pFB)));
+
+ /* NOTE: we implicitly suppose t->texelBytes == 2 */
+
+ words = (image->Width * image->Height) >> 1;
+
+ DEBUG_TEX(("\n\n"));
+
+ switch (t->image[level].internalFormat) {
+ case GL_RGB:
+ case 3:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_RGB:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ /* The UGLY way, and SLOW : use DMA FIXME ! */
+
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+ /* data = PACK_COLOR_565(src[0],src[1],src[2]); */
+ data = S3VIRGEPACKCOLOR555(src[0],src[1],src[2],255)
+ |(S3VIRGEPACKCOLOR555(src[3],src[4],src[5],255)<<16);
+
+ *dest++ = data;
+ /* src += 3; */
+ src +=6;
+ }
+ }
+ break;
+
+ case GL_RGBA:
+ case 4:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_RGBA:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+
+ /* data = PACK_COLOR_8888(src[0],src[1],src[2],src[3]); */
+ data = S3VIRGEPACKCOLOR4444(src[0], src[1],src[2], src[3])
+ | (S3VIRGEPACKCOLOR4444(src[4], src[5], src[6], src[7]) << 16);
+
+ *dest++ = data;
+ /* src += 4; */
+ src += 8;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_LUMINANCE:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+
+ /* data = PACK_COLOR_888(src[0],src[0],src[0]); */
+ data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[0])
+ | (S3VIRGEPACKCOLOR4444(src[1],src[1],src[1],src[1]) << 16);
+
+ *dest++ = data;
+ /* src ++; */
+ src +=2;
+ }
+ }
+ break;
+
+ case GL_INTENSITY:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_INTENSITY:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+
+ /* data = PACK_COLOR_8888(src[0],src[0],src[0],src[0]); */
+ data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[0])
+ | (S3VIRGEPACKCOLOR4444(src[1],src[1],src[1],src[1]) << 16);
+
+ *dest++ = data;
+ /* src ++; */
+ src += 2;
+ }
+ }
+ break;
+
+ case GL_LUMINANCE_ALPHA:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_LUMINANCE_ALPHA:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+
+ /* data = PACK_COLOR_8888(src[0],src[0],src[0],src[1]); */
+ data = S3VIRGEPACKCOLOR4444(src[0],src[0],src[0],src[1])
+ | (S3VIRGEPACKCOLOR4444(src[2],src[2],src[2],src[3]) << 16);
+
+ *dest++ = data;
+ /* src += 2; */
+ src += 4;
+ }
+ }
+ break;
+
+ case GL_ALPHA:
+ {
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_ALPHA:\n"));
+/*
+ if (level == 0)
+ ;
+*/
+ for (i = 0; i < words; i++) {
+ unsigned int data;
+
+ /* data = PACK_COLOR_8888(255,255,255,src[0]); */
+ data = S3VIRGEPACKCOLOR4444(255,255,255,src[0])
+ | (S3VIRGEPACKCOLOR4444(255,255,255,src[1]) << 16);
+
+ *dest++ = data;
+ /* src += 1; */
+ src += 2;
+ }
+ }
+ break;
+
+ /* TODO: Translate color indices *now*:
+ */
+ case GL_COLOR_INDEX:
+ {
+
+ GLubyte *dst = (GLubyte *)(t->BufAddr + t->image[level].offset);
+ GLubyte *src = (GLubyte *)image->Data;
+
+ DEBUG_TEX(("GL_COLOR_INDEX:\n"));
+
+ for (j = 0 ; j < image->Height ; j++, dst += t->Pitch) {
+ for (i = 0 ; i < image->Width ; i++) {
+ dst[i] = src[0];
+ src += 1;
+ }
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Not supported texture format %s\n",
+ _mesa_lookup_enum_by_nr(image->Format));
+ }
+
+ DEBUG_TEX(("words = %i\n\n", words));
+}
+
+void s3vPrintLocalLRU( s3vContextPtr vmesa )
+{
+ s3vTextureObjectPtr t;
+ int sz = 1 << (vmesa->s3vScreen->logTextureGranularity);
+
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vPrintLocalLRU: #%i ***\n", ++times));
+#endif
+
+ foreach( t, &vmesa->TexObjList ) {
+ if (!t->globj)
+ fprintf(stderr, "Placeholder %d at %x sz %x\n",
+ t->MemBlock->ofs / sz,
+ t->MemBlock->ofs,
+ t->MemBlock->size);
+ else
+ fprintf(stderr, "Texture at %x sz %x\n",
+ t->MemBlock->ofs,
+ t->MemBlock->size);
+
+ }
+}
+
+void s3vPrintGlobalLRU( s3vContextPtr vmesa )
+{
+ int i, j;
+ S3VTexRegionPtr list = vmesa->sarea->texList;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vPrintGlobalLRU: #%i ***\n", ++times));
+#endif
+
+ for (i = 0, j = S3V_NR_TEX_REGIONS ; i < S3V_NR_TEX_REGIONS ; i++) {
+ fprintf(stderr, "list[%d] age %d next %d prev %d\n",
+ j, list[j].age, list[j].next, list[j].prev);
+ j = list[j].next;
+ if (j == S3V_NR_TEX_REGIONS) break;
+ }
+
+ if (j != S3V_NR_TEX_REGIONS)
+ fprintf(stderr, "Loop detected in global LRU\n");
+}
+
+
+void s3vResetGlobalLRU( s3vContextPtr vmesa )
+{
+ S3VTexRegionPtr list = vmesa->sarea->texList;
+ int sz = 1 << vmesa->s3vScreen->logTextureGranularity;
+ int i;
+
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vResetGlobalLRU: #%i ***\n", ++times));
+#endif
+
+ /* (Re)initialize the global circular LRU list. The last element
+ * in the array (S3V_NR_TEX_REGIONS) is the sentinal. Keeping it
+ * at the end of the array allows it to be addressed rationally
+ * when looking up objects at a particular location in texture
+ * memory.
+ */
+ for (i = 0 ; (i+1) * sz <= vmesa->s3vScreen->textureSize ; i++) {
+ list[i].prev = i-1;
+ list[i].next = i+1;
+ list[i].age = 0;
+ }
+
+ i--;
+ list[0].prev = S3V_NR_TEX_REGIONS;
+ list[i].prev = i-1;
+ list[i].next = S3V_NR_TEX_REGIONS;
+ list[S3V_NR_TEX_REGIONS].prev = i;
+ list[S3V_NR_TEX_REGIONS].next = 0;
+ vmesa->sarea->texAge = 0;
+}
+
+
+void s3vUpdateTexLRU( s3vContextPtr vmesa, s3vTextureObjectPtr t )
+{
+/*
+ int i;
+ int logsz = vmesa->s3vScreen->logTextureGranularity;
+ int start = t->MemBlock->ofs >> logsz;
+ int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
+ S3VTexRegionPtr list = vmesa->sarea->texList;
+*/
+
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vUpdateTexLRU: #%i ***\n", ++times));
+#endif
+
+ vmesa->texAge = ++vmesa->sarea->texAge;
+
+ /* Update our local LRU
+ */
+ move_to_head( &(vmesa->TexObjList), t );
+
+ /* Update the global LRU
+ */
+#if 0
+ for (i = start ; i <= end ; i++) {
+
+ list[i].in_use = 1;
+ list[i].age = vmesa->texAge;
+
+ /* remove_from_list(i)
+ */
+ list[(unsigned)list[i].next].prev = list[i].prev;
+ list[(unsigned)list[i].prev].next = list[i].next;
+
+ /* insert_at_head(list, i)
+ */
+ list[i].prev = S3V_NR_TEX_REGIONS;
+ list[i].next = list[S3V_NR_TEX_REGIONS].next;
+ list[(unsigned)list[S3V_NR_TEX_REGIONS].next].prev = i;
+ list[S3V_NR_TEX_REGIONS].next = i;
+ }
+#endif
+}
+
+
+/* Called for every shared texture region which has increased in age
+ * since we last held the lock.
+ *
+ * Figures out which of our textures have been ejected by other clients,
+ * and pushes a placeholder texture onto the LRU list to represent
+ * the other client's textures.
+ */
+void s3vTexturesGone( s3vContextPtr vmesa,
+ GLuint offset,
+ GLuint size,
+ GLuint in_use )
+{
+ s3vTextureObjectPtr t, tmp;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vTexturesGone: #%i ***\n", ++times));
+#endif
+
+ foreach_s ( t, tmp, &vmesa->TexObjList ) {
+
+ if (t->MemBlock->ofs >= offset + size ||
+ t->MemBlock->ofs + t->MemBlock->size <= offset)
+ continue;
+
+ /* It overlaps - kick it off. Need to hold onto the currently bound
+ * objects, however.
+ */
+ s3vSwapOutTexObj( vmesa, t );
+ }
+
+ if (in_use) {
+ t = (s3vTextureObjectPtr) calloc(1,sizeof(*t));
+ if (!t) return;
+
+ t->MemBlock = mmAllocMem( vmesa->texHeap, size, 0, offset);
+ insert_at_head( &vmesa->TexObjList, t );
+ }
+
+ /* Reload any lost textures referenced by current vertex buffer.
+ */
+#if 0
+ if (vmesa->vertex_buffer) {
+ int i, j;
+
+ fprintf(stderr, "\n\nreload tex\n");
+
+ for (i = 0 ; i < vmesa->statenr ; i++) {
+ for (j = 0 ; j < 2 ; j++) {
+ s3vTextureObjectPtr t = vmesa->state_tex[j][i];
+ if (t) {
+ if (t->MemBlock == 0)
+ s3vUploadTexImages( vmesa, t );
+ }
+ }
+ }
+
+ /* Hard to do this with the lock held:
+ */
+ /* S3V_FIREVERTICES( vmesa ); */
+ }
+#endif
+}
+
+
+/* This is called with the lock held. May have to eject our own and/or
+ * other client's texture objects to make room for the upload.
+ */
+void s3vUploadTexImages( s3vContextPtr vmesa, s3vTextureObjectPtr t )
+{
+ int i;
+ int ofs;
+ int numLevels;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ static unsigned int try=0;
+
+ DEBUG_TEX(("*** s3vUploadTexImages: #%i ***\n", ++times));
+ DEBUG_TEX(("vmesa->texHeap = 0x%x; t->totalSize = %i\n",
+ (unsigned int)vmesa->texHeap, t->totalSize));
+#endif
+
+ /* Do we need to eject LRU texture objects?
+ */
+ if (!t->MemBlock) {
+
+ while (1)
+ {
+ /* int try = 0; */
+ DEBUG_TEX(("trying to alloc mem for tex (try %i)\n", ++try));
+
+ t->MemBlock = mmAllocMem( vmesa->texHeap, t->totalSize, 12, 0 );
+
+ if (t->MemBlock)
+ break;
+
+ if (vmesa->TexObjList.prev == vmesa->CurrentTexObj[0]) {
+/* || vmesa->TexObjList.prev == vmesa->CurrentTexObj[1]) {
+ fprintf(stderr, "Hit bound texture in upload\n");
+ s3vPrintLocalLRU( vmesa ); */
+ return;
+ }
+
+ if (vmesa->TexObjList.prev == &(vmesa->TexObjList)) {
+/* fprintf(stderr, "Failed to upload texture, sz %d\n",
+ t->totalSize);
+ mmDumpMemInfo( vmesa->texHeap ); */
+ return;
+ }
+
+ DEBUG_TEX(("swapping out: %p\n", vmesa->TexObjList.prev));
+ s3vSwapOutTexObj( vmesa, vmesa->TexObjList.prev );
+ }
+
+ ofs = t->MemBlock->ofs;
+
+ t->BufAddr = vmesa->s3vScreen->texOffset + ofs;
+
+ DEBUG_TEX(("ofs = 0x%x\n", ofs));
+ DEBUG_TEX(("t->BufAddr = 0x%x\n", t->BufAddr));
+
+/* FIXME: check if we need it */
+#if 0
+ if (t == vmesa->CurrentTexObj[0]) {
+ vmesa->dirty |= S3V_UPLOAD_TEX0;
+ vmesa->restore_primitive = -1;
+ }
+#endif
+
+#if 0
+ if (t == vmesa->CurrentTexObj[1])
+ vmesa->dirty |= S3V_UPLOAD_TEX1;
+#endif
+
+ s3vUpdateTexLRU( vmesa, t );
+ }
+
+#if 0
+ if (vmesa->dirtyAge >= GET_DISPATCH_AGE(vmesa))
+ s3vWaitAgeLocked( vmesa, vmesa->dirtyAge );
+#endif
+
+#if _TEXLOCK
+ S3V_SIMPLE_FLUSH_LOCK(vmesa);
+#endif
+ numLevels = t->lastLevel - t->firstLevel + 1;
+ for (i = 0 ; i < numLevels ; i++)
+ if (t->dirty_images & (1<<i))
+ s3vUploadTexLevel( vmesa, t, i );
+
+ t->dirty_images = 0;
+#if _TEXLOCK
+ S3V_SIMPLE_UNLOCK(vmesa);
+#endif
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_texstate.c b/src/mesa/drivers/dri/s3v/s3v_texstate.c
new file mode 100644
index 0000000000..7141e39182
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_texstate.c
@@ -0,0 +1,303 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "glheader.h"
+#include "macros.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "enums.h"
+
+#include "mm.h"
+#include "s3v_context.h"
+#include "s3v_tex.h"
+
+
+static void s3vSetTexImages( s3vContextPtr vmesa,
+ struct gl_texture_object *tObj )
+{
+ GLuint height, width, pitch, i, /*textureFormat,*/ log_pitch;
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr) tObj->DriverData;
+ const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+ GLint firstLevel, lastLevel, numLevels;
+ GLint log2Width, log2Height;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vSetTexImages: #%i ***\n", ++times));
+#endif
+
+ t->texelBytes = 2; /* FIXME: always 2 ? */
+
+ /* Compute which mipmap levels we really want to send to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ * Yes, this looks overly complicated, but it's all needed.
+ */
+ if (tObj->MinFilter == GL_LINEAR || tObj->MinFilter == GL_NEAREST) {
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+
+ numLevels = lastLevel - firstLevel + 1;
+
+ log2Width = tObj->Image[firstLevel]->WidthLog2;
+ log2Height = tObj->Image[firstLevel]->HeightLog2;
+
+
+ /* Figure out the amount of memory required to hold all the mipmap
+ * levels. Choose the smallest pitch to accomodate the largest
+ * mipmap:
+ */
+ width = tObj->Image[firstLevel]->Width * t->texelBytes;
+ for (pitch = 32, log_pitch=2 ; pitch < width ; pitch *= 2 )
+ log_pitch++;
+
+ /* All images must be loaded at this pitch. Count the number of
+ * lines required:
+ */
+ for ( height = i = 0 ; i < numLevels ; i++ ) {
+ t->image[i].image = tObj->Image[firstLevel + i];
+ t->image[i].offset = height * pitch;
+ t->image[i].internalFormat = baseImage->Format;
+ height += t->image[i].image->Height;
+ t->TextureBaseAddr[i] = (t->BufAddr + t->image[i].offset +
+ _TEXALIGN) & (CARD32)(~_TEXALIGN);
+ }
+
+ t->Pitch = pitch;
+ t->WidthLog2 = log2Width;
+ t->totalSize = height*pitch;
+ t->max_level = i-1;
+ vmesa->dirty |= S3V_UPLOAD_TEX0 /* | S3V_UPLOAD_TEX1*/;
+ vmesa->restore_primitive = -1;
+ DEBUG(("<><>pitch = TexStride = %i\n", pitch));
+ DEBUG(("log2Width = %i\n", log2Width));
+
+ s3vUploadTexImages( vmesa, t );
+}
+
+static void s3vUpdateTexEnv( GLcontext *ctx, GLuint unit )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ const struct gl_texture_object *tObj = texUnit->_Current;
+ const GLuint format = tObj->Image[tObj->BaseLevel]->Format;
+/*
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
+ GLuint tc;
+*/
+ GLuint alpha = 0;
+ CARD32 cmd = vmesa->CMD;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vUpdateTexEnv: %i ***\n", ++times));
+#endif
+
+ cmd &= ~TEX_COL_MASK;
+ cmd &= ~TEX_BLEND_MAKS;
+/* cmd &= ~ALPHA_BLEND_MASK; */
+
+ DEBUG(("format = "));
+
+ switch (format) {
+ case GL_RGB:
+ DEBUG_TEX(("GL_RGB\n"));
+ cmd |= TEX_COL_ARGB1555;
+ break;
+ case GL_LUMINANCE:
+ DEBUG_TEX(("GL_LUMINANCE\n"));
+ cmd |= TEX_COL_ARGB4444;
+ alpha = 1; /* FIXME: check */
+ break;
+ case GL_ALPHA:
+ DEBUG_TEX(("GL_ALPHA\n"));
+ cmd |= TEX_COL_ARGB4444;
+ alpha = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ DEBUG_TEX(("GL_LUMINANCE_ALPHA\n"));
+ cmd |= TEX_COL_ARGB4444;
+ alpha = 1;
+ break;
+ case GL_INTENSITY:
+ DEBUG_TEX(("GL_INTENSITY\n"));
+ cmd |= TEX_COL_ARGB4444;
+ alpha = 1;
+ break;
+ case GL_RGBA:
+ DEBUG_TEX(("GL_RGBA\n"));
+ cmd |= TEX_COL_ARGB4444;
+ alpha = 1;
+ break;
+ case GL_COLOR_INDEX:
+ DEBUG_TEX(("GL_COLOR_INDEX\n"));
+ cmd |= TEX_COL_PAL;
+ break;
+ }
+
+ DEBUG_TEX(("EnvMode = "));
+
+ switch (texUnit->EnvMode) {
+ case GL_REPLACE:
+ DEBUG_TEX(("GL_REPLACE\n"));
+ cmd |= TEX_REFLECT; /* FIXME */
+ vmesa->_tri[1] = DO_TEX_UNLIT_TRI; /* FIXME: white tri hack */
+ vmesa->_alpha_tex = ALPHA_TEX /* * alpha */;
+ break;
+ case GL_MODULATE:
+ DEBUG_TEX(("GL_MODULATE\n"));
+ cmd |= TEX_MODULATE;
+ vmesa->_tri[1] = DO_TEX_LIT_TRI;
+#if 0
+ if (alpha)
+ vmesa->_alpha_tex = ALPHA_TEX /* * alpha */;
+ else
+ vmesa->_alpha_tex = ALPHA_SRC /* * alpha */;
+#else
+ vmesa->_alpha_tex = ALPHA_TEX ;
+#endif
+ break;
+ case GL_ADD:
+ DEBUG_TEX(("DEBUG_TEX\n"));
+ /* do nothing ???*/
+ break;
+ case GL_DECAL:
+ DEBUG_TEX(("GL_DECAL\n"));
+ cmd |= TEX_DECAL;
+ vmesa->_tri[1] = DO_TEX_LIT_TRI;
+ vmesa->_alpha_tex = ALPHA_OFF;
+ break;
+ case GL_BLEND:
+ DEBUG_TEX(("GL_BLEND\n"));
+ cmd |= TEX_DECAL;
+ vmesa->_tri[1] = DO_TEX_LIT_TRI;
+ vmesa->_alpha_tex = ALPHA_OFF; /* FIXME: sure? */
+ break;
+ default:
+ fprintf(stderr, "unknown tex env mode");
+ return;
+ }
+
+ DEBUG_TEX(("\n\n vmesa->CMD was 0x%x\n", vmesa->CMD));
+ DEBUG_TEX(( " vmesa->CMD is 0x%x\n\n", cmd ));
+
+ vmesa->_alpha[1] = vmesa->_alpha_tex;
+ vmesa->CMD = cmd; /* | MIPMAP_LEVEL(8); */
+ vmesa->restore_primitive = -1;
+}
+
+static void s3vUpdateTexUnit( GLcontext *ctx, GLuint unit )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ CARD32 cmd = vmesa->CMD;
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vUpdateTexUnit: %i ***\n", ++times));
+ DEBUG_TEX(("and vmesa->CMD was 0x%x\n", vmesa->CMD));
+#endif
+
+ if (texUnit->_ReallyEnabled == TEXTURE0_2D)
+ {
+ struct gl_texture_object *tObj = texUnit->_Current;
+ s3vTextureObjectPtr t = (s3vTextureObjectPtr)tObj->DriverData;
+
+ /* Upload teximages (not pipelined)
+ */
+ if (t->dirty_images) {
+#if _TEXFLUSH
+ DMAFLUSH();
+#endif
+ s3vSetTexImages( vmesa, tObj );
+ if (!t->MemBlock) {
+#if _TEXFALLBACK
+ FALLBACK( vmesa, S3V_FALLBACK_TEXTURE, GL_TRUE );
+#endif
+ return;
+ }
+ }
+
+ /* Update state if this is a different texture object to last
+ * time.
+ */
+#if 1
+ if (vmesa->CurrentTexObj[unit] != t) {
+ vmesa->dirty |= S3V_UPLOAD_TEX0 /* << unit */;
+ vmesa->CurrentTexObj[unit] = t;
+ s3vUpdateTexLRU( vmesa, t ); /* done too often */
+ }
+#endif
+
+ /* Update texture environment if texture object image format or
+ * texture environment state has changed.
+ */
+ if (tObj->Image[tObj->BaseLevel]->Format != vmesa->TexEnvImageFmt[unit]) {
+ vmesa->TexEnvImageFmt[unit] = tObj->Image[tObj->BaseLevel]->Format;
+ s3vUpdateTexEnv( ctx, unit );
+ }
+#if 1
+ cmd = vmesa->CMD & ~MIP_MASK;
+ vmesa->dirty |= S3V_UPLOAD_TEX0 /* << unit */;
+ vmesa->CurrentTexObj[unit] = t;
+ vmesa->TexOffset = t->TextureBaseAddr[tObj->BaseLevel];
+ vmesa->TexStride = t->Pitch;
+ cmd |= MIPMAP_LEVEL(t->WidthLog2);
+
+ DEBUG_TEX(("\n\n>> vmesa->CMD was 0x%x\n", vmesa->CMD));
+ DEBUG_TEX(( ">> vmesa->CMD is 0x%x\n\n", cmd ));
+ DEBUG_TEX(("t->WidthLog2 = %i\n", t->WidthLog2));
+ DEBUG_TEX(("MIPMAP_LEVEL(t->WidthLog2) = 0x%x\n", MIPMAP_LEVEL(t->WidthLog2)));
+
+ vmesa->CMD = cmd;
+ vmesa->restore_primitive = -1;
+#endif
+ }
+ else if (texUnit->_ReallyEnabled) { /* _ReallyEnabled but != TEXTURE0_2D */
+#if _TEXFALLBACK
+ FALLBACK( vmesa, S3V_FALLBACK_TEXTURE, GL_TRUE );
+#endif
+ }
+ else /*if (vmesa->CurrentTexObj[unit])*/ { /* !_ReallyEnabled */
+ vmesa->CurrentTexObj[unit] = 0;
+ vmesa->TexEnvImageFmt[unit] = 0;
+ vmesa->dirty &= ~(S3V_UPLOAD_TEX0<<unit);
+ }
+}
+
+
+void s3vUpdateTextureState( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+#if TEX_DEBUG_ON
+ static unsigned int times=0;
+ DEBUG_TEX(("*** s3vUpdateTextureState: #%i ***\n", ++times));
+#endif
+
+ if (!ctx->Texture._ReallyEnabled) {
+ DEBUG_TEX(("!ctx->Texture._ReallyEnabled\n"));
+ return;
+ }
+
+#if _TEXFALLBACK
+ FALLBACK( vmesa, S3V_FALLBACK_TEXTURE, GL_FALSE );
+#endif
+ s3vUpdateTexUnit( ctx, 0 );
+#if 0
+ s3vUpdateTexUnit( ctx, 1 );
+#endif
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_tris.c b/src/mesa/drivers/dri/s3v/s3v_tris.c
new file mode 100644
index 0000000000..3b52340b4c
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_tris.c
@@ -0,0 +1,850 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/ioctl.h>
+
+#include "s3v_context.h"
+#include "s3v_vb.h"
+#include "s3v_tris.h"
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+/***********************************************************************
+ * Build hardware rasterization functions *
+ ***********************************************************************/
+
+#define DO_TRI 1
+#define HAVE_RGBA 1
+#define HAVE_SPEC 0
+#define HAVE_BACK_COLORS 0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX s3vVertex
+#define TAB rast_tab
+
+#define VERT_SET_RGBA( v, c ) \
+do { \
+ UNCLAMPED_FLOAT_TO_RGBA_CHAN( v->ub4[4], c); \
+/* *(v->ub4[4]) = c; \ */ \
+} while (0)
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4]
+/*
+#define VERT_COPY_RGBA1( v0, v1 ) v0->ui[4] = v1->ui[4]
+*/
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx]
+
+#define S3V_OFFSET_BIT 0x01
+#define S3V_TWOSIDE_BIT 0x02
+#define S3V_UNFILLED_BIT 0x04
+#define S3V_FALLBACK_BIT 0x08
+#define S3V_MAX_TRIFUNC 0x10
+
+
+static struct {
+ points_func points;
+ line_func line;
+ triangle_func triangle;
+ quad_func quad;
+} rast_tab[S3V_MAX_TRIFUNC];
+
+#define S3V_RAST_CULL_BIT 0x01
+#define S3V_RAST_FLAT_BIT 0x02
+#define S3V_RAST_TEX_BIT 0x04
+
+static s3v_point_func s3v_point_tab[0x8];
+static s3v_line_func s3v_line_tab[0x8];
+static s3v_tri_func s3v_tri_tab[0x8];
+static s3v_quad_func s3v_quad_tab[0x8];
+
+#define IND (0)
+#define TAG(x) x
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_CULL_BIT)
+#define TAG(x) x##_cull
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_CULL_BIT|S3V_RAST_FLAT_BIT)
+#define TAG(x) x##_cull_flat
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_TEX_BIT)
+#define TAG(x) x##_tex
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_CULL_BIT|S3V_RAST_TEX_BIT)
+#define TAG(x) x##_cull_tex
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_FLAT_BIT|S3V_RAST_TEX_BIT)
+#define TAG(x) x##_flat_tex
+#include "s3v_tritmp.h"
+
+#define IND (S3V_RAST_CULL_BIT|S3V_RAST_FLAT_BIT|S3V_RAST_TEX_BIT)
+#define TAG(x) x##_cull_flat_tex
+#include "s3v_tritmp.h"
+
+static void init_rast_tab( void )
+{
+ DEBUG(("*** init_rast_tab ***\n"));
+
+ s3v_init();
+ s3v_init_cull();
+ s3v_init_flat();
+ s3v_init_cull_flat();
+ s3v_init_tex();
+ s3v_init_cull_tex();
+ s3v_init_flat_tex();
+ s3v_init_cull_flat_tex();
+}
+
+/***********************************************************************
+ * Rasterization fallback helpers *
+ ***********************************************************************/
+
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+
+#if 0
+static void
+s3v_fallback_quad( s3vContextPtr vmesa,
+ const s3vVertex *v0,
+ const s3vVertex *v1,
+ const s3vVertex *v2,
+ const s3vVertex *v3 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ SWvertex v[4];
+ s3v_translate_vertex( ctx, v0, &v[0] );
+ s3v_translate_vertex( ctx, v1, &v[1] );
+ s3v_translate_vertex( ctx, v2, &v[2] );
+ s3v_translate_vertex( ctx, v3, &v[3] );
+ DEBUG(("s3v_fallback_quad\n"));
+/* _swrast_Quad( ctx, &v[0], &v[1], &v[2], &v[3] ); */
+}
+
+static void
+s3v_fallback_tri( s3vContextPtr vmesa,
+ const s3vVertex *v0,
+ const s3vVertex *v1,
+ const s3vVertex *v2 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ SWvertex v[3];
+ s3v_translate_vertex( ctx, v0, &v[0] );
+ s3v_translate_vertex( ctx, v1, &v[1] );
+ s3v_translate_vertex( ctx, v2, &v[2] );
+ DEBUG(("s3v_fallback_tri\n"));
+/* _swrast_Triangle( ctx, &v[0], &v[1], &v[2] ); */
+}
+
+static void
+s3v_fallback_line( s3vContextPtr vmesa,
+ const s3vVertex *v0,
+ const s3vVertex *v1 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ SWvertex v[2];
+ s3v_translate_vertex( ctx, v0, &v[0] );
+ s3v_translate_vertex( ctx, v1, &v[1] );
+ DEBUG(("s3v_fallback_line\n"));
+ _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+/*
+static void
+s3v_fallback_point( s3vContextPtr vmesa,
+ const s3vVertex *v0 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ SWvertex v[1];
+ s3v_translate_vertex( ctx, v0, &v[0] );
+ _swrast_Point( ctx, &v[0] );
+}
+*/
+#endif
+
+/***********************************************************************
+ * Choose rasterization functions *
+ ***********************************************************************/
+
+#define _S3V_NEW_RASTER_STATE (_NEW_FOG | \
+ _NEW_TEXTURE | \
+ _DD_NEW_TRI_SMOOTH | \
+ _DD_NEW_LINE_SMOOTH | \
+ _DD_NEW_POINT_SMOOTH | \
+ _DD_NEW_TRI_STIPPLE | \
+ _DD_NEW_LINE_STIPPLE)
+
+#define LINE_FALLBACK (0)
+#define TRI_FALLBACK (0)
+
+static void s3v_nodraw_triangle(GLcontext *ctx, s3vVertex *v0,
+ s3vVertex *v1, s3vVertex *v2)
+{
+ (void) (ctx && v0 && v1 && v2);
+}
+
+static void s3v_nodraw_quad(GLcontext *ctx,
+ s3vVertex *v0, s3vVertex *v1,
+ s3vVertex *v2, s3vVertex *v3)
+{
+ (void) (ctx && v0 && v1 && v2 && v3);
+}
+
+void s3vChooseRasterState(GLcontext *ctx);
+
+void s3vChooseRasterState(GLcontext *ctx)
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint ind = 0;
+
+ DEBUG(("*** s3vChooseRasterState ***\n"));
+
+ if (ctx->Polygon.CullFlag) {
+ if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+ vmesa->draw_tri = (s3v_tri_func)s3v_nodraw_triangle;
+ vmesa->draw_quad = (s3v_quad_func)s3v_nodraw_quad;
+ return;
+ }
+ ind |= S3V_RAST_CULL_BIT;
+ /* s3v_update_cullsign(ctx); */
+ } /* else vmesa->backface_sign = 0; */
+
+ if ( flags & DD_FLATSHADE )
+ ind |= S3V_RAST_FLAT_BIT;
+
+ if ( ctx->Texture._ReallyEnabled ) {
+ ind |= S3V_RAST_TEX_BIT;
+ }
+
+ DEBUG(("ind = %i\n", ind));
+
+ vmesa->draw_line = s3v_line_tab[ind];
+ vmesa->draw_tri = s3v_tri_tab[ind];
+ vmesa->draw_quad = s3v_quad_tab[ind];
+ vmesa->draw_point = s3v_point_tab[ind];
+
+#if 0
+ /* Hook in fallbacks for specific primitives. CURRENTLY DISABLED
+ */
+
+ if (flags & LINE_FALLBACK)
+ vmesa->draw_line = s3v_fallback_line;
+
+ if (flags & TRI_FALLBACK) {
+ DEBUG(("TRI_FALLBACK\n"));
+ vmesa->draw_tri = s3v_fallback_tri;
+ vmesa->draw_quad = s3v_fallback_quad;
+ }
+#endif
+}
+
+
+
+
+/***********************************************************************
+ * Macros for t_dd_tritmp.h to draw basic primitives *
+ ***********************************************************************/
+
+#define TRI( v0, v1, v2 ) \
+do { \
+ /*
+ if (DO_FALLBACK) \
+ vmesa->draw_tri( vmesa, v0, v1, v2 ); \
+ else */ \
+ DEBUG(("TRI: max was here\n")); /* \
+ s3v_draw_tex_triangle( vmesa, v0, v1, v2 ); */ \
+ vmesa->draw_tri( vmesa, v0, v1, v2 ); \
+} while (0)
+
+#define QUAD( v0, v1, v2, v3 ) \
+do { \
+ DEBUG(("QUAD: max was here\n")); \
+ vmesa->draw_quad( vmesa, v0, v1, v2, v3 ); \
+} while (0)
+
+#define LINE( v0, v1 ) \
+do { \
+ DEBUG(("LINE: max was here\n")); \
+ vmesa->draw_line( vmesa, v0, v1 ); \
+} while (0)
+
+#define POINT( v0 ) \
+do { \
+ vmesa->draw_point( vmesa, v0 ); \
+} while (0)
+
+
+/***********************************************************************
+ * Build render functions from dd templates *
+ ***********************************************************************/
+
+/*
+#define S3V_OFFSET_BIT 0x01
+#define S3V_TWOSIDE_BIT 0x02
+#define S3V_UNFILLED_BIT 0x04
+#define S3V_FALLBACK_BIT 0x08
+#define S3V_MAX_TRIFUNC 0x10
+
+
+static struct {
+ points_func points;
+ line_func line;
+ triangle_func triangle;
+ quad_func quad;
+} rast_tab[S3V_MAX_TRIFUNC];
+*/
+
+#define DO_FALLBACK (IND & S3V_FALLBACK_BIT)
+#define DO_OFFSET (IND & S3V_OFFSET_BIT)
+#define DO_UNFILLED (IND & S3V_UNFILLED_BIT)
+#define DO_TWOSIDE (IND & S3V_TWOSIDE_BIT)
+#define DO_FLAT 0
+#define DO_TRI 1
+#define DO_QUAD 1
+#define DO_LINE 1
+#define DO_POINTS 1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA 1
+#define HAVE_SPEC 0
+#define HAVE_BACK_COLORS 0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX s3vVertex
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a > 0)
+#define GET_VERTEX(e) (vmesa->verts + (e<<vmesa->vertex_stride_shift))
+
+#if 0
+#define VERT_SET_RGBA( v, c ) \
+do { \
+/* UNCLAMPED_FLOAT_TO_RGBA_CHAN( v->ub4[4], c) */ \
+} while (0)
+
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[4] = v1->ui[4]
+/*
+#define VERT_COPY_RGBA1( v0, v1 ) v0->ui[4] = v1->ui[4]
+*/
+#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[4]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[4] = color[idx]
+#endif
+
+#define LOCAL_VARS(n) \
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx); \
+ GLuint color[n]; \
+ (void) color;
+
+
+/***********************************************************************
+ * Helpers for rendering unfilled primitives *
+ ***********************************************************************/
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+ PrimType_Points,
+ PrimType_Lines,
+ PrimType_Lines,
+ PrimType_Lines,
+ PrimType_Triangles,
+ PrimType_Triangles,
+ PrimType_Triangles,
+ PrimType_Triangles,
+ PrimType_Triangles,
+ PrimType_Triangles
+};
+
+static void s3vResetLineStipple( GLcontext *ctx );
+static void s3vRasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void s3vRenderPrimitive( GLcontext *ctx, GLenum prim );
+/*
+extern static void s3v_lines_emit(GLcontext *ctx, GLuint start, GLuint end);
+extern static void s3v_tris_emit(GLcontext *ctx, GLuint start, GLuint end);
+*/
+#define RASTERIZE(x) if (vmesa->hw_primitive != hw_prim[x]) \
+ s3vRasterPrimitive( ctx, hw_prim[x] )
+#define RENDER_PRIMITIVE vmesa->render_primitive
+#define TAG(x) x
+#define IND S3V_FALLBACK_BIT
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+/***********************************************************************
+ * Generate GL render functions *
+ ***********************************************************************/
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_TWOSIDE_BIT|S3V_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_OFFSET_BIT|S3V_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_TWOSIDE_BIT|S3V_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (S3V_TWOSIDE_BIT|S3V_OFFSET_BIT|S3V_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_render_tab( void )
+{
+ DEBUG(("*** init_render_tab ***\n"));
+
+ init();
+ init_offset();
+ init_twoside();
+ init_twoside_offset();
+ init_unfilled();
+ init_offset_unfilled();
+ init_twoside_unfilled();
+ init_twoside_offset_unfilled();
+}
+
+
+/**********************************************************************/
+/* Render unclipped begin/end objects */
+/**********************************************************************/
+
+#define VERT(x) (s3vVertex *)(s3vverts + (x << shift))
+
+#define RENDER_POINTS( start, count ) \
+ DEBUG(("RENDER_POINTS...(ok)\n")); \
+ for ( ; start < count ; start++) \
+ vmesa->draw_line( vmesa, VERT(start), VERT(start) )
+ /* vmesa->draw_point( vmesa, VERT(start) ) */
+
+#define RENDER_LINE( v0, v1 ) \
+ /* DEBUG(("RENDER_LINE...(ok)\n")); \ */ \
+ vmesa->draw_line( vmesa, VERT(v0), VERT(v1) ); \
+ DEBUG(("RENDER_LINE...(ok)\n"))
+
+#define RENDER_TRI( v0, v1, v2 ) \
+ DEBUG(("RENDER_TRI...(ok)\n")); \
+ vmesa->draw_tri( vmesa, VERT(v0), VERT(v1), VERT(v2) )
+
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+ DEBUG(("RENDER_QUAD...(ok)\n")); \
+ /* s3v_draw_quad( vmesa, VERT(v0), VERT(v1), VERT(v2),VERT(v3) ) */\
+ /* s3v_draw_triangle( vmesa, VERT(v0), VERT(v1), VERT(v2) ); \
+ s3v_draw_triangle( vmesa, VERT(v0), VERT(v2), VERT(v3) ) */ \
+ vmesa->draw_quad( vmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+
+#define INIT(x) s3vRenderPrimitive( ctx, x );
+#undef LOCAL_VARS
+#define LOCAL_VARS \
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx); \
+ const GLuint shift = vmesa->vertex_stride_shift; \
+ const char *s3vverts = (char *)vmesa->verts; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) stipple;
+#define RESET_STIPPLE if ( stipple ) s3vResetLineStipple( ctx );
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) (x)
+#define TAG(x) s3v_##x##_verts
+#include "tnl_dd/t_dd_rendertmp.h"
+
+
+/**********************************************************************/
+/* Render clipped primitives */
+/**********************************************************************/
+
+static void s3vRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+ GLuint n )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint prim = vmesa->render_primitive;
+
+ DEBUG(("I AM in: s3vRenderClippedPoly\n"));
+
+ /* Render the new vertices as an unclipped polygon.
+ */
+ if (1)
+ {
+ GLuint *tmp = VB->Elts;
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]
+ ( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+
+ VB->Elts = tmp;
+ }
+
+ /* Restore the render primitive
+ */
+#if 1
+ if (prim != GL_POLYGON) {
+ DEBUG(("and prim != GL_POLYGON\n"));
+ tnl->Driver.Render.PrimitiveNotify( ctx, prim );
+ }
+
+#endif
+}
+
+static void s3vRenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ /*tnl->Driver.LineFunc = s3v_line_tab[2];*/ /* _swsetup_Line; */
+
+ DEBUG(("I AM in: s3vRenderClippedLine\n"));
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+
+/**********************************************************************/
+/* Choose render functions */
+/**********************************************************************/
+
+
+
+#define _S3V_NEW_RENDERSTATE (_DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE | \
+ _DD_NEW_TRI_OFFSET)
+
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+static void s3vChooseRenderState(GLcontext *ctx)
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint flags = ctx->_TriangleCaps;
+ GLuint index = 0;
+
+ DEBUG(("s3vChooseRenderState\n"));
+
+ if (flags & ANY_RASTER_FLAGS) {
+ if (flags & DD_TRI_LIGHT_TWOSIDE) index |= S3V_TWOSIDE_BIT;
+ if (flags & DD_TRI_OFFSET) index |= S3V_OFFSET_BIT;
+ if (flags & DD_TRI_UNFILLED) index |= S3V_UNFILLED_BIT;
+ }
+
+ DEBUG(("vmesa->RenderIndex = %i\n", vmesa->RenderIndex));
+ DEBUG(("index = %i\n", index));
+
+ if (vmesa->RenderIndex != index) {
+ vmesa->RenderIndex = index;
+
+ tnl->Driver.Render.Points = rast_tab[index].points;
+ tnl->Driver.Render.Line = rast_tab[index].line;
+ tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+ tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+ if (vmesa->RenderIndex == 0)
+ tnl->Driver.Render.PrimTabVerts = s3v_render_tab_verts;
+ else
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.ClippedLine = s3vRenderClippedLine;
+ tnl->Driver.Render.ClippedPolygon = s3vRenderClippedPoly;
+ }
+}
+
+
+/**********************************************************************/
+/* High level hooks for t_vb_render.c */
+/**********************************************************************/
+
+
+
+/* Determine the rasterized primitive when not drawing unfilled
+ * polygons.
+ *
+ * Used only for the default render stage which always decomposes
+ * primitives to trianges/lines/points. For the accelerated stage,
+ * which renders strips as strips, the equivalent calculations are
+ * performed in s3v_render.c.
+ */
+
+static void s3vRasterPrimitive( GLcontext *ctx, GLuint hwprim )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+/* __DRIdrawablePrivate *dPriv = vmesa->driDrawable; */
+ CARD32 cmd = vmesa->CMD;
+
+ unsigned int _hw_prim = hwprim;
+
+ DEBUG(("s3vRasterPrimitive: hwprim = 0x%x ", _hw_prim));
+
+/* printf("* vmesa->CMD = 0x%x\n", vmesa->CMD); */
+
+ if (vmesa->hw_primitive != _hw_prim)
+ {
+ DEBUG(("(new one) ***\n"));
+ cmd &= ~DO_MASK;
+ cmd &= ~ALPHA_BLEND_MASK;
+ vmesa->hw_primitive = _hw_prim;
+
+ if (_hw_prim == PrimType_Triangles) {
+ /* TRI */
+ DEBUG(("->switching to tri\n"));
+ cmd |= (vmesa->_tri[vmesa->_3d_mode] | vmesa->_alpha[vmesa->_3d_mode]);
+ } else if (_hw_prim == PrimType_Lines
+ || _hw_prim == PrimType_Points) {
+ /* LINE */
+ DEBUG(("->switching to line\n"));
+ cmd |= (DO_3D_LINE | vmesa->_alpha[0]);
+ } else {
+ /* ugh? */
+ DEBUG(("->switching to your sis'ass\n"));
+ }
+
+ DEBUG(("\n"));
+
+ vmesa->restore_primitive = _hw_prim;
+ /* 0xacc16827: good value -> lightened newave!!! */
+ vmesa->CMD = cmd;
+ CMDCHANGE();
+ }
+}
+
+static void s3vRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+ CARD32 cmd = vmesa->CMD;
+
+ unsigned int _hw_prim = hw_prim[prim];
+
+ vmesa->render_primitive = prim;
+ vmesa->hw_primitive = _hw_prim;
+
+ DEBUG(("s3vRenderPrimitive #%i ", prim));
+ DEBUG(("_hw_prim = 0x%x\n", _hw_prim));
+
+/* printf(" vmesa->CMD = 0x%x\n", vmesa->CMD); */
+
+ if (_hw_prim != vmesa->restore_primitive) {
+ DEBUG(("_hw_prim != vmesa->restore_primitive (was 0x%x)\n",
+ vmesa->restore_primitive));
+#if 1
+ cmd &= ~DO_MASK;
+ cmd &= ~ALPHA_BLEND_MASK;
+/*
+ printf(" cmd = 0x%x\n", cmd);
+ printf(" vmesa->_3d_mode=%i; vmesa->_tri[vmesa->_3d_mode]=0x%x\n",
+ vmesa->_3d_mode, vmesa->_tri[vmesa->_3d_mode]);
+ printf("vmesa->alpha[0] = 0x%x; vmesa->alpha[1] = 0x%x\n",
+ vmesa->_alpha[0], vmesa->_alpha[1]);
+*/
+ if (_hw_prim == PrimType_Triangles) { /* TRI */
+ DEBUG(("->switching to tri\n"));
+ cmd |= (vmesa->_tri[vmesa->_3d_mode] | vmesa->_alpha[vmesa->_3d_mode]);
+ DEBUG(("vmesa->TexStride = %i\n", vmesa->TexStride));
+ DEBUG(("vmesa->TexOffset = %i\n", vmesa->TexOffset));
+ DMAOUT_CHECK(3DTRI_Z_BASE, 12);
+ } else { /* LINE */
+ DEBUG(("->switching to line\n"));
+ cmd |= (DO_3D_LINE | vmesa->_alpha[0]);
+ DMAOUT_CHECK(3DLINE_Z_BASE, 12);
+ }
+
+ DMAOUT(vmesa->s3vScreen->depthOffset & 0x003FFFF8);
+ DMAOUT(vmesa->DestBase);
+ /* DMAOUT(vmesa->ScissorLR); */
+ /* DMAOUT(vmesa->ScissorTB); */
+
+ /* NOTE: we need to restore all these values since we
+ * are coming back from a vmesa->restore_primitive */
+ DMAOUT( (0 << 16) | (dPriv->w-1) );
+ DMAOUT( (0 << 16) | (dPriv->h-1) );
+ DMAOUT( (vmesa->SrcStride << 16) | vmesa->TexStride );
+ DMAOUT(vmesa->SrcStride);
+ DMAOUT(vmesa->TexOffset);
+ DMAOUT(vmesa->TextureBorderColor);
+ DMAOUT(0); /* FOG */
+ DMAOUT(0);
+ DMAOUT(0);
+ DMAOUT(cmd);
+ /* 0xacc16827: good value -> lightened newave!!! */
+ DMAFINISH();
+
+ vmesa->CMD = cmd;
+#endif
+ }
+
+ DEBUG(("\n"));
+
+ vmesa->restore_primitive = _hw_prim;
+}
+
+static void s3vRunPipeline( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+
+ DEBUG(("*** s3vRunPipeline ***\n"));
+
+ if ( vmesa->new_state )
+ s3vDDUpdateHWState( ctx );
+
+ if (vmesa->new_gl_state) {
+
+ if (vmesa->new_gl_state & _NEW_TEXTURE) {
+ s3vUpdateTextureState( ctx );
+ }
+
+ if (!vmesa->Fallback) {
+ if (vmesa->new_gl_state & _S3V_NEW_VERTEX)
+ s3vChooseVertexState( ctx );
+
+ if (vmesa->new_gl_state & _S3V_NEW_RASTER_STATE)
+ s3vChooseRasterState( ctx );
+
+ if (vmesa->new_gl_state & _S3V_NEW_RENDERSTATE)
+ s3vChooseRenderState( ctx );
+ }
+
+ vmesa->new_gl_state = 0;
+
+ }
+
+ _tnl_run_pipeline( ctx );
+}
+
+static void s3vRenderStart( GLcontext *ctx )
+{
+ /* Check for projective texturing. Make sure all texcoord
+ * pointers point to something. (fix in mesa?)
+ */
+
+ DEBUG(("s3vRenderStart\n"));
+ /* s3vCheckTexSizes( ctx ); */
+}
+
+static void s3vRenderFinish( GLcontext *ctx )
+{
+ if (0)
+ _swrast_flush( ctx ); /* never needed */
+}
+
+static void s3vResetLineStipple( GLcontext *ctx )
+{
+/* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
+
+ /* Reset the hardware stipple counter.
+ */
+/*
+ CHECK_DMA_BUFFER(vmesa, 1);
+ WRITE(vmesa->buf, UpdateLineStippleCounters, 0);
+*/
+}
+
+
+/**********************************************************************/
+/* Transition to/from hardware rasterization. */
+/**********************************************************************/
+
+
+void s3vFallback( s3vContextPtr vmesa, GLuint bit, GLboolean mode )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint oldfallback = vmesa->Fallback;
+
+ DEBUG(("*** s3vFallback: "));
+
+ if (mode) {
+ vmesa->Fallback |= bit;
+ if (oldfallback == 0) {
+ DEBUG(("oldfallback == 0 ***\n"));
+ _swsetup_Wakeup( ctx );
+ _tnl_need_projected_coords( ctx, GL_TRUE );
+ vmesa->RenderIndex = ~0;
+ }
+ }
+ else {
+ DEBUG(("***\n"));
+ vmesa->Fallback &= ~bit;
+ if (oldfallback == bit) {
+ _swrast_flush( ctx );
+ tnl->Driver.Render.Start = s3vRenderStart;
+ tnl->Driver.Render.PrimitiveNotify = s3vRenderPrimitive;
+ tnl->Driver.Render.Finish = s3vRenderFinish;
+ tnl->Driver.Render.BuildVertices = s3vBuildVertices;
+ tnl->Driver.Render.ResetLineStipple = s3vResetLineStipple;
+ vmesa->new_gl_state |= (_S3V_NEW_RENDERSTATE|
+ _S3V_NEW_RASTER_STATE|
+ _S3V_NEW_VERTEX);
+ }
+ }
+}
+
+
+/**********************************************************************/
+/* Initialization. */
+/**********************************************************************/
+
+
+void s3vInitTriFuncs( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ static int firsttime = 1;
+
+ if (firsttime) {
+ init_rast_tab();
+ init_render_tab();
+ firsttime = 0;
+ }
+
+ vmesa->RenderIndex = ~0;
+
+ tnl->Driver.RunPipeline = s3vRunPipeline;
+ tnl->Driver.Render.Start = s3vRenderStart;
+ tnl->Driver.Render.Finish = s3vRenderFinish;
+ tnl->Driver.Render.PrimitiveNotify = s3vRenderPrimitive;
+ tnl->Driver.Render.ResetLineStipple = s3vResetLineStipple;
+/*
+ tnl->Driver.RenderInterp = _swsetup_RenderInterp;
+ tnl->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
+*/
+ tnl->Driver.Render.BuildVertices = s3vBuildVertices;
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_tris.h b/src/mesa/drivers/dri/s3v/s3v_tris.h
new file mode 100644
index 0000000000..0010a7fe0a
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_tris.h
@@ -0,0 +1,11 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef _S3V_TRIS_H
+#define _S3V_TRIS_H
+
+extern void s3vDDTrifuncInit(void);
+extern void s3vDDChooseTriRenderState(GLcontext *);
+
+#endif /* !(_S3V_TRIS_H) */
diff --git a/src/mesa/drivers/dri/s3v/s3v_tritmp.h b/src/mesa/drivers/dri/s3v/s3v_tritmp.h
new file mode 100644
index 0000000000..60a5e60dc5
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_tritmp.h
@@ -0,0 +1,899 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+/**** MACROS start ****/
+
+/* point/line macros */
+
+#define LINE_VERT_VARS \
+ SWvertex v[3]; \
+ s3vVertex* vvv[2]; \
+ int x[3], y[3], z[3]; \
+ int idx[3]; \
+ int dx01, dy01; \
+ int delt02; \
+ int deltzy, zstart; \
+ int start02, end01; \
+ int ystart, y01y12; \
+ int i, tmp, tmp2, tmp3; \
+ GLfloat ydiff, fy[3]
+
+#define LINE_FLAT_VARS \
+ int arstart, gbstart; \
+ int deltarx, deltgbx, deltary, deltgby; \
+ GLubyte *(col)[3]
+
+#define LINE_GOURAUD_VARS \
+ int arstart, gbstart; \
+ int deltary, deltgby; \
+ int ctmp, ctmp2, ctmp3, ctmp4; \
+ GLubyte *(col)[3]
+
+#define SORT_LINE_VERT() \
+do { \
+ if(v[0].win[1] <= v[1].win[1]) { \
+\
+ idx[0] = 0; \
+ idx[1] = 1; \
+\
+ } else if (v[0].win[1] > v[1].win[1]) { \
+\
+ idx[0] = 1; \
+ idx[1] = 0; \
+\
+ } \
+} while(0)
+
+#define SET_LINE_VERT() \
+do { \
+ x[0] = (v[idx[0]].win[0] * 1024.0f * 1024.0f); /* 0x100000 */ \
+ y[0] = fy[0] = dPriv->h - v[idx[0]].win[1]; \
+ z[0] = (v[idx[0]].win[2]) * 1024.0f * 32.0f; /* 0x8000; */ \
+\
+ x[1] = (v[idx[1]].win[0] * 1024.0f * 1024.0f); /* 0x100000 */ \
+ y[1] = dPriv->h - v[idx[1]].win[1]; \
+ z[1] = (v[idx[1]].win[2]) * 1024.0f * 32.0f; /* 0x8000 */ \
+} while(0)
+
+#define SET_LINE_XY() \
+do { \
+ tmp = v[idx[0]].win[0]; \
+ tmp2 = v[idx[1]].win[0]; \
+\
+ dx01 = x[0] - x[1]; \
+ dy01 = y[0] - y[1]; \
+\
+ ydiff = fy[0] - (float)y[0]; \
+ ystart = y[0]; \
+ y01y12 = dy01 + 1; \
+} while (0)
+
+#define SET_LINE_DIR() \
+do { \
+ if (tmp2 > tmp) { \
+ y01y12 |= 0x80000000; \
+ tmp3 = tmp2-tmp; \
+ } else { \
+ tmp3 = tmp-tmp2; \
+ } \
+\
+ end01 = ((tmp << 16) | tmp2); \
+\
+ if (dy01) \
+ delt02 = -(dx01/dy01); \
+ else \
+ delt02 = 0; \
+\
+ if (dy01 > tmp3) { /* Y MAJ */ \
+ /* NOTE: tmp3 always >=0 */ \
+ start02 = x[0]; \
+ } else if (delt02 >= 0){ /* X MAJ - positive delta */ \
+ start02 = x[0] + delt02/2; \
+ dy01 = tmp3; /* could be 0 */ \
+ } else { /* X MAJ - negative delta */ \
+ start02 = x[0] + delt02/2 + ((1 << 20) - 1); \
+ dy01 = tmp3; /* could be 0 */ \
+ } \
+} while(0)
+
+#define SET_LINE_Z() \
+do { \
+ zstart = z[0]; \
+\
+ if (dy01) { \
+ deltzy = (z[1] - z[0])/dy01; \
+ } else { \
+ deltzy = 0; /* dy01 = tmp3 = 0 (it's a point)*/ \
+ } \
+} while (0)
+
+#define SET_LINE_FLAT_COL() \
+do { \
+ col[0] = &(v[idx[0]].color[0]); \
+ deltarx = deltary = deltgbx = deltgby = 0; \
+ gbstart = (((col[0][1]) << 23) | ((col[0][2]) << 7)); \
+ arstart = (((col[0][3]) << 23) | ((col[0][0]) << 7)); \
+} while(0)
+
+#define SET_LINE_GOURAUD_COL() \
+do { \
+ col[0] = &(v[idx[0]].color[0]); \
+ col[1] = &(v[idx[1]].color[0]); \
+\
+ vvv[0] = _v0; \
+ vvv[1] = _v1; \
+\
+ for (i=0; i<2; i++) { \
+ /* FIXME: swapped ! */ \
+ col[i][0] = vvv[!idx[i]]->v.color.red; \
+ col[i][1] = vvv[!idx[i]]->v.color.green; \
+ col[i][2] = vvv[!idx[i]]->v.color.blue; \
+ col[i][3] = vvv[!idx[i]]->v.color.alpha; \
+ } \
+\
+ if (dy01) { \
+\
+ ctmp = ((col[0][1] - col[1][1]) << 7) / dy01; \
+ ctmp2 = ((col[0][2] - col[1][2]) << 7) / dy01; \
+ deltgby = ((ctmp << 16) & 0xFFFF0000) | (ctmp2 & 0xFFFF); \
+\
+ ctmp3 = ((col[0][3] - col[1][3]) << 7) / dy01; \
+ ctmp4 = ((col[0][0] - col[1][0]) << 7) / dy01; \
+ deltary = ((ctmp3 << 16) & 0xFFFF0000) | (ctmp4 & 0xFFFF); \
+ } else { \
+ ctmp = ((col[1][1] - col[0][1]) << 7); \
+ ctmp2 = ((col[1][2] - col[0][2]) << 7); \
+ deltgby = ((ctmp << 16) & 0xFFFF0000) | (ctmp2 & 0xFFFF); \
+\
+ ctmp3 = ((col[1][3] - col[0][3]) << 7); \
+ ctmp4 = ((col[1][0] - col[0][0]) << 7); \
+ deltary = ((ctmp3 << 16) & 0xFFFF0000) | (ctmp4 & 0xFFFF); \
+ deltgby = deltary = 0; \
+ } \
+\
+ idx[0] = 1; /* FIXME: swapped */ \
+\
+ gbstart = \
+ (((int)((ydiff * ctmp) + (col[idx[0]][1] << 7)) << 16) & 0x7FFF0000) \
+ | ((int)((ydiff * ctmp2) + (col[idx[0]][2] << 7)) & 0x7FFF); \
+ arstart = \
+ (((int)((ydiff * ctmp3) + (col[idx[0]][3] << 7)) << 16) & 0x7FFF0000) \
+ | ((int)((ydiff * ctmp4) + (col[idx[0]][0] << 7)) & 0x7FFF); \
+} while(0)
+
+#define SEND_LINE_COL() \
+do { \
+ DMAOUT(deltgby); \
+ DMAOUT(deltary); \
+ DMAOUT(gbstart); \
+ DMAOUT(arstart); \
+} while (0)
+
+#define SEND_LINE_VERT() \
+do { \
+ DMAOUT(deltzy); \
+ DMAOUT(zstart); \
+ DMAOUT(0); \
+ DMAOUT(0); \
+ DMAOUT(0); \
+ DMAOUT(end01); \
+ DMAOUT(delt02); \
+ DMAOUT(start02); \
+ DMAOUT(ystart); \
+ DMAOUT(y01y12); \
+} while (0)
+
+
+/* tri macros (mostly stolen from utah-glx...) */
+
+#define VERT_VARS \
+ SWvertex v[3]; \
+ int x[3], y[3], z[3]; \
+ int idx[3]; \
+ int dx01, dy01; \
+ int dx02, dy02; \
+ int dx12, dy12; \
+ int delt01, delt02, delt12; \
+ int deltzx, deltzy, zstart; \
+ int start02, end01, end12; \
+ int ystart, y01y12; \
+ int i, tmp, lr; \
+ GLfloat ydiff, fy[3]
+
+#define GOURAUD_VARS \
+ int arstart, gbstart; \
+ int deltarx, deltgbx, deltary, deltgby; \
+ int ctmp, ctmp2, ctmp3, ctmp4; \
+ GLubyte *(col)[3]
+
+#define FLAT_VARS \
+ int arstart, gbstart; \
+ int deltarx, deltgbx, deltary, deltgby; \
+ GLubyte *(col)[3]
+
+#define TEX_VARS \
+ int u0, u1, u2; \
+ GLfloat ru0, ru1, ru2; \
+ int v0, v1, v2; \
+ GLfloat rv0, rv1, rv2; \
+ GLfloat w0, w1, w2; \
+ GLfloat rw0, rw1, rw2; \
+ int baseu, basev; \
+ int d0, d1, d2; \
+ int deltdx, deltvx, deltux, deltdy, deltvy, deltuy; \
+ int deltwx, deltwy; \
+ int rbaseu, rbasev; \
+ int dstart, ustart, wstart, vstart; \
+ static int stmp = 0; \
+ s3vTextureObjectPtr t
+
+#define SORT_VERT() \
+do { \
+ for (i=0; i<3; i++) \
+ fy[i] = v[i].win[1]; \
+\
+ if (fy[1] > fy[0]) { /* (fy[1] > fy[0]) */ \
+\
+ if (fy[2] > fy[0]) { \
+ idx[0] = 0; \
+ if (fy[1] > fy[2]) { \
+ idx[1] = 2; \
+ idx[2] = 1; \
+ } else { \
+ idx[1] = 1; \
+ idx[2] = 2; \
+ } \
+ } else { \
+ idx[0] = 2; \
+ idx[1] = 0; \
+ idx[2] = 1; \
+ } \
+ } else { /* (fy[1] < y[0]) */ \
+ if (fy[2] > fy[0]) { \
+ idx[0] = 1; \
+ idx[1] = 0; \
+ idx[2] = 2; \
+ } else { \
+ idx[2] = 0; \
+ if (fy[2] > fy[1]) { \
+ idx[0] = 1; \
+ idx[1] = 2; \
+ } else { \
+ idx[0] = 2; \
+ idx[1] = 1; \
+ } \
+ } \
+ } \
+} while(0)
+
+#define SET_VERT() \
+do { \
+ for (i=0; i<3; i++) \
+ { \
+ x[i] = ((v[idx[i]].win[0]) * /* 0x100000*/ 1024.0 * 1024.0); \
+ y[i] = fy[i] = (dPriv->h - v[idx[i]].win[1]); \
+ z[i] = ((v[idx[i]].win[2]) * /* 0x8000 */ 1024.0 * 32.0); \
+ } \
+\
+ ydiff = fy[0] - (float)y[0]; \
+\
+ ystart = y[0]; \
+\
+ dx12 = x[2] - x[1]; \
+ dy12 = y[1] - y[2]; \
+ dx01 = x[1] - x[0]; \
+ dy01 = y[0] - y[1]; \
+ dx02 = x[2] - x[0]; \
+ dy02 = y[0] - y[2]; \
+\
+ delt01 = delt02 = delt12 = 0; \
+} while (0)
+
+
+#define SET_XY() \
+do { \
+ if (dy01) delt01 = dx01 / dy01; \
+ if (dy12) delt12 = dx12 / dy12; \
+ delt02 = dx02 / dy02; \
+\
+ start02 = x[0] + (ydiff * delt02); \
+ end01 = x[0] + (ydiff * delt01); \
+ end12 = x[1] + ((fy[1] - (GLfloat)y[1]) * delt12); \
+} while (0)
+
+#define SET_DIR() \
+do { \
+ tmp = x[1] - (dy01 * delt02 + x[0]); \
+ if (tmp > 0) { \
+ lr = 0x80000000; \
+ } else { \
+ tmp *= -1; \
+ lr = 0; \
+ } \
+ tmp >>= 20; \
+\
+ y01y12 = ((((y[0] - y[1]) & 0x7FF) << 16) \
+ | ((y[1] - y[2]) & 0x7FF) | lr); \
+} while (0)
+
+#define SET_Z() \
+do { \
+ deltzy = (z[2] - z[0]) / dy02; \
+ if (tmp) { \
+ deltzx = (z[1] - (dy01 * deltzy + z[0])) / tmp; \
+ } else { \
+ deltzx = 0; \
+ } \
+ zstart = (deltzy * ydiff) + z[0]; \
+} while (0)
+
+#define SET_FLAT_COL() \
+do { \
+ col[0] = &(v[0].color[0]); \
+ deltarx = deltary = deltgbx = deltgby = 0; \
+ gbstart = (((col[0][1]) << 23) | ((col[0][2]) << 7)); \
+ arstart = (((col[0][3]) << 23) | ((col[0][0]) << 7)); \
+} while(0)
+
+#define SET_GOURAUD_COL() \
+do { \
+ col[0] = &(v[idx[0]].color[0]); \
+ col[1] = &(v[idx[1]].color[0]); \
+ col[2] = &(v[idx[2]].color[0]); \
+\
+ ctmp = ((col[2][3] - col[0][3]) << 7) / dy02; \
+ ctmp2 = ((col[2][0] - col[0][0]) << 7) / dy02; \
+ deltary = ((ctmp << 16) & 0xFFFF0000) | (ctmp2 & 0xFFFF); \
+ ctmp3 = ((col[2][1] - col[0][1]) << 7) / dy02; \
+ ctmp4 = ((col[2][2] - col[0][2]) << 7) / dy02; \
+ deltgby = ((ctmp3 << 16) & 0xFFFF0000) | (ctmp4 & 0xFFFF); \
+ gbstart = \
+ (((int)((ydiff * ctmp3) + (col[0][1] << 7)) << 16) & 0x7FFF0000) \
+ | ((int)((ydiff * ctmp4) + (col[0][2] << 7)) & 0x7FFF); \
+ arstart = \
+ (((int)((ydiff * ctmp) + (col[0][3] << 7)) << 16) & 0x7FFF0000) \
+ | ((int)((ydiff * ctmp2) + (col[0][0] << 7)) & 0x7FFF); \
+ if (tmp) { \
+ int ax, rx, gx, bx; \
+ ax = ((col[1][3] << 7) - (dy01 * ctmp + (col[0][3] << 7))) / tmp; \
+ rx = ((col[1][0] << 7) - (dy01 * ctmp2 + (col[0][0] << 7))) / tmp; \
+ gx = ((col[1][1] << 7) - (dy01 * ctmp3 + (col[0][1] << 7))) / tmp; \
+ bx = ((col[1][2] << 7) - (dy01 * ctmp4 + (col[0][2] << 7))) / tmp; \
+ deltarx = ((ax << 16) & 0xFFFF0000) | (rx & 0xFFFF); \
+ deltgbx = ((gx << 16) & 0xFFFF0000) | (bx & 0xFFFF); \
+ } else { \
+ deltgbx = deltarx = 0; \
+ } \
+} while (0)
+
+#define SET_TEX_VERT() \
+do { \
+ t = ((s3vTextureObjectPtr) \
+ ctx->Texture.Unit[0]._Current->DriverData); \
+ deltwx = deltwy = wstart = deltdx = deltdy = dstart = 0; \
+\
+ u0 = (v[idx[0]].texcoord[0][0] \
+ * (GLfloat)(t->image[0].image->Width) * 256.0); \
+ u1 = (v[idx[1]].texcoord[0][0] \
+ * (GLfloat)(t->globj->Image[0]->Width) * 256.0); \
+ u2 = (v[idx[2]].texcoord[0][0] \
+ * (GLfloat)(t->globj->Image[0]->Width) * 256.0); \
+ v0 = (v[idx[0]].texcoord[0][1] \
+ * (GLfloat)(t->globj->Image[0]->Height) * 256.0); \
+ v1 = (v[idx[1]].texcoord[0][1] \
+ * (GLfloat)(t->globj->Image[0]->Height) * 256.0); \
+ v2 = (v[idx[2]].texcoord[0][1] \
+ * (GLfloat)(t->globj->Image[0]->Height) * 256.0); \
+\
+ w0 = (v[idx[0]].win[3]); \
+ w1 = (v[idx[1]].win[3]); \
+ w2 = (v[idx[2]].win[3]); \
+} while (0)
+
+#define SET_BASEUV() \
+do { \
+ if (u0 < u1) { \
+ if (u0 < u2) { \
+ baseu = u0; \
+ } else { \
+ baseu = u2; \
+ } \
+ } else { \
+ if (u1 < u2) { \
+ baseu = u1; \
+ } else { \
+ baseu = u2; \
+ } \
+ } \
+\
+ if (v0 < v1) { \
+ if (v0 < v2) { \
+ basev = v0; \
+ } else { \
+ basev = v2; \
+ } \
+ } else { \
+ if (v1 < v2) { \
+ basev = v1; \
+ } else { \
+ basev = v2; \
+ } \
+ } \
+} while (0)
+
+
+#define SET_RW() \
+do { \
+ /* GLfloat minW; \
+\
+ if (w0 < w1) { \
+ if (w0 < w2) { \
+ minW = w0; \
+ } else { \
+ minW = w2; \
+ } \
+ } else { \
+ if (w1 < w2) { \
+ minW = w1; \
+ } else { \
+ minW = w2; \
+ } \
+ } */ \
+\
+ rw0 = (512.0 * w0); \
+ rw1 = (512.0 * w1); \
+ rw2 = (512.0 * w2); \
+} while (0)
+
+#define SET_D() \
+do { \
+ GLfloat sxy, suv; \
+ int lev; \
+\
+ suv = (v[idx[0]].texcoord[0][0] - \
+ v[idx[2]].texcoord[0][0]) * \
+ (v[idx[1]].texcoord[0][1] - \
+ v[idx[2]].texcoord[0][1]) - \
+ (v[idx[1]].texcoord[0][0] - \
+ v[idx[2]].texcoord[0][0]) * \
+ (v[idx[0]].texcoord[0][1] - \
+ v[idx[2]].texcoord[0][2]); \
+\
+ sxy = (v[idx[0]].texcoord[0][0] - \
+ v[idx[2]].texcoord[0][0]) * \
+ (v[idx[1]].texcoord[0][1] - \
+ v[idx[2]].texcoord[0][1]) - \
+ (v[idx[1]].texcoord[0][0] - \
+ v[idx[2]].texcoord[0][0]) * \
+ (v[idx[0]].texcoord[0][1] - \
+ v[idx[2]].texcoord[0][2]); \
+\
+ if (sxy < 0) sxy *= -1.0; \
+ if (suv < 0) suv *= -1.0; \
+\
+ lev = *(int*)&suv - *(int *)&sxy; \
+ if (lev < 0) \
+ lev = 0; \
+ else \
+ lev >>=23; \
+ dstart = (lev << 27); \
+} while (0)
+
+#define SET_UVWD() \
+do { \
+ SET_BASEUV(); \
+ SET_RW(); \
+ SET_D(); \
+ ru0 = (((u0 - baseu) * rw0)); \
+ ru1 = (((u1 - baseu) * rw1)); \
+ ru2 = (((u2 - baseu) * rw2)); \
+ rv0 = (((v0 - basev) * rw0)); \
+ rv1 = (((v1 - basev) * rw1)); \
+ rv2 = (((v2 - basev) * rw2)); \
+\
+ while (baseu < 0) { baseu += (t->globj->Image[0]->Width << 8); } \
+ while (basev < 0) { basev += (t->globj->Image[0]->Height << 8); } \
+\
+ if (!(baseu & 0xFF)) \
+ { baseu = (baseu >> 8); } \
+ else \
+ { baseu = (baseu >> 8) + 1; } \
+\
+ if ((basev & 0x80) || !(basev & 0xFF)) \
+ { basev = (basev >> 8); } \
+ else \
+ { basev = (basev >> 8) - 1; } \
+\
+ rbaseu = (baseu) << (16 - t->globj->Image[0]->WidthLog2); \
+ rbasev = (basev) << (16 - t->globj->Image[0]->WidthLog2); \
+ deltuy = (((ru2 - ru0) / dy02)); \
+ deltvy = (((rv2 - rv0) / dy02)); \
+ rw0 *= (1024.0 * 512.0); \
+ rw1 *= (1024.0 * 512.0); \
+ rw2 *= (1024.0 * 512.0); \
+ deltwy = ((rw2 - rw0) / dy02); \
+ if (tmp) { \
+ deltux = ((ru1 - (dy01 * deltuy + ru0)) / tmp); \
+ deltvx = ((rv1 - (dy01 * deltvy + rv0)) / tmp); \
+ deltwx = ((rw1 - (dy01 * deltwy + rw0)) / tmp); \
+ } else { deltux = deltvx = deltwx = 0; } \
+ ustart = (deltuy * ydiff) + (ru0); \
+ vstart = (deltvy * ydiff) + (rv0); \
+ wstart = (deltwy * ydiff) + (rw0); \
+} while (0)
+
+#define SEND_UVWD() \
+do { \
+ DMAOUT((rbasev & 0xFFFF)); \
+ DMAOUT((0xa0000000 | (rbaseu & 0xFFFF))); \
+ DMAOUT(deltwx); \
+ DMAOUT(deltwy); \
+ DMAOUT(wstart); \
+ DMAOUT(deltdx); \
+ DMAOUT(deltvx); \
+ DMAOUT(deltux); \
+ DMAOUT(deltdy); \
+ DMAOUT(deltvy); \
+ DMAOUT(deltuy); \
+ DMAOUT(dstart); \
+ DMAOUT(vstart); \
+ DMAOUT(ustart); \
+} while (0)
+
+#define SEND_VERT() \
+do { \
+ DMAOUT(deltzx); \
+ DMAOUT(deltzy); \
+ DMAOUT(zstart); \
+ DMAOUT(delt12); \
+ DMAOUT(end12); \
+ DMAOUT(delt01); \
+ DMAOUT(end01); \
+ DMAOUT(delt02); \
+ DMAOUT(start02); \
+ DMAOUT(ystart); \
+ DMAOUT(y01y12); \
+} while (0)
+
+#define SEND_COL() \
+do { \
+ DMAOUT(deltgbx); \
+ DMAOUT(deltarx); \
+ DMAOUT(deltgby); \
+ DMAOUT(deltary); \
+ DMAOUT(gbstart); \
+ DMAOUT(arstart); \
+} while (0)
+
+/**** MACROS end ****/
+
+
+
+
+static void TAG(s3v_point)( s3vContextPtr vmesa,
+ const s3vVertex *_v0 )
+{
+}
+
+static void TAG(s3v_line)( s3vContextPtr vmesa,
+ const s3vVertex *_v0,
+ const s3vVertex *_v1 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+
+ LINE_VERT_VARS;
+#if (IND & S3V_RAST_FLAT_BIT)
+ LINE_FLAT_VARS;
+#else
+ LINE_GOURAUD_VARS;
+#endif
+#if (IND & S3V_RAST_CULL_BIT)
+ GLfloat cull;
+#endif
+
+ DEBUG(("*** s3v_line: "));
+#if (IND & S3V_RAST_CULL_BIT)
+ DEBUG(("cull "));
+#endif
+#if (IND & S3V_RAST_FLAT_BIT)
+ DEBUG(("flat "));
+#endif
+
+ DEBUG(("***\n"));
+
+#if 0
+ s3v_print_vertex(ctx, _v0);
+ s3v_print_vertex(ctx, _v1);
+#endif
+
+ s3v_translate_vertex( ctx, _v0, &v[0] );
+ s3v_translate_vertex( ctx, _v1, &v[1] );
+
+#if (IND & S3V_RAST_CULL_BIT)
+ /* FIXME: should we cull lines too? */
+#endif
+ (void)v; /* v[0]; v[1]; */
+
+ SORT_LINE_VERT();
+ SET_LINE_VERT();
+
+ SET_LINE_XY();
+ SET_LINE_DIR();
+ SET_LINE_Z();
+
+#if (IND & S3V_RAST_FLAT_BIT)
+ SET_LINE_FLAT_COL();
+#else
+ SET_LINE_GOURAUD_COL();
+#endif
+
+ DMAOUT_CHECK(3DLINE_GBD, 15);
+ SEND_LINE_COL();
+ DMAOUT(0);
+ SEND_LINE_VERT();
+ DMAFINISH();
+}
+
+static void TAG(s3v_triangle)( s3vContextPtr vmesa,
+ const s3vVertex *_v0,
+ const s3vVertex *_v1,
+ const s3vVertex *_v2 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+
+ VERT_VARS;
+#if (IND & S3v_RAST_FLAT_BIT)
+ FLAT_VARS;
+#else
+ GOURAUD_VARS;
+#endif
+#if (IND & S3V_RAST_TEX_BIT)
+ TEX_VARS;
+#endif
+#if (IND & S3V_RAST_CULL_BIT)
+ GLfloat cull;
+#endif
+
+ DEBUG(("*** s3v_triangle: "));
+#if (IND & S3V_RAST_CULL_BIT)
+ DEBUG(("cull "));
+#endif
+#if (IND & S3V_RAST_FLAT_BIT)
+ DEBUG(("flat "));
+#endif
+#if (IND & S3V_RAST_TEX_BIT)
+ DEBUG(("tex "));
+#endif
+
+DEBUG(("***\n"));
+
+#if 0
+ s3v_print_vertex(ctx, _v0);
+ s3v_print_vertex(ctx, _v1);
+ s3v_print_vertex(ctx, _v2);
+#endif
+
+ s3v_translate_vertex( ctx, _v0, &v[0] );
+ s3v_translate_vertex( ctx, _v1, &v[1] );
+ s3v_translate_vertex( ctx, _v2, &v[2] );
+
+#if (IND & S3V_RAST_CULL_BIT)
+ cull = vmesa->backface_sign *
+ ((v[1].win[0] - v[0].win[0]) * (v[0].win[1] - v[2].win[1]) +
+ (v[1].win[1] - v[0].win[1]) * (v[2].win[0] - v[0].win[0]));
+
+ if (cull < vmesa->cull_zero /* -0.02f */) return;
+#endif
+
+ (void)v; /* v[0]; v[1]; v[2]; */
+
+ SORT_VERT();
+ SET_VERT();
+
+ if (dy02 == 0) return;
+
+ SET_XY();
+ SET_DIR();
+ SET_Z();
+
+#if (IND & S3V_RAST_TEX_BIT)
+ SET_TEX_VERT();
+ SET_UVWD();
+#endif
+
+#if (IND & S3V_RAST_FLAT_BIT)
+ SET_FLAT_COL();
+#else
+ SET_GOURAUD_COL();
+#endif
+
+#if (IND & S3V_RAST_TEX_BIT)
+ DMAOUT_CHECK(3DTRI_BASEV, 31);
+ SEND_UVWD();
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#else
+ DMAOUT_CHECK(3DTRI_GBX, 17);
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#endif
+}
+
+static void TAG(s3v_quad)( s3vContextPtr vmesa,
+ const s3vVertex *_v0,
+ const s3vVertex *_v1,
+ const s3vVertex *_v2,
+ const s3vVertex *_v3 )
+{
+ GLcontext *ctx = vmesa->glCtx;
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+
+ SWvertex temp_v[4];
+ VERT_VARS;
+#if (IND & S3v_RAST_FLAT_BIT)
+ FLAT_VARS;
+#else
+ GOURAUD_VARS;
+#endif
+#if (IND & S3V_RAST_TEX_BIT)
+ TEX_VARS;
+#endif
+#if (IND & S3V_RAST_CULL_BIT)
+ GLfloat cull;
+#endif
+
+ DEBUG(("*** s3v_quad: "));
+#if (IND & S3V_RAST_CULL_BIT)
+ DEBUG(("cull "));
+ /* printf(""); */ /* speed trick */
+#endif
+#if (IND & S3V_RAST_FLAT_BIT)
+ DEBUG(("flat "));
+#endif
+#if (IND & S3V_RAST_TEX_BIT)
+ DEBUG(("tex "));
+#endif
+
+ DEBUG(("***\n"));
+
+#if 0
+ s3v_print_vertex(ctx, _v0);
+ s3v_print_vertex(ctx, _v1);
+ s3v_print_vertex(ctx, _v2);
+ s3v_print_vertex(ctx, _v3);
+#endif
+ s3v_translate_vertex( ctx, _v0, &temp_v[0] );
+ s3v_translate_vertex( ctx, _v1, &temp_v[1] );
+ s3v_translate_vertex( ctx, _v2, &temp_v[2] );
+ s3v_translate_vertex( ctx, _v3, &temp_v[3] );
+
+ /* FIRST TRI (0,1,2) */
+
+ /* ROMEO */
+ /* printf(""); */ /* speed trick (a) [turn on if (a) is return]*/
+
+ v[0] = temp_v[0];
+ v[1] = temp_v[1];
+ v[2] = temp_v[2];
+
+#if (IND & S3V_RAST_CULL_BIT)
+ cull = vmesa->backface_sign *
+ ((v[1].win[0] - v[0].win[0]) * (v[0].win[1] - v[2].win[1]) +
+ (v[1].win[1] - v[0].win[1]) * (v[2].win[0] - v[0].win[0]));
+
+ if (cull < vmesa->cull_zero /* -0.02f */) goto second; /* return; */ /* (a) */
+#endif
+
+#if 0
+ v[0] = temp_v[0];
+ v[1] = temp_v[1];
+ v[2] = temp_v[2];
+#else
+ (void) v;
+#endif
+ SORT_VERT();
+ SET_VERT();
+
+ if (dy02 == 0) goto second;
+
+ SET_XY();
+ SET_DIR();
+ SET_Z();
+
+#if (IND & S3V_RAST_TEX_BIT)
+ SET_TEX_VERT();
+ SET_UVWD();
+#endif
+
+#if (IND & S3V_RAST_FLAT_BIT)
+ SET_FLAT_COL();
+#else
+ SET_GOURAUD_COL();
+#endif
+
+#if (IND & S3V_RAST_TEX_BIT)
+ DMAOUT_CHECK(3DTRI_BASEV, 31);
+ SEND_UVWD();
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#else
+ DMAOUT_CHECK(3DTRI_GBX, 17);
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#endif
+
+ /* SECOND TRI (0,2,3) */
+
+second:
+ v[0] = temp_v[0];
+ v[1] = temp_v[2];
+ v[2] = temp_v[3];
+
+#if (IND & S3V_RAST_CULL_BIT)
+ cull = vmesa->backface_sign *
+ ((v[1].win[0] - v[0].win[0]) * (v[0].win[1] - v[2].win[1]) +
+ (v[1].win[1] - v[0].win[1]) * (v[2].win[0] - v[0].win[0]));
+
+ if (cull < /* -0.02f */ vmesa->cull_zero) return;
+#endif
+
+/* second: */
+
+ /* ROMEO */
+ /* printf(""); */ /* speed trick */
+
+ v[0] = temp_v[0];
+ v[1] = temp_v[2];
+ v[2] = temp_v[3];
+
+ SORT_VERT();
+ SET_VERT();
+
+ if (dy02 == 0) return;
+
+ SET_XY();
+ SET_DIR();
+ SET_Z();
+
+#if (IND & S3V_RAST_TEX_BIT)
+ SET_TEX_VERT();
+ SET_UVWD();
+#endif
+
+#if (IND & S3V_RAST_FLAT_BIT)
+ SET_FLAT_COL();
+#else
+ SET_GOURAUD_COL();
+#endif
+
+#if (IND & S3V_RAST_TEX_BIT)
+ DMAOUT_CHECK(3DTRI_BASEV, 31);
+ SEND_UVWD();
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#else
+ DMAOUT_CHECK(3DTRI_GBX, 17);
+ SEND_COL();
+ SEND_VERT();
+ DMAFINISH();
+#endif
+}
+
+static void TAG(s3v_init)(void)
+{
+ s3v_point_tab[IND] = TAG(s3v_point);
+ s3v_line_tab[IND] = TAG(s3v_line);
+ s3v_tri_tab[IND] = TAG(s3v_triangle);
+ s3v_quad_tab[IND] = TAG(s3v_quad);
+}
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/dri/s3v/s3v_vb.c b/src/mesa/drivers/dri/s3v/s3v_vb.c
new file mode 100644
index 0000000000..f8ca6d15ee
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_vb.c
@@ -0,0 +1,341 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "mem.h"
+#include "macros.h"
+#include "colormac.h"
+#include "mmath.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+#include "tnl/tnl.h"
+
+#include "s3v_context.h"
+#include "s3v_vb.h"
+#include "s3v_tris.h"
+
+#define S3V_XYZW_BIT 0x1
+#define S3V_RGBA_BIT 0x2
+#define S3V_TEX0_BIT 0x4
+#define S3V_PTEX_BIT 0x8
+#define S3V_FOG_BIT 0x10
+#define S3V_MAX_SETUP 0x20
+
+static struct {
+ void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+ interp_func interp;
+ copy_pv_func copy_pv;
+ GLboolean (*check_tex_sizes)( GLcontext *ctx );
+ GLuint vertex_size;
+ GLuint vertex_stride_shift;
+ GLuint vertex_format;
+} setup_tab[S3V_MAX_SETUP];
+
+
+/* Only one vertex format, atm, so no need to give them names:
+ */
+#define TINY_VERTEX_FORMAT 1
+#define NOTEX_VERTEX_FORMAT 0
+#define TEX0_VERTEX_FORMAT 0
+#define TEX1_VERTEX_FORMAT 0
+#define PROJ_TEX1_VERTEX_FORMAT 0
+#define TEX2_VERTEX_FORMAT 0
+#define TEX3_VERTEX_FORMAT 0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & S3V_XYZW_BIT)
+#define DO_RGBA (IND & S3V_RGBA_BIT)
+#define DO_SPEC 0
+#define DO_FOG (IND & S3V_FOG_BIT)
+#define DO_TEX0 (IND & S3V_TEX0_BIT)
+#define DO_TEX1 0
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & S3V_PTEX_BIT)
+
+#define VERTEX s3vVertex
+#define LOCALVARS /* s3vContextPtr vmesa = S3V_CONTEXT(ctx); */
+#define GET_VIEWPORT_MAT() 0 /* vmesa->hw_viewport */
+#define GET_TEXSOURCE(n) n
+#define GET_VERTEX_FORMAT() 0
+#define GET_VERTEX_STORE() S3V_CONTEXT(ctx)->verts
+#define GET_VERTEX_STRIDE_SHIFT() S3V_CONTEXT(ctx)->vertex_stride_shift
+#define INVALIDATE_STORED_VERTICES()
+#define GET_UBYTE_COLOR_STORE() &S3V_CONTEXT(ctx)->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &S3V_CONTEXT(ctx)->UbyteSecondaryColor
+
+#define HAVE_HW_VIEWPORT 1 /* FIXME */
+#define HAVE_HW_DIVIDE 1
+#define HAVE_RGBA_COLOR 0 /* we're BGRA */
+#define HAVE_TINY_VERTICES 1
+#define HAVE_NOTEX_VERTICES 1
+#define HAVE_TEX0_VERTICES 1
+#define HAVE_TEX1_VERTICES 0
+#define HAVE_TEX2_VERTICES 0
+#define HAVE_TEX3_VERTICES 0
+#define HAVE_PTEX_VERTICES 1
+
+/*
+#define SUBPIXEL_X -.5
+#define SUBPIXEL_Y -.5
+#define UNVIEWPORT_VARS GLfloat h = S3V_CONTEXT(ctx)->driDrawable->h
+#define UNVIEWPORT_X(x) x - SUBPIXEL_X
+#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y
+#define UNVIEWPORT_Z(z) z / vmesa->depth_scale
+*/
+
+#define PTEX_FALLBACK() /* never needed */
+
+#define IMPORT_QUALIFIER
+#define IMPORT_FLOAT_COLORS s3v_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS s3v_import_float_spec_colors
+
+#define INTERP_VERTEX setup_tab[S3V_CONTEXT(ctx)->SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[S3V_CONTEXT(ctx)->SetupIndex].copy_pv
+
+
+
+/***********************************************************************
+ * Generate pv-copying and translation functions *
+ ***********************************************************************/
+
+#define TAG(x) s3v_##x
+#include "tnl_dd/t_dd_vb.c"
+
+/***********************************************************************
+ * Generate vertex emit and interp functions *
+ ***********************************************************************/
+
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT|S3V_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT|S3V_TEX0_BIT|S3V_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_TEX0_BIT)
+#define TAG(x) x##_t0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_RGBA_BIT)
+#define TAG(x) x##_g
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_RGBA_BIT|S3V_TEX0_BIT)
+#define TAG(x) x##_gt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT|S3V_FOG_BIT)
+#define TAG(x) x##_wgf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT|S3V_FOG_BIT|S3V_TEX0_BIT)
+#define TAG(x) x##_wgft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_XYZW_BIT|S3V_RGBA_BIT|S3V_FOG_BIT|S3V_TEX0_BIT|S3V_PTEX_BIT)
+#define TAG(x) x##_wgfpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_FOG_BIT)
+#define TAG(x) x##_f
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_RGBA_BIT | S3V_FOG_BIT)
+#define TAG(x) x##_gf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (S3V_RGBA_BIT | S3V_FOG_BIT | S3V_TEX0_BIT)
+#define TAG(x) x##_gft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+static void init_setup_tab( void )
+{
+ init_wg(); /* pos + col */
+ init_wgt0(); /* pos + col + tex0 */
+ init_wgpt0(); /* pos + col + p-tex0 (?) */
+ init_t0(); /* tex0 */
+ init_g(); /* col */
+ init_gt0(); /* col + tex */
+ init_wgf();
+ init_wgft0();
+ init_wgfpt0();
+ init_f();
+ init_gf();
+ init_gft0();
+}
+
+
+#if 0
+void s3vPrintSetupFlags(char *msg, GLuint flags )
+{
+ fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+ msg,
+ (int)flags,
+ (flags & S3V_XYZW_BIT) ? " xyzw," : "",
+ (flags & S3V_RGBA_BIT) ? " rgba," : "",
+ (flags & S3V_SPEC_BIT) ? " spec," : "",
+ (flags & S3V_FOG_BIT) ? " fog," : "",
+ (flags & S3V_TEX0_BIT) ? " tex-0," : "",
+ (flags & S3V_TEX1_BIT) ? " tex-1," : "");
+}
+#endif
+
+
+void s3vCheckTexSizes( GLcontext *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+
+ if (!setup_tab[vmesa->SetupIndex].check_tex_sizes(ctx)) {
+
+ vmesa->SetupIndex |= (S3V_PTEX_BIT|S3V_RGBA_BIT);
+
+ if (1 || !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ tnl->Driver.Render.Interp = setup_tab[vmesa->SetupIndex].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[vmesa->SetupIndex].copy_pv;
+ }
+ }
+}
+
+void s3vBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ GLubyte *v = ((GLubyte *)vmesa->verts +
+ (start<<vmesa->vertex_stride_shift));
+ GLuint stride = 1<<vmesa->vertex_stride_shift;
+ GLuint ind = 0;
+
+ DEBUG(("*** s3vBuildVertices ***\n"));
+ DEBUG(("vmesa->SetupNewInputs = 0x%x\n", vmesa->SetupNewInputs));
+ DEBUG(("vmesa->SetupIndex = 0x%x\n", vmesa->SetupIndex));
+
+#if 1
+ setup_tab[vmesa->SetupIndex].emit( ctx, start, count, v, stride );
+#else
+ newinputs |= vmesa->SetupNewInputs;
+ vmesa->SetupNewInputs = 0;
+
+ DEBUG(("newinputs is 0x%x\n", newinputs));
+
+ if (!newinputs) {
+ DEBUG(("!newinputs\n"));
+ return;
+ }
+
+ if (newinputs & VERT_CLIP) {
+ setup_tab[vmesa->SetupIndex].emit( ctx, start, count, v, stride );
+ DEBUG(("newinputs & VERT_CLIP\n"));
+ return;
+ } /* else { */
+/* GLuint ind = 0; */
+
+ if (newinputs & VERT_RGBA) {
+ DEBUG(("newinputs & VERT_RGBA\n"));
+ ind |= S3V_RGBA_BIT;
+ }
+
+ if (newinputs & VERT_TEX0) {
+ DEBUG(("newinputs & VERT_TEX0\n"));
+ ind |= S3V_TEX0_BIT;
+ }
+
+ if (newinputs & VERT_FOG_COORD)
+ ind |= S3V_FOG_BIT;
+
+ if (vmesa->SetupIndex & S3V_PTEX_BIT)
+ ind = ~0;
+
+ ind &= vmesa->SetupIndex;
+
+ DEBUG(("vmesa->SetupIndex = 0x%x\n", vmesa->SetupIndex));
+ DEBUG(("ind = 0x%x\n", ind));
+ DEBUG(("ind & vmesa->SetupIndex = 0x%x\n", (ind & vmesa->SetupIndex)));
+
+ if (ind) {
+ setup_tab[ind].emit( ctx, start, count, v, stride );
+ }
+#endif
+}
+
+void s3vChooseVertexState( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT( ctx );
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ GLuint ind = S3V_XYZW_BIT | S3V_RGBA_BIT;
+
+ /* FIXME: will segv in tnl_dd/t_dd_vbtmp.h (line 196) on some demos */
+/*
+ if (ctx->Fog.Enabled)
+ ind |= S3V_FOG_BIT;
+*/
+
+
+ if (ctx->Texture._ReallyEnabled) {
+ _tnl_need_projected_coords( ctx, GL_FALSE );
+ ind |= S3V_TEX0_BIT;
+ } else {
+ _tnl_need_projected_coords( ctx, GL_TRUE );
+ }
+
+ vmesa->SetupIndex = ind;
+
+ if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+ tnl->Driver.Render.Interp = s3v_interp_extras;
+ tnl->Driver.Render.CopyPV = s3v_copy_pv_extras;
+ } else {
+ tnl->Driver.Render.Interp = setup_tab[ind].interp;
+ tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+ }
+}
+
+
+void s3vInitVB( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+ vmesa->verts = (char *)ALIGN_MALLOC(size * 4 * 16, 32);
+
+ {
+ static int firsttime = 1;
+ if (firsttime) {
+ init_setup_tab();
+ firsttime = 0;
+ vmesa->vertex_stride_shift = 6 /* 4 */; /* FIXME - only one vertex setup */
+ }
+ }
+}
+
+
+void s3vFreeVB( GLcontext *ctx )
+{
+ s3vContextPtr vmesa = S3V_CONTEXT(ctx);
+ if (vmesa->verts) {
+ ALIGN_FREE(vmesa->verts);
+ vmesa->verts = 0;
+ }
+
+ if (vmesa->UbyteSecondaryColor.Ptr) {
+ ALIGN_FREE(vmesa->UbyteSecondaryColor.Ptr);
+ vmesa->UbyteSecondaryColor.Ptr = 0;
+ }
+
+ if (vmesa->UbyteColor.Ptr) {
+ ALIGN_FREE(vmesa->UbyteColor.Ptr);
+ vmesa->UbyteColor.Ptr = 0;
+ }
+}
diff --git a/src/mesa/drivers/dri/s3v/s3v_vb.h b/src/mesa/drivers/dri/s3v/s3v_vb.h
new file mode 100644
index 0000000000..b35d804e62
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_vb.h
@@ -0,0 +1,39 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#ifndef S3VVB_INC
+#define S3VVB_INC
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+
+#define _S3V_NEW_VERTEX (_NEW_TEXTURE | \
+ _DD_NEW_TRI_UNFILLED | \
+ _DD_NEW_TRI_LIGHT_TWOSIDE)
+
+
+extern void s3vChooseVertexState( GLcontext *ctx );
+extern void s3vCheckTexSizes( GLcontext *ctx );
+extern void s3vBuildVertices( GLcontext *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint newinputs );
+
+
+extern void s3v_import_float_colors( GLcontext *ctx );
+extern void s3v_import_float_spec_colors( GLcontext *ctx );
+
+extern void s3v_translate_vertex( GLcontext *ctx,
+ const s3vVertex *src,
+ SWvertex *dst );
+
+extern void s3vInitVB( GLcontext *ctx );
+extern void s3vFreeVB( GLcontext *ctx );
+
+extern void s3v_print_vertex( GLcontext *ctx, const s3vVertex *v );
+#if 0
+extern void s3vPrintSetupFlags(char *msg, GLuint flags );
+#endif
+
+#endif
diff --git a/src/mesa/drivers/dri/s3v/s3v_xmesa.c b/src/mesa/drivers/dri/s3v/s3v_xmesa.c
new file mode 100644
index 0000000000..b012c1b9cc
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3v_xmesa.c
@@ -0,0 +1,326 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#include "s3v_context.h"
+#include "s3v_vb.h"
+#include "context.h"
+#include "mmath.h"
+#include "matrix.h"
+#include "s3v_dri.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "array_cache/acache.h"
+
+/* #define DEBUG(str) printf str */
+
+static GLboolean
+s3vInitDriver(__DRIscreenPrivate *sPriv)
+{
+ sPriv->private = (void *) s3vCreateScreen( sPriv );
+
+ if (!sPriv->private) {
+ s3vDestroyScreen( sPriv );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static void
+s3vDestroyContext(__DRIcontextPrivate *driContextPriv)
+{
+ s3vContextPtr vmesa = (s3vContextPtr)driContextPriv->driverPrivate;
+
+ if (vmesa) {
+ _swsetup_DestroyContext( vmesa->glCtx );
+ _tnl_DestroyContext( vmesa->glCtx );
+ _ac_DestroyContext( vmesa->glCtx );
+ _swrast_DestroyContext( vmesa->glCtx );
+
+ s3vFreeVB( vmesa->glCtx );
+
+ /* free the Mesa context */
+ vmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(vmesa->glCtx);
+
+ Xfree(vmesa);
+ driContextPriv->driverPrivate = NULL;
+ }
+}
+
+
+static GLboolean
+s3vCreateBuffer( Display *dpy,
+ __DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer(mesaVis,
+ GL_FALSE, /* software depth buffer? */
+ mesaVis->stencilBits > 0,
+ mesaVis->accumRedBits > 0,
+ mesaVis->alphaBits > 0
+ );
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+s3vDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+static void
+s3vSwapBuffers(Display *dpy, void *drawablePrivate)
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ __DRIscreenPrivate *sPriv;
+ GLcontext *ctx;
+ s3vContextPtr vmesa;
+ s3vScreenPtr s3vscrn;
+
+ vmesa = (s3vContextPtr) dPriv->driContextPriv->driverPrivate;
+ sPriv = vmesa->driScreen;
+ s3vscrn = vmesa->s3vScreen;
+ ctx = vmesa->glCtx;
+
+ DEBUG(("*** s3vSwapBuffers ***\n"));
+
+/* DMAFLUSH(); */
+
+ _mesa_swapbuffers( ctx );
+
+ vmesa = (s3vContextPtr) dPriv->driContextPriv->driverPrivate;
+/* driScrnPriv = vmesa->driScreen; */
+
+/* if (vmesa->EnabledFlags & S3V_BACK_BUFFER) */
+
+/* _mesa_swapbuffers( ctx ); */
+#if 1
+{
+ int x0, y0, x1, y1;
+/*
+ int nRect = dPriv->numClipRects;
+ XF86DRIClipRectPtr pRect = dPriv->pClipRects;
+
+ __DRIscreenPrivate *driScrnPriv = vmesa->driScreen;
+*/
+
+/*
+ DEBUG(("s3vSwapBuffers: S3V_BACK_BUFFER = 1 - nClip = %i\n", nRect));
+*/
+/* vmesa->drawOffset=vmesa->s3vScreen->backOffset; */
+
+ x0 = dPriv->x;
+ y0 = dPriv->y;
+
+ x1 = x0 + dPriv->w - 1;
+ y1 = y0 + dPriv->h - 1;
+
+ DMAOUT_CHECK(BITBLT_SRC_BASE, 15);
+ DMAOUT(vmesa->s3vScreen->backOffset);
+ DMAOUT(0); /* 0xc0000000 */
+ DMAOUT( ((x0 << 16) | x1) );
+ DMAOUT( ((y0 << 16) | y1) );
+ DMAOUT( (vmesa->DestStride << 16) | vmesa->SrcStride );
+ DMAOUT( (~(0)) );
+ DMAOUT( (~(0)) );
+ DMAOUT(0);
+ DMAOUT(0);
+ /* FIXME */
+ DMAOUT(0);
+ DMAOUT(0);
+ DMAOUT( (0x01 | /* Autoexecute */
+ 0x02 | /* clip */
+ 0x04 | /* 16 bit */
+ 0x20 | /* draw */
+ 0x400 | /* word alignment (bit 10=1) */
+ (0x2 << 11) | /* offset = 1 byte */
+ (0xCC << 17) | /* rop #204 */
+ (0x3 << 25)) ); /* l-r, t-b */
+ DMAOUT(vmesa->ScissorWH);
+ DMAOUT( /* 0 */ vmesa->SrcXY );
+ DMAOUT( (dPriv->x << 16) | dPriv->y );
+ DMAFINISH();
+
+ DMAFLUSH();
+
+ vmesa->restore_primitive = -1;
+
+}
+#endif
+}
+
+static GLboolean
+s3vMakeCurrent(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv)
+{
+ int x1,x2,y1,y2;
+ int cx, cy, cw, ch;
+ unsigned int src_stride, dest_stride;
+ int cl;
+
+ s3vContextPtr vmesa;
+ __DRIdrawablePrivate *dPriv = driDrawPriv;
+
+ DEBUG(("s3vMakeCurrent\n"));
+
+ DEBUG(("dPriv->x=%i y=%i w=%i h=%i\n", dPriv->x, dPriv->y,
+ dPriv->w, dPriv->h));
+
+ if (driContextPriv) {
+ GET_CURRENT_CONTEXT(ctx);
+ s3vContextPtr oldVirgeCtx = ctx ? S3V_CONTEXT(ctx) : NULL;
+ s3vContextPtr newVirgeCtx = (s3vContextPtr) driContextPriv->driverPrivate;
+
+ if ( newVirgeCtx != oldVirgeCtx ) {
+
+ newVirgeCtx->dirty = ~0;
+ cl = 1;
+ DEBUG(("newVirgeCtx != oldVirgeCtx\n"));
+/* s3vUpdateClipping(newVirgeCtx->glCtx ); */
+ }
+
+ if (newVirgeCtx->driDrawable != driDrawPriv) {
+ newVirgeCtx->driDrawable = driDrawPriv;
+ DEBUG(("driDrawable != driDrawPriv\n"));
+ s3vUpdateWindow ( newVirgeCtx->glCtx );
+ s3vUpdateViewportOffset( newVirgeCtx->glCtx );
+/* s3vUpdateClipping(newVirgeCtx->glCtx ); */
+ }
+/*
+ s3vUpdateWindow ( newVirgeCtx->glCtx );
+ s3vUpdateViewportOffset( newVirgeCtx->glCtx );
+*/
+
+/*
+ _mesa_make_current2( newVirgeCtx->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate );
+
+ _mesa_set_viewport(newVirgeCtx->glCtx, 0, 0,
+ newVirgeCtx->driDrawable->w,
+ newVirgeCtx->driDrawable->h);
+*/
+
+#if 0
+ newVirgeCtx->Window &= ~W_GIDMask;
+ newVirgeCtx->Window |= (driDrawPriv->index << 5);
+ CHECK_DMA_BUFFER(newVirgeCtx,1);
+ WRITE(newVirgeCtx->buf, S3VWindow, newVirgeCtx->Window);
+#endif
+
+
+
+ newVirgeCtx->new_state |= S3V_NEW_WINDOW; /* FIXME */
+
+ _mesa_make_current2( newVirgeCtx->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate );
+
+ if (!newVirgeCtx->glCtx->Viewport.Width) {
+ _mesa_set_viewport(newVirgeCtx->glCtx, 0, 0,
+ driDrawPriv->w, driDrawPriv->h);
+
+/* s3vUpdateClipping(newVirgeCtx->glCtx ); */
+ }
+
+/*
+ if (cl) {
+ s3vUpdateClipping(newVirgeCtx->glCtx );
+ cl =0;
+ }
+*/
+
+ newVirgeCtx->new_state |= S3V_NEW_CLIP;
+
+ if (1) {
+ cx = dPriv->x;
+ cw = dPriv->w;
+ cy = dPriv->y;
+ ch = dPriv->h;
+ }
+
+ x1 = y1 = 0;
+ x2 = cw-1;
+ y2 = ch-1;
+
+/* src_stride = vmesa->s3vScreen->w * vmesa->s3vScreen->cpp;
+ dest_stride = ((x2+31)&~31) * vmesa->s3vScreen->cpp; */
+ src_stride = vmesa->driScreen->fbWidth * 2;
+ dest_stride = ((x2+31)&~31) * 2;
+ } else {
+ _mesa_make_current( 0, 0 );
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+s3vUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+ return GL_TRUE;
+}
+
+static GLboolean
+s3vOpenFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+ return GL_TRUE;
+}
+
+static GLboolean
+s3vCloseFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+ return GL_TRUE;
+}
+
+
+static struct __DriverAPIRec s3vAPI = {
+ s3vInitDriver,
+ s3vDestroyScreen,
+ s3vCreateContext,
+ s3vDestroyContext,
+ s3vCreateBuffer,
+ s3vDestroyBuffer,
+ s3vSwapBuffers,
+ s3vMakeCurrent,
+ s3vUnbindContext,
+ s3vOpenFullScreen,
+ s3vCloseFullScreen
+};
+
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return: pointer to a __DRIscreenPrivate.
+ */
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp=NULL;
+
+ DEBUG(("__driCreateScreen: psp = %p\n", psp));
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &s3vAPI);
+ DEBUG(("__driCreateScreen: psp = %p\n", psp));
+ return (void *) psp;
+}
+
+void __driRegisterExtensions(void)
+{
+ /* No extensions */
+}
diff --git a/src/mesa/drivers/dri/s3v/s3virgetri.h b/src/mesa/drivers/dri/s3v/s3virgetri.h
new file mode 100644
index 0000000000..5519cfd741
--- /dev/null
+++ b/src/mesa/drivers/dri/s3v/s3virgetri.h
@@ -0,0 +1,383 @@
+/*
+ * Author: Max Lingua <sunmax@libero.it>
+ */
+
+#define LOCAL_VARS \
+ int vert0, vert1, vert2; \
+ GLfloat y0, y1, y2, ydiff; \
+ int iy0, iy1, iy2; \
+ int x0, x1, x2, z0, z1, z2; \
+ int dy01, dy02, dy12, dx01, dx02, dx12; \
+ int delt02, delt01, delt12, end01, end12, start02; \
+ int zstart, arstart, gbstart; \
+ int deltzy, deltzx, deltarx, deltgbx, deltary, deltgby; \
+ GLubyte (*colours)[4]; \
+ GLubyte (*scolours)[4]; \
+ static int tp = 0; \
+ int tmp, lr
+
+#define LOCAL_TEX_VARS \
+ int u0, u1, u2; \
+ GLfloat ru0, ru1, ru2; \
+ int v0, v1, v2; \
+ GLfloat rv0, rv1, rv2; \
+ GLfloat w0, w1, w2; \
+ GLfloat rw0, rw1, rw2; \
+ int baseu, basev; \
+ int d0, d1, d2; \
+ int deltdx, deltvx, deltux, deltdy, deltvy, deltuy; \
+ int deltwx, deltwy; \
+ int rbaseu, rbasev; \
+ int dstart, ustart, wstart, vstart; \
+ static int stmp = 0; \
+ s3virgeTextureObject_t *t
+
+#define CULL_BACKFACE() \
+ do { \
+ GLfloat *w0 = VB->Win.data[e0]; \
+ GLfloat *w1 = VB->Win.data[e1]; \
+ GLfloat *w2 = VB->Win.data[e2]; \
+ float cull; \
+ cull = ctx->backface_sign * ((w1[0] - w0[0]) * (w0[1] - w2[1]) + \
+ (w1[1] - w0[1]) * (w2[0] - w0[0])); \
+ if (cull < 0) \
+ return; \
+ } while (0)
+
+#define SORT_VERTICES() \
+ do { \
+ y0 = VB->Win.data[e0][1]; \
+ y1 = VB->Win.data[e1][1]; \
+ y2 = VB->Win.data[e2][1]; \
+ if (y1 > y0) { \
+ if (y2 > y0) { \
+ vert0 = e0; \
+ if (y1 > y2) { vert2 = e1; vert1 = e2; } else { vert2 = e2; vert1 = e1; } \
+ } else { vert0 = e2; vert1 = e0; vert2 = e1; } \
+ } else { \
+ if (y2 > y0) { vert0 = e1; vert1 = e0; vert2 = e2; } else { \
+ vert2 = e0; \
+ if (y2 > y1) { vert0 = e1; vert1 = e2; } else { vert0 = e2; vert1 = e1; } \
+ } \
+ } \
+ } while (0)
+
+#define SET_VARIABLES() \
+ do { \
+ iy0 = y0 = ((s3virgeDB->height - (VB->Win.data[vert0][1]))); \
+ iy1 = y1 = ((s3virgeDB->height - (VB->Win.data[vert1][1]))); \
+ iy2 = y2 = ((s3virgeDB->height - (VB->Win.data[vert2][1]))); \
+ if (iy0 == iy2) { return; } \
+ ydiff = y0 - (float)iy0; \
+ x0 = ((VB->Win.data[vert0][0]) * 1024.0 * 1024.0); \
+ x1 = ((VB->Win.data[vert1][0]) * 1024.0 * 1024.0); \
+ x2 = ((VB->Win.data[vert2][0]) * 1024.0 * 1024.0); \
+ z0 = (VB->Win.data[vert0][2] * 1024.0 * 32.0); \
+ z1 = (VB->Win.data[vert1][2] * 1024.0 * 32.0); \
+ z2 = (VB->Win.data[vert2][2] * 1024.0 * 32.0); \
+ dx12 = x2 - x1; \
+ dy12 = iy1 - iy2; \
+ dx01 = x1 - x0; \
+ dy01 = iy0 - iy1; \
+ dx02 = x2 - x0; \
+ dy02 = iy0 - iy2; \
+ delt12 = delt02 = delt01 = 0; \
+ } while (0)
+
+#define SET_TEX_VARIABLES() \
+ do { \
+ t = ((s3virgeTextureObject_t *)ctx->Texture.Unit[0].Current->DriverData); \
+ deltwx = deltwy = wstart = deltdx = deltdy = dstart = 0; \
+ u0 = (VB->TexCoordPtr[0]->data[vert0][0] * (GLfloat)(t->tObj->Image[0]->Width) * 256.0); \
+ u1 = (VB->TexCoordPtr[0]->data[vert1][0] * (GLfloat)(t->tObj->Image[0]->Width) * 256.0); \
+ u2 = (VB->TexCoordPtr[0]->data[vert2][0] * (GLfloat)(t->tObj->Image[0]->Width) * 256.0); \
+ v0 = (VB->TexCoordPtr[0]->data[vert0][1] * (GLfloat)(t->tObj->Image[0]->Height) * 256.0); \
+ v1 = (VB->TexCoordPtr[0]->data[vert1][1] * (GLfloat)(t->tObj->Image[0]->Height) * 256.0); \
+ v2 = (VB->TexCoordPtr[0]->data[vert2][1] * (GLfloat)(t->tObj->Image[0]->Height) * 256.0); \
+ w0 = (VB->Win.data[vert0][3]); \
+ w1 = (VB->Win.data[vert1][3]); \
+ w2 = (VB->Win.data[vert2][3]); \
+ } while (0)
+
+#define FLATSHADE_COLORS() \
+ do { \
+ GLubyte *col = &(colours[pv][0]); \
+ deltarx = deltary = deltgbx = deltgby = 0; \
+ gbstart = (((col[1]) << 23) | ((col[2]) << 7)); \
+ arstart = (((col[3]) << 23) | ((col[0]) << 7)); \
+ } while (0)
+
+#define GOURAUD_COLORS() \
+ do { \
+ int ctmp, ctmp2, ctmp3, ctmp4; \
+ GLubyte *col0, *col1, *col2; \
+ col0 = &(colours[vert0][0]); \
+ col1 = &(colours[vert1][0]); \
+ col2 = &(colours[vert2][0]); \
+ ctmp = ((col2[3] - col0[3]) << 7) / dy02; \
+ ctmp2 = ((col2[0] - col0[0]) << 7) / dy02; \
+ deltary = ((ctmp << 16) & 0xFFFF0000) | (ctmp2 & 0xFFFF); \
+ ctmp3 = ((col2[1] - col0[1]) << 7) / dy02; \
+ ctmp4 = ((col2[2] - col0[2]) << 7) / dy02; \
+ deltgby = ((ctmp3 << 16) & 0xFFFF0000) | (ctmp4 & 0xFFFF); \
+ gbstart = (((int)((ydiff * ctmp3) + (col0[1] << 7)) << 16) & 0x7FFF0000) | \
+ ((int)((ydiff * ctmp4) + (col0[2] << 7)) & 0x7FFF); \
+ arstart = (((int)((ydiff * ctmp) + (col0[3] << 7)) << 16) & 0x7FFF0000) | \
+ ((int)((ydiff * ctmp2) + (col0[0] << 7)) & 0x7FFF); \
+ if (tmp) { \
+ int ax, rx, gx, bx; \
+ ax = ((col1[3] << 7) - (dy01 * ctmp + (col0[3] << 7))) / tmp; \
+ rx = ((col1[0] << 7) - (dy01 * ctmp2 + (col0[0] << 7))) / tmp; \
+ gx = ((col1[1] << 7) - (dy01 * ctmp3 + (col0[1] << 7))) / tmp; \
+ bx = ((col1[2] << 7) - (dy01 * ctmp4 + (col0[2] << 7))) / tmp; \
+ deltarx = ((ax << 16) & 0xFFFF0000) | (rx & 0xFFFF); \
+ deltgbx = ((gx << 16) & 0xFFFF0000) | (bx & 0xFFFF); \
+ } else { \
+ deltgbx = deltarx = 0; \
+ } \
+ } while (0)
+
+#define SET_XY() \
+ do { \
+ delt02 = dx02 / dy02; \
+ if (dy12) delt12 = dx12 / dy12; \
+ if (dy01) delt01 = dx01 / dy01; \
+ start02 = (ydiff * delt02) + x0; \
+ end01 = (ydiff * delt01) + x0; \
+ end12 = ((y1 - (GLfloat)iy1) * delt12) + x1; \
+ } while (0)
+
+#define SET_DIR() \
+ do { \
+ tmp = x1 - (dy01 * delt02 + x0); \
+ if (tmp > 0) { \
+ lr = 0x80000000; \
+ } else { \
+ tmp *= -1; \
+ lr = 0; \
+ } \
+ tmp >>= 20; \
+ } while (0)
+
+#define SET_Z() \
+ do { \
+ deltzy = (z2 - z0) / dy02; \
+ if (tmp) { \
+ deltzx = (z1 - (dy01 * deltzy + z0)) / tmp; \
+ } else { deltzx = 0; } \
+ zstart = (deltzy * ydiff) + z0; \
+ } while (0)
+
+#define SET_BASEUV() \
+ do { \
+ if (u0 < u1) { \
+ if (u0 < u2) { \
+ baseu = u0; \
+ } else { \
+ baseu = u2; \
+ } \
+ } else { \
+ if (u1 < u2) { \
+ baseu = u1; \
+ } else { \
+ baseu = u2; \
+ } \
+ } \
+ if (v0 < v1) { \
+ if (v0 < v2) { \
+ basev = v0; \
+ } else { \
+ basev = v2; \
+ } \
+ } else { \
+ if (v1 < v2) { \
+ basev = v1; \
+ } else { \
+ basev = v2; \
+ } \
+ } \
+ } while (0)
+
+#define SET_RW() \
+ do { \
+ /* GLfloat minW; \
+ if (w0 < w1) { \
+ if (w0 < w2) { \
+ minW = w0; \
+ } else { \
+ minW = w2; \
+ } \
+ } else { \
+ if (w1 < w2) { \
+ minW = w1; \
+ } else { \
+ minW = w2; \
+ } \
+ } */ \
+ rw0 = (512.0 * w0); \
+ rw1 = (512.0 * w1); \
+ rw2 = (512.0 * w2); \
+ } while (0)
+
+
+#define SET_D() \
+ do { \
+ GLfloat sxy, suv; \
+ int lev; \
+ suv = (VB->TexCoordPtr[0]->data[vert0][0] - \
+ VB->TexCoordPtr[0]->data[vert2][0]) * \
+ (VB->TexCoordPtr[0]->data[vert1][1] - \
+ VB->TexCoordPtr[0]->data[vert2][1]) - \
+ (VB->TexCoordPtr[0]->data[vert1][0] - \
+ VB->TexCoordPtr[0]->data[vert2][0]) * \
+ (VB->TexCoordPtr[0]->data[vert0][1] - \
+ VB->TexCoordPtr[0]->data[vert2][2]); \
+ sxy = (VB->Win.data[vert0][0] - \
+ VB->Win.data[vert2][0]) * \
+ (VB->Win.data[vert1][1] - \
+ VB->Win.data[vert2][1]) - \
+ (VB->Win.data[vert1][0] - \
+ VB->Win.data[vert2][0]) * \
+ (VB->Win.data[vert0][1] - \
+ VB->Win.data[vert2][2]); \
+ if (sxy < 0) sxy *= -1.0; \
+ if (suv < 0) suv *= -1.0; \
+ lev = *(int*)&suv - *(int *)&sxy; \
+ if (lev < 0) \
+ lev = 0; \
+ else \
+ lev >>=23; \
+ dstart = (lev << 27); \
+ } while (0)
+
+
+
+#define SET_UVWD() \
+ do { \
+ SET_BASEUV(); \
+ SET_RW(); \
+ SET_D(); \
+ ru0 = (((u0 - baseu) * rw0)); \
+ ru1 = (((u1 - baseu) * rw1)); \
+ ru2 = (((u2 - baseu) * rw2)); \
+ rv0 = (((v0 - basev) * rw0)); \
+ rv1 = (((v1 - basev) * rw1)); \
+ rv2 = (((v2 - basev) * rw2)); \
+ while (baseu < 0) { baseu += (t->tObj->Image[0]->Width << 8); } \
+ while (basev < 0) { basev += (t->tObj->Image[0]->Height << 8); } \
+ if (!(baseu & 0xFF)) { baseu = (baseu >> 8); } else { baseu = (baseu >> 8) + 1; } \
+ if ((basev & 0x80) || !(basev & 0xFF)) { basev = (basev >> 8); } else { basev = (basev >> 8) - 1; } \
+ rbaseu = (baseu) << (16 - t->widthLog2); \
+ rbasev = (basev) << (16 - t->widthLog2); \
+ deltuy = (((ru2 - ru0) / dy02)); \
+ deltvy = (((rv2 - rv0) / dy02)); \
+ rw0 *= (1024.0 * 512.0); \
+ rw1 *= (1024.0 * 512.0); \
+ rw2 *= (1024.0 * 512.0); \
+ deltwy = ((rw2 - rw0) / dy02); \
+ if (tmp) { \
+ deltux = ((ru1 - (dy01 * deltuy + ru0)) / tmp); \
+ deltvx = ((rv1 - (dy01 * deltvy + rv0)) / tmp); \
+ deltwx = ((rw1 - (dy01 * deltwy + rw0)) / tmp); \
+ } else { deltux = deltvx = deltwx = 0; } \
+ ustart = (deltuy * ydiff) + (ru0); \
+ vstart = (deltvy * ydiff) + (rv0); \
+ wstart = (deltwy * ydiff) + (rw0); \
+ } while (0)
+
+
+#define SEND_COLORS() \
+ do { \
+ WAITFIFOEMPTY(6); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_GBX), deltgbx); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_ARX), deltarx); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_GBY), deltgby); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_ARY), deltary); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_GS_BS), gbstart); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_AS_RS), arstart); \
+ } while (0)
+
+#define SEND_VERTICES() \
+ do { \
+ WAITFIFOEMPTY(6); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_ZSTART), zstart); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_ZXD), deltzx); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_ZYD), deltzy); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXDELTA12), delt12); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXEND12), end12); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXDELTA01), delt01); \
+ WAITFIFOEMPTY(5); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXEND01), end01); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXDELTA02), delt02); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TXSTART02), start02); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TYS), iy0); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_TY01_Y12), \
+ ((((iy0 - iy1) & 0x7FF) << 16) | \
+ ((iy1 - iy2) & 0x7FF) | lr)); \
+ } while (0)
+
+#define SEND_UVWD() \
+ do { \
+ WAITFIFOEMPTY(7); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_BASEV), (rbasev & 0xFFFF)); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_BASEU), (0xa0000000 | (rbaseu & 0xFFFF))); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_WXD), deltwx); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_WYD), deltwy); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_WSTART), wstart); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_DXD), deltdx); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_VXD), deltvx); \
+ WAITFIFOEMPTY(7); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_UXD), deltux); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_DYD), deltdy); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_VYD), deltvy); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_UYD), deltuy); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_DSTART), dstart); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_VSTART), vstart); \
+ OUTREG( (S3VIRGE_3DTRI_REG | S3VIRGE_3DTRI_USTART), ustart); \
+ } while (0)
+
+#define DMA_SEND_UVWD() \
+ do { \
+ DMAOUT((rbasev & 0xFFFF)); \
+ DMAOUT((0xa0000000 | (rbaseu & 0xFFFF))); \
+ DMAOUT(deltwx); \
+ DMAOUT(deltwy); \
+ DMAOUT(wstart); \
+ DMAOUT(deltdx); \
+ DMAOUT(deltvx); \
+ DMAOUT(deltux); \
+ DMAOUT(deltdy); \
+ DMAOUT(deltvy); \
+ DMAOUT(deltuy); \
+ DMAOUT(dstart); \
+ DMAOUT(vstart); \
+ DMAOUT(ustart); \
+ } while (0)
+
+
+#define DMA_SEND_COLORS() \
+ do { \
+ DMAOUT(deltgbx); \
+ DMAOUT(deltarx); \
+ DMAOUT(deltgby); \
+ DMAOUT(deltary); \
+ DMAOUT(gbstart); \
+ DMAOUT(arstart); \
+ } while (0)
+
+#define DMA_SEND_VERTICES() \
+ do { \
+ DMAOUT(deltzx); \
+ DMAOUT(deltzy); \
+ DMAOUT(zstart); \
+ DMAOUT(delt12); \
+ DMAOUT(end12); \
+ DMAOUT(delt01); \
+ DMAOUT(end01); \
+ DMAOUT(delt02); \
+ DMAOUT(start02); \
+ DMAOUT(iy0); \
+ DMAOUT(((((iy0 - iy1) & 0x7FF) << 16) | \
+ ((iy1 - iy2) & 0x7FF) | lr)); \
+ } while (0)
+