diff options
author | Adam Jackson <ajax@freedesktop.org> | 2004-12-16 19:26:23 +0000 |
---|---|---|
committer | Adam Jackson <ajax@freedesktop.org> | 2004-12-16 19:26:23 +0000 |
commit | c403bcb8a7be437976d5adce41189fff1e7f690f (patch) | |
tree | fcd53d612d1725eb2609c49031e04da54a52370b /src/mesa/drivers/dri/s3v | |
parent | 8662c5d98febd8efaf5f8ee47d34c7fcfd597ce3 (diff) |
Import s3virge and trident drivers. Not functional yet; no Makefile, no DRI-aware DDX.
Diffstat (limited to 'src/mesa/drivers/dri/s3v')
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) + |