@@ -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; | |||
} |
@@ -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_ */ |
@@ -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; | |||
} |
@@ -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); | |||
} |
@@ -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 | |||
} |
@@ -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__ */ |
@@ -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_ */ |
@@ -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 */ |
@@ -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 */ | |||
}; |
@@ -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); | |||
} |
@@ -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; |
@@ -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; | |||
} | |||
} |
@@ -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; */ | |||
} |
@@ -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 ); | |||
} |
@@ -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 |
@@ -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 | |||
} |
@@ -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 | |||
} |
@@ -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; | |||
} |
@@ -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) */ |
@@ -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 |
@@ -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; | |||
} | |||
} |
@@ -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 |
@@ -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 */ | |||
} |
@@ -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) | |||
@@ -0,0 +1,419 @@ | |||
/* | |||
* Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. | |||
* | |||
* Permission to use, copy, modify, distribute, and sell this software and its | |||
* documentation for any purpose is hereby granted without fee, provided that | |||
* the above copyright notice appear in all copies and that both that | |||
* copyright notice and this permission notice appear in supporting | |||
* documentation, and that the name of Alan Hourihane not be used in | |||
* advertising or publicity pertaining to distribution of the software without | |||
* specific, written prior permission. Alan Hourihane makes no representations | |||
* about the suitability of this software for any purpose. It is provided | |||
* "as is" without express or implied warranty. | |||
* | |||
* ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
* EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
* PERFORMANCE OF THIS SOFTWARE. | |||
* | |||
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> | |||
* | |||
* Trident CyberBladeXP driver. | |||
* | |||
*/ | |||
#include "trident_dri.h" | |||
#include "trident_context.h" | |||
#include "trident_lock.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" | |||
static const struct gl_pipeline_stage *trident_pipeline[] = { | |||
&_tnl_vertex_transform_stage, | |||
&_tnl_normal_transform_stage, | |||
&_tnl_lighting_stage, | |||
&_tnl_texgen_stage, | |||
&_tnl_texture_transform_stage, | |||
&_tnl_render_stage, | |||
0, | |||
}; | |||
GLboolean tridentCreateContext( Display *dpy, const __GLcontextModes *glVisual, | |||
__DRIcontextPrivate *driContextPriv, | |||
void *sharedContextPrivate) | |||
{ | |||
GLcontext *ctx, *shareCtx; | |||
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; | |||
tridentContextPtr tmesa; | |||
tridentScreenPtr tridentscrn; | |||
#if 0 | |||
drm_trident_sarea_t *saPriv=(drm_trident_sarea_t *)(((char*)sPriv->pSAREA)+ | |||
sizeof(XF86DRISAREARec)); | |||
#endif | |||
tmesa = (tridentContextPtr) CALLOC( sizeof(*tmesa) ); | |||
if ( !tmesa ) return GL_FALSE; | |||
/* Allocate the Mesa context */ | |||
if (sharedContextPrivate) | |||
shareCtx = ((tridentContextPtr) sharedContextPrivate)->glCtx; | |||
else | |||
shareCtx = NULL; | |||
tmesa->glCtx = _mesa_create_context(glVisual, shareCtx, tmesa, GL_TRUE); | |||
if (!tmesa->glCtx) { | |||
FREE(tmesa); | |||
return GL_FALSE; | |||
} | |||
tmesa->display = dpy; | |||
tmesa->driContext = driContextPriv; | |||
tmesa->driScreen = sPriv; | |||
tmesa->driDrawable = NULL; /* Set by XMesaMakeCurrent */ | |||
tmesa->hHWContext = driContextPriv->hHWContext; | |||
tmesa->driHwLock = &sPriv->pSAREA->lock; | |||
tmesa->driFd = sPriv->fd; | |||
#if 0 | |||
tmesa->sarea = saPriv; | |||
#endif | |||
tridentscrn = tmesa->tridentScreen = (tridentScreenPtr)(sPriv->private); | |||
ctx = tmesa->glCtx; | |||
ctx->Const.MaxTextureLevels = 13; /* 4K by 4K? Is that right? */ | |||
ctx->Const.MaxTextureUnits = 1; /* Permedia 3 */ | |||
ctx->Const.MinLineWidth = 0.0; | |||
ctx->Const.MaxLineWidth = 255.0; | |||
ctx->Const.MinLineWidthAA = 0.0; | |||
ctx->Const.MaxLineWidthAA = 65536.0; | |||
ctx->Const.MinPointSize = 0.0; | |||
ctx->Const.MaxPointSize = 255.0; | |||
ctx->Const.MinPointSizeAA = 0.5; /* 4x4 quality mode */ | |||
ctx->Const.MaxPointSizeAA = 16.0; | |||
ctx->Const.PointSizeGranularity = 0.25; | |||
#if 0 | |||
tmesa->texHeap = mmInit( 0, tmesa->tridentScreen->textureSize ); | |||
make_empty_list(&tmesa->TexObjList); | |||
make_empty_list(&tmesa->SwappedOut); | |||
tmesa->CurrentTexObj[0] = 0; | |||
tmesa->CurrentTexObj[1] = 0; /* Permedia 3, second texture */ | |||
tmesa->RenderIndex = ~0; | |||
#endif | |||
/* Initialize the software rasterizer and helper modules. | |||
*/ | |||
_swrast_CreateContext( ctx ); | |||
_ac_CreateContext( ctx ); | |||
_tnl_CreateContext( ctx ); | |||
_swsetup_CreateContext( ctx ); | |||
/* Install the customized pipeline: | |||
*/ | |||
_tnl_destroy_pipeline( ctx ); | |||
_tnl_install_pipeline( ctx, trident_pipeline ); | |||
/* Configure swrast to match hardware characteristics: | |||
*/ | |||
_swrast_allow_pixel_fog( ctx, GL_FALSE ); | |||
_swrast_allow_vertex_fog( ctx, GL_TRUE ); | |||
tridentInitVB( ctx ); | |||
tridentDDInitExtensions( ctx ); | |||
tridentDDInitDriverFuncs( ctx ); | |||
tridentDDInitStateFuncs( ctx ); | |||
#if 0 | |||
tridentDDInitSpanFuncs( ctx ); | |||
tridentDDInitTextureFuncs( ctx ); | |||
#endif | |||
tridentDDInitTriFuncs( ctx ); | |||
tridentDDInitState( tmesa ); | |||
driContextPriv->driverPrivate = (void *)tmesa; | |||
UNLOCK_HARDWARE(tmesa); | |||
return GL_TRUE; | |||
} | |||
static void | |||
tridentDestroyContext(__DRIcontextPrivate *driContextPriv) | |||
{ | |||
tridentContextPtr tmesa = (tridentContextPtr)driContextPriv->driverPrivate; | |||
if (tmesa) { | |||
_swsetup_DestroyContext( tmesa->glCtx ); | |||
_tnl_DestroyContext( tmesa->glCtx ); | |||
_ac_DestroyContext( tmesa->glCtx ); | |||
_swrast_DestroyContext( tmesa->glCtx ); | |||
/* free the Mesa context */ | |||
tmesa->glCtx->DriverCtx = NULL; | |||
_mesa_destroy_context(tmesa->glCtx); | |||
Xfree(tmesa); | |||
driContextPriv->driverPrivate = NULL; | |||
} | |||
} | |||
static GLboolean | |||
tridentCreateBuffer( 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 | |||
tridentDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) | |||
{ | |||
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate)); | |||
} | |||
static void | |||
tridentSwapBuffers(Display *dpy, void *drawablePrivate) | |||
{ | |||
__DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate; | |||
(void) dpy; | |||
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { | |||
tridentContextPtr tmesa; | |||
GLcontext *ctx; | |||
tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate; | |||
ctx = tmesa->glCtx; | |||
if (ctx->Visual.doubleBufferMode) { | |||
_mesa_swapbuffers( ctx ); /* flush pending rendering comands */ | |||
tridentCopyBuffer( dPriv ); | |||
} | |||
} | |||
else { | |||
/* XXX this shouldn't be an error but we can't handle it for now */ | |||
_mesa_problem(NULL, "tridentSwapBuffers: drawable has no context!\n"); | |||
} | |||
} | |||
static GLboolean | |||
tridentMakeCurrent(__DRIcontextPrivate *driContextPriv, | |||
__DRIdrawablePrivate *driDrawPriv, | |||
__DRIdrawablePrivate *driReadPriv) | |||
{ | |||
if (driContextPriv) { | |||
GET_CURRENT_CONTEXT(ctx); | |||
tridentContextPtr oldCtx = ctx ? TRIDENT_CONTEXT(ctx) : NULL; | |||
tridentContextPtr newCtx = (tridentContextPtr) driContextPriv->driverPrivate; | |||
if ( newCtx != oldCtx ) { | |||
newCtx->dirty = ~0; | |||
} | |||
if (newCtx->driDrawable != driDrawPriv) { | |||
newCtx->driDrawable = driDrawPriv; | |||
#if 0 | |||
tridentUpdateWindow ( newCtx->glCtx ); | |||
tridentUpdateViewportOffset( newCtx->glCtx ); | |||
#endif | |||
} | |||
newCtx->drawOffset = newCtx->tridentScreen->backOffset; | |||
newCtx->drawPitch = newCtx->tridentScreen->backPitch; | |||
_mesa_make_current2( newCtx->glCtx, | |||
(GLframebuffer *) driDrawPriv->driverPrivate, | |||
(GLframebuffer *) driReadPriv->driverPrivate ); | |||
if (!newCtx->glCtx->Viewport.Width) { | |||
_mesa_set_viewport(newCtx->glCtx, 0, 0, | |||
driDrawPriv->w, driDrawPriv->h); | |||
} | |||
} else { | |||
_mesa_make_current( 0, 0 ); | |||
} | |||
return GL_TRUE; | |||
} | |||
static GLboolean | |||
tridentUnbindContext( __DRIcontextPrivate *driContextPriv ) | |||
{ | |||
return GL_TRUE; | |||
} | |||
static GLboolean | |||
tridentOpenFullScreen(__DRIcontextPrivate *driContextPriv) | |||
{ | |||
return GL_TRUE; | |||
} | |||
static GLboolean | |||
tridentCloseFullScreen(__DRIcontextPrivate *driContextPriv) | |||
{ | |||
return GL_TRUE; | |||
} | |||
tridentScreenPtr tridentCreateScreen( __DRIscreenPrivate *sPriv ) | |||
{ | |||
TRIDENTDRIPtr tDRIPriv = (TRIDENTDRIPtr)sPriv->pDevPriv; | |||
tridentScreenPtr tridentScreen; | |||
int i; | |||
#if 0 | |||
/* Check the DRI version */ | |||
{ | |||
int major, minor, patch; | |||
if ( XF86DRIQueryVersion( sPriv->display, &major, &minor, &patch ) ) { | |||
if ( major != 3 || minor != 1 || patch < 0 ) { | |||
__driUtilMessage( "r128 DRI driver expected DRI version 3.1.x but got version %d.%d.%d", major, minor, patch ); | |||
return GL_FALSE; | |||
} | |||
} | |||
} | |||
/* Check that the DDX driver version is compatible */ | |||
if ( sPriv->ddxMajor != 4 || | |||
sPriv->ddxMinor != 0 || | |||
sPriv->ddxPatch < 0 ) { | |||
__driUtilMessage( "r128 DRI driver expected DDX driver version 4.0.x but got version %d.%d.%d", sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch ); | |||
return GL_FALSE; | |||
} | |||
/* Check that the DRM driver version is compatible */ | |||
if ( sPriv->drmMajor != 2 || | |||
sPriv->drmMinor != 1 || | |||
sPriv->drmPatch < 0 ) { | |||
__driUtilMessage( "r128 DRI driver expected DRM driver version 2.1.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); | |||
return GL_FALSE; | |||
} | |||
#endif | |||
/* Allocate the private area */ | |||
tridentScreen = (tridentScreenPtr) CALLOC( sizeof(*tridentScreen) ); | |||
if ( !tridentScreen ) return NULL; | |||
tridentScreen->driScreen = sPriv; | |||
tridentScreen->frontOffset = tDRIPriv->frontOffset; | |||
tridentScreen->backOffset = tDRIPriv->backOffset; | |||
tridentScreen->depthOffset = tDRIPriv->depthOffset; | |||
tridentScreen->frontPitch = tDRIPriv->frontPitch; | |||
tridentScreen->backPitch = tDRIPriv->backPitch; | |||
tridentScreen->depthPitch = tDRIPriv->depthPitch; | |||
tridentScreen->width = tDRIPriv->width; | |||
tridentScreen->height = tDRIPriv->height; | |||
printf("%d %d\n",tridentScreen->width,tridentScreen->height); | |||
printf("%d %d\n",tridentScreen->frontPitch,tridentScreen->backPitch); | |||
printf("offset 0x%x 0x%x\n",tridentScreen->backOffset,tridentScreen->depthOffset); | |||
tridentScreen->mmio.handle = tDRIPriv->regs; | |||
tridentScreen->mmio.size = 0x20000; | |||
if (drmMap(sPriv->fd, | |||
tridentScreen->mmio.handle, tridentScreen->mmio.size, | |||
(drmAddressPtr)&tridentScreen->mmio.map)) { | |||
FREE(tridentScreen); | |||
return GL_FALSE; | |||
} | |||
printf("MAPPED at 0x%x\n",tridentScreen->mmio.map); | |||
return tridentScreen; | |||
} | |||
/* Destroy the device specific screen private data struct. | |||
*/ | |||
void tridentDestroyScreen( __DRIscreenPrivate *sPriv ) | |||
{ | |||
tridentScreenPtr tridentScreen = (tridentScreenPtr)sPriv->private; | |||
FREE(tridentScreen); | |||
} | |||
static GLboolean | |||
tridentInitDriver(__DRIscreenPrivate *sPriv) | |||
{ | |||
sPriv->private = (void *) tridentCreateScreen( sPriv ); | |||
if (!sPriv->private) { | |||
tridentDestroyScreen( sPriv ); | |||
return GL_FALSE; | |||
} | |||
return GL_TRUE; | |||
} | |||
static struct __DriverAPIRec tridentAPI = { | |||
tridentInitDriver, | |||
tridentDestroyScreen, | |||
tridentCreateContext, | |||
tridentDestroyContext, | |||
tridentCreateBuffer, | |||
tridentDestroyBuffer, | |||
tridentSwapBuffers, | |||
tridentMakeCurrent, | |||
tridentUnbindContext, | |||
tridentOpenFullScreen, | |||
tridentCloseFullScreen | |||
}; | |||
/* | |||
* 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; | |||
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &tridentAPI); | |||
return (void *) psp; | |||
} | |||
void __driRegisterExtensions(void) | |||
{ | |||
/* No extensions */ | |||
} |
@@ -0,0 +1,209 @@ | |||
/* | |||
* Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. | |||
* | |||
* Permission to use, copy, modify, distribute, and sell this software and its | |||
* documentation for any purpose is hereby granted without fee, provided that | |||
* the above copyright notice appear in all copies and that both that | |||
* copyright notice and this permission notice appear in supporting | |||
* documentation, and that the name of Alan Hourihane not be used in | |||
* advertising or publicity pertaining to distribution of the software without | |||
* specific, written prior permission. Alan Hourihane makes no representations | |||
* about the suitability of this software for any purpose. It is provided | |||
* "as is" without express or implied warranty. | |||
* | |||
* ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
* EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
* PERFORMANCE OF THIS SOFTWARE. | |||
* | |||
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> | |||
* | |||
* Trident CyberBladeXP driver. | |||
* | |||
*/ | |||
#ifndef _TRIDENT_CONTEXT_H_ | |||
#define _TRIDENT_CONTEXT_H_ | |||
#include "compiler.h" | |||
#include "dri_util.h" | |||
#include "macros.h" | |||
#include "mtypes.h" | |||
#include "drm.h" | |||
#include "mm.h" | |||
#define SUBPIXEL_X (0.0F) | |||
#define SUBPIXEL_Y (0.125F) | |||
#define _TRIDENT_NEW_VERTEX (_NEW_TEXTURE | \ | |||
_DD_NEW_TRI_UNFILLED | \ | |||
_DD_NEW_TRI_LIGHT_TWOSIDE) | |||
#define TRIDENT_FALLBACK_TEXTURE 0x01 | |||
#define TRIDENT_FALLBACK_DRAW_BUFFER 0x02 | |||
#define TRIDENT_NEW_CLIP 0x01 | |||
#define TRIDENT_UPLOAD_COMMAND_D 0x00000001 | |||
#define TRIDENT_UPLOAD_CONTEXT 0x04000000 | |||
#define TRIDENT_UPLOAD_CLIPRECTS 0x80000000 | |||
#define TAG(x) trident##x | |||
#include "tnl_dd/t_dd_vertex.h" | |||
#undef TAG | |||
struct trident_context; | |||
typedef struct trident_context tridentContextRec; | |||
typedef struct trident_context *tridentContextPtr; | |||
typedef void (*trident_quad_func)( tridentContextPtr, | |||
const tridentVertex *, | |||
const tridentVertex *, | |||
const tridentVertex *, | |||
const tridentVertex * ); | |||
typedef void (*trident_tri_func)( tridentContextPtr, | |||
const tridentVertex *, | |||
const tridentVertex *, | |||
const tridentVertex * ); | |||
typedef void (*trident_line_func)( tridentContextPtr, | |||
const tridentVertex *, | |||
const tridentVertex * ); | |||
typedef void (*trident_point_func)( tridentContextPtr, | |||
const tridentVertex * ); | |||
typedef struct { | |||
drmHandle handle; /* Handle to the DRM region */ | |||
drmSize size; /* Size of the DRM region */ | |||
unsigned char *map; /* Mapping of the DRM region */ | |||
} tridentRegionRec, *tridentRegionPtr; | |||
typedef struct { | |||
__DRIscreenPrivate *driScreen; /* Back pointer to DRI screen */ | |||
drmBufMapPtr buffers; | |||
unsigned int frontOffset; | |||
unsigned int frontPitch; | |||
unsigned int backOffset; | |||
unsigned int backPitch; | |||
unsigned int depthOffset; | |||
unsigned int depthPitch; | |||
unsigned int width; | |||
unsigned int height; | |||
unsigned int cpp; | |||
#if 0 | |||
unsigned int sarea_priv_offset; | |||
#endif | |||
tridentRegionRec mmio; | |||
} tridentScreenRec, *tridentScreenPtr; | |||
struct trident_context { | |||
GLcontext *glCtx; /* Mesa context */ | |||
__DRIcontextPrivate *driContext; | |||
__DRIscreenPrivate *driScreen; | |||
__DRIdrawablePrivate *driDrawable; | |||
GLuint new_gl_state; | |||
GLuint new_state; | |||
GLuint dirty; | |||
#if 0 | |||
drm_trident_sarea_t *sarea; | |||
#endif | |||
/* 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 */ | |||
int lastStamp; /* mirror driDrawable->lastStamp */ | |||
drmContext hHWContext; | |||
drmLock *driHwLock; | |||
int driFd; | |||
tridentScreenPtr tridentScreen; /* Screen private DRI data */ | |||
/* Visual, drawable, cliprect and scissor information | |||
*/ | |||
GLenum DrawBuffer; | |||
GLint drawOffset, drawPitch; | |||
GLint drawX, drawY; /* origin of drawable in draw buffer */ | |||
GLint readOffset, readPitch; | |||
GLuint numClipRects; /* Cliprects for the draw buffer */ | |||
XF86DRIClipRectPtr pClipRects; | |||
GLint scissor; | |||
XF86DRIClipRectRec ScissorRect; /* Current software scissor */ | |||
GLuint Fallback; | |||
GLuint RenderIndex; | |||
GLuint SetupNewInputs; | |||
GLuint SetupIndex; | |||
GLfloat hw_viewport[16]; | |||
GLfloat depth_scale; | |||
GLuint vertex_format; | |||
GLuint vertex_size; | |||
GLuint vertex_stride_shift; | |||
char *verts; | |||
GLint tmu_source[2]; | |||
GLuint hw_primitive; | |||
GLenum render_primitive; | |||
trident_point_func draw_point; | |||
trident_line_func draw_line; | |||
trident_tri_func draw_tri; | |||
trident_quad_func draw_quad; | |||
#if 0 | |||
gammaTextureObjectPtr CurrentTexObj[2]; | |||
struct gamma_texture_object_t TexObjList; | |||
struct gamma_texture_object_t SwappedOut; | |||
GLenum TexEnvImageFmt[2]; | |||
memHeap_t *texHeap; | |||
int lastSwap; | |||
int texAge; | |||
int ctxAge; | |||
int dirtyAge; | |||
int lastStamp; | |||
#endif | |||
/* Chip state */ | |||
int commandD; | |||
/* Context State */ | |||
int ClearColor; | |||
}; | |||
void tridentDDInitExtensions( GLcontext *ctx ); | |||
void tridentDDInitDriverFuncs( GLcontext *ctx ); | |||
void tridentDDInitSpanFuncs( GLcontext *ctx ); | |||
void tridentDDInitState( tridentContextPtr tmesa ); | |||
void tridentInitHW( tridentContextPtr tmesa ); | |||
void tridentDDInitStateFuncs( GLcontext *ctx ); | |||
void tridentDDInitTextureFuncs( GLcontext *ctx ); | |||
void tridentDDInitTriFuncs( GLcontext *ctx ); | |||
extern void tridentBuildVertices( GLcontext *ctx, | |||
GLuint start, | |||
GLuint count, | |||
GLuint newinputs ); | |||
#define TRIDENT_CONTEXT(ctx) ((tridentContextPtr)(ctx->DriverCtx)) | |||
#endif /* _TRIDENT_CONTEXT_H_ */ |
@@ -0,0 +1,127 @@ | |||
/* | |||
* Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. | |||
* | |||
* Permission to use, copy, modify, distribute, and sell this software and its | |||
* documentation for any purpose is hereby granted without fee, provided that | |||
* the above copyright notice appear in all copies and that both that | |||
* copyright notice and this permission notice appear in supporting | |||
* documentation, and that the name of Alan Hourihane not be used in | |||
* advertising or publicity pertaining to distribution of the software without | |||
* specific, written prior permission. Alan Hourihane makes no representations | |||
* about the suitability of this software for any purpose. It is provided | |||
* "as is" without express or implied warranty. | |||
* | |||
* ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
* EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
* PERFORMANCE OF THIS SOFTWARE. | |||
* | |||
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> | |||
* | |||
* Trident CyberBladeXP driver. | |||
* | |||
*/ | |||
#include "trident_context.h" | |||
#include "trident_lock.h" | |||
#if defined(USE_X86_ASM) | |||
#include "X86/common_x86_asm.h" | |||
#endif | |||
#include "swrast/swrast.h" | |||
#include "context.h" | |||
#define TRIDENT_DATE "20020318" | |||
/* Return the width and height of the current color buffer. | |||
*/ | |||
static void tridentDDGetBufferSize( GLframebuffer *framebuffer, | |||
GLuint *width, GLuint *height ) | |||
{ | |||
GET_CURRENT_CONTEXT(ctx); | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
LOCK_HARDWARE(tmesa); | |||
*width = tmesa->driDrawable->w; | |||
*height = tmesa->driDrawable->h; | |||
UNLOCK_HARDWARE(tmesa); | |||
} | |||
/* Return various strings for glGetString(). | |||
*/ | |||
static const GLubyte *tridentDDGetString( GLcontext *ctx, GLenum name ) | |||
{ | |||
static char buffer[128]; | |||
switch ( name ) { | |||
case GL_VENDOR: | |||
return (GLubyte *)"Alan Hourihane"; | |||
case GL_RENDERER: | |||
sprintf( buffer, "Mesa DRI Trident " TRIDENT_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 tridentDDInitExtensions( GLcontext *ctx ) | |||
{ | |||
/* None... */ | |||
} | |||
/* Initialize the driver's misc functions. | |||
*/ | |||
void tridentDDInitDriverFuncs( GLcontext *ctx ) | |||
{ | |||
ctx->Driver.GetBufferSize = tridentDDGetBufferSize; | |||
ctx->Driver.GetString = tridentDDGetString; | |||
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; | |||
} |
@@ -0,0 +1,552 @@ | |||
/* | |||
* Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. | |||
* | |||
* Permission to use, copy, modify, distribute, and sell this software and its | |||
* documentation for any purpose is hereby granted without fee, provided that | |||
* the above copyright notice appear in all copies and that both that | |||
* copyright notice and this permission notice appear in supporting | |||
* documentation, and that the name of Alan Hourihane not be used in | |||
* advertising or publicity pertaining to distribution of the software without | |||
* specific, written prior permission. Alan Hourihane makes no representations | |||
* about the suitability of this software for any purpose. It is provided | |||
* "as is" without express or implied warranty. | |||
* | |||
* ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
* EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
* PERFORMANCE OF THIS SOFTWARE. | |||
* | |||
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> | |||
* | |||
* Trident CyberBladeXP driver. | |||
* | |||
*/ | |||
#include "trident_context.h" | |||
#include "trident_lock.h" | |||
#include "swrast/swrast.h" | |||
#define TRIDENTPACKCOLOR332(r, g, b) \ | |||
(((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6)) | |||
#define TRIDENTPACKCOLOR1555(r, g, b, a) \ | |||
((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ | |||
((a) ? 0x8000 : 0)) | |||
#define TRIDENTPACKCOLOR565(r, g, b) \ | |||
((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) | |||
#define TRIDENTPACKCOLOR888(r, g, b) \ | |||
(((r) << 16) | ((g) << 8) | (b)) | |||
#define TRIDENTPACKCOLOR8888(r, g, b, a) \ | |||
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) | |||
#define TRIDENTPACKCOLOR4444(r, g, b, a) \ | |||
((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) | |||
static __inline__ GLuint tridentPackColor( GLuint cpp, | |||
GLubyte r, GLubyte g, | |||
GLubyte b, GLubyte a ) | |||
{ | |||
switch ( cpp ) { | |||
case 2: | |||
return TRIDENTPACKCOLOR565( r, g, b ); | |||
case 4: | |||
return TRIDENTPACKCOLOR8888( r, g, b, a ); | |||
default: | |||
return 0; | |||
} | |||
} | |||
void tridentUploadHwStateLocked( tridentContextPtr tmesa ) | |||
{ | |||
unsigned char *MMIO = tmesa->tridentScreen->mmio.map; | |||
#if 0 | |||
ATISAREAPrivPtr sarea = tmesa->sarea; | |||
trident_context_regs_t *regs = &(sarea->ContextState); | |||
#endif | |||
if ( tmesa->dirty & TRIDENT_UPLOAD_COMMAND_D ) { | |||
MMIO_OUT32(MMIO, 0x00281C, tmesa->commandD ); | |||
tmesa->dirty &= ~TRIDENT_UPLOAD_COMMAND_D; | |||
} | |||
if ( tmesa->dirty & TRIDENT_UPLOAD_CLIPRECTS ) { | |||
/* XXX FIX ME ! */ | |||
MMIO_OUT32(MMIO, 0x002C80 , 0x20008000 | tmesa->tridentScreen->height ); | |||
MMIO_OUT32(MMIO, 0x002C84 , 0x20000000 | tmesa->tridentScreen->width ); | |||
tmesa->dirty &= ~TRIDENT_UPLOAD_CLIPRECTS; | |||
} | |||
tmesa->dirty = 0; | |||
} | |||
/* Copy the back color buffer to the front color buffer. | |||
*/ | |||
void tridentCopyBuffer( const __DRIdrawablePrivate *dPriv ) | |||
{ | |||
unsigned char *MMIO; | |||
tridentContextPtr tmesa; | |||
GLint nbox, i, ret; | |||
int busy; | |||
XF86DRIClipRectPtr pbox; | |||
assert(dPriv); | |||
assert(dPriv->driContextPriv); | |||
assert(dPriv->driContextPriv->driverPrivate); | |||
tmesa = (tridentContextPtr) dPriv->driContextPriv->driverPrivate; | |||
MMIO = tmesa->tridentScreen->mmio.map; | |||
LOCK_HARDWARE( tmesa ); | |||
/* use front buffer cliprects */ | |||
nbox = dPriv->numClipRects; | |||
pbox = dPriv->pClipRects; | |||
for ( i = 0 ; i < nbox ; i++ ) { | |||
#if 0 | |||
GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox ); | |||
XF86DRIClipRectPtr b = tmesa->sarea->boxes; | |||
GLint n = 0; | |||
for ( ; i < nr ; i++ ) { | |||
*b++ = pbox[i]; | |||
n++; | |||
} | |||
tmesa->sarea->nbox = n; | |||
#endif | |||
MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4); | |||
MMIO_OUT32(MMIO, 0x2154, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4); | |||
MMIO_OUT8(MMIO, 0x2127, 0xCC); /* Copy Rop */ | |||
MMIO_OUT32(MMIO, 0x2128, 0x4); /* scr2scr */ | |||
MMIO_OUT32(MMIO, 0x2138, (pbox->x1 << 16) | pbox->y1); | |||
MMIO_OUT32(MMIO, 0x213C, (pbox->x1 << 16) | pbox->y1); | |||
MMIO_OUT32(MMIO, 0x2140, (pbox->x2 - pbox->x1) << 16 | (pbox->y2 - pbox->y1) ); | |||
MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ | |||
#define GE_BUSY 0x80 | |||
for (;;) { | |||
busy = MMIO_IN8(MMIO, 0x2120); | |||
if ( !(busy & GE_BUSY) ) | |||
break; | |||
} | |||
} | |||
UNLOCK_HARDWARE( tmesa ); | |||
#if 0 | |||
tmesa->dirty |= (MACH64_UPLOAD_CONTEXT | | |||
MACH64_UPLOAD_MISC | | |||
MACH64_UPLOAD_CLIPRECTS); | |||
#endif | |||
} | |||
static void tridentDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all, | |||
GLint cx, GLint cy, GLint cw, GLint ch ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
unsigned char *MMIO = tmesa->tridentScreen->mmio.map; | |||
__DRIdrawablePrivate *dPriv = tmesa->driDrawable; | |||
int busy; | |||
GLuint flags = 0; | |||
GLint i; | |||
GLint ret; | |||
#define DRM_TRIDENT_FRONT 0x01 | |||
#define DRM_TRIDENT_BACK 0x02 | |||
#define DRM_TRIDENT_DEPTH 0x04 | |||
if ( tmesa->new_state ) | |||
tridentDDUpdateHWState( ctx ); | |||
if ( mask & DD_FRONT_LEFT_BIT ) { | |||
flags |= DRM_TRIDENT_FRONT; | |||
mask &= ~DD_FRONT_LEFT_BIT; | |||
} | |||
if ( mask & DD_BACK_LEFT_BIT ) { | |||
flags |= DRM_TRIDENT_BACK; | |||
mask &= ~DD_BACK_LEFT_BIT; | |||
} | |||
if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) { | |||
flags |= DRM_TRIDENT_DEPTH; | |||
mask &= ~DD_DEPTH_BIT; | |||
} | |||
LOCK_HARDWARE(tmesa); | |||
if ( flags ) { | |||
cx += tmesa->drawX; | |||
cy += tmesa->drawY; | |||
/* HACK!!! | |||
*/ | |||
if ( tmesa->dirty & ~TRIDENT_UPLOAD_CLIPRECTS ) { | |||
tridentUploadHwStateLocked( tmesa ); | |||
} | |||
for ( i = 0 ; i < tmesa->numClipRects ; i++ ) { | |||
#if 0 | |||
int nr = MIN2( i + TRIDENT_NR_SAREA_CLIPRECTS, tmesa->numClipRects ); | |||
XF86DRIClipRectPtr box = tmesa->pClipRects; | |||
XF86DRIClipRectPtr b = tmesa->sarea->boxes; | |||
GLint n = 0; | |||
if ( !all ) { | |||
for ( ; i < nr ; i++ ) { | |||
GLint x = box[i].x1; | |||
GLint y = box[i].y1; | |||
GLint w = box[i].x2 - x; | |||
GLint h = box[i].y2 - y; | |||
if ( x < cx ) w -= cx - x, x = cx; | |||
if ( y < cy ) h -= cy - y, y = cy; | |||
if ( x + w > cx + cw ) w = cx + cw - x; | |||
if ( y + h > cy + ch ) h = cy + ch - y; | |||
if ( w <= 0 ) continue; | |||
if ( h <= 0 ) continue; | |||
b->x1 = x; | |||
b->y1 = y; | |||
b->x2 = x + w; | |||
b->y2 = y + h; | |||
b++; | |||
n++; | |||
} | |||
} else { | |||
for ( ; i < nr ; i++ ) { | |||
*b++ = box[i]; | |||
n++; | |||
} | |||
} | |||
tmesa->sarea->nbox = n; | |||
#endif | |||
if (flags & DRM_TRIDENT_BACK) { | |||
MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->backPitch << 20 | tmesa->tridentScreen->backOffset>>4); | |||
MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ | |||
MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); | |||
MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ | |||
MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); | |||
MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); | |||
MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ | |||
#define GE_BUSY 0x80 | |||
for (;;) { | |||
busy = MMIO_IN8(MMIO, 0x2120); | |||
if ( !(busy & GE_BUSY) ) | |||
break; | |||
} | |||
} | |||
if (flags & DRM_TRIDENT_DEPTH) { | |||
MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->depthPitch << 20 | tmesa->tridentScreen->depthOffset>>4); | |||
MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ | |||
MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); | |||
MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ | |||
MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); | |||
MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); | |||
MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ | |||
#define GE_BUSY 0x80 | |||
for (;;) { | |||
busy = MMIO_IN8(MMIO, 0x2120); | |||
if ( !(busy & GE_BUSY) ) | |||
break; | |||
} | |||
} | |||
MMIO_OUT32(MMIO, 0x2150, tmesa->tridentScreen->frontPitch << 20 | tmesa->tridentScreen->frontOffset>>4); | |||
if (flags & DRM_TRIDENT_FRONT) { | |||
MMIO_OUT8(MMIO, 0x2127, 0xF0); /* Pat Rop */ | |||
MMIO_OUT32(MMIO, 0x2158, tmesa->ClearColor); | |||
MMIO_OUT32(MMIO, 0x2128, 0x4000); /* solidfill */ | |||
MMIO_OUT32(MMIO, 0x2138, cx << 16 | cy); | |||
MMIO_OUT32(MMIO, 0x2140, cw << 16 | ch); | |||
MMIO_OUT8(MMIO, 0x2124, 0x01); /* BLT */ | |||
#define GE_BUSY 0x80 | |||
for (;;) { | |||
busy = MMIO_IN8(MMIO, 0x2120); | |||
if ( !(busy & GE_BUSY) ) | |||
break; | |||
} | |||
} | |||
} | |||
#if 0 | |||
tmesa->dirty |= (TRIDENT_UPLOAD_CONTEXT | | |||
TRIDENT_UPLOAD_MISC | | |||
TRIDENT_UPLOAD_CLIPRECTS); | |||
#endif | |||
} | |||
UNLOCK_HARDWARE(tmesa); | |||
if ( mask ) | |||
_swrast_Clear( ctx, mask, all, cx, cy, cw, ch ); | |||
} | |||
static void tridentDDShadeModel( GLcontext *ctx, GLenum mode ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
GLuint s = tmesa->commandD; | |||
#define TRIDENT_FLAT_SHADE 0x000000E0 | |||
#define TRIDENT_FLAT_SHADE_VERTEX_C 0x00000060 | |||
#define TRIDENT_FLAT_SHADE_GOURAUD 0x00000080 | |||
s &= ~TRIDENT_FLAT_SHADE; | |||
switch ( mode ) { | |||
case GL_FLAT: | |||
s |= TRIDENT_FLAT_SHADE_VERTEX_C; | |||
break; | |||
case GL_SMOOTH: | |||
s |= TRIDENT_FLAT_SHADE_GOURAUD; | |||
break; | |||
default: | |||
return; | |||
} | |||
if ( tmesa->commandD != s ) { | |||
tmesa->commandD = s; | |||
tmesa->dirty |= TRIDENT_UPLOAD_COMMAND_D; | |||
} | |||
} | |||
void tridentCalcViewport( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
const GLfloat *v = ctx->Viewport._WindowMap.m; | |||
GLfloat *m = tmesa->hw_viewport; | |||
/* See also trident_translate_vertex. | |||
*/ | |||
m[MAT_SX] = v[MAT_SX]; | |||
m[MAT_TX] = v[MAT_TX] + tmesa->drawX + SUBPIXEL_X; | |||
m[MAT_SY] = - v[MAT_SY]; | |||
m[MAT_TY] = - v[MAT_TY] + tmesa->driDrawable->h + tmesa->drawY + SUBPIXEL_Y; | |||
#if 0 | |||
m[MAT_SZ] = v[MAT_SZ] * tmesa->depth_scale; | |||
m[MAT_TZ] = v[MAT_TZ] * tmesa->depth_scale; | |||
#else | |||
m[MAT_SZ] = v[MAT_SZ]; | |||
m[MAT_TZ] = v[MAT_TZ]; | |||
#endif | |||
tmesa->SetupNewInputs = ~0; | |||
} | |||
static void tridentDDViewport( GLcontext *ctx, | |||
GLint x, GLint y, | |||
GLsizei width, GLsizei height ) | |||
{ | |||
tridentCalcViewport( ctx ); | |||
} | |||
static void tridentDDDepthRange( GLcontext *ctx, | |||
GLclampd nearval, GLclampd farval ) | |||
{ | |||
tridentCalcViewport( ctx ); | |||
} | |||
void tridentSetCliprects( tridentContextPtr tmesa, GLenum mode ) | |||
{ | |||
__DRIdrawablePrivate *dPriv = tmesa->driDrawable; | |||
switch ( mode ) { | |||
case GL_FRONT_LEFT: | |||
if (dPriv->numClipRects == 0) { | |||
static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0}; | |||
tmesa->numClipRects = 1; | |||
tmesa->pClipRects = &zeroareacliprect; | |||
} else { | |||
tmesa->numClipRects = dPriv->numClipRects; | |||
tmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; | |||
} | |||
tmesa->drawX = dPriv->x; | |||
tmesa->drawY = dPriv->y; | |||
break; | |||
case GL_BACK_LEFT: | |||
if ( dPriv->numBackClipRects == 0 ) { | |||
if (dPriv->numClipRects == 0) { | |||
static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0}; | |||
tmesa->numClipRects = 1; | |||
tmesa->pClipRects = &zeroareacliprect; | |||
} else { | |||
tmesa->numClipRects = dPriv->numClipRects; | |||
tmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects; | |||
tmesa->drawX = dPriv->x; | |||
tmesa->drawY = dPriv->y; | |||
} | |||
} | |||
else { | |||
tmesa->numClipRects = dPriv->numBackClipRects; | |||
tmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects; | |||
tmesa->drawX = dPriv->backX; | |||
tmesa->drawY = dPriv->backY; | |||
} | |||
break; | |||
default: | |||
return; | |||
} | |||
#if 0 | |||
tmesa->dirty |= TRIDENT_UPLOAD_CLIPRECTS; | |||
#endif | |||
} | |||
static GLboolean tridentDDSetDrawBuffer( GLcontext *ctx, GLenum mode ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
int found = GL_TRUE; | |||
if ( tmesa->DrawBuffer != mode ) { | |||
tmesa->DrawBuffer = mode; | |||
switch ( mode ) { | |||
case GL_FRONT_LEFT: | |||
tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE ); | |||
tmesa->drawOffset = tmesa->tridentScreen->frontOffset; | |||
tmesa->drawPitch = tmesa->tridentScreen->frontPitch; | |||
tridentSetCliprects( tmesa, GL_FRONT_LEFT ); | |||
break; | |||
case GL_BACK_LEFT: | |||
tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_FALSE ); | |||
tmesa->drawOffset = tmesa->tridentScreen->backOffset; | |||
tmesa->drawPitch = tmesa->tridentScreen->backPitch; | |||
tridentSetCliprects( tmesa, GL_BACK_LEFT ); | |||
break; | |||
default: | |||
tridentFallback( tmesa, TRIDENT_FALLBACK_DRAW_BUFFER, GL_TRUE ); | |||
found = GL_FALSE; | |||
break; | |||
} | |||
#if 0 | |||
tmesa->setup.dst_off_pitch = (((tmesa->drawPitch/8) << 22) | | |||
(tmesa->drawOffset >> 3)); | |||
tmesa->dirty |= MACH64_UPLOAD_DST_OFF_PITCH | MACH64_UPLOAD_CONTEXT; | |||
#endif | |||
} | |||
return found; | |||
} | |||
static void tridentDDClearColor( GLcontext *ctx, | |||
const GLchan color[4] ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
tmesa->ClearColor = tridentPackColor( tmesa->tridentScreen->cpp, | |||
color[0], color[1], | |||
color[2], color[3] ); | |||
} | |||
void tridentDDUpdateState( 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 ); | |||
TRIDENT_CONTEXT(ctx)->new_gl_state |= new_state; | |||
} | |||
/* Initialize the context's hardware state. | |||
*/ | |||
void tridentDDInitState( tridentContextPtr tmesa ) | |||
{ | |||
tmesa->new_state = 0; | |||
switch ( tmesa->glCtx->Visual.depthBits ) { | |||
case 16: | |||
tmesa->depth_scale = 1.0 / (GLfloat)0xffff; | |||
break; | |||
case 24: | |||
tmesa->depth_scale = 1.0 / (GLfloat)0xffffff; | |||
break; | |||
} | |||
} | |||
void tridentDDUpdateHWState( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
int new_state = tmesa->new_state; | |||
if ( new_state ) | |||
{ | |||
tmesa->new_state = 0; | |||
#if 0 | |||
/* Update the various parts of the context's state. | |||
*/ | |||
if ( new_state & GAMMA_NEW_ALPHA ) | |||
tridentUpdateAlphaMode( ctx ); | |||
if ( new_state & GAMMA_NEW_DEPTH ) | |||
tridentUpdateZMode( ctx ); | |||
if ( new_state & GAMMA_NEW_FOG ) | |||
gammaUpdateFogAttrib( ctx ); | |||
if ( new_state & GAMMA_NEW_CLIP ) | |||
gammaUpdateClipping( ctx ); | |||
if ( new_state & GAMMA_NEW_POLYGON ) | |||
gammaUpdatePolygon( ctx ); | |||
if ( new_state & GAMMA_NEW_CULL ) | |||
gammaUpdateCull( ctx ); | |||
if ( new_state & GAMMA_NEW_MASKS ) | |||
gammaUpdateMasks( ctx ); | |||
if ( new_state & GAMMA_NEW_STIPPLE ) | |||
gammaUpdateStipple( ctx ); | |||
#endif | |||
} | |||
/* HACK ! */ | |||
#if 0 | |||
gammaEmitHwState( tmesa ); | |||
#endif | |||
} | |||
/* Initialize the driver's state functions. | |||
*/ | |||
void tridentDDInitStateFuncs( GLcontext *ctx ) | |||
{ | |||
ctx->Driver.UpdateState = tridentDDUpdateState; | |||
ctx->Driver.Clear = tridentDDClear; | |||
ctx->Driver.DepthRange = tridentDDDepthRange; | |||
ctx->Driver.ShadeModel = tridentDDShadeModel; | |||
ctx->Driver.Viewport = tridentDDViewport; | |||
/* 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; | |||
} |
@@ -0,0 +1,435 @@ | |||
/* | |||
* Copyright 2002 by Alan Hourihane, Sychdyn, North Wales, UK. | |||
* | |||
* Permission to use, copy, modify, distribute, and sell this software and its | |||
* documentation for any purpose is hereby granted without fee, provided that | |||
* the above copyright notice appear in all copies and that both that | |||
* copyright notice and this permission notice appear in supporting | |||
* documentation, and that the name of Alan Hourihane not be used in | |||
* advertising or publicity pertaining to distribution of the software without | |||
* specific, written prior permission. Alan Hourihane makes no representations | |||
* about the suitability of this software for any purpose. It is provided | |||
* "as is" without express or implied warranty. | |||
* | |||
* ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |||
* EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |||
* PERFORMANCE OF THIS SOFTWARE. | |||
* | |||
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> | |||
* | |||
* Trident CyberBladeXP driver. | |||
* | |||
*/ | |||
#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 "swrast/swrast.h" | |||
#include "tnl/t_context.h" | |||
#include "tnl/tnl.h" | |||
#include "trident_context.h" | |||
#define TRIDENT_TEX1_BIT 0x1 | |||
#define TRIDENT_TEX0_BIT 0x2 | |||
#define TRIDENT_RGBA_BIT 0x4 | |||
#define TRIDENT_SPEC_BIT 0x8 | |||
#define TRIDENT_FOG_BIT 0x10 | |||
#define TRIDENT_XYZW_BIT 0x20 | |||
#define TRIDENT_PTEX_BIT 0x40 | |||
#define TRIDENT_MAX_SETUP 0x80 | |||
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[TRIDENT_MAX_SETUP]; | |||
#define TINY_VERTEX_FORMAT 1 | |||
#define NOTEX_VERTEX_FORMAT 2 | |||
#define TEX0_VERTEX_FORMAT 3 | |||
#define TEX1_VERTEX_FORMAT 4 | |||
#define PROJ_TEX1_VERTEX_FORMAT 5 | |||
#define TEX2_VERTEX_FORMAT 6 | |||
#define TEX3_VERTEX_FORMAT 7 | |||
#define PROJ_TEX3_VERTEX_FORMAT 8 | |||
#define DO_XYZW (IND & TRIDENT_XYZW_BIT) | |||
#define DO_RGBA (IND & TRIDENT_RGBA_BIT) | |||
#define DO_SPEC (IND & TRIDENT_SPEC_BIT) | |||
#define DO_FOG (IND & TRIDENT_FOG_BIT) | |||
#define DO_TEX0 (IND & TRIDENT_TEX0_BIT) | |||
#define DO_TEX1 (IND & TRIDENT_TEX1_BIT) | |||
#define DO_TEX2 0 | |||
#define DO_TEX3 0 | |||
#define DO_PTEX (IND & TRIDENT_PTEX_BIT) | |||
#define VERTEX tridentVertex | |||
#define LOCALVARS tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
#define GET_VIEWPORT_MAT() tmesa->hw_viewport | |||
#define GET_TEXSOURCE(n) tmesa->tmu_source[n] | |||
#define GET_VERTEX_FORMAT() tmesa->vertex_format | |||
#define GET_VERTEX_STORE() tmesa->verts | |||
#define GET_VERTEX_STRIDE_SHIFT() tmesa->vertex_stride_shift | |||
#define GET_UBYTE_COLOR_STORE() &tmesa->UbyteColor | |||
#define GET_UBYTE_SPEC_COLOR_STORE() &tmesa->UbyteSecondaryColor | |||
#define HAVE_HW_VIEWPORT 0 | |||
#define HAVE_HW_DIVIDE 0 | |||
#define HAVE_RGBA_COLOR 0 | |||
#define HAVE_TINY_VERTICES 1 | |||
#define HAVE_NOTEX_VERTICES 1 | |||
#define HAVE_TEX0_VERTICES 1 | |||
#define HAVE_TEX1_VERTICES 1 | |||
#define HAVE_TEX2_VERTICES 0 | |||
#define HAVE_TEX3_VERTICES 0 | |||
#define HAVE_PTEX_VERTICES 0 | |||
#define UNVIEWPORT_VARS \ | |||
const GLfloat dx = - tmesa->drawX - SUBPIXEL_X; \ | |||
const GLfloat dy = (tmesa->driDrawable->h + \ | |||
tmesa->drawY + SUBPIXEL_Y); \ | |||
const GLfloat sz = 1.0 / tmesa->depth_scale | |||
#define UNVIEWPORT_X(x) x + dx; | |||
#define UNVIEWPORT_Y(y) - y + dy; | |||
#define UNVIEWPORT_Z(z) z * sz; | |||
#define PTEX_FALLBACK() tridentFallback(TRIDENT_CONTEXT(ctx), TRIDENT_FALLBACK_TEXTURE, 1) | |||
#define IMPORT_FLOAT_COLORS trident_import_float_colors | |||
#define IMPORT_FLOAT_SPEC_COLORS trident_import_float_spec_colors | |||
#define INTERP_VERTEX setup_tab[tmesa->SetupIndex].interp | |||
#define COPY_PV_VERTEX setup_tab[tmesa->SetupIndex].copy_pv | |||
/*********************************************************************** | |||
* Generate pv-copying and translation functions * | |||
***********************************************************************/ | |||
#define TAG(x) trident_##x | |||
#include "tnl_dd/t_dd_vb.c" | |||
/*********************************************************************** | |||
* Generate vertex emit and interp functions * | |||
***********************************************************************/ | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT) | |||
#define TAG(x) x##_wg | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT) | |||
#define TAG(x) x##_wgs | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_wgt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_wgt0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_TEX0_BIT|TRIDENT_PTEX_BIT) | |||
#define TAG(x) x##_wgpt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_wgst0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_wgst0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_PTEX_BIT) | |||
#define TAG(x) x##_wgspt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT) | |||
#define TAG(x) x##_wgf | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT) | |||
#define TAG(x) x##_wgfs | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_wgft0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_wgft0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT|TRIDENT_PTEX_BIT) | |||
#define TAG(x) x##_wgfpt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_wgfst0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_wgfst0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_PTEX_BIT) | |||
#define TAG(x) x##_wgfspt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_t0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_t0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_FOG_BIT) | |||
#define TAG(x) x##_f | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_ft0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_ft0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT) | |||
#define TAG(x) x##_g | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT) | |||
#define TAG(x) x##_gs | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_gt0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_gt0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_gst0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_gst0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT) | |||
#define TAG(x) x##_gf | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT) | |||
#define TAG(x) x##_gfs | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_gft0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_gft0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT) | |||
#define TAG(x) x##_gfst0 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
#define IND (TRIDENT_RGBA_BIT|TRIDENT_FOG_BIT|TRIDENT_SPEC_BIT|TRIDENT_TEX0_BIT|TRIDENT_TEX1_BIT) | |||
#define TAG(x) x##_gfst0t1 | |||
#include "tnl_dd/t_dd_vbtmp.h" | |||
static void init_setup_tab( void ) | |||
{ | |||
init_wg(); | |||
init_wgs(); | |||
init_wgt0(); | |||
init_wgt0t1(); | |||
init_wgpt0(); | |||
init_wgst0(); | |||
init_wgst0t1(); | |||
init_wgspt0(); | |||
init_wgf(); | |||
init_wgfs(); | |||
init_wgft0(); | |||
init_wgft0t1(); | |||
init_wgfpt0(); | |||
init_wgfst0(); | |||
init_wgfst0t1(); | |||
init_wgfspt0(); | |||
init_t0(); | |||
init_t0t1(); | |||
init_f(); | |||
init_ft0(); | |||
init_ft0t1(); | |||
init_g(); | |||
init_gs(); | |||
init_gt0(); | |||
init_gt0t1(); | |||
init_gst0(); | |||
init_gst0t1(); | |||
init_gf(); | |||
init_gfs(); | |||
init_gft0(); | |||
init_gft0t1(); | |||
init_gfst0(); | |||
init_gfst0t1(); | |||
} | |||
void tridentBuildVertices( GLcontext *ctx, | |||
GLuint start, | |||
GLuint count, | |||
GLuint newinputs ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT( ctx ); | |||
GLubyte *v = ((GLubyte *)tmesa->verts + (start<<tmesa->vertex_stride_shift)); | |||
GLuint stride = 1<<tmesa->vertex_stride_shift; | |||
newinputs |= tmesa->SetupNewInputs; | |||
tmesa->SetupNewInputs = 0; | |||
if (!newinputs) | |||
return; | |||
if (newinputs & VERT_CLIP) { | |||
setup_tab[tmesa->SetupIndex].emit( ctx, start, count, v, stride ); | |||
} else { | |||
GLuint ind = 0; | |||
if (newinputs & VERT_RGBA) | |||
ind |= TRIDENT_RGBA_BIT; | |||
if (newinputs & VERT_SPEC_RGB) | |||
ind |= TRIDENT_SPEC_BIT; | |||
if (newinputs & VERT_TEX0) | |||
ind |= TRIDENT_TEX0_BIT; | |||
if (newinputs & VERT_TEX1) | |||
ind |= TRIDENT_TEX1_BIT; | |||
if (newinputs & VERT_FOG_COORD) | |||
ind |= TRIDENT_FOG_BIT; | |||
if (tmesa->SetupIndex & TRIDENT_PTEX_BIT) | |||
ind = ~0; | |||
ind &= tmesa->SetupIndex; | |||
if (ind) { | |||
setup_tab[ind].emit( ctx, start, count, v, stride ); | |||
} | |||
} | |||
} | |||
void tridentCheckTexSizes( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT( ctx ); | |||
if (!setup_tab[tmesa->SetupIndex].check_tex_sizes(ctx)) { | |||
TNLcontext *tnl = TNL_CONTEXT(ctx); | |||
/* Invalidate stored verts | |||
*/ | |||
tmesa->SetupNewInputs = ~0; | |||
tmesa->SetupIndex |= TRIDENT_PTEX_BIT; | |||
if (!tmesa->Fallback && | |||
!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { | |||
tnl->Driver.Render.Interp = setup_tab[tmesa->SetupIndex].interp; | |||
tnl->Driver.Render.CopyPV = setup_tab[tmesa->SetupIndex].copy_pv; | |||
} | |||
} | |||
} | |||
void tridentChooseVertexState( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT( ctx ); | |||
TNLcontext *tnl = TNL_CONTEXT(ctx); | |||
GLuint ind = TRIDENT_XYZW_BIT|TRIDENT_RGBA_BIT; | |||
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) | |||
ind |= TRIDENT_SPEC_BIT; | |||
if (ctx->Fog.Enabled) | |||
ind |= TRIDENT_FOG_BIT; | |||
if (ctx->Texture._ReallyEnabled) { | |||
ind |= TRIDENT_TEX0_BIT; | |||
if (ctx->Texture.Unit[0]._ReallyEnabled && | |||
ctx->Texture.Unit[1]._ReallyEnabled) { | |||
ind |= TRIDENT_TEX1_BIT; | |||
} | |||
} | |||
tmesa->SetupIndex = ind; | |||
if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) { | |||
tnl->Driver.Render.Interp = trident_interp_extras; | |||
tnl->Driver.Render.CopyPV = trident_copy_pv_extras; | |||
} else { | |||
tnl->Driver.Render.Interp = setup_tab[ind].interp; | |||
tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv; | |||
} | |||
if (setup_tab[ind].vertex_format != tmesa->vertex_format) { | |||
tmesa->vertex_format = setup_tab[ind].vertex_format; | |||
tmesa->vertex_size = setup_tab[ind].vertex_size; | |||
tmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift; | |||
} | |||
} | |||
void tridentInitVB( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
GLuint size = TNL_CONTEXT(ctx)->vb.Size; | |||
tmesa->verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 ); | |||
{ | |||
static int firsttime = 1; | |||
if (firsttime) { | |||
init_setup_tab(); | |||
firsttime = 0; | |||
} | |||
} | |||
} | |||
void tridentFreeVB( GLcontext *ctx ) | |||
{ | |||
tridentContextPtr tmesa = TRIDENT_CONTEXT(ctx); | |||
if (tmesa->verts) { | |||
ALIGN_FREE(tmesa->verts); | |||
tmesa->verts = 0; | |||
} | |||
if (tmesa->UbyteSecondaryColor.Ptr) { | |||
ALIGN_FREE(tmesa->UbyteSecondaryColor.Ptr); | |||
tmesa->UbyteSecondaryColor.Ptr = 0; | |||
} | |||
if (tmesa->UbyteColor.Ptr) { | |||
ALIGN_FREE(tmesa->UbyteColor.Ptr); | |||
tmesa->UbyteColor.Ptr = 0; | |||
} | |||
} |