Files
glide/glide2x/cvg/glide/tests/plib.c

1398 lines
47 KiB
C

/*
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
**
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
** THE UNITED STATES.
**
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
**
**
** $Revision$
** $Date$
**
*/
#include <stdlib.h>
#include <stdarg.h>
#ifndef __linux__
#include <conio.h>
#endif
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include <math.h>
#include <glide.h>
#include "tlib.h"
#include "plib.h"
#define MAX_HANDLES 32
//the following may need to go onto the heap... currently need 10K, not bad
static tlTxMnTexture_t tlTxMnMngr[MAX_HANDLES];
static hTexId_t hFstOpnTexId = H_FSTTEXID; //0 is the NULL handle
static GrChipID_t currTMU = GR_TMU0;
static FxBool bMultiRevOrder;
static FxBool bMultiOffsetFix;
/* static helper prototypes */
static FxU32 prGetLodSize( GrTexInfo *const disTexInfo, GrLOD_t disLOD );
static FxU32 prTexMultiMemRequired( FxU32 deMipMask, GrTexBaseRange_t deRange,
GrTexInfo* deTexInfo );
static void prGetLod( GrTexInfo *lpTexInfo, GrLOD_t deLod, void *data );
static void prPopLod( GrTexInfo *lpDeTexInfo, mipMapEnd_t deMipMapEnd );
static void prPushLod( GrTexInfo *lpDeTexInfo, mipMapEnd_t deMipMapEnd );
static FxU32 prGetTxMnAdd( hTexId_t deTexId, GrLOD_t deLod );
static int prGetLodWidth( GrLOD_t lod, GrAspectRatio_t aspect );
static int prGetLodHeight( GrLOD_t lod, GrAspectRatio_t aspect );
static FxU32 prGetMultiMemBump( const GrTexInfo *const deTexInfo,
GrTexBaseRange_t deTexBase,
FxU32 deMipMask );
/*-------------------------------------------------------------------
Function: plTxMnLoadTxMngr
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
hTexId_t
plTxMnLoadTxMngr( TlTexture* lpTexture )
{
/* assumptions */
assert( lpTexture );
/* code */
tlTxMnMngr[ hFstOpnTexId ].lpTlTextureInfo = lpTexture;
tlTxMnMngr[ hFstOpnTexId ].origLargeLod = lpTexture->info.largeLod;
tlTxMnMngr[ hFstOpnTexId ].origSmallLod = lpTexture->info.smallLod;
SET_DOWNLOADABLE( tlTxMnMngr[hFstOpnTexId], FXFALSE);
SET_MULTIBASE( tlTxMnMngr[hFstOpnTexId], FXFALSE);
SET_TRILINEAR( tlTxMnMngr[hFstOpnTexId], FXFALSE);
SET_BEENPOPD( tlTxMnMngr[hFstOpnTexId], FXFALSE);
SET_DIRTY( tlTxMnMngr[hFstOpnTexId], FXFALSE);
return (hFstOpnTexId++);
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetDownload
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
static void
prTxMnSetBeenPopd( hTexId_t deTexId, FxBool bBeenPopd )
{
SET_BEENPOPD( tlTxMnMngr[deTexId], bBeenPopd );
SET_DIRTY( tlTxMnMngr[deTexId], FXTRUE ); /* just for messing with it */
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetDownload
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
void
plTxMnSetDownload( hTexId_t deTexId, FxBool bDownLoad )
{
/* assumptions */
assert( deTexId < hFstOpnTexId );
/* code */
SET_DOWNLOADABLE( tlTxMnMngr[deTexId], bDownLoad );
SET_DIRTY( tlTxMnMngr[deTexId], FXTRUE ); /* just for messing with it */
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetMultibase
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
void
plTxMnSetMultibase( hTexId_t deTexId, FxBool bMultibase )
{
/* assumptions */
assert( deTexId < hFstOpnTexId );
/* code */
SET_MULTIBASE( tlTxMnMngr[deTexId], bMultibase );
SET_DIRTY( tlTxMnMngr[deTexId], FXTRUE ); /* just for messing with it */
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnGetMultibase
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
FxBool
plTxMnGetMultibase( hTexId_t deTexId )
{
assert( deTexId < hFstOpnTexId );
return (IS_MULTIBASE(tlTxMnMngr[deTexId]) );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetMultiRevOrder
Date: 7/6/97
Implementor(s): psw
Library:
Description:
Sets the global bMultiRevOrder which is used by plTxMnDownloadAll
to determine the order of the multibase segments in tmu mem
Arguments:
FxBool bOrder
Return:
void
-------------------------------------------------------------------*/
void
plTxMnSetMultiRevOrder( FxBool bOrder )
{
bMultiRevOrder = bOrder;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnGetMultiRevOrder
Date: 7/6/97
Implementor(s): psw
Library:
Description:
Returns the current status of the bMultiRevOrder static global
Arguments:
none
Return:
FxBool
-------------------------------------------------------------------*/
FxBool
plTxMnGetMultiRevOrder( )
{
return ( bMultiRevOrder );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetMultiOffsetFix
Date: 7/16/97
Implementor(s): psw
Library:
Description:
Sets the global bMultiOffsetFix which is used by plTxMnTextureSource
to determine to use the Multibase offset fix
Arguments:
FxBool bOrder
Return:
void
-------------------------------------------------------------------*/
void
plTxMnSetMultiOffsetFix( FxBool bOffsetFix )
{
bMultiOffsetFix = bOffsetFix;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnGetMultiOffsetFix
Date: 7/16/97
Implementor(s): psw
Library:
Description:
Returns the current status of the bMultiOffsetFix static global
Arguments:
none
Return:
FxBool
-------------------------------------------------------------------*/
FxBool
plTxMnGetMultiOffsetFix( )
{
return ( bMultiOffsetFix );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnSetTrilinear
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
void
plTxMnSetTrilinear( hTexId_t deTexId, FxBool bTrilinear )
{
/* assumptions */
assert( deTexId < hFstOpnTexId );
/* trilinear && <2-lods are mutex */
if ( (tlTxMnMngr[ deTexId ].lpTlTextureInfo->info.smallLod -
tlTxMnMngr[ deTexId ].lpTlTextureInfo->info.largeLod) >= 1)
{
SET_TRILINEAR( tlTxMnMngr[deTexId], bTrilinear );
SET_DIRTY( tlTxMnMngr[deTexId], FXTRUE ); /* just for messing with it */
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnGetTrilinear
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Arguments:
Return:
-------------------------------------------------------------------*/
FxBool
plTxMnGetTrilinear( hTexId_t deTexId )
{
assert( deTexId < hFstOpnTexId );
return (IS_TRILINEAR(tlTxMnMngr[deTexId]) );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnReset
Date: 6/26/97
Implementor(s): psw
Library:
Description:
Resets the respective texture back to its base state
Arguments:
hTexId_t deTexId - the id of the tlTxMnMngr texture to reset
Return:
void
-------------------------------------------------------------------*/
void
plTxMnReset( hTexId_t deTexId )
{
/* initializations */
tlTxMnTexture_t *lpThisTxMnTexture;
GrTexInfo *lpThisTexInfo;
/* assumptions */
assert( deTexId < hFstOpnTexId );
/* initializations */
lpThisTxMnTexture = &tlTxMnMngr[deTexId];
lpThisTexInfo = &lpThisTxMnTexture->lpTlTextureInfo->info;
/* code */
SET_MULTIBASE( tlTxMnMngr[deTexId], FXFALSE );
SET_TRILINEAR( tlTxMnMngr[deTexId], FXFALSE );
bMultiRevOrder = FXFALSE;
/* SET_DIRTY( tlTxMnMngr[deTexId], FXFALSE ); */
while ( lpThisTexInfo->largeLod > lpThisTxMnTexture->origLargeLod )
prPushLod( lpThisTexInfo, topOfMipMap );/* reset d'm data ptrs */
while ( lpThisTexInfo->smallLod < lpThisTxMnTexture->origSmallLod )
prPushLod (lpThisTexInfo, btmOfMipMap );/* reset d'm data ptrs */
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnDownloadAll
Date: 6/27/97
Implementor(s): psw
Library:
Description:
Downloads all the textures be held by tlTexManMngr[]
Will determine if the textures are to be downloaded
in (linear || multibase) && (BOTH || EVEN/ODD) mode based upon
their flags and do the right thang
Arguments:
None
Return:
void
-------------------------------------------------------------------*/
void
plTxMnDownloadAll( )
{
/* definitions */
hTexId_t hCurrTexId;
FxU32 currTexMemReq;
FxU32 currStartAdd;
tlTxMnTexture_t *lpThisTxMnTexture;
GrTexInfo *lpThisTexInfo;
TlTexture *lpThisTlTex;
/* assumptions */
assert(hFstOpnTexId != 0);
/* initializations */
currStartAdd = grTexMinAddress(currTMU);
/* code */
for ( hCurrTexId = H_FSTTEXID; hCurrTexId < hFstOpnTexId; ++hCurrTexId )
{ /* here we go */
if (IS_DOWNLOADABLE(tlTxMnMngr[hCurrTexId]))
{ /* download it */
lpThisTxMnTexture = &tlTxMnMngr[hCurrTexId];
lpThisTlTex = lpThisTxMnTexture->lpTlTextureInfo;
lpThisTexInfo = &lpThisTlTex->info;
if (!IS_MULTIBASE(*lpThisTxMnTexture))
{ /* not multibased */
if (!IS_TRILINEAR(*lpThisTxMnTexture))
{ /* not trilinear mip'd */
currTexMemReq = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH, lpThisTexInfo);
assert( currStartAdd + currTexMemReq < grTexMaxAddress(currTMU) );
grTexDownloadMipMap( currTMU, currStartAdd,
GR_MIPMAPLEVELMASK_BOTH, lpThisTexInfo );
lpThisTxMnTexture->u0.bothAdd = currStartAdd;
currStartAdd += currTexMemReq;
} /* if !IS_TRILINEAR && !IS_MULTIBASE */
else
{ /* else it is being rendered as trilinear mip'd */
/* first do the even segment */
currTexMemReq = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN, lpThisTexInfo);
assert( currStartAdd + currTexMemReq < grTexMaxAddress(currTMU) );
grTexDownloadMipMap( currTMU, currStartAdd,
GR_MIPMAPLEVELMASK_EVEN, lpThisTexInfo );
lpThisTxMnTexture->u0.evenAdd = currStartAdd;
currStartAdd += currTexMemReq;
/* next do the odd segment */
currTexMemReq = grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD, lpThisTexInfo);
assert( currStartAdd + currTexMemReq < grTexMaxAddress(currTMU) );
grTexDownloadMipMap( currTMU, currStartAdd,
GR_MIPMAPLEVELMASK_ODD, lpThisTexInfo );
lpThisTxMnTexture->u1.oddAdd = currStartAdd;
currStartAdd += currTexMemReq;
} /* else !IS_MULTIBASE && IS_TRILINEAR */
} /* if !IS_MULTIBASE */
else /* else it is multibased */
{
/* stack frame definitions */
FxU32 *lpxAdd;
GrTexBaseRange_t tTxBse;
grTexMultibase(currTMU, FXTRUE); /* turn on multibase */
if (!IS_TRILINEAR(*lpThisTxMnTexture))
{ /* non trilinear mip'd multibase texture
** if bMultiRevOrder is True, get the addresses for the Multibase segs
** in reverse order, 32_TO_1 to 256, else get them in 256 to 32_TO_1 */
for ( tTxBse = bMultiRevOrder ? GR_TEXBASE_32_TO_1 : GR_TEXBASE_256,
lpxAdd = bMultiRevOrder ? &lpThisTxMnTexture->u3.multiR3Add :
&lpThisTxMnTexture->u0.multiR0Add;
bMultiRevOrder ? lpxAdd >= &lpThisTxMnTexture->u0.multiR0Add :
lpxAdd <= &lpThisTxMnTexture->u3.multiR3Add;
(bMultiRevOrder ? --tTxBse : ++tTxBse),
(bMultiRevOrder ? --lpxAdd : ++lpxAdd) )
{ /* this loop just gets the texture addresses - the multibase
** segments will be in reverse order, but in the same linear block */
currTexMemReq = prTexMultiMemRequired( GR_MIPMAPLEVELMASK_BOTH,
tTxBse, lpThisTexInfo);
if (currTexMemReq != 0) /* if the LOD(s) !missing, ie. pop'd */
{
assert( currStartAdd + currTexMemReq < grTexMaxAddress(currTMU) );
*lpxAdd = currStartAdd;
currStartAdd += currTexMemReq; /* bump the current TMU address */
}
} /* for */
for ( tTxBse = GR_TEXBASE_256, lpxAdd = &lpThisTxMnTexture->u0.multiR0Add;
lpxAdd <= &lpThisTxMnTexture->u3.multiR3Add;
++tTxBse, ++lpxAdd )
{ /* this loop actually does the downloading - in the proper order...
** GR_TEXBASE_256 to GR_TEXBASE_32_TO_1 */
/* stack frame definitions */
GrTexInfo tmpInfo;
GrTexInfo *lpTmpInfo = &tmpInfo;
/* initializations */
/* multibase requires that I munge the data for downloading */
*lpTmpInfo = *lpThisTexInfo;
if ((lpThisTexInfo->largeLod <= (FxI32) tTxBse ) &&
(lpThisTexInfo->smallLod >= (FxI32) tTxBse ))
{ /* if the TexBase exists in the lod range */
while ( lpTmpInfo->largeLod < (FxI32) tTxBse )
prPopLod( lpTmpInfo, topOfMipMap ); /* munge the top */
if ( tTxBse != GR_TEXBASE_32_TO_1 )
lpTmpInfo->smallLod = lpTmpInfo->largeLod; /* munge the btm */
grTexDownloadMipMap(currTMU, *lpxAdd, /* download mung'd data */
GR_MIPMAPLEVELMASK_BOTH, lpTmpInfo );
} /* if */
} /* for */
} /* if !IS_TRILINEAR && IS_MULTIBASE */
else
{ /* else it is a multibased trilinear mipmap, aka motherfucker
** if bMultiRevOrder is True, get the addresses for the Multibase segs
** in reverse order, 32_TO_1 to 256, else get them in 256 to 32_TO_1 */
for (tTxBse = bMultiRevOrder ? GR_TEXBASE_32_TO_1+1 : GR_TEXBASE_256,
lpxAdd = bMultiRevOrder ? &lpThisTxMnTexture->u4.multiR3EvenAdd :
&lpThisTxMnTexture->u0.multiR0EvenAdd;
bMultiRevOrder ? lpxAdd >= &lpThisTxMnTexture->u0.multiR0EvenAdd :
lpxAdd <= &lpThisTxMnTexture->u4.multiR3EvenAdd;
(bMultiRevOrder ? --tTxBse : ++tTxBse),
(bMultiRevOrder ? --lpxAdd : ++lpxAdd) )
{ /* this loop just gets the texture addresses */
if ( tTxBse % 2 ) /* is it odd? */
currTexMemReq = prTexMultiMemRequired(GR_MIPMAPLEVELMASK_ODD,
tTxBse, lpThisTexInfo); /* 1,3 */
else /* even */
currTexMemReq = prTexMultiMemRequired(GR_MIPMAPLEVELMASK_EVEN,
(tTxBse>3?3:tTxBse),
lpThisTexInfo);/* 0,2,3 */
/* prTexMulti.. only knows about 0-3 */
if (currTexMemReq != 0) /* if the LOD(s) !missing, ie. pop'd */
{
assert( currStartAdd + currTexMemReq < grTexMaxAddress(currTMU) );
*lpxAdd = currStartAdd;
currStartAdd += currTexMemReq;/* bump the current TMU address */
}
} /* for */
for (tTxBse = GR_TEXBASE_256,
lpxAdd = &lpThisTxMnTexture->u0.multiR0EvenAdd;
lpxAdd <= &lpThisTxMnTexture->u4.multiR3EvenAdd;
++tTxBse, ++lpxAdd ) /* tTxBse will actually overrun...
** overrun = GR_TEXBASE_32_TO_1 + 1
** (tTxBse>3?3:tTxBse) will fix this
** required for 32to1_ODD and 32to1_EVEN */
/* actually (tTxBse>GR_TEXBASE_32_TO_1:GR_TEXBASE_32_TO_1?tTxBse) */
{ /* this loop actually does the downloading - in the proper order...
** GR_TEXBASE_256 to GR_TEXBASE_32_TO_1 */
/* stack frame definitions */
GrTexInfo tmpInfo;
GrTexInfo *lpTmpInfo = &tmpInfo;
/* initializations */
/* multibase requires that I munge the data, hence the data copies */
*lpTmpInfo = *lpThisTexInfo;
if ((lpThisTexInfo->largeLod <= (FxI32) (tTxBse>3?3:tTxBse)) &&
(lpThisTexInfo->smallLod >= (FxI32) (tTxBse>3?3:tTxBse)))
{ /* if an lod actually exits in the range */
while ( lpTmpInfo->largeLod < (FxI32)(tTxBse>3?3:tTxBse) )
prPopLod( lpTmpInfo, topOfMipMap ); /* munge the top */
if ( (tTxBse>3?3:tTxBse) != GR_TEXBASE_32_TO_1 )
lpTmpInfo->smallLod = lpTmpInfo->largeLod; /* munge the btm */
if ( tTxBse % 2 ) /* is it odd? */
grTexDownloadMipMap(currTMU, *lpxAdd, /* download mung'd odd data */
GR_MIPMAPLEVELMASK_ODD, lpTmpInfo );
else
grTexDownloadMipMap(currTMU, *lpxAdd, /* download mung'd even data */
GR_MIPMAPLEVELMASK_EVEN, lpTmpInfo );
} /* if */
} /* for */
} /* else IS_TRILINEAR && IS_MULTIBASE */
grTexMultibase(currTMU, FXFALSE); /* turn off multibase */
} /* else IS_MULTIBASE */
if ( lpThisTlTex->tableType != NO_TABLE )
grTexDownloadTable(currTMU, lpThisTlTex->tableType,
&lpThisTlTex->tableData );
} /* if IS_DOWNLOADABLE */
} /* for ( i = 0; i < fstOpnTexId; ++i ) */
} /* plTxMnDownloadAll */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnTexSource
Date: 6/28/97
Implementor(s): psw
Library:
Description:
Renders the texture associated with hTexId. Will setup the rendering
modes based upon the tlTxMnMngr[deTexId].flags fields, i.e.,
(linear || multibase) && (BOTH || EVEN/ODD) modes. Also uses
the addresses saved by previous call to tlTxMnDownloadAll
Arguments:
hTexId_t deTexId - handle to the texture
FxU32 deMipMask - mipmap mask
Return:
void
-------------------------------------------------------------------*/
void
plTxMnTexSource( hTexId_t deTexId, FxU32 deMipMask )
{
/* definitions */
tlTxMnTexture_t *lpThisTxMnTexture;
GrTexInfo thisTexInfo,
*lpThisTexInfo;
TlTexture *lpThisTlTex;
FxU32 *lpxAdd,
xAdd;
GrTexBaseRange_t tTexBase;
/* assumptions */
assert( deTexId < hFstOpnTexId );
assert((deMipMask >= GR_TEXBASE_256) &&
(deMipMask <= GR_TEXBASE_32_TO_1));
/* initializations */
lpThisTxMnTexture = &tlTxMnMngr[deTexId];
lpThisTlTex = lpThisTxMnTexture->lpTlTextureInfo;
lpThisTexInfo = &thisTexInfo;
*lpThisTexInfo = lpThisTxMnTexture->lpTlTextureInfo->info;
/*
if ((lpThisTlTex->tableType == GR_NCCTABLE_NCC0) ||
(lpThisTlTex->tableType == GR_NCCTABLE_NCC1))
grTexNCCTable( currTMU, lpThisTlTex->tableType );
*/
if (!IS_MULTIBASE(*lpThisTxMnTexture))
{ /* not multibased */
if (!IS_TRILINEAR(*lpThisTxMnTexture))
grTexSource( currTMU, lpThisTxMnTexture->u0.bothAdd, deMipMask, lpThisTexInfo );
else /* IS_TRILINEAR */
if ( deMipMask == GR_MIPMAPLEVELMASK_EVEN ) /* first do the even segment */
grTexSource( currTMU, lpThisTxMnTexture->u0.evenAdd, deMipMask, lpThisTexInfo );
else /* next do the odd segment */
grTexSource( currTMU, lpThisTxMnTexture->u1.oddAdd, deMipMask, lpThisTexInfo );
}/* if !IS_MULTIBASE */
else
{ /* else it is multibased */
grTexMultibase(currTMU, FXTRUE); /* turn on multibase */
if (!IS_TRILINEAR(*lpThisTxMnTexture))
{ /* really dependant on the unions being in the proper order */
lpxAdd = &lpThisTxMnTexture->u0.multiR0Add;
for (tTexBase = GR_TEXBASE_256; tTexBase <= GR_TEXBASE_32_TO_1;
++tTexBase, ++lpxAdd)
/* next i check that the current TexBase is in the lod range */
if ((lpThisTexInfo->largeLod <= (FxI32) tTexBase) &&
(lpThisTexInfo->smallLod >= (FxI32) tTexBase))
{
xAdd = *lpxAdd;
if (bMultiOffsetFix)
xAdd -= prGetMultiMemBump(lpThisTexInfo, tTexBase, deMipMask);
grTexMultibaseAddress(currTMU, tTexBase, xAdd, deMipMask,
lpThisTexInfo );
}
} /* if !IS_TRILINEAR */
else
{ /* else it is a multibased trilinear mipmap */
if ( deMipMask == GR_MIPMAPLEVELMASK_EVEN ) /* do the even segments */
{
lpxAdd = &lpThisTxMnTexture->u0.multiR0EvenAdd;/* set lpxAdd to 1st add */
for (tTexBase = GR_TEXBASE_256; tTexBase <= GR_TEXBASE_32_TO_1;
tTexBase = ( tTexBase + 2 == GR_TEXBASE_32_TO_1 + 1 ) ? /* 32t1 is both even & odd */
GR_TEXBASE_32_TO_1 : tTexBase + 2, lpxAdd += 2 ) /* even segs r at even indices */
/* next i check that the current TexBase is in the lod range */
if ((lpThisTexInfo->largeLod <= (FxI32) tTexBase) &&
(lpThisTexInfo->smallLod >= (FxI32) tTexBase))
{
xAdd = *lpxAdd;
if (bMultiOffsetFix)
xAdd -= prGetMultiMemBump(lpThisTexInfo, tTexBase, deMipMask);
grTexMultibaseAddress(currTMU, tTexBase, xAdd, deMipMask,
lpThisTexInfo);
}
} /* if - even */
else /* else do the odd segments */
{
lpxAdd = &lpThisTxMnTexture->u1.multiR1OddAdd;
for (tTexBase = GR_TEXBASE_128; tTexBase <= GR_TEXBASE_32_TO_1;
tTexBase+=2, lpxAdd+=2 ) /* odd segs r at odd indices */
/* next i check that the current TexBase is in the lod range */
if ((lpThisTexInfo->largeLod <= (FxI32) tTexBase) &&
(lpThisTexInfo->smallLod >= (FxI32) tTexBase))
{
xAdd = *lpxAdd;
if (bMultiOffsetFix)
xAdd -= prGetMultiMemBump(lpThisTexInfo, tTexBase, deMipMask);
grTexMultibaseAddress( currTMU, tTexBase, xAdd, deMipMask,
lpThisTexInfo );
}
} /* else - odd */
} /* else IS_TRILINEAR && IS_MULTIBASE */
grTexMultibase(currTMU, FXFALSE); /* turn off multibase */
} /* else IS_MULTIBASE */
} /* plTxMnRender */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnGetInfo
Date: 6/27/97
Implementor(s): psw
Library:
Description:
simply fills in GrTexInfo struct with info about Texture
Arguments:
hTexId_t deTexHndl - the texture that you want to know about
GrTexInfo *deGrTexInfo - the info struct you want filled
Return:
void
-------------------------------------------------------------------*/
void
plTxMnGetInfo( hTexId_t deTexHndl, GrTexInfo *deGrTexInfo )
{
/* assumptions */
assert (deGrTexInfo);
assert ( deTexHndl < hFstOpnTexId );
*deGrTexInfo = tlTxMnMngr[deTexHndl].lpTlTextureInfo->info;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plPopLod
Date: 6/17/97
Implementor(s): psw
Library:
Description:
Basically a wrapper for prPopLod
Arguments:
hTexId_t thisTexId
mipMapEnd_t deMipMapEnd
Return:
none
-------------------------------------------------------------------*/
void
plPopLod( hTexId_t hCurrTexture, mipMapEnd_t deMipMapEnd )
{
/* definitions */
GrTexInfo *lpThisTexInfo;
tlTxMnTexture_t *lpThisTxMnTexture;
/* assumptions */
assert( hCurrTexture < hFstOpnTexId );
/* initializations */
lpThisTxMnTexture = &tlTxMnMngr[hCurrTexture];
lpThisTexInfo = &lpThisTxMnTexture->lpTlTextureInfo->info;
/* code */
if ( lpThisTexInfo->smallLod == lpThisTexInfo->largeLod )
return; /* no reason to go on, nothing to do */
if ((IS_TRILINEAR(*lpThisTxMnTexture)) &&
((lpThisTexInfo->smallLod - lpThisTexInfo->largeLod) == 2 ) )
return; /* trilinear && <2-lods are mutex */
prPopLod( lpThisTexInfo, deMipMapEnd );
} /* plPopLod */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plPushLod
Date: 6/17/97
Implementor(s): psw
Library:
Description:
Basically a wrapper for prPushLod
Arguments:
hTexId_t thisTexId
mipMapEnd_t deMipMapEnd
Return:
none
-------------------------------------------------------------------*/
void
plPushLod( hTexId_t hCurrTexture, mipMapEnd_t deMipMapEnd )
{
/* definitions */
GrTexInfo *lpThisTexInfo;/* info struct associated with curr tlTxMnMnger obj */
tlTxMnTexture_t *lpThisTxMnTexture;
/* assumptions */
assert( hCurrTexture < hFstOpnTexId );
/* initializations */
lpThisTxMnTexture = &tlTxMnMngr[hCurrTexture];
lpThisTexInfo = &lpThisTxMnTexture->lpTlTextureInfo->info;
/* code */
if ((deMipMapEnd == topOfMipMap) &&
(lpThisTexInfo->largeLod == lpThisTxMnTexture->origLargeLod))
return; /* already at the top of the stack */
if ((deMipMapEnd == btmOfMipMap) &&
(lpThisTexInfo->smallLod == lpThisTxMnTexture->origSmallLod))
return; /* already at the bottom of the stack */
prPushLod( lpThisTexInfo, deMipMapEnd);
} /* plPushLod */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plCreateTlTexture
Date: 6/20/97
Implementor(s): psw
Library:
Description:
creates a TlTexture
Arguments:
GrTexInfo*
FxU16 []
Return:
void
-------------------------------------------------------------------*/
void
plCreateTlTexture( TlTexture *deTlTexture, FxU16 daColors[] )
{
/* definitions */
GrLOD_t tCurrLod; /* the current LOD */
int nBytePerPixel; /* number of bytes per pixel */
FxU8 *spLilTex; /* 8bit LOD data ptr */
FxU16 *mpBigTex; /* 16bit LOD data ptr */
void *lpvCurrLod; /* curr LOD data ptr */
FxU32 xLodNumBytes; /* number of bytes to write in curr LOD */
GrTexInfo *lpThisTexInfo; /* ptr to GrTexInfo in TlTexture struct */
/* assumptions */
assert( deTlTexture );
assert( deTlTexture->info.data );
assert( deTlTexture->info.smallLod > deTlTexture->info.largeLod );
/* no palettized */
assert( (deTlTexture->info.format != GR_TEXFMT_YIQ_422) ||
(deTlTexture->info.format != GR_TEXFMT_P_8) ||
(deTlTexture->info.format != GR_TEXFMT_AYIQ_8422) ||
(deTlTexture->info.format != GR_TEXFMT_AP_88) );
/* initializations */
lpThisTexInfo = &deTlTexture->info;
/* code */
if ((lpThisTexInfo->format == GR_TEXFMT_RGB_332) ||
(lpThisTexInfo->format == GR_TEXFMT_YIQ_422) ||
(lpThisTexInfo->format == GR_TEXFMT_ALPHA_8) ||
(lpThisTexInfo->format == GR_TEXFMT_INTENSITY_8) ||
(lpThisTexInfo->format == GR_TEXFMT_P_8))
nBytePerPixel = 1; /* 8-bit formats */
else
nBytePerPixel = 2; /* 16-bit formats */
lpvCurrLod = lpThisTexInfo->data;
if ((deTlTexture->info.format != GR_TEXFMT_YIQ_422) ||
(deTlTexture->info.format != GR_TEXFMT_P_8) ||
(deTlTexture->info.format != GR_TEXFMT_AYIQ_8422) ||
(deTlTexture->info.format != GR_TEXFMT_AP_88) )
deTlTexture->tableType = NO_TABLE; /* fuck me */
for ( tCurrLod = lpThisTexInfo->largeLod;
tCurrLod <= (lpThisTexInfo->smallLod); ++tCurrLod )
{
if ( nBytePerPixel == 1 )
{
xLodNumBytes = prGetLodSize( lpThisTexInfo, tCurrLod );
for (spLilTex = (FxU8*) lpvCurrLod;
spLilTex < (FxU8*) ((FxU32)lpvCurrLod + xLodNumBytes);
++spLilTex )
*spLilTex = (FxU8) daColors[tCurrLod];
lpvCurrLod = (void*) spLilTex;
}
else
{
xLodNumBytes = prGetLodSize( lpThisTexInfo, tCurrLod );
for (mpBigTex = (FxU16*) lpvCurrLod;
mpBigTex < (FxU16*) ((FxU32)lpvCurrLod + xLodNumBytes);
++mpBigTex )
*mpBigTex = daColors[tCurrLod];
lpvCurrLod = (void*) mpBigTex;
}
}
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnDwnldMipMapLod
Date: 7/7/97
Implementor(s): psw
Library:
Description:
downloads a mipmap lod, deLod, from a src TxMnTexture to a dst
TxMnTexture.
***multibase not yet supported, not clearly defined
Arguments:
hTexId_t dstTexId - destination TxMnTexture id
hTexId_t srcTexId - source TxMnTexture id
GrLOD_t deLod - the lod to download in srcTexId
Return:
void
-------------------------------------------------------------------*/
void
plTxMnDwnldMipMapLod( hTexId_t dstTexId, hTexId_t srcTexId, GrLOD_t deLod )
{
/* definitions */
GrTexInfo *lpDstTexInfo,
*lpSrcTexInfo;
tlTxMnTexture_t *lpDstTxMnTexture,
*lpSrcTxMnTexture;
void *lpvData;
FxU32 thisAdd;
GrLOD_t thisLgLod;
FxU32 thisMask;
/* assumptions */
assert( dstTexId < hFstOpnTexId );
assert( srcTexId < hFstOpnTexId );
assert( IS_DOWNLOADABLE(tlTxMnMngr[dstTexId]) );
/* initializations */
lpDstTxMnTexture = &tlTxMnMngr[dstTexId];
lpSrcTxMnTexture = &tlTxMnMngr[srcTexId];
lpDstTexInfo = &lpDstTxMnTexture->lpTlTextureInfo->info;
lpSrcTexInfo = &lpSrcTxMnTexture->lpTlTextureInfo->info;
/* just some error checking */
if ( ((lpDstTexInfo->format) != (lpSrcTexInfo->format)) ||
((lpDstTexInfo->aspectRatio) != (lpSrcTexInfo->aspectRatio)) ||
((lpSrcTxMnTexture->origLargeLod) > deLod) ||
((lpSrcTxMnTexture->origSmallLod) < deLod) ||
((lpDstTxMnTexture->origLargeLod) > deLod) ||
((lpDstTxMnTexture->origSmallLod) < deLod) )
return; /* nonfatal error, just return */
/* code */
/* get the data */
lpvData = malloc(prGetLodSize(lpSrcTexInfo, deLod));
assert(lpvData);
prGetLod(lpSrcTexInfo, deLod, lpvData);
/* now i have an lod to download */
/* get the address */
thisAdd = prGetTxMnAdd( dstTexId, deLod );
/* get the mask */
if (!IS_TRILINEAR(*lpDstTxMnTexture))
thisMask = GR_MIPMAPLEVELMASK_BOTH;
else /* it is trilinear */
thisMask = deLod%2 ? GR_MIPMAPLEVELMASK_ODD : GR_MIPMAPLEVELMASK_EVEN;
/* get the largeLod, SPECIAL case for multibase */
if (!IS_MULTIBASE(*lpDstTxMnTexture))
thisLgLod = lpDstTexInfo->largeLod;
else /* is is multibase */
thisLgLod = deLod < GR_LOD_32 ? deLod :
lpDstTexInfo->largeLod > GR_LOD_32 ?
lpDstTexInfo->largeLod : GR_LOD_32;
grTexDownloadMipMapLevel( currTMU, thisAdd, deLod, thisLgLod,
lpDstTexInfo->aspectRatio, lpDstTexInfo->format,
thisMask, lpvData );
free(lpvData);
} /* plTxMnDwnldMipMapLod */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: plTxMnDwnldMipMapLod
Date: 7/7/97
Implementor(s): psw
Library:
Description:
downloads a mipmap lod, deLod, from a src TxMnTexture to a dst
TxMnTexture.
Arguments:
hTexId_t dstTexId - destination TxMnTexture id
hTexId_t srcTexId - source TxMnTexture id
GrLOD_t deLod - the lod to download in srcTexId
Return:
void
-------------------------------------------------------------------*/
void
plTxMnDwnldMipMapLodPrtl( hTexId_t dstTexId, hTexId_t srcTexId, GrLOD_t deLod,
int nFstRow, int nLstRow )
{
/* definitions */
GrTexInfo *lpDstTexInfo,
*lpSrcTexInfo;
tlTxMnTexture_t *lpDstTxMnTexture,
*lpSrcTxMnTexture;
void *lpvData;
FxU32 thisAdd;
GrLOD_t thisLgLod;
FxU32 thisMask;
/* assumptions */
assert( dstTexId < hFstOpnTexId );
assert( srcTexId < hFstOpnTexId );
assert( IS_DOWNLOADABLE(tlTxMnMngr[dstTexId]) );
assert( nFstRow <= nLstRow );
/* initializations */
lpDstTxMnTexture = &tlTxMnMngr[dstTexId];
lpSrcTxMnTexture = &tlTxMnMngr[srcTexId];
lpDstTexInfo = &lpDstTxMnTexture->lpTlTextureInfo->info;
lpSrcTexInfo = &lpSrcTxMnTexture->lpTlTextureInfo->info;
/* code */
/* just some error checking */
if ( ((lpDstTexInfo->format) != (lpSrcTexInfo->format)) ||
((lpDstTexInfo->aspectRatio) != (lpSrcTexInfo->aspectRatio)) ||
((lpSrcTxMnTexture->origLargeLod) > deLod) ||
((lpSrcTxMnTexture->origSmallLod) < deLod) ||
((lpDstTxMnTexture->origLargeLod) > deLod) ||
((lpDstTxMnTexture->origSmallLod) < deLod) ||
(nFstRow > prGetLodHeight( deLod, lpDstTexInfo->aspectRatio)) )
return; /* nonfatal error, just return */
/* because i'm a nice guy */
// if (nLstRow >= prGetLodHeight( deLod, lpDstTexInfo->aspectRatio))
// nLstRow = (-1) + prGetLodHeight( deLod, lpDstTexInfo->aspectRatio);
/* not so nice */
/* get the data */
lpvData = malloc(prGetLodSize(lpSrcTexInfo, deLod));
assert(lpvData);
prGetLod(lpSrcTexInfo, deLod, lpvData);
/* now i have an lod to download */
/* get the address */
thisAdd = prGetTxMnAdd( dstTexId, deLod );
/* get the mask */
if (!IS_TRILINEAR(*lpDstTxMnTexture))
thisMask = GR_MIPMAPLEVELMASK_BOTH;
else /* it is trilinear */
thisMask = deLod%2 ? GR_MIPMAPLEVELMASK_ODD : GR_MIPMAPLEVELMASK_EVEN;
/* get the largeLod, SPECIAL case for multibase */
if (!IS_MULTIBASE(*lpDstTxMnTexture))
thisLgLod = lpDstTexInfo->largeLod;
else /* is is multibase */
thisLgLod = deLod < GR_LOD_32 ? deLod :
lpDstTexInfo->largeLod > GR_LOD_32 ?
lpDstTexInfo->largeLod : GR_LOD_32;
grTexDownloadMipMapLevelPartial( currTMU, thisAdd, deLod, thisLgLod,
lpDstTexInfo->aspectRatio, lpDstTexInfo->format,
thisMask, lpvData, nFstRow, nLstRow );
free(lpvData);
}
/*-------------------------------------------------------------------*/
/* static helpers */
/*-------------------------------------------------------------------
Function: prGetTxMnAdd
Date: 7/14/97
Implementor(s): psw
Library:
Description:
returns the address of the texture seg in linear memory that contains
the LOD being sought based on TxMn id
Arguments:
hTexId_t deTexId - destination TxMnTexture id
GrLOD_t deLod - the lod to locate the seg in
Return:
FxU32 - address of the seg containing deLod
-------------------------------------------------------------------*/
static FxU32
prGetTxMnAdd( hTexId_t deTexId, GrLOD_t deLod )
{
/* definitions */
tlTxMnTexture_t *lpThisTxMnTxtre;
FxU32 xAdd;
/* initializations */
lpThisTxMnTxtre = &tlTxMnMngr[deTexId];
/* code */
if (!IS_MULTIBASE(*lpThisTxMnTxtre))
{ /* not multibased */
if (!IS_TRILINEAR(*lpThisTxMnTxtre))
xAdd = lpThisTxMnTxtre->u0.bothAdd;
else /* IS_TRILINEAR */
xAdd = (deLod%2) ? lpThisTxMnTxtre->u1.oddAdd :
lpThisTxMnTxtre->u0.evenAdd ;
} /* if !IS_MULTIBASE */
else /* this is going to be fucking ugly! */
{ /* else it is multibased */
if (!IS_TRILINEAR(*lpThisTxMnTxtre))
{
switch ( deLod )
{ /* some things are better done with a switch... */
case GR_LOD_256:
xAdd = (FxU32) &lpThisTxMnTxtre->u0.multiR0Add;
break;
case GR_LOD_128:
xAdd = (FxU32) &lpThisTxMnTxtre->u1.multiR1Add;
break;
case GR_LOD_64:
xAdd = (FxU32) &lpThisTxMnTxtre->u2.multiR2Add;
break;
default:
xAdd = (FxU32) &lpThisTxMnTxtre->u3.multiR3Add;
break;
}
} /* if !IS_TRILINEAR */
else
{
switch ( deLod )
{ /* some things are better done with a switch... */
case GR_LOD_256:
xAdd = (FxU32) &lpThisTxMnTxtre->u0.multiR0EvenAdd;
break;
case GR_LOD_128:
xAdd = (FxU32) &lpThisTxMnTxtre->u1.multiR1OddAdd;
break;
case GR_LOD_64:
xAdd = (FxU32) &lpThisTxMnTxtre->u2.multiR2EvenAdd;
break;
default: /* deLod <= 32_TO_1, key is could be < */
xAdd = (deLod % 2) ? (FxU32) &lpThisTxMnTxtre->u3.multiR3OddAdd :
(FxU32) &lpThisTxMnTxtre->u4.multiR3EvenAdd;
break;
}
} /* else IS_TRILINEAR */
} /* else IS_MULTIBASE */
return (xAdd);
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: prGetLod
Date: 7/7/97
Implementor(s): psw
Library:
Description:
gets the lod specific data out of a GrTexInfo designated by
lpTexInfo, used primarily by plTxMnDwnldMipMapLod
Arguments:
GrTexInfo *lpTexInfo - destination TxMnTexture id
GrLOD_t deLod - the lod get in deTexId
void *lpvData - pointer to data to propagate
Return:
void
-------------------------------------------------------------------*/
static void
prGetLod( GrTexInfo *lpTexInfo, GrLOD_t deLod, void *lpvData )
{
/* definitions */
GrTexInfo thisTexInfo,
*lpThisTexInfo;
GrLOD_t lod;
FxU32 i, xNumBytes;
FxU8 *lpSrc,
*lpDst;
/* initializations */
lpThisTexInfo = &thisTexInfo;
*lpThisTexInfo = *lpTexInfo; /* munge a copy */
/* code */
/* mod copy to get deLod at the top */
for ( lod = lpThisTexInfo->largeLod; lod < deLod; ++lod )
prPopLod( lpThisTexInfo, topOfMipMap );
/* get the size of top lod */
xNumBytes = prGetLodSize( lpThisTexInfo, lpThisTexInfo->largeLod );
/* read the top lod data into *lpvData */
lpSrc = (FxU8*) lpThisTexInfo->data;
lpDst = (FxU8*) lpvData;
for ( i = 0; i < xNumBytes; ++i )
*lpDst++ = *lpSrc++;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: prPushLod
Date: 7/7/97
Implementor(s): psw
Library:
Description:
This routine actually modifies the GrTexInfo struct data to push
data BACK on the top or bottom of the mipmap. pushes a single lod
Arguments:
GrTexInfo *lpDeTexInfo
mipMapEnd_t deMipMapEnd
Return:
none
-------------------------------------------------------------------*/
static void
prPushLod( GrTexInfo *lpDeTexInfo, mipMapEnd_t deMipMapEnd )
{
if (deMipMapEnd == topOfMipMap)
lpDeTexInfo->data = (void*)( (FxU32) lpDeTexInfo->data -
prGetLodSize(lpDeTexInfo, --lpDeTexInfo->largeLod));
else
++lpDeTexInfo->smallLod;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: prPopLod
Date: 7/7/97
Implementor(s): psw
Library:
Description:
This routine actually modifies the GrTexInfo struct data to pop
data off the top or bottom of the mipmap. pops off a single lod
Arguments:
GrTexInfo *lpDeTexInfo
mipMapEnd_t deMipMapEnd
Return:
none
-------------------------------------------------------------------*/
static void
prPopLod( GrTexInfo *lpDeTexInfo, mipMapEnd_t deMipMapEnd )
{
if (deMipMapEnd == topOfMipMap)
lpDeTexInfo->data = (void*)( (FxU32) lpDeTexInfo->data +
prGetLodSize(lpDeTexInfo, lpDeTexInfo->largeLod++));
else
--lpDeTexInfo->smallLod;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: prGetLodSize
Date: 6/18/97
Implementor(s): psw
Library:
Description:
returns the size, in number of bytes, of an LOD based upon format,
LOD level and aspect ratio. this routine is meant to be used on
the void* in the GrTexInfo struct.
Arguments:
GrTexInfo *const disTexInfo - pointer to the Texture Info
GrLOD_t disLOD - the lod to get the size of
Return:
FxU32
-------------------------------------------------------------------*/
static FxU32
prGetLodSize( GrTexInfo *const deTexInfo, GrLOD_t deLod )
{
/* definitions */
int nPxlFctr;
int yAspctDvdr[] = {3, 2, 1, 0, 1, 2, 3}; /* ie. GR_ASPECT_1x8 = 2^3 */
int yLodFctr[] = {8, 7, 6, 5, 4, 3, 2, 1, 0}; /* ie. GR_LOD_256 = 2^8 */
FxU32 xNumBytes;
GrAspectRatio_t thisAR;
GrLOD_t thisLod;
/* code */
if ((deTexInfo->format == GR_TEXFMT_RGB_332) ||
(deTexInfo->format == GR_TEXFMT_YIQ_422) ||
(deTexInfo->format == GR_TEXFMT_ALPHA_8) ||
(deTexInfo->format == GR_TEXFMT_INTENSITY_8) ||
(deTexInfo->format == GR_TEXFMT_P_8))
nPxlFctr = 1; /* 8-bit formats */
else
nPxlFctr = 2; /* all else are 16-bit formats */
thisAR = deTexInfo->aspectRatio; /* thisAspectRatio */
thisLod = deLod; /* thisLod */
/* the general formula is xNumBytes=nBytesPerPixel*nPixels
** nPixels=maxPixels/aspectRatio
** maxPixels for GR_LOD_256=256*256 or 2^8*2^8, hence the following formula...*/
if ( yAspctDvdr[thisAR] < yLodFctr[thisLod] )
xNumBytes = nPxlFctr << yLodFctr[thisLod] << yLodFctr[thisLod] >>
yAspctDvdr[thisAR];
else
xNumBytes = nPxlFctr << yLodFctr[thisLod];
return xNumBytes;
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------
Function: prTexMultiMemRequired
Date: 6/27/97
Implementor(s): psw
Library:
Description:
calculates and returns the amount of memory required for the
individual multibase texture segments in BOTH, EVEN or ODD modes
traps cases for missing LODs
Arguments:
FxU32 deMipMask (GR_MIPMAPLEVELMASK)
GrTexBaseRange_t deRange
GrAspectRatio_t deRatio
GrTextureFormat_t deFormat
Return:
FxU32 - memory required
-------------------------------------------------------------------*/
static
FxU32 prTexMultiMemRequired( FxU32 deMipMask, GrTexBaseRange_t deMultiSeg,
GrTexInfo* deTexInfo )
{
/* definitions */
GrTexInfo tmpTexInfo,
*lpTmpTexInfo; /* create a copy of the GrTexInfo */
FxU32 thisSegMemReq = 0x0;
GrLOD_t lod;
/* initializations */
lpTmpTexInfo = &tmpTexInfo;
*lpTmpTexInfo = *deTexInfo; /* copy passed data, then prepare to munge */
/* code */
if ((lpTmpTexInfo->largeLod > (FxI32) deMultiSeg) ||
(lpTmpTexInfo->smallLod < (FxI32) deMultiSeg))
return 0; /* the deMultiSeg !exist in the lod range of info */
/* else it does */
for (lod = lpTmpTexInfo->largeLod; lod < (FxI32) deMultiSeg; ++lod)
prPopLod( lpTmpTexInfo, topOfMipMap ); /* munge the top */
if ( deMultiSeg != GR_TEXBASE_32_TO_1)
lpTmpTexInfo->smallLod = lpTmpTexInfo->largeLod; /* munge the btm */
thisSegMemReq = grTexTextureMemRequired( deMipMask, lpTmpTexInfo );
return thisSegMemReq;
} /* prTexMultiMemRequired */
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
static int
prGetLodWidth( GrLOD_t lod, GrAspectRatio_t aspect )
{
int yAspctWdvdr[] = {0, 0, 0, 0, 1, 2, 3};
int yLodFctr[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
int val;
val = yLodFctr[lod] > yAspctWdvdr[aspect] ?
1 << yLodFctr[lod] >> yAspctWdvdr[aspect] : 1;
return( val );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
static int
prGetLodHeight( GrLOD_t lod, GrAspectRatio_t aspect )
{
int yAspctHdvdr[] = {3, 2, 1, 0, 0, 0, 0};
int yLodFctr[] = {8, 7, 6, 5, 4, 3, 2, 1, 0};
int val;
val = yLodFctr[lod] > yAspctHdvdr[aspect] ?
1 << yLodFctr[lod] >> yAspctHdvdr[aspect] : 1;
return( val );
}
/*-------------------------------------------------------------------*/
/*-------------------------------------------------------------------*/
static FxU32
prGetMultiMemBump( const GrTexInfo *const deTexInfo,
GrTexBaseRange_t deTexBase,
FxU32 deMipMask )
{ /* this fixes some multibase fuckage */
/* definitions */
FxU32 xMemBump,
xAllMemReq,
xSegMemReq;
GrTexInfo tmpTexInfo,
*lpTmpTexInfo;
/* initializations */
lpTmpTexInfo = &tmpTexInfo;
*lpTmpTexInfo = *deTexInfo;
/* code */
lpTmpTexInfo->largeLod = GR_LOD_256;
xAllMemReq = grTexTextureMemRequired( deMipMask, lpTmpTexInfo );
lpTmpTexInfo->largeLod = deTexBase != GR_TEXBASE_32_TO_1 ? deTexBase :
lpTmpTexInfo->largeLod > (FxI32) deTexBase ?
lpTmpTexInfo->largeLod : GR_LOD_32;
xSegMemReq = grTexTextureMemRequired( deMipMask, lpTmpTexInfo );
xMemBump = xAllMemReq - xSegMemReq;
return (xMemBump);
}