Converted the Savage texture management to use Ian's common texmem code.

This commit is contained in:
Felix Kuehling 2005-01-24 01:15:12 +00:00
parent c74ffb8266
commit 428a5e82fc
4 changed files with 236 additions and 572 deletions

View file

@ -55,6 +55,8 @@
#include "savage_dri.h"
#include "texmem.h"
#include "xmlpool.h"
/* Driver-specific options
@ -295,7 +297,6 @@ savageCreateContext( const __GLcontextModes *mesaVis,
savageScreenPrivate *savageScreen = (savageScreenPrivate *)sPriv->private;
drm_savage_sarea_t *saPriv=(drm_savage_sarea_t *)(((char*)sPriv->pSAREA)+
savageScreen->sarea_priv_offset);
GLuint maxTextureSize, minTextureSize, maxTextureLevels;
int i;
imesa = (savageContextPtr)Xcalloc(sizeof(savageContext), 1);
if (!imesa) {
@ -332,60 +333,6 @@ savageCreateContext( const __GLcontextModes *mesaVis,
imesa->float_depth = driQueryOptionb(&imesa->optionCache, "float_depth") &&
savageScreen->chipset >= S3_SAVAGE4;
imesa->no_rast = driQueryOptionb(&imesa->optionCache, "no_rast");
imesa->texture_depth = driQueryOptioni (&imesa->optionCache,
"texture_depth");
if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
imesa->texture_depth = ( savageScreen->cpp == 4 ) ?
DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
if (savageScreen->chipset >= S3_SAVAGE4)
ctx->Const.MaxTextureUnits = 2;
else
ctx->Const.MaxTextureUnits = 1;
if (driQueryOptioni(&imesa->optionCache, "texture_units") <
ctx->Const.MaxTextureUnits)
ctx->Const.MaxTextureUnits =
driQueryOptioni(&imesa->optionCache, "texture_units");
ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
/* Set the maximum texture size small enough that we can guarentee
* that all texture units can bind a maximal texture and have them
* in memory at once.
*/
if (savageScreen->textureSize[SAVAGE_CARD_HEAP] >
savageScreen->textureSize[SAVAGE_AGP_HEAP]) {
maxTextureSize = savageScreen->textureSize[SAVAGE_CARD_HEAP];
minTextureSize = savageScreen->textureSize[SAVAGE_AGP_HEAP];
} else {
maxTextureSize = savageScreen->textureSize[SAVAGE_AGP_HEAP];
minTextureSize = savageScreen->textureSize[SAVAGE_CARD_HEAP];
}
if (ctx->Const.MaxTextureUnits == 2) {
/* How to distribute two maximum sized textures to two texture heaps?
* If the smaller heap is less then half the size of the bigger one
* then the maximum size is half the size of the bigger heap.
* Otherwise it's the size of the smaller heap. */
if (minTextureSize < maxTextureSize / 2)
maxTextureSize = maxTextureSize / 2;
else
maxTextureSize = minTextureSize;
}
for (maxTextureLevels = 1; maxTextureLevels <= 11; ++maxTextureLevels) {
GLuint size = 1 << maxTextureLevels;
size *= size * 4; /* 4 bytes per texel */
size = size * 4/3; /* all mipmap levels together take roughly
4/3 the size of the biggest level */
if (size > maxTextureSize)
break;
}
ctx->Const.MaxTextureLevels = maxTextureLevels;
if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/
__driUtilMessage("Not enough texture memory. "
"Falling back to indirect rendering.");
Xfree(imesa);
return GL_FALSE;
}
#if 0
ctx->Const.MinLineWidth = 1.0;
@ -419,19 +366,56 @@ savageCreateContext( const __GLcontextModes *mesaVis,
/* change texHeap initialize to support two kind of texture heap*/
/* here is some parts of initialization, others in InitDriver() */
(void) memset( imesa->textureHeaps, 0, sizeof( imesa->textureHeaps ) );
make_empty_list( & imesa->swapped );
imesa->lastTexHeap = savageScreen->texVirtual[SAVAGE_AGP_HEAP] ? 2 : 1;
/*allocate texHeap for multi-tex*/
{
int i;
for(i=0;i<imesa->lastTexHeap;i++)
{
imesa->texHeap[i] = mmInit( 0, savageScreen->textureSize[i] );
make_empty_list(&imesa->TexObjList[i]);
}
make_empty_list(&imesa->SwappedOut);
for (i = 0; i < imesa->lastTexHeap; i++) {
imesa->textureHeaps[i] = driCreateTextureHeap(
i, imesa,
savageScreen->textureSize[i],
11, /* 2^11 = 2k alignment */
SAVAGE_NR_TEX_REGIONS,
(drmTextureRegionPtr)imesa->sarea->texList[i],
&imesa->sarea->texAge[i],
&imesa->swapped,
sizeof( savageTexObj ),
(destroy_texture_object_t *) savageDestroyTexObj );
driSetTextureSwapCounterLocation( imesa->textureHeaps[i],
& imesa->c_textureSwaps );
}
imesa->texture_depth = driQueryOptioni (&imesa->optionCache,
"texture_depth");
if (imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FB)
imesa->texture_depth = ( savageScreen->cpp == 4 ) ?
DRI_CONF_TEXTURE_DEPTH_32 : DRI_CONF_TEXTURE_DEPTH_16;
if (savageScreen->chipset >= S3_SAVAGE4)
ctx->Const.MaxTextureUnits = 2;
else
ctx->Const.MaxTextureUnits = 1;
if (driQueryOptioni(&imesa->optionCache, "texture_units") <
ctx->Const.MaxTextureUnits)
ctx->Const.MaxTextureUnits =
driQueryOptioni(&imesa->optionCache, "texture_units");
ctx->Const.MaxTextureImageUnits = ctx->Const.MaxTextureUnits;
ctx->Const.MaxTextureCoordUnits = ctx->Const.MaxTextureUnits;
driCalculateMaxTextureLevels( imesa->textureHeaps,
imesa->lastTexHeap,
& ctx->Const,
4,
11, /* max 2D texture size is 2048x2048 */
0, /* 3D textures unsupported. */
0, /* cube textures unsupported. */
0, /* texture rectangles unsupported. */
12,
GL_FALSE );
if (ctx->Const.MaxTextureLevels <= 6) { /*spec requires at least 64x64*/
__driUtilMessage("Not enough texture memory. "
"Falling back to indirect rendering.");
Xfree(imesa);
return GL_FALSE;
}
imesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
@ -464,11 +448,8 @@ savageCreateContext( const __GLcontextModes *mesaVis,
imesa->RenderIndex = ~0;
imesa->dirty = ~0;
imesa->lostContext = GL_TRUE;
imesa->TextureMode = ctx->Texture.Unit[0].EnvMode;
imesa->CurrentTexObj[0] = 0;
imesa->CurrentTexObj[1] = 0;
imesa->texAge[SAVAGE_CARD_HEAP]=0;
imesa->texAge[SAVAGE_AGP_HEAP]=0;
/* Initialize the software rasterizer and helper modules.
*/
@ -529,25 +510,17 @@ static void
savageDestroyContext(__DRIcontextPrivate *driContextPriv)
{
savageContextPtr imesa = (savageContextPtr) driContextPriv->driverPrivate;
GLuint i;
assert (imesa); /* should never be NULL */
if (imesa) {
savageTextureObjectPtr next_t, t;
savageFlushVertices(imesa);
savageReleaseIndexedVerts(imesa);
savageFlushCmdBuf(imesa, GL_TRUE); /* release DMA buffer */
WAIT_IDLE_EMPTY(imesa);
/* update for multi-tex*/
{
int i;
for(i=0;i<imesa->lastTexHeap;i++)
foreach_s (t, next_t, &(imesa->TexObjList[i]))
savageDestroyTexObj(imesa, t);
}
foreach_s (t, next_t, &(imesa->SwappedOut))
savageDestroyTexObj(imesa, t);
for (i = 0; i < imesa->lastTexHeap; i++)
driDestroyTextureHeap(imesa->textureHeaps[i]);
free(imesa->cmdBuf.base);
free(imesa->clientVtxBuf.buf);
@ -785,43 +758,10 @@ void savageGetLock( savageContextPtr imesa, GLuint flags )
sarea->ctxOwner = me;
}
/* Shared texture managment - if another client has played with
* texture space, figure out which if any of our textures have been
* ejected, and update our global LRU.
*/
/*frank just for compiling,texAge,texList,AGP*/
for(heap= 0 ;heap < imesa->lastTexHeap ; heap++)
{
if (sarea->texAge[heap] != imesa->texAge[heap]) {
int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
int idx, nr = 0;
for (heap = 0; heap < imesa->lastTexHeap; ++heap) {
DRI_AGE_TEXTURES( imesa->textureHeaps[heap] );
}
/* Have to go right round from the back to ensure stuff ends up
* LRU in our local list...
*/
for (idx = sarea->texList[heap][SAVAGE_NR_TEX_REGIONS].prev ;
idx != SAVAGE_NR_TEX_REGIONS && nr < SAVAGE_NR_TEX_REGIONS ;
idx = sarea->texList[heap][idx].prev, nr++)
{
if (sarea->texList[heap][idx].age > imesa->texAge[heap])
{
savageTexturesGone(imesa, heap ,idx * sz, sz,
sarea->texList[heap][idx].in_use);
}
}
if (nr == SAVAGE_NR_TEX_REGIONS)
{
savageTexturesGone(imesa, heap, 0,
imesa->savageScreen->textureSize[heap], 0);
savageResetGlobalLRU( imesa , heap );
}
imesa->texAge[heap] = sarea->texAge[heap];
}
} /* end of for loop */
if (dPriv->lastStamp != stamp)
savageXMesaWindowMoved( imesa );

View file

@ -38,10 +38,11 @@ typedef struct savage_texture_object_t *savageTextureObjectPtr;
#include "drm.h"
#include "savage_drm.h"
#include "savage_init.h"
#include "savage_3d_reg.h"
#include "mm.h"
#include "tnl/t_vertex.h"
#include "savagetex.h"
#include "texmem.h"
#include "xmlconfig.h"
@ -153,18 +154,11 @@ struct savage_context_t {
GLcontext *glCtx;
int lastTexHeap;
savageTextureObjectPtr CurrentTexObj[2];
struct savage_texture_object_t TexObjList[SAVAGE_NR_TEX_HEAPS];
struct savage_texture_object_t SwappedOut;
GLuint c_texupload;
GLuint c_texusage;
GLuint tex_thrash;
GLuint TextureMode;
driTexHeap *textureHeaps[SAVAGE_NR_TEX_HEAPS];
driTextureObject swapped;
driTextureObject *CurrentTexObj[2];
/* Hardware state
*/
@ -192,7 +186,6 @@ struct savage_context_t {
/* Manage hardware state */
GLuint dirty;
GLboolean lostContext;
memHeap_t *texHeap[SAVAGE_NR_TEX_HEAPS];
GLuint bTexEn1;
/* One of the few bits of hardware state that can't be calculated
* completely on the fly:
@ -275,9 +268,6 @@ struct savage_context_t {
drm_clip_rect_t draw_rect;
drm_clip_rect_t scissor_rect;
/*Texture aging and DMA based aging*/
unsigned int texAge[SAVAGE_NR_TEX_HEAPS];
drm_context_t hHWContext;
drm_hw_lock_t *driHwLock;
GLuint driFd;
@ -298,6 +288,10 @@ struct savage_context_t {
GLboolean hw_stencil;
/* Performance counters
*/
GLuint c_textureSwaps;
/* Configuration cache
*/
driOptionCache optionCache;

View file

@ -186,9 +186,9 @@ static void savageUploadTiny (const savageTileInfo *tileInfo,
/** \brief Upload an image from mesa's internal copy.
*/
static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
static void savageUploadTexLevel( savageTexObjPtr t, int level )
{
const struct gl_texture_image *image = t->image[level].image;
const struct gl_texture_image *image = t->base.tObj->Image[0][level];
const savageTileInfo *tileInfo = t->tileInfo;
GLuint width = image->Width2, height = image->Height2;
GLuint bpp = t->texelBytes;
@ -207,7 +207,7 @@ static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
GLuint wInTiles = width / tileInfo->width;
GLuint hInTiles = height / tileInfo->height;
GLubyte *srcTRow = image->Data, *src;
GLubyte *dest = (GLubyte *)(t->BufAddr + t->image[level].offset);
GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset);
GLuint x, y;
for (y = 0; y < hInTiles; ++y) {
src = srcTRow;
@ -224,7 +224,7 @@ static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
savageUploadTile (tileInfo, width / tileInfo->subWidth,
height / tileInfo->subHeight, bpp,
image->Data, width * bpp,
(GLubyte *)(t->BufAddr+t->image[level].offset));
(GLubyte *)(t->bufAddr+t->image[level].offset));
}
} else {
GLuint minHeight, minWidth, hRepeat, vRepeat, x, y;
@ -241,7 +241,7 @@ static void savageUploadTexLevel( savageTextureObjectPtr t, int level )
GLuint offset = y * tileInfo->subWidth*height * bpp;
for (x = 0; x < hRepeat; ++x) {
savageUploadTiny (tileInfo, width, height, bpp, image->Data,
(GLubyte *)(t->BufAddr +
(GLubyte *)(t->bufAddr +
t->image[level].offset+offset));
offset += width * bpp;
}
@ -270,48 +270,47 @@ static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) {
return 64 * bpp;
}
static void savageSetTexWrapping(savageTextureObjectPtr tex, GLenum s, GLenum t)
static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t)
{
tex->texParams.sWrapMode = s;
tex->texParams.tWrapMode = t;
tex->setup.sWrapMode = s;
tex->setup.tWrapMode = t;
}
static void savageSetTexFilter(savageTextureObjectPtr t,
GLenum minf, GLenum magf)
static void savageSetTexFilter(savageTexObjPtr t, GLenum minf, GLenum magf)
{
t->texParams.minFilter = minf;
t->texParams.magFilter = magf;
t->setup.minFilter = minf;
t->setup.magFilter = magf;
}
/* Need a fallback ?
*/
static void savageSetTexBorderColor(savageTextureObjectPtr t, GLubyte color[4])
static void savageSetTexBorderColor(savageTexObjPtr t, GLubyte color[4])
{
/* t->Setup[SAVAGE_TEXREG_TEXBORDERCOL] = */
t->texParams.boarderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]);
/*t->setup.borderColor = SAVAGEPACKCOLOR8888(color[0],color[1],color[2],color[3]); */
}
static savageTextureObjectPtr
static savageTexObjPtr
savageAllocTexObj( struct gl_texture_object *texObj )
{
savageTextureObjectPtr t;
savageTexObjPtr t;
t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
t = (savageTexObjPtr) calloc(1,sizeof(*t));
texObj->DriverData = t;
if ( t != NULL ) {
/* Initialize non-image-dependent parts of the state:
*/
t->globj = texObj;
t->base.tObj = texObj;
/* FIXME Something here to set initial values for other parts of
* FIXME t->setup?
*/
make_empty_list( t );
make_empty_list( &t->base );
savageSetTexWrapping(t,texObj->WrapS,texObj->WrapT);
savageSetTexFilter(t,texObj->MinFilter,texObj->MagFilter);
@ -333,7 +332,6 @@ savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
( imesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16 );
const GLboolean isSavage4 = (imesa->savageScreen->chipset >= S3_SAVAGE4);
(void) format;
(void) type;
switch ( internalFormat ) {
case 4:
@ -468,9 +466,10 @@ savageChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
static void savageSetTexImages( savageContextPtr imesa,
const struct gl_texture_object *tObj )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
struct gl_texture_image *image = tObj->Image[0][tObj->BaseLevel];
GLuint offset, i, textureFormat, size;
GLint firstLevel, lastLevel;
assert(t);
assert(image);
@ -508,6 +507,7 @@ static void savageSetTexImages( savageContextPtr imesa,
_mesa_problem(imesa->glCtx, "Bad texture format in %s", __FUNCTION__);
return;
}
t->hwFormat = textureFormat;
/* Select tiling format depending on the chipset and bytes per texel */
if (imesa->savageScreen->chipset <= S3_SAVAGE4)
@ -515,288 +515,92 @@ static void savageSetTexImages( savageContextPtr imesa,
else
t->tileInfo = &tileInfo_pro[t->texelBytes];
/* Compute which mipmap levels we really want to send to the hardware.
*/
driCalculateTextureFirstLastLevel( &t->base );
firstLevel = t->base.firstLevel;
lastLevel = t->base.lastLevel;
/* Figure out the size now (and count the levels). Upload won't be done
* until later.
*/
t->dirty_images = 0;
offset = 0;
size = 1;
for ( i = 0 ; i < SAVAGE_TEX_MAXLEVELS && tObj->Image[0][i] ; i++ ) {
image = tObj->Image[0][i];
t->image[i].image = image;
for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) {
t->image[i].offset = offset;
t->image[i].internalFormat = textureFormat;
t->dirty_images |= (1<<i);
image = tObj->Image[0][i];
size = savageTexImageSize (image->Width2, image->Height2,
t->texelBytes);
offset += size;
}
t->totalSize = offset;
t->base.lastLevel = i-1;
t->base.totalSize = offset;
/* the last three mipmap levels don't add to the offset. They are packed
* into 64 pixels. */
if (size == 0)
t->totalSize += 64 * t->texelBytes;
/* 2k-aligned */
t->totalSize = (t->totalSize + 2047UL) & ~2047UL;
t->max_level = i-1;
t->min_level = 0;
t->base.totalSize += 64 * t->texelBytes;
/* 2k-aligned (really needed?) */
t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL;
}
void savageDestroyTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
void savageDestroyTexObj(savageContextPtr imesa, driTextureObject *t)
{
if (!t) return;
/* See if it was the driver's current object.
*/
/* 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 (t->age > imesa->dirtyAge)
imesa->dirtyAge = t->age;
}
if (t->globj)
t->globj->DriverData = 0;
remove_from_list(t);
free(t);
if ( imesa != NULL )
{
GLuint i;
for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ )
{
if ( t == imesa->CurrentTexObj[ i ] ) {
assert( t->bound & (1 << i) );
imesa->CurrentTexObj[ i ] = NULL;
}
}
}
}
static void savageSwapOutTexObj(savageContextPtr imesa, savageTextureObjectPtr t)
{
if (t->MemBlock) {
mmFreeMem(t->MemBlock);
t->MemBlock = 0;
if (t->age > imesa->dirtyAge)
imesa->dirtyAge = t->age;
}
t->dirty_images = ~0;
move_to_tail(&(imesa->SwappedOut), t);
}
void savagePrintLocalLRU( savageContextPtr imesa , GLuint heap)
{
savageTextureObjectPtr t;
int sz = 1 << (imesa->savageScreen->logTextureGranularity[heap]);
foreach( t, &imesa->TexObjList[heap] ) {
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 (bound %d) at %x sz %x\n",
t->bound,
t->MemBlock->ofs,
t->MemBlock->size);
}
}
void savagePrintGlobalLRU( savageContextPtr imesa , GLuint heap)
{
int i, j;
drm_tex_region_t *list = imesa->sarea->texList[heap];
for (i = 0, j = SAVAGE_NR_TEX_REGIONS ; i < SAVAGE_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 == SAVAGE_NR_TEX_REGIONS) break;
}
if (j != SAVAGE_NR_TEX_REGIONS)
fprintf(stderr, "Loop detected in global LRU\n");
for (i = 0 ; i < SAVAGE_NR_TEX_REGIONS ; i++)
{
fprintf(stderr,"list[%d] age %d next %d prev %d\n",
i, list[i].age, list[i].next, list[i].prev);
}
}
void savageResetGlobalLRU( savageContextPtr imesa, GLuint heap )
{
drm_tex_region_t *list = imesa->sarea->texList[heap];
int sz = 1 << imesa->savageScreen->logTextureGranularity[heap];
int i;
/* (Re)initialize the global circular LRU list. The last element
* in the array (SAVAGE_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 <= imesa->savageScreen->textureSize[heap]; i++) {
list[i].prev = i-1;
list[i].next = i+1;
list[i].age = 0;
}
i--;
list[0].prev = SAVAGE_NR_TEX_REGIONS;
list[i].prev = i-1;
list[i].next = SAVAGE_NR_TEX_REGIONS;
list[SAVAGE_NR_TEX_REGIONS].prev = i;
list[SAVAGE_NR_TEX_REGIONS].next = 0;
imesa->sarea->texAge[heap] = 0;
}
static void savageUpdateTexLRU( savageContextPtr imesa, savageTextureObjectPtr t )
{
int i;
int heap = t->heap;
int logsz = imesa->savageScreen->logTextureGranularity[heap];
int start = t->MemBlock->ofs >> logsz;
int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
drm_tex_region_t *list = imesa->sarea->texList[heap];
imesa->texAge[heap] = ++imesa->sarea->texAge[heap];
/* Update our local LRU
*/
move_to_head( &(imesa->TexObjList[heap]), t );
/* Update the global LRU
*/
for (i = start ; i <= end ; i++) {
list[i].in_use = 1;
list[i].age = imesa->texAge[heap];
/* 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 = SAVAGE_NR_TEX_REGIONS;
list[i].next = list[SAVAGE_NR_TEX_REGIONS].next;
list[(unsigned)list[SAVAGE_NR_TEX_REGIONS].next].prev = i;
list[SAVAGE_NR_TEX_REGIONS].next = i;
}
}
/* 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.
/* Upload a texture's images to one of the texture heaps. May have to
* eject our own and/or other client's texture objects to make room
* for the upload.
*/
void savageTexturesGone( savageContextPtr imesa,
GLuint heap,
GLuint offset,
GLuint size,
GLuint in_use )
static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t )
{
savageTextureObjectPtr t, tmp;
const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
GLuint i;
assert(t);
LOCK_HARDWARE(imesa);
foreach_s ( t, tmp, &imesa->TexObjList[heap] ) {
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.
*/
if (t->bound)
savageSwapOutTexObj( imesa, t );
else
savageDestroyTexObj( imesa, t );
}
if (in_use) {
t = (savageTextureObjectPtr) calloc(1,sizeof(*t));
if (!t) return;
t->heap = heap;
t->MemBlock = mmAllocMem( imesa->texHeap[heap], size, 0, offset);
if(!t->MemBlock)
{
free(t);
return;
}
insert_at_head( &imesa->TexObjList[heap], t );
}
}
/* 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.
*/
int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
{
int heap;
int i;
int ofs;
heap = t->heap = SAVAGE_CARD_HEAP;
/* Do we need to eject LRU texture objects?
*/
if (!t->MemBlock) {
while (1)
{
t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
if (t->MemBlock)
break;
else if (imesa->lastTexHeap == 2)
{
heap = t->heap = SAVAGE_AGP_HEAP;
t->MemBlock = mmAllocMem( imesa->texHeap[heap], t->totalSize, 12, 0 );
if (t->MemBlock)
break;
}
if (!t->base.memBlock) {
GLint heap;
GLuint ofs;
if (imesa->TexObjList[heap].prev->bound) {
fprintf(stderr, "Hit bound texture in upload\n");
savagePrintLocalLRU( imesa,heap );
return -1;
}
if (imesa->TexObjList[heap].prev == &(imesa->TexObjList[heap])) {
fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
mmDumpMemInfo( imesa->texHeap[heap] );
return -1;
}
savageSwapOutTexObj( imesa, imesa->TexObjList[heap].prev );
heap = driAllocateTexture(imesa->textureHeaps, imesa->lastTexHeap,
(driTextureObject *)t);
if (heap == -1) {
UNLOCK_HARDWARE(imesa);
return;
}
ofs = t->MemBlock->ofs;
t->texParams.hwPhysAddress = imesa->savageScreen->textureOffset[heap] + ofs;
t->BufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
ofs = t->base.memBlock->ofs;
t->setup.physAddr = imesa->savageScreen->textureOffset[heap] + ofs;
t->bufAddr = (char *)((GLuint) imesa->savageScreen->texVirtual[heap] + ofs);
imesa->dirty |= SAVAGE_UPLOAD_GLOBAL; /* FIXME: really needed? */
}
/* Let the world know we've used this memory recently.
*/
LOCK_HARDWARE(imesa);
savageUpdateTexLRU( imesa, t );
driUpdateTextureLRU( &t->base );
UNLOCK_HARDWARE(imesa);
if (t->dirty_images) {
if (t->base.dirty_images[0]) {
savageFlushVertices (imesa);
LOCK_HARDWARE(imesa);
savageFlushCmdBufLocked (imesa, GL_FALSE);
@ -804,22 +608,14 @@ int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t )
if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU)
fprintf(stderr, "*");
for (i = t->min_level ; i <= t->max_level ; i++)
if (t->dirty_images & (1<<i))
savageUploadTexLevel( t, i );
for (i = 0 ; i < numLevels ; i++) {
const GLint j = t->base.firstLevel + i; /* the texObj's level */
if (t->base.dirty_images[0] & (1<<j))
savageUploadTexLevel( t, j );
}
UNLOCK_HARDWARE(imesa);
t->base.dirty_images[0] = 0;
}
t->dirty_images = 0;
return 0;
}
static void savageTexSetUnit( savageTextureObjectPtr t, GLuint unit )
{
if (t->current_unit == unit) return;
t->current_unit = unit;
}
@ -829,7 +625,8 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
savageTextureObjectPtr t;
struct gl_texture_image *image;
savageTexObjPtr t;
GLuint format;
/* disable */
@ -857,19 +654,15 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
return;
}
if (t->current_unit != 0)
savageTexSetUnit( t, 0 );
imesa->CurrentTexObj[0] = t;
t->bound |= 1;
imesa->CurrentTexObj[0] = &t->base;
t->base.bound |= 1;
if (t->dirty_images) {
if (t->base.dirty_images[0]) {
savageSetTexImages(imesa, tObj);
savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
savageUploadTexImages(imesa, t);
}
if (t->MemBlock)
savageUpdateTexLRU( imesa, t );
driUpdateTextureLRU( &t->base );
format = tObj->Image[0][tObj->BaseLevel]->Format;
@ -1026,11 +819,11 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
}
imesa->regs.s4.texCtrl[0].ni.uMode =
t->texParams.sWrapMode == GL_REPEAT ? 0 : 1;
t->setup.sWrapMode == GL_REPEAT ? 0 : 1;
imesa->regs.s4.texCtrl[0].ni.vMode =
t->texParams.tWrapMode == GL_REPEAT ? 0 : 1;
t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
switch (t->texParams.minFilter)
switch (t->setup.minFilter)
{
case GL_NEAREST:
imesa->regs.s4.texCtrl[0].ni.filterMode = TFM_Point;
@ -1070,17 +863,18 @@ static void savageUpdateTex0State_s4( GLcontext *ctx )
imesa->regs.s4.texCtrl[0].ni.dBias = bias & 0x1ff;
}
image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s4.texDescr.ni.tex0En = GL_TRUE;
imesa->regs.s4.texDescr.ni.tex0Width = t->image[0].image->WidthLog2;
imesa->regs.s4.texDescr.ni.tex0Height = t->image[0].image->HeightLog2;
imesa->regs.s4.texDescr.ni.tex0Fmt = t->image[0].internalFormat;
imesa->regs.s4.texCtrl[0].ni.dMax = t->max_level;
imesa->regs.s4.texDescr.ni.tex0Width = image->WidthLog2;
imesa->regs.s4.texDescr.ni.tex0Height = image->HeightLog2;
imesa->regs.s4.texDescr.ni.tex0Fmt = t->hwFormat;
imesa->regs.s4.texCtrl[0].ni.dMax = t->base.lastLevel - t->base.firstLevel;
if (imesa->regs.s4.texDescr.ni.tex1En)
imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->texParams.hwPhysAddress | 0x2;
if(t->heap == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[0].ui = (u_int32_t) t->setup.physAddr | 0x2;
if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[0].ui |= 0x1;
return;
@ -1089,7 +883,8 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
savageTextureObjectPtr t;
struct gl_texture_image *image;
savageTexObjPtr t;
GLuint format;
/* disable */
@ -1125,20 +920,16 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
return;
}
if (t->current_unit != 1)
savageTexSetUnit( t, 1 );
imesa->CurrentTexObj[1] = &t->base;
imesa->CurrentTexObj[1] = t;
t->base.bound |= 2;
t->bound |= 2;
if (t->dirty_images) {
if (t->base.dirty_images[0]) {
savageSetTexImages(imesa, tObj);
savageUploadTexImages(imesa, imesa->CurrentTexObj[1]);
savageUploadTexImages(imesa, t);
}
if (t->MemBlock)
savageUpdateTexLRU( imesa, t );
driUpdateTextureLRU( &t->base );
format = tObj->Image[0][tObj->BaseLevel]->Format;
@ -1229,11 +1020,11 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
}
imesa->regs.s4.texCtrl[1].ni.uMode =
t->texParams.sWrapMode == GL_REPEAT ? 0 : 1;
t->setup.sWrapMode == GL_REPEAT ? 0 : 1;
imesa->regs.s4.texCtrl[1].ni.vMode =
t->texParams.tWrapMode == GL_REPEAT ? 0 : 1;
t->setup.tWrapMode == GL_REPEAT ? 0 : 1;
switch (t->texParams.minFilter)
switch (t->setup.minFilter)
{
case GL_NEAREST:
imesa->regs.s4.texCtrl[1].ni.filterMode = TFM_Point;
@ -1273,22 +1064,24 @@ static void savageUpdateTex1State_s4( GLcontext *ctx )
imesa->regs.s4.texCtrl[1].ni.dBias = bias & 0x1ff;
}
image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s4.texDescr.ni.tex1En = GL_TRUE;
imesa->regs.s4.texDescr.ni.tex1Width = t->image[0].image->WidthLog2;
imesa->regs.s4.texDescr.ni.tex1Height = t->image[0].image->HeightLog2;
imesa->regs.s4.texDescr.ni.tex1Fmt = t->image[0].internalFormat;
imesa->regs.s4.texCtrl[1].ni.dMax = t->max_level;
imesa->regs.s4.texDescr.ni.tex1Width = image->WidthLog2;
imesa->regs.s4.texDescr.ni.tex1Height = image->HeightLog2;
imesa->regs.s4.texDescr.ni.tex1Fmt = t->hwFormat;
imesa->regs.s4.texCtrl[1].ni.dMax = t->base.lastLevel - t->base.firstLevel;
imesa->regs.s4.texDescr.ni.texBLoopEn = GL_TRUE;
imesa->regs.s4.texAddr[1].ui = (u_int32_t) t->texParams.hwPhysAddress| 2;
if(t->heap == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[1].ui = (u_int32_t) t->setup.physAddr | 2;
if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s4.texAddr[1].ui |= 0x1;
}
static void savageUpdateTexState_s3d( GLcontext *ctx )
{
savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
struct gl_texture_object *tObj;
savageTextureObjectPtr t;
struct gl_texture_image *image;
savageTexObjPtr t;
GLuint format;
/* disable */
@ -1316,19 +1109,15 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
return;
}
if (t->current_unit != 0)
savageTexSetUnit( t, 0 );
imesa->CurrentTexObj[0] = &t->base;
t->base.bound |= 1;
imesa->CurrentTexObj[0] = t;
t->bound |= 1;
if (t->dirty_images) {
if (t->base.dirty_images[0]) {
savageSetTexImages(imesa, tObj);
savageUploadTexImages(imesa, imesa->CurrentTexObj[0]);
savageUploadTexImages(imesa, t);
}
if (t->MemBlock)
savageUpdateTexLRU( imesa, t );
driUpdateTextureLRU( &t->base );
format = tObj->Image[0][tObj->BaseLevel]->Format;
@ -1357,12 +1146,12 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
truth. */
imesa->regs.s3d.texCtrl.ni.uWrapEn = 0;
imesa->regs.s3d.texCtrl.ni.vWrapEn = 0;
if (t->texParams.sWrapMode == GL_CLAMP)
if (t->setup.sWrapMode == GL_CLAMP)
imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Clamp;
else
imesa->regs.s3d.texCtrl.ni.wrapMode = TAM_Wrap;
switch (t->texParams.minFilter) {
switch (t->setup.minFilter) {
case GL_NEAREST:
imesa->regs.s3d.texCtrl.ni.filterMode = TFM_Point;
imesa->regs.s3d.texCtrl.ni.mipmapDisable = GL_TRUE;
@ -1413,14 +1202,15 @@ static void savageUpdateTexState_s3d( GLcontext *ctx )
imesa->regs.s3d.texCtrl.ni.dBias = bias & 0x1ff;
}
image = tObj->Image[0][tObj->BaseLevel];
imesa->regs.s3d.texCtrl.ni.texEn = GL_TRUE;
imesa->regs.s3d.texDescr.ni.texWidth = t->image[0].image->WidthLog2;
imesa->regs.s3d.texDescr.ni.texHeight = t->image[0].image->HeightLog2;
assert (t->image[0].internalFormat <= 7);
imesa->regs.s3d.texDescr.ni.texFmt = t->image[0].internalFormat;
imesa->regs.s3d.texDescr.ni.texWidth = image->WidthLog2;
imesa->regs.s3d.texDescr.ni.texHeight = image->HeightLog2;
assert (t->hwFormat <= 7);
imesa->regs.s3d.texDescr.ni.texFmt = t->hwFormat;
imesa->regs.s3d.texAddr.ui = (u_int32_t) t->texParams.hwPhysAddress| 2;
if(t->heap == SAVAGE_AGP_HEAP)
imesa->regs.s3d.texAddr.ui = (u_int32_t) t->setup.physAddr | 2;
if(t->base.heap->heapId == SAVAGE_AGP_HEAP)
imesa->regs.s3d.texAddr.ui |= 0x1;
}
@ -1500,9 +1290,9 @@ static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
if (t) {
savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
driSwapOutTextureObject( &t->base );
} else {
t = savageAllocTexObj(texObj);
if (!t) {
@ -1513,7 +1303,7 @@ static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level,
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images |= (1 << level);
t->base.dirty_images[0] |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
@ -1528,10 +1318,10 @@ static void savageTexSubImage1D( GLcontext *ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
assert( t ); /* this _should_ be true */
if (t) {
savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
driSwapOutTextureObject( &t->base );
} else {
t = savageAllocTexObj(texObj);
if (!t) {
@ -1542,7 +1332,7 @@ static void savageTexSubImage1D( GLcontext *ctx,
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
t->dirty_images |= (1 << level);
t->base.dirty_images[0] |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
@ -1554,9 +1344,9 @@ static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
if (t) {
savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
driSwapOutTextureObject( &t->base );
} else {
t = savageAllocTexObj(texObj);
if (!t) {
@ -1567,7 +1357,7 @@ static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level,
_mesa_store_teximage2d( ctx, target, level, internalFormat,
width, height, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images |= (1 << level);
t->base.dirty_images[0] |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
@ -1582,10 +1372,10 @@ static void savageTexSubImage2D( GLcontext *ctx,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) texObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData;
assert( t ); /* this _should_ be true */
if (t) {
savageSwapOutTexObj( SAVAGE_CONTEXT(ctx), t );
driSwapOutTextureObject( &t->base );
} else {
t = savageAllocTexObj(texObj);
if (!t) {
@ -1596,7 +1386,7 @@ static void savageTexSubImage2D( GLcontext *ctx,
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images |= (1 << level);
t->base.dirty_images[0] |= (1 << level);
SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE;
}
@ -1604,7 +1394,7 @@ static void savageTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
savageTextureObjectPtr t = (savageTextureObjectPtr) tObj->DriverData;
savageTexObjPtr t = (savageTexObjPtr) tObj->DriverData;
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
if (!t || (target != GL_TEXTURE_1D && target != GL_TEXTURE_2D))
@ -1645,37 +1435,21 @@ static void savageBindTexture( GLcontext *ctx, GLenum target,
static void savageDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
{
savageTextureObjectPtr t = (savageTextureObjectPtr)tObj->DriverData;
driTextureObject *t = (driTextureObject *)tObj->DriverData;
savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
if (t) {
if (t->bound) {
imesa->CurrentTexObj[t->bound-1] = 0;
imesa->new_state |= SAVAGE_NEW_TEXTURE;
FLUSH_BATCH(imesa);
}
savageDestroyTexObj(imesa,t);
tObj->DriverData=0;
driDestroyTextureObject(t);
}
/* Free mipmap images and the texture object itself */
_mesa_delete_texture_object(ctx, tObj);
}
static GLboolean savageIsTextureResident( GLcontext *ctx,
struct gl_texture_object *t )
{
savageTextureObjectPtr mt;
/* LOCK_HARDWARE; */
mt = (savageTextureObjectPtr)t->DriverData;
/* UNLOCK_HARDWARE; */
return mt && mt->MemBlock;
}
static struct gl_texture_object *
savageNewTextureObject( GLcontext *ctx, GLuint name, GLenum target )
{
@ -1697,6 +1471,6 @@ void savageDDInitTextureFuncs( struct dd_function_table *functions )
functions->BindTexture = savageBindTexture;
functions->NewTextureObject = savageNewTextureObject;
functions->DeleteTexture = savageDeleteTexture;
functions->IsTextureResident = savageIsTextureResident;
functions->IsTextureResident = driIsTextureResident;
functions->TexParameter = savageTexParameter;
}

View file

@ -27,39 +27,11 @@
#define SAVAGETEX_INC
#include "mtypes.h"
#include "mm.h"
#include "savagecontext.h"
#include "savage_3d_reg.h"
#define VALID_SAVAGE_TEXTURE_OBJECT(tobj) (tobj)
#include "texmem.h"
#define SAVAGE_TEX_MAXLEVELS 11
#define MIN_TILE_CHUNK 8
#define MIPMAP_CHUNK 4
/* 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'
*/
typedef struct {
GLuint sWrapMode;
GLuint tWrapMode;
GLuint minFilter;
GLuint magFilter;
GLuint boarderColor;
GLuint hwPhysAddress;
} savage_texture_parameter_t;
/** \brief Texture tiling information */
typedef struct savage_tileinfo_t {
@ -69,36 +41,29 @@ typedef struct savage_tileinfo_t {
GLuint tinyOffset[2]; /**< internal offsets size 1 and 2 images */
} savageTileInfo, *savageTileInfoPtr;
struct savage_texture_object_t {
struct savage_texture_object_t *next, *prev;
struct gl_texture_object *globj;
GLuint age;
const savageTileInfo *tileInfo;
GLuint texelBytes;
GLuint totalSize;
GLuint bound;
GLuint heap;
typedef struct {
GLuint offset;
GLuint *dirtyTiles; /* bit vector of dirty tiles (still unused) */
} savageTexImage;
PMemBlock MemBlock;
char *BufAddr;
GLuint min_level;
GLuint max_level;
GLuint dirty_images;
typedef struct {
driTextureObject base;
struct {
const struct gl_texture_image *image;
GLuint offset; /* into BufAddr */
GLuint height;
GLuint internalFormat;
} image[SAVAGE_TEX_MAXLEVELS];
GLubyte *bufAddr;
/* Support for multitexture.
*/
GLuint current_unit;
savage_texture_parameter_t texParams;
};
GLuint age;
savageTexImage image[SAVAGE_TEX_MAXLEVELS];
struct {
GLuint sWrapMode, tWrapMode;
GLuint minFilter, magFilter;
GLuint physAddr;
} setup;
GLuint hwFormat;
GLuint texelBytes;
const savageTileInfo *tileInfo;
} savageTexObj, *savageTexObjPtr;
#define SAVAGE_NO_PALETTE 0x0
#define SAVAGE_USE_PALETTE 0x1
@ -111,15 +76,6 @@ struct savage_texture_object_t {
void savageUpdateTextureState( GLcontext *ctx );
void savageDDInitTextureFuncs( struct dd_function_table *functions );
void savageDestroyTexObj( savageContextPtr imesa, savageTextureObjectPtr t);
int savageUploadTexImages( savageContextPtr imesa, savageTextureObjectPtr t );
void savageResetGlobalLRU( savageContextPtr imesa , GLuint heap);
void savageTexturesGone( savageContextPtr imesa, GLuint heap,
GLuint start, GLuint end,
GLuint in_use );
void savagePrintLocalLRU( savageContextPtr imesa ,GLuint heap);
void savagePrintGlobalLRU( savageContextPtr imesa ,GLuint heap);
void savageDestroyTexObj( savageContextPtr imesa, driTextureObject *t );
#endif