From: George Sapountzis Date: Thu, 7 Dec 2006 16:01:13 +0000 (+0200) Subject: Bug 7260: mach64 texture memory mng cleanup X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5b35132b41427798e02a66a8e39583fffbe9d232;p=mesa.git Bug 7260: mach64 texture memory mng cleanup mach64 uses its own set of texture memory management routines which are buggy, running a second DRI client kills the first one. This patch ports mach64 code to the stock dri texture managment code. --- diff --git a/src/mesa/drivers/dri/mach64/mach64_context.c b/src/mesa/drivers/dri/mach64/mach64_context.c index 03ec96a222e..2ab1cf2617e 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.c +++ b/src/mesa/drivers/dri/mach64/mach64_context.c @@ -102,6 +102,7 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual, mach64ContextPtr mmesa; mach64ScreenPtr mach64Screen; int i, heap; + GLuint *c_textureSwapsPtr = NULL; #if DO_DEBUG MACH64_DEBUG = driParseDebugString(getenv("MACH64_DEBUG"), debug_control); @@ -153,15 +154,28 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual, mmesa->CurrentTexObj[0] = NULL; mmesa->CurrentTexObj[1] = NULL; - make_empty_list( &mmesa->SwappedOut ); + (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) ); + make_empty_list( &mmesa->swapped ); mmesa->firstTexHeap = mach64Screen->firstTexHeap; mmesa->lastTexHeap = mach64Screen->firstTexHeap + mach64Screen->numTexHeaps; for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) { - make_empty_list( &mmesa->TexObjList[i] ); - mmesa->texHeap[i] = mmInit( 0, mach64Screen->texSize[i] ); - mmesa->lastTexAge[i] = -1; + mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa, + mach64Screen->texSize[i], + 6, /* align to 64-byte boundary, use 12 for page-size boundary */ + MACH64_NR_TEX_REGIONS, + (drmTextureRegionPtr)mmesa->sarea->tex_list[i], + &mmesa->sarea->tex_age[i], + &mmesa->swapped, + sizeof( mach64TexObj ), + (destroy_texture_object_t *) mach64DestroyTexObj ); + +#if ENABLE_PERF_BOXES + c_textureSwapsPtr = & mmesa->c_textureSwaps; +#endif + driSetTextureSwapCounterLocation( mmesa->texture_heaps[i], + c_textureSwapsPtr ); } mmesa->RenderIndex = -1; /* Impossible value */ @@ -176,17 +190,25 @@ GLboolean mach64CreateContext( const __GLcontextModes *glVisual, * Test for 2 textures * bytes/texel * size * size. There's no * need to account for mipmaps since we only upload one level. */ - heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP; - - if ( mach64Screen->texSize[heap] >= 2 * mach64Screen->cpp * 1024*1024 ) { - ctx->Const.MaxTextureLevels = 11; /* 1024x1024 */ - } else if ( mach64Screen->texSize[heap] >= 2 * mach64Screen->cpp * 512*512 ) { - ctx->Const.MaxTextureLevels = 10; /* 512x512 */ - } else { - ctx->Const.MaxTextureLevels = 9; /* 256x256 */ - } ctx->Const.MaxTextureUnits = 2; + ctx->Const.MaxTextureImageUnits = 2; + ctx->Const.MaxTextureCoordUnits = 2; + + heap = mach64Screen->IsPCI ? MACH64_CARD_HEAP : MACH64_AGP_HEAP; + + driCalculateMaxTextureLevels( & mmesa->texture_heaps[heap], + 1, + & ctx->Const, + mach64Screen->cpp, + 10, /* max 2D texture size is 1024x1024 */ + 0, /* 3D textures unsupported. */ + 0, /* cube textures unsupported. */ + 0, /* texture rectangles unsupported. */ + 1, /* mipmapping unsupported. */ + GL_TRUE, /* need to have both textures in + either local or AGP memory */ + 0 ); #if ENABLE_PERF_BOXES mmesa->boxes = ( getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL ); @@ -250,31 +272,29 @@ void mach64DestroyContext( __DRIcontextPrivate *driContextPriv ) assert(mmesa); /* should never be null */ if ( mmesa ) { - if (mmesa->glCtx->Shared->RefCount == 1) { + GLboolean release_texture_heaps; + + release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1); + + _swsetup_DestroyContext( mmesa->glCtx ); + _tnl_DestroyContext( mmesa->glCtx ); + _ac_DestroyContext( mmesa->glCtx ); + _swrast_DestroyContext( mmesa->glCtx ); + + if (release_texture_heaps) { /* This share group is about to go away, free our private * texture object data. */ - mach64TexObjPtr t, next_t; int i; for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) { - foreach_s ( t, next_t, &mmesa->TexObjList[i] ) { - mach64DestroyTexObj( mmesa, t ); - } - mmDestroy( mmesa->texHeap[i] ); - mmesa->texHeap[i] = NULL; + driDestroyTextureHeap( mmesa->texture_heaps[i] ); + mmesa->texture_heaps[i] = NULL; } - foreach_s ( t, next_t, &mmesa->SwappedOut ) { - mach64DestroyTexObj( mmesa, t ); - } + assert( is_empty_list( & mmesa->swapped ) ); } - _swsetup_DestroyContext( mmesa->glCtx ); - _tnl_DestroyContext( mmesa->glCtx ); - _ac_DestroyContext( mmesa->glCtx ); - _swrast_DestroyContext( mmesa->glCtx ); - mach64FreeVB( mmesa->glCtx ); /* Free the vertex buffer */ diff --git a/src/mesa/drivers/dri/mach64/mach64_context.h b/src/mesa/drivers/dri/mach64/mach64_context.h index e718b96c188..8d89452412b 100644 --- a/src/mesa/drivers/dri/mach64/mach64_context.h +++ b/src/mesa/drivers/dri/mach64/mach64_context.h @@ -134,46 +134,17 @@ typedef void (*mach64_line_func)( mach64ContextPtr, typedef void (*mach64_point_func)( mach64ContextPtr, mach64Vertex * ); -#ifdef TEXMEM struct mach64_texture_object { driTextureObject base; - GLuint offset; + GLuint bufAddr; - GLuint dirty; - GLuint age; + GLint heap; /* same as base.heap->heapId */ - GLint widthLog2; - GLint heightLog2; - GLint maxLog2; - - GLint hasAlpha; - GLint textureFormat; - - /* Have to keep these separate due to how they are programmed. - * FIXME: Why don't we just use the tObj values? + /* For communicating values from mach64AllocTexObj(), mach64SetTexImages() + * to mach64UpdateTextureUnit(). Alternately, we can use the tObj values or + * set the context registers directly. */ - GLboolean BilinearMin; - GLboolean BilinearMag; - GLboolean ClampS; - GLboolean ClampT; -}; -#else -struct mach64_texture_object { - struct mach64_texture_object *next; - struct mach64_texture_object *prev; - struct gl_texture_object *tObj; - - struct mem_block *memBlock; - GLuint offset; - GLuint size; - - GLuint dirty; - GLuint age; - - GLint bound; - GLint heap; - GLint widthLog2; GLint heightLog2; GLint maxLog2; @@ -181,19 +152,14 @@ struct mach64_texture_object { GLint hasAlpha; GLint textureFormat; - /* Have to keep these separate due to how they are programmed. - * FIXME: Why don't we just use the tObj values? - */ GLboolean BilinearMin; GLboolean BilinearMag; GLboolean ClampS; GLboolean ClampT; }; -#endif typedef struct mach64_texture_object mach64TexObj, *mach64TexObjPtr; - struct mach64_context { GLcontext *glCtx; @@ -229,17 +195,10 @@ struct mach64_context { /* Texture object bookkeeping */ mach64TexObjPtr CurrentTexObj[2]; -#ifdef TEXMEM - unsigned nr_heaps; - driTexHeap * texture_heaps[ R128_NR_TEX_HEAPS ]; - driTextureObject swapped; -#else - mach64TexObj TexObjList[MACH64_NR_TEX_HEAPS]; - mach64TexObj SwappedOut; - struct mem_block *texHeap[MACH64_NR_TEX_HEAPS]; - GLuint lastTexAge[MACH64_NR_TEX_HEAPS]; + GLint firstTexHeap, lastTexHeap; -#endif + driTexHeap *texture_heaps[MACH64_NR_TEX_HEAPS]; + driTextureObject swapped; /* Fallback rasterization functions */ diff --git a/src/mesa/drivers/dri/mach64/mach64_lock.c b/src/mesa/drivers/dri/mach64/mach64_lock.c index 26f66f02309..b73e350111f 100644 --- a/src/mesa/drivers/dri/mach64/mach64_lock.c +++ b/src/mesa/drivers/dri/mach64/mach64_lock.c @@ -91,8 +91,6 @@ void mach64GetLock( mach64ContextPtr mmesa, GLuint flags ) } for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) { - if ( mmesa->texHeap[i] && (sarea->tex_age[i] != mmesa->lastTexAge[i]) ) { - mach64AgeTextures( mmesa, i ); - } + DRI_AGE_TEXTURES( mmesa->texture_heaps[i] ); } } diff --git a/src/mesa/drivers/dri/mach64/mach64_screen.c b/src/mesa/drivers/dri/mach64/mach64_screen.c index b17de01acc5..1014b8acd52 100644 --- a/src/mesa/drivers/dri/mach64/mach64_screen.c +++ b/src/mesa/drivers/dri/mach64/mach64_screen.c @@ -305,7 +305,7 @@ mach64CreateScreen( __DRIscreenPrivate *sPriv ) mach64Screen->texSize[MACH64_AGP_HEAP] = 0; mach64Screen->logTexGranularity[MACH64_AGP_HEAP] = 0; } else { - if (mach64Screen->texSize[MACH64_CARD_HEAP] > 0) { + if (serverInfo->textureSize > 0) { mach64Screen->numTexHeaps = MACH64_NR_TEX_HEAPS; mach64Screen->firstTexHeap = MACH64_CARD_HEAP; } else { diff --git a/src/mesa/drivers/dri/mach64/mach64_tex.c b/src/mesa/drivers/dri/mach64/mach64_tex.c index 6459deef784..5288d321ced 100644 --- a/src/mesa/drivers/dri/mach64/mach64_tex.c +++ b/src/mesa/drivers/dri/mach64/mach64_tex.c @@ -116,21 +116,20 @@ mach64AllocTexObj( struct gl_texture_object *texObj ) fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj ); t = (mach64TexObjPtr) CALLOC_STRUCT( mach64_texture_object ); + texObj->DriverData = t; if ( !t ) return NULL; /* Initialize non-image-dependent parts of the state: */ - t->tObj = texObj; + t->base.tObj = texObj; + t->base.dirty_images[0] = (1 << 0); - t->offset = 0; + t->bufAddr = 0; - t->dirty = 1; - - make_empty_list( t ); + make_empty_list( (driTextureObject *) t ); mach64SetTexWrap( t, texObj->WrapS, texObj->WrapT ); - /*mach64SetTexMaxAnisotropy( t, texObj->MaxAnisotropy );*/ mach64SetTexFilter( t, texObj->MinFilter, texObj->MagFilter ); mach64SetTexBorderColor( t, texObj->_BorderChan ); @@ -251,18 +250,17 @@ static void mach64TexImage1D( GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); - mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData; + driTextureObject * t = (driTextureObject *) texObj->DriverData; if ( t ) { - mach64SwapOutTexObj( mmesa, t ); + driSwapOutTextureObject( t ); } else { - t = mach64AllocTexObj(texObj); + t = (driTextureObject *) mach64AllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); return; } - texObj->DriverData = t; } /* Note, this will call mach64ChooseTextureFormat */ @@ -285,19 +283,18 @@ static void mach64TexSubImage1D( GLcontext *ctx, struct gl_texture_image *texImage ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); - mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData; + driTextureObject * t = (driTextureObject *) texObj->DriverData; assert( t ); /* this _should_ be true */ if ( t ) { - mach64SwapOutTexObj( mmesa, t ); + driSwapOutTextureObject( t ); } else { - t = mach64AllocTexObj(texObj); + t = (driTextureObject *) mach64AllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); return; } - texObj->DriverData = t; } _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, @@ -316,18 +313,17 @@ static void mach64TexImage2D( GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); - mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData; + driTextureObject * t = (driTextureObject *) texObj->DriverData; if ( t ) { - mach64SwapOutTexObj( mmesa, t ); + driSwapOutTextureObject( t ); } else { - t = mach64AllocTexObj(texObj); + t = (driTextureObject *) mach64AllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); return; } - texObj->DriverData = t; } /* Note, this will call mach64ChooseTextureFormat */ @@ -350,19 +346,18 @@ static void mach64TexSubImage2D( GLcontext *ctx, struct gl_texture_image *texImage ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); - mach64TexObjPtr t = (mach64TexObjPtr) texObj->DriverData; + driTextureObject * t = (driTextureObject *) texObj->DriverData; assert( t ); /* this _should_ be true */ if ( t ) { - mach64SwapOutTexObj( mmesa, t ); + driSwapOutTextureObject( t ); } else { - t = mach64AllocTexObj(texObj); + t = (driTextureObject *) mach64AllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); return; } - texObj->DriverData = t; } _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, @@ -372,44 +367,6 @@ static void mach64TexSubImage2D( GLcontext *ctx, mmesa->new_state |= MACH64_NEW_TEXTURE; } -/* Due to the way we must program texture state into the Rage Pro, - * we must leave these calculations to the absolute last minute. - */ -void mach64EmitTexStateLocked( mach64ContextPtr mmesa, - mach64TexObjPtr t0, - mach64TexObjPtr t1 ) -{ - drm_mach64_sarea_t *sarea = mmesa->sarea; - drm_mach64_context_regs_t *regs = &(mmesa->setup); - - /* for multitex, both textures must be local or AGP */ - if ( t0 && t1 ) - assert(t0->heap == t1->heap); - - if ( t0 ) { - if (t0->heap == MACH64_CARD_HEAP) { -#if ENABLE_PERF_BOXES - mmesa->c_texsrc_card++; -#endif - mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP; - } else { -#if ENABLE_PERF_BOXES - mmesa->c_texsrc_agp++; -#endif - mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP; - } - mmesa->setup.tex_offset = t0->offset; - } - - if ( t1 ) { - mmesa->setup.secondary_tex_off = t1->offset; - } - - memcpy( &sarea->context_state.tex_size_pitch, ®s->tex_size_pitch, - MACH64_NR_TEXTURE_REGS * sizeof(GLuint) ); -} - - /* ================================================================ * Device Driver API texture functions */ @@ -491,24 +448,23 @@ static void mach64DDTexParameter( GLcontext *ctx, GLenum target, _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexParameter"); return; } - tObj->DriverData = t; } switch ( pname ) { case GL_TEXTURE_MIN_FILTER: case GL_TEXTURE_MAG_FILTER: - if ( t->bound ) FLUSH_BATCH( mmesa ); + if ( t->base.bound ) FLUSH_BATCH( mmesa ); mach64SetTexFilter( t, tObj->MinFilter, tObj->MagFilter ); break; case GL_TEXTURE_WRAP_S: case GL_TEXTURE_WRAP_T: - if ( t->bound ) FLUSH_BATCH( mmesa ); + if ( t->base.bound ) FLUSH_BATCH( mmesa ); mach64SetTexWrap( t, tObj->WrapS, tObj->WrapT ); break; case GL_TEXTURE_BORDER_COLOR: - if ( t->bound ) FLUSH_BATCH( mmesa ); + if ( t->base.bound ) FLUSH_BATCH( mmesa ); mach64SetTexBorderColor( t, tObj->_BorderChan ); break; @@ -522,8 +478,8 @@ static void mach64DDTexParameter( GLcontext *ctx, GLenum target, * For mach64 we're only concerned with the base level * since that's the only texture we upload. */ - if ( t->bound ) FLUSH_BATCH( mmesa ); - mach64SwapOutTexObj( mmesa, t ); + if ( t->base.bound ) FLUSH_BATCH( mmesa ); + driSwapOutTextureObject( (driTextureObject *) t ); break; default: @@ -547,7 +503,7 @@ static void mach64DDBindTexture( GLcontext *ctx, GLenum target, FLUSH_BATCH( mmesa ); if ( mmesa->CurrentTexObj[unit] ) { - mmesa->CurrentTexObj[unit]->bound &= ~(unit+1); + mmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit); mmesa->CurrentTexObj[unit] = NULL; } @@ -558,33 +514,37 @@ static void mach64DDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj ) { mach64ContextPtr mmesa = MACH64_CONTEXT(ctx); - mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData; + driTextureObject * t = (driTextureObject *) tObj->DriverData; if ( t ) { if ( t->bound && mmesa ) { FLUSH_BATCH( mmesa ); - mmesa->CurrentTexObj[t->bound-1] = 0; mmesa->new_state |= MACH64_NEW_TEXTURE; } - mach64DestroyTexObj( mmesa, t ); - tObj->DriverData = NULL; + driDestroyTextureObject( t ); + /* Free mipmap images and the texture object itself */ _mesa_delete_texture_object(ctx, tObj); - } } -static GLboolean mach64DDIsTextureResident( GLcontext *ctx, - struct gl_texture_object *tObj ) +/** + * Allocate a new texture object. + * Called via ctx->Driver.NewTextureObject. + * Note: we could use containment here to 'derive' the driver-specific + * texture object from the core mesa gl_texture_object. Not done at this time. + */ +static struct gl_texture_object * +mach64NewTextureObject( GLcontext *ctx, GLuint name, GLenum target ) { - mach64TexObjPtr t = (mach64TexObjPtr)tObj->DriverData; - - return ( t && t->memBlock ); + struct gl_texture_object *obj; + obj = _mesa_new_texture_object(ctx, name, target); + mach64AllocTexObj( obj ); + return obj; } - void mach64InitTextureFuncs( struct dd_function_table *functions ) { functions->TexEnv = mach64DDTexEnv; @@ -593,18 +553,15 @@ void mach64InitTextureFuncs( struct dd_function_table *functions ) functions->TexSubImage1D = mach64TexSubImage1D; functions->TexImage2D = mach64TexImage2D; functions->TexSubImage2D = mach64TexSubImage2D; - functions->TexImage3D = _mesa_store_teximage3d; - functions->TexSubImage3D = _mesa_store_texsubimage3d; - functions->CopyTexImage1D = _swrast_copy_teximage1d; - functions->CopyTexImage2D = _swrast_copy_teximage2d; - functions->CopyTexSubImage1D = _swrast_copy_texsubimage1d; - functions->CopyTexSubImage2D = _swrast_copy_texsubimage2d; - functions->CopyTexSubImage3D = _swrast_copy_texsubimage3d; functions->TexParameter = mach64DDTexParameter; functions->BindTexture = mach64DDBindTexture; + functions->NewTextureObject = mach64NewTextureObject; functions->DeleteTexture = mach64DDDeleteTexture; + functions->IsTextureResident = driIsTextureResident; + functions->UpdateTexturePalette = NULL; functions->ActiveTexture = NULL; - functions->IsTextureResident = mach64DDIsTextureResident; - functions->PrioritizeTexture = NULL; + functions->PrioritizeTexture = NULL; + + driInitTextureFormats(); } diff --git a/src/mesa/drivers/dri/mach64/mach64_tex.h b/src/mesa/drivers/dri/mach64/mach64_tex.h index d950dd12b44..f6cf1cf8020 100644 --- a/src/mesa/drivers/dri/mach64/mach64_tex.h +++ b/src/mesa/drivers/dri/mach64/mach64_tex.h @@ -34,25 +34,15 @@ extern void mach64UpdateTextureState( GLcontext *ctx ); -extern void mach64SwapOutTexObj( mach64ContextPtr mach64ctx, - mach64TexObjPtr t ); - extern void mach64UploadTexImages( mach64ContextPtr mach64ctx, mach64TexObjPtr t ); extern void mach64UploadMultiTexImages( mach64ContextPtr mach64ctx, mach64TexObjPtr t0, mach64TexObjPtr t1 ); -extern void mach64AgeTextures( mach64ContextPtr mach64ctx, int heap ); extern void mach64DestroyTexObj( mach64ContextPtr mach64ctx, mach64TexObjPtr t ); -extern void mach64UpdateTexLRU( mach64ContextPtr mach64ctx, - mach64TexObjPtr t ); - -extern void mach64PrintLocalLRU( mach64ContextPtr mach64ctx, int heap ); -extern void mach64PrintGlobalLRU( mach64ContextPtr mach64ctx, int heap ); - extern void mach64EmitTexStateLocked( mach64ContextPtr mmesa, mach64TexObjPtr t0, mach64TexObjPtr t1 ); diff --git a/src/mesa/drivers/dri/mach64/mach64_texmem.c b/src/mesa/drivers/dri/mach64/mach64_texmem.c index 017fd3535d5..3b7b93b9842 100644 --- a/src/mesa/drivers/dri/mach64/mach64_texmem.c +++ b/src/mesa/drivers/dri/mach64/mach64_texmem.c @@ -49,333 +49,19 @@ */ void mach64DestroyTexObj( mach64ContextPtr mmesa, mach64TexObjPtr t ) { -#if ENABLE_PERF_BOXES - /* Bump the performace counter */ - if (mmesa) - mmesa->c_textureSwaps++; -#endif - if ( !t ) return; - -#if 0 - if ( t->tObj && t->memBlock && mmesa ) { - /* not a placeholder, so release from global LRU if necessary */ - int heap = t->heap; - drmTextureRegion *list = mmesa->sarea->tex_list[heap]; - int log2sz = mmesa->mach64Screen->logTexGranularity[heap]; - int start = t->memBlock->ofs >> log2sz; - int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz; - int i; - - mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap]; - - /* Update the global LRU */ - for ( i = start ; i <= end ; i++ ) { - /* do we own this block? */ - if (list[i].in_use == mmesa->hHWContext) { - list[i].in_use = 0; - list[i].age = mmesa->lastTexAge[heap]; - - /* remove_from_list(i) */ - list[(GLuint)list[i].next].prev = list[i].prev; - list[(GLuint)list[i].prev].next = list[i].next; - } - } - } -#endif - - if ( t->memBlock ) { - mmFreeMem( t->memBlock ); - t->memBlock = NULL; - } - - if ( t->tObj ) { - t->tObj->DriverData = NULL; - } - - if ( t->bound && mmesa ) - mmesa->CurrentTexObj[t->bound-1] = NULL; - - remove_from_list( t ); - FREE( t ); -} - -/* Keep track of swapped out texture objects. - */ -void mach64SwapOutTexObj( mach64ContextPtr mmesa, - mach64TexObjPtr t ) -{ -#if ENABLE_PERF_BOXES - /* Bump the performace counter */ - if (mmesa) - mmesa->c_textureSwaps++; -#endif - -#if 0 - if ( t->tObj && t->memBlock && mmesa ) { - /* not a placeholder, so release from global LRU if necessary */ - int heap = t->heap; - drmTextureRegion *list = mmesa->sarea->tex_list[heap]; - int log2sz = mmesa->mach64Screen->logTexGranularity[heap]; - int start = t->memBlock->ofs >> log2sz; - int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz; - int i; - - mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap]; - - /* Update the global LRU */ - for ( i = start ; i <= end ; i++ ) { - /* do we own this block? */ - if (list[i].in_use == mmesa->hHWContext) { - list[i].in_use = 0; - list[i].age = mmesa->lastTexAge[heap]; - - /* remove_from_list(i) */ - list[(GLuint)list[i].next].prev = list[i].prev; - list[(GLuint)list[i].prev].next = list[i].next; - } - } - } -#endif - - if ( t->memBlock ) { - mmFreeMem( t->memBlock ); - t->memBlock = NULL; - } - - t->dirty = ~0; - move_to_tail( &mmesa->SwappedOut, t ); -} - -/* Print out debugging information about texture LRU. - */ -void mach64PrintLocalLRU( mach64ContextPtr mmesa, int heap ) -{ - mach64TexObjPtr t; - int sz = 1 << (mmesa->mach64Screen->logTexGranularity[heap]); - - fprintf( stderr, "\nLocal LRU, heap %d:\n", heap ); - - foreach( t, &mmesa->TexObjList[heap] ) { - if ( !t->tObj ) { - fprintf( stderr, "Placeholder %d at 0x%x sz 0x%x\n", - t->memBlock->ofs / sz, - t->memBlock->ofs, - t->memBlock->size ); - } else { - fprintf( stderr, "Texture (bound %d) at 0x%x sz 0x%x\n", - t->bound, - t->memBlock->ofs, - t->memBlock->size ); - } - } - - fprintf( stderr, "\n" ); -} - -void mach64PrintGlobalLRU( mach64ContextPtr mmesa, int heap ) -{ - drm_tex_region_t *list = mmesa->sarea->tex_list[heap]; - int i, j; - - fprintf( stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list ); - - for ( i = 0, j = MACH64_NR_TEX_REGIONS ; i < MACH64_NR_TEX_REGIONS ; i++ ) { - fprintf( stderr, "list[%d] age %d in_use %d next %d prev %d\n", - j, list[j].age, list[j].in_use, list[j].next, list[j].prev ); - j = list[j].next; - if ( j == MACH64_NR_TEX_REGIONS ) break; - } - - if ( j != MACH64_NR_TEX_REGIONS ) { - fprintf( stderr, "Loop detected in global LRU\n" ); - for ( i = 0 ; i < MACH64_NR_TEX_REGIONS ; i++ ) { - fprintf( stderr, "list[%d] age %d in_use %d next %d prev %d\n", - i, list[i].age, list[i].in_use, list[i].next, list[i].prev ); - } - } + unsigned i; - fprintf( stderr, "\n" ); -} - -/* Reset the global texture LRU. - */ -/* NOTE: This function is only called while holding the hardware lock */ -static void mach64ResetGlobalLRU( mach64ContextPtr mmesa, int heap ) -{ - drm_tex_region_t *list = mmesa->sarea->tex_list[heap]; - int sz = 1 << mmesa->mach64Screen->logTexGranularity[heap]; - int i; - - /* (Re)initialize the global circular LRU list. The last element in - * the array (MACH64_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. + /* See if it was the driver's current object. */ - for ( i = 0 ; (i+1) * sz <= mmesa->mach64Screen->texSize[heap] ; i++ ) { - list[i].prev = i-1; - list[i].next = i+1; - list[i].age = 0; - list[i].in_use = 0; - } - - i--; - list[0].prev = MACH64_NR_TEX_REGIONS; - list[i].prev = i-1; - list[i].next = MACH64_NR_TEX_REGIONS; - list[MACH64_NR_TEX_REGIONS].prev = i; - list[MACH64_NR_TEX_REGIONS].next = 0; - mmesa->sarea->tex_age[heap] = 0; -} - -/* Update the local and global texture LRUs. - */ -/* NOTE: This function is only called while holding the hardware lock */ -void mach64UpdateTexLRU( mach64ContextPtr mmesa, - mach64TexObjPtr t ) -{ - int heap = t->heap; - drm_tex_region_t *list = mmesa->sarea->tex_list[heap]; - int log2sz = mmesa->mach64Screen->logTexGranularity[heap]; - int start = t->memBlock->ofs >> log2sz; - int end = (t->memBlock->ofs + t->memBlock->size - 1) >> log2sz; - int i; - - mmesa->lastTexAge[heap] = ++mmesa->sarea->tex_age[heap]; - - if ( !t->memBlock ) { - fprintf( stderr, "no memblock\n\n" ); - return; - } - - /* Update our local LRU */ - move_to_head( &mmesa->TexObjList[heap], t ); - - /* Update the global LRU */ - for ( i = start ; i <= end ; i++ ) { - list[i].in_use = mmesa->hHWContext; - list[i].age = mmesa->lastTexAge[heap]; - -#if 0 - /* if this is the last region, it's not in the list */ - if ( !(i*(1< mmesa->mach64Screen->texSize[heap] ) ) { -#endif - /* remove_from_list(i) */ - list[(GLuint)list[i].next].prev = list[i].prev; - list[(GLuint)list[i].prev].next = list[i].next; -#if 0 - } -#endif - - /* insert_at_head(list, i) */ - list[i].prev = MACH64_NR_TEX_REGIONS; - list[i].next = list[MACH64_NR_TEX_REGIONS].next; - list[(GLuint)list[MACH64_NR_TEX_REGIONS].next].prev = i; - list[MACH64_NR_TEX_REGIONS].next = i; - } - - if ( MACH64_DEBUG & DEBUG_VERBOSE_LRU ) { - mach64PrintGlobalLRU( mmesa, t->heap ); - mach64PrintLocalLRU( mmesa, t->heap ); - } -} - -/* Update our notion of what textures have been changed since we last - * held the lock. This pertains to both our local textures and the - * textures belonging to other clients. Keep track of other client's - * textures by pushing a placeholder texture onto the LRU list -- these - * are denoted by (tObj == NULL). - */ -/* NOTE: This function is only called while holding the hardware lock */ -static void mach64TexturesGone( mach64ContextPtr mmesa, int heap, - int offset, int size, int in_use ) -{ - mach64TexObjPtr t, tmp; - - foreach_s ( t, tmp, &mmesa->TexObjList[heap] ) { - if ( t->memBlock->ofs >= offset + size || - t->memBlock->ofs + t->memBlock->size <= offset ) - continue; - - /* It overlaps - kick it out. Need to hold onto the currently - * bound objects, however. - */ - if ( t->bound ) { - mach64SwapOutTexObj( mmesa, t ); - } else { - mach64DestroyTexObj( mmesa, t ); - } - } - - if ( in_use > 0 && in_use != mmesa->hHWContext ) { - t = (mach64TexObjPtr) CALLOC( sizeof(*t) ); - if (!t) return; - - t->memBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset ); - if ( !t->memBlock ) { - fprintf( stderr, "Couldn't alloc placeholder sz %x ofs %x\n", - (int)size, (int)offset ); - mmDumpMemInfo( mmesa->texHeap[heap] ); - return; - } - insert_at_head( &mmesa->TexObjList[heap], t ); - } -} - -/* Update our client's shared texture state. If another client has - * modified a region in which we have textures, then we need to figure - * out which of our textures has been removed, and update our global - * LRU. - */ -void mach64AgeTextures( mach64ContextPtr mmesa, int heap ) -{ - drm_mach64_sarea_t *sarea = mmesa->sarea; - - if ( sarea->tex_age[heap] != mmesa->lastTexAge[heap] ) { - int sz = 1 << mmesa->mach64Screen->logTexGranularity[heap]; - int nr = 0; - int idx; - - /* Have to go right round from the back to ensure stuff ends up - * LRU in our local list... Fix with a cursor pointer. - */ - for ( idx = sarea->tex_list[heap][MACH64_NR_TEX_REGIONS].prev ; - idx != MACH64_NR_TEX_REGIONS && nr < MACH64_NR_TEX_REGIONS ; - idx = sarea->tex_list[heap][idx].prev, nr++ ) + if ( mmesa != NULL ) + { + for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ ) { - /* If switching texturing schemes, then the SAREA might not - * have been properly cleared, so we need to reset the - * global texture LRU. - */ - if ( idx * sz > mmesa->mach64Screen->texSize[heap] ) { - nr = MACH64_NR_TEX_REGIONS; - break; - } - - if ( sarea->tex_list[heap][idx].age > mmesa->lastTexAge[heap] ) { - mach64TexturesGone( mmesa, heap, idx * sz, sz, - sarea->tex_list[heap][idx].in_use ); - } - } - - /* If switching texturing schemes, then the SAREA might not - * have been properly cleared, so we need to reset the - * global texture LRU. - */ - if ( nr == MACH64_NR_TEX_REGIONS ) { - mach64TexturesGone( mmesa, heap, 0, - mmesa->mach64Screen->texSize[heap], 0 ); - mach64ResetGlobalLRU( mmesa, heap ); + if ( t == mmesa->CurrentTexObj[ i ] ) { + assert( t->base.bound & (1 << i) ); + mmesa->CurrentTexObj[ i ] = NULL; + } } - - if ( 0 ) { - mach64PrintGlobalLRU( mmesa, heap ); - mach64PrintLocalLRU( mmesa, heap ); - } - - mmesa->dirty |= (MACH64_UPLOAD_CONTEXT | - MACH64_UPLOAD_TEX0IMAGE | - MACH64_UPLOAD_TEX1IMAGE); - mmesa->lastTexAge[heap] = sarea->tex_age[heap]; } } @@ -395,7 +81,7 @@ static void mach64UploadAGPSubImage( mach64ContextPtr mmesa, if ( ( level < 0 ) || ( level > mmesa->glCtx->Const.MaxTextureLevels ) ) return; - image = t->tObj->Image[0][level]; + image = t->base.tObj->Image[0][level]; if ( !image ) return; @@ -424,14 +110,13 @@ static void mach64UploadAGPSubImage( mach64ContextPtr mmesa, fprintf( stderr, "mach64UploadSubImage: %d,%d of %d,%d at %d,%d\n", width, height, image->Width, image->Height, x, y ); fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d\n", - (GLuint)t->offset, (GLint)width, dwords ); - mmDumpMemInfo( mmesa->texHeap[t->heap] ); + (GLuint)t->bufAddr, (GLint)width, dwords ); } assert(image->Data); { - CARD32 *dst = (CARD32 *)((char *)mach64Screen->agpTextures.map + t->memBlock->ofs); + CARD32 *dst = (CARD32 *)((char *)mach64Screen->agpTextures.map + t->base.memBlock->ofs); const GLubyte *src = (const GLubyte *) image->Data + (y * image->Width + x) * image->TexFormat->TexelBytes; const GLuint bytes = width * height * image->TexFormat->TexelBytes; @@ -460,7 +145,7 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa, if ( ( level < 0 ) || ( level > mmesa->glCtx->Const.MaxTextureLevels ) ) return; - image = t->tObj->Image[0][level]; + image = t->base.tObj->Image[0][level]; if ( !image ) return; @@ -543,7 +228,7 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa, } dwords = width * height / texelsPerDword; - offset = t->offset; + offset = t->bufAddr; #if ENABLE_PERF_BOXES /* Bump the performance counter */ @@ -555,7 +240,6 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa, width, height, image->Width, image->Height, x, y ); fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d\n", (GLuint)offset, (GLint)width, dwords ); - mmDumpMemInfo( mmesa->texHeap[t->heap] ); } /* Subdivide the texture if required (account for the registers added by the drm) */ @@ -594,78 +278,32 @@ static void mach64UploadLocalSubImage( mach64ContextPtr mmesa, */ void mach64UploadTexImages( mach64ContextPtr mmesa, mach64TexObjPtr t ) { - GLint heap; - if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, mmesa->glCtx, t ); } assert(t); - assert(t->tObj); - - /* Choose the heap appropriately */ - heap = MACH64_CARD_HEAP; + assert(t->base.tObj); - if ( !mmesa->mach64Screen->IsPCI && - t->size > mmesa->mach64Screen->texSize[heap] ) { - heap = MACH64_AGP_HEAP; - } - - /* Do we need to eject LRU texture objects? */ - if ( !t->memBlock ) { - t->heap = heap; + if ( !t->base.memBlock ) { + int heap; - /* Allocate a memory block on a 64-byte boundary */ - t->memBlock = mmAllocMem( mmesa->texHeap[heap], t->size, 6, 0 ); + /* NULL heaps are skipped */ + heap = driAllocateTexture( mmesa->texture_heaps, MACH64_NR_TEX_HEAPS, + (driTextureObject *) t ); - /* Try AGP before kicking anything out of local mem */ - if ( !mmesa->mach64Screen->IsPCI && !t->memBlock && heap == MACH64_CARD_HEAP ) { - t->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP], - t->size, 6, 0 ); - - if ( t->memBlock ) - heap = t->heap = MACH64_AGP_HEAP; + if ( heap == -1 ) { + fprintf( stderr, "%s: upload texture failure, sz=%d\n", __FUNCTION__, + t->base.totalSize ); + exit(-1); + return; } - /* Kick out textures until the requested texture fits */ - while ( !t->memBlock ) { - if ( mmesa->TexObjList[heap].prev->bound ) { - fprintf( stderr, - "mach64UploadTexImages: ran into bound texture\n" ); - return; - } - if ( mmesa->TexObjList[heap].prev == &mmesa->TexObjList[heap] ) { - if ( mmesa->mach64Screen->IsPCI ) { - fprintf( stderr, "%s: upload texture failure on " - "local texture heaps, sz=%d\n", __FUNCTION__, - t->size ); - return; - } else if ( heap == MACH64_CARD_HEAP ) { - heap = t->heap = MACH64_AGP_HEAP; - continue; - } else { - int i; - fprintf( stderr, "%s: upload texture failure on " - "%sAGP texture heaps, sz=%d\n", __FUNCTION__, - mmesa->firstTexHeap == MACH64_CARD_HEAP ? "both local and " : "", - t->size ); - for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) { - mach64PrintLocalLRU( mmesa, i ); - mmDumpMemInfo( mmesa->texHeap[i] ); - } - exit(-1); - return; - } - } - - mach64SwapOutTexObj( mmesa, mmesa->TexObjList[heap].prev ); - - t->memBlock = mmAllocMem( mmesa->texHeap[heap], t->size, 6, 0 ); - } + t->heap = heap; /* Set the base offset of the texture image */ - t->offset = mmesa->mach64Screen->texOffset[heap] + t->memBlock->ofs; + t->bufAddr = mmesa->mach64Screen->texOffset[heap] + t->base.memBlock->ofs; /* Force loading the new state into the hardware */ mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL | @@ -673,142 +311,152 @@ void mach64UploadTexImages( mach64ContextPtr mmesa, mach64TexObjPtr t ) } /* Let the world know we've used this memory recently */ - mach64UpdateTexLRU( mmesa, t ); + driUpdateTextureLRU( (driTextureObject *) t ); /* Upload any images that are new */ - if ( t->dirty ) { + if ( t->base.dirty_images[0] ) { + const GLint j = t->base.tObj->BaseLevel; if (t->heap == MACH64_AGP_HEAP) { /* Need to make sure any vertex buffers in the queue complete */ mach64WaitForIdleLocked( mmesa ); - mach64UploadAGPSubImage( mmesa, t, t->tObj->BaseLevel, 0, 0, - t->tObj->Image[0][t->tObj->BaseLevel]->Width, - t->tObj->Image[0][t->tObj->BaseLevel]->Height ); + mach64UploadAGPSubImage( mmesa, t, j, 0, 0, + t->base.tObj->Image[0][j]->Width, + t->base.tObj->Image[0][j]->Height ); } else { - mach64UploadLocalSubImage( mmesa, t, t->tObj->BaseLevel, 0, 0, - t->tObj->Image[0][t->tObj->BaseLevel]->Width, - t->tObj->Image[0][t->tObj->BaseLevel]->Height ); + mach64UploadLocalSubImage( mmesa, t, j, 0, 0, + t->base.tObj->Image[0][j]->Width, + t->base.tObj->Image[0][j]->Height ); } mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH; + t->base.dirty_images[0] = 0; } mmesa->dirty |= MACH64_UPLOAD_TEXTURE; +} + + +/* Allocate memory from the same texture heap `heap' for both textures + * `u0' and `u1'. + */ +static int mach64AllocateMultiTex( mach64ContextPtr mmesa, + mach64TexObjPtr u0, + mach64TexObjPtr u1, + int heap, GLboolean alloc_u0 ) +{ + /* Both objects should be bound */ + assert( u0->base.bound && u1->base.bound ); + + if ( alloc_u0 ) { + /* Evict u0 from its current heap */ + if ( u0->base.memBlock ) { + assert( u0->heap != heap ); + driSwapOutTextureObject( (driTextureObject *) u0 ); + } + + /* Try to allocate u0 in the chosen heap */ + u0->heap = driAllocateTexture( &mmesa->texture_heaps[heap], 1, + (driTextureObject *) u0 ); + + if ( u0->heap == -1 ) { + return -1; + } + } + + /* Evict u1 from its current heap */ + if ( u1->base.memBlock ) { + assert( u1->heap != heap ); + driSwapOutTextureObject( (driTextureObject *) u1 ); + } + + /* Try to allocate u1 in the same heap as u0 */ + u1->heap = driAllocateTexture( &mmesa->texture_heaps[heap], 1, + (driTextureObject *) u1 ); + + if ( u1->heap == -1 ) { + return -1; + } - t->dirty = 0; + /* Bound objects are not evicted */ + assert( u0->base.memBlock && u1->base.memBlock ); + assert( u0->heap == u1->heap ); + + return heap; } /* The mach64 needs to have both primary and secondary textures in either * local or AGP memory, so we need a "buddy system" to make sure that allocation * succeeds or fails for both textures. - * FIXME: This needs to be optimized better. */ void mach64UploadMultiTexImages( mach64ContextPtr mmesa, mach64TexObjPtr t0, mach64TexObjPtr t1 ) { - GLint heap; - if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) { fprintf( stderr, "%s( %p, %p %p )\n", __FUNCTION__, mmesa->glCtx, t0, t1 ); } assert(t0 && t1); - assert(t0->tObj && t1->tObj); + assert(t0->base.tObj && t1->base.tObj); - /* Choose the heap appropriately */ - heap = MACH64_CARD_HEAP; + if ( !t0->base.memBlock || !t1->base.memBlock || t0->heap != t1->heap ) { + mach64TexObjPtr u0 = NULL; + mach64TexObjPtr u1 = NULL; + unsigned totalSize = t0->base.totalSize + t1->base.totalSize; - if ( !mmesa->mach64Screen->IsPCI && - ((t0->size + t1->size) > mmesa->mach64Screen->texSize[heap]) ) { - heap = MACH64_AGP_HEAP; - } + int heap, ret; - /* Do we need to eject LRU texture objects? */ - if ( !t0->memBlock || !t1->memBlock || t0->heap != t1->heap ) { - /* FIXME: starting from scratch for now to keep it simple */ - if ( t0->memBlock ) { - mach64SwapOutTexObj( mmesa, t0 ); - } - if ( t1->memBlock ) { - mach64SwapOutTexObj( mmesa, t1 ); - } - t0->heap = t1->heap = heap; - /* Allocate a memory block on a 64-byte boundary */ - t0->memBlock = mmAllocMem( mmesa->texHeap[heap], t0->size, 6, 0 ); - if ( t0->memBlock ) { - t1->memBlock = mmAllocMem( mmesa->texHeap[heap], t1->size, 6, 0 ); - if ( !t1->memBlock ) { - mmFreeMem( t0->memBlock ); - t0->memBlock = NULL; - } + /* Check if one of the textures is already swapped in a heap and the + * other texture fits in that heap. + */ + if ( t0->base.memBlock && totalSize <= t0->base.heap->size ) { + u0 = t0; + u1 = t1; + } else if ( t1->base.memBlock && totalSize <= t1->base.heap->size ) { + u0 = t1; + u1 = t0; } - /* Try AGP before kicking anything out of local mem */ - if ( (!t0->memBlock || !t1->memBlock) && heap == MACH64_CARD_HEAP ) { - t0->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP], t0->size, 6, 0 ); - if ( t0->memBlock ) { - t1->memBlock = mmAllocMem( mmesa->texHeap[MACH64_AGP_HEAP], t1->size, 6, 0 ); - if ( !t1->memBlock ) { - mmFreeMem( t0->memBlock ); - t0->memBlock = NULL; - } + + if ( u0 ) { + heap = u0->heap; + + ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_FALSE ); + } else { + /* Both textures are swapped out or collocation is impossible */ + u0 = t0; + u1 = t1; + + /* Choose the heap appropriately */ + heap = MACH64_CARD_HEAP; + + if ( totalSize > mmesa->texture_heaps[heap]->size ) { + heap = MACH64_AGP_HEAP; } - if ( t0->memBlock && t1->memBlock ) - heap = t0->heap = t1->heap = MACH64_AGP_HEAP; + ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_TRUE ); } - /* Kick out textures until the requested texture fits */ - while ( !t0->memBlock || !t1->memBlock ) { - if ( mmesa->TexObjList[heap].prev->bound ) { - fprintf( stderr, - "%s: ran into bound texture\n", __FUNCTION__ ); - return; - } - if ( mmesa->TexObjList[heap].prev == &mmesa->TexObjList[heap] ) { - if ( mmesa->mach64Screen->IsPCI ) { - fprintf( stderr, "%s: upload texture failure on local " - "texture heaps, tex0 sz=%d tex1 sz=%d\n", __FUNCTION__, - t0->size, t1->size ); - return; - } else if ( heap == MACH64_CARD_HEAP ) { - /* If only one allocation succeeded, start over again in AGP */ - if (t0->memBlock) { - mmFreeMem( t0->memBlock ); - t0->memBlock = NULL; - } - if (t1->memBlock) { - mmFreeMem( t1->memBlock ); - t1->memBlock = NULL; - } - heap = t0->heap = t1->heap = MACH64_AGP_HEAP; - continue; - } else { - int i; - fprintf( stderr, "%s: upload texture failure on %s" - "AGP texture heaps, tex0 sz=%d tex1 sz=%d\n", __FUNCTION__, - mmesa->firstTexHeap == MACH64_CARD_HEAP ? "both local and " : "", - t0->size, t1->size ); - for ( i = mmesa->firstTexHeap ; i < mmesa->lastTexHeap ; i++ ) { - mach64PrintLocalLRU( mmesa, i ); - mmDumpMemInfo( mmesa->texHeap[i] ); - } - exit(-1); - return; - } - } + if ( ret == -1 && heap == MACH64_CARD_HEAP ) { + /* Try AGP if local memory failed */ + heap = MACH64_AGP_HEAP; - mach64SwapOutTexObj( mmesa, mmesa->TexObjList[heap].prev ); - - if (!t0->memBlock) - t0->memBlock = mmAllocMem( mmesa->texHeap[heap], t0->size, 6, 0 ); - if (!t1->memBlock) - t1->memBlock = mmAllocMem( mmesa->texHeap[heap], t1->size, 6, 0 ); + ret = mach64AllocateMultiTex( mmesa, u0, u1, heap, GL_TRUE ); + } + + if ( ret == -1 ) { + /* FIXME: + * Swap out all textures from the AGP heap and re-run allocation, this + * should succeed in all cases. + */ + fprintf( stderr, "%s: upload multi-texture failure, sz0=%d sz1=%d\n", + __FUNCTION__, t0->base.totalSize, t1->base.totalSize ); + exit(-1); } /* Set the base offset of the texture image */ - t0->offset = mmesa->mach64Screen->texOffset[heap] + t0->memBlock->ofs; - t1->offset = mmesa->mach64Screen->texOffset[heap] + t1->memBlock->ofs; + t0->bufAddr = mmesa->mach64Screen->texOffset[heap] + t0->base.memBlock->ofs; + t1->bufAddr = mmesa->mach64Screen->texOffset[heap] + t1->base.memBlock->ofs; /* Force loading the new state into the hardware */ mmesa->dirty |= (MACH64_UPLOAD_SCALE_3D_CNTL | @@ -816,42 +464,43 @@ void mach64UploadMultiTexImages( mach64ContextPtr mmesa, } /* Let the world know we've used this memory recently */ - mach64UpdateTexLRU( mmesa, t0 ); - mach64UpdateTexLRU( mmesa, t1 ); + driUpdateTextureLRU( (driTextureObject *) t0 ); + driUpdateTextureLRU( (driTextureObject *) t1 ); /* Upload any images that are new */ - if ( t0->dirty ) { + if ( t0->base.dirty_images[0] ) { + const GLint j0 = t0->base.tObj->BaseLevel; if (t0->heap == MACH64_AGP_HEAP) { /* Need to make sure any vertex buffers in the queue complete */ mach64WaitForIdleLocked( mmesa ); - mach64UploadAGPSubImage( mmesa, t0, t0->tObj->BaseLevel, 0, 0, - t0->tObj->Image[0][t0->tObj->BaseLevel]->Width, - t0->tObj->Image[0][t0->tObj->BaseLevel]->Height ); + mach64UploadAGPSubImage( mmesa, t0, j0, 0, 0, + t0->base.tObj->Image[0][j0]->Width, + t0->base.tObj->Image[0][j0]->Height ); } else { - mach64UploadLocalSubImage( mmesa, t0, t0->tObj->BaseLevel, 0, 0, - t0->tObj->Image[0][t0->tObj->BaseLevel]->Width, - t0->tObj->Image[0][t0->tObj->BaseLevel]->Height ); + mach64UploadLocalSubImage( mmesa, t0, j0, 0, 0, + t0->base.tObj->Image[0][j0]->Width, + t0->base.tObj->Image[0][j0]->Height ); } mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH; + t0->base.dirty_images[0] = 0; } - if ( t1->dirty ) { + if ( t1->base.dirty_images[0] ) { + const GLint j1 = t1->base.tObj->BaseLevel; if (t1->heap == MACH64_AGP_HEAP) { /* Need to make sure any vertex buffers in the queue complete */ mach64WaitForIdleLocked( mmesa ); - mach64UploadAGPSubImage( mmesa, t1, t1->tObj->BaseLevel, 0, 0, - t1->tObj->Image[0][t1->tObj->BaseLevel]->Width, - t1->tObj->Image[0][t1->tObj->BaseLevel]->Height ); + mach64UploadAGPSubImage( mmesa, t1, j1, 0, 0, + t1->base.tObj->Image[0][j1]->Width, + t1->base.tObj->Image[0][j1]->Height ); } else { - mach64UploadLocalSubImage( mmesa, t1, t1->tObj->BaseLevel, 0, 0, - t1->tObj->Image[0][t1->tObj->BaseLevel]->Width, - t1->tObj->Image[0][t1->tObj->BaseLevel]->Height ); + mach64UploadLocalSubImage( mmesa, t1, j1, 0, 0, + t1->base.tObj->Image[0][j1]->Width, + t1->base.tObj->Image[0][j1]->Height ); } mmesa->setup.tex_cntl |= MACH64_TEX_CACHE_FLUSH; + t1->base.dirty_images[0] = 0; } mmesa->dirty |= MACH64_UPLOAD_TEXTURE; - - t0->dirty = 0; - t1->dirty = 0; } diff --git a/src/mesa/drivers/dri/mach64/mach64_texstate.c b/src/mesa/drivers/dri/mach64/mach64_texstate.c index b6a9e3f931e..3ace370d70d 100644 --- a/src/mesa/drivers/dri/mach64/mach64_texstate.c +++ b/src/mesa/drivers/dri/mach64/mach64_texstate.c @@ -47,11 +47,6 @@ static void mach64SetTexImages( mach64ContextPtr mmesa, { mach64TexObjPtr t = (mach64TexObjPtr) tObj->DriverData; struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel]; -#if 0 - int log2Pitch, log2Height, log2Size, log2MinSize; - int i; - GLint firstLevel, lastLevel; -#endif int totalSize; assert(t); @@ -92,77 +87,17 @@ static void mach64SetTexImages( mach64ContextPtr mmesa, _mesa_problem(mmesa->glCtx, "Bad texture format in %s", __FUNCTION__); }; -#if 0 - /* 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. - */ - 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 */ - - log2Pitch = tObj->Image[firstLevel]->WidthLog2; - log2Height = tObj->Image[firstLevel]->HeightLog2; - log2Size = MAX2(log2Pitch, log2Height); - log2MinSize = log2Size; - - t->dirty = 0; - totalSize = 0; - for ( i = firstLevel; i <= lastLevel; i++ ) { - const struct gl_texture_image *texImage; - - texImage = tObj->Image[i]; - if ( !texImage || !texImage->Data ) { - lastLevel = i - 1; - break; - } - - log2MinSize = texImage->MaxLog2; - - t->image[i - firstLevel].offset = totalSize; - t->image[i - firstLevel].width = tObj->Image[i]->Width; - t->image[i - firstLevel].height = tObj->Image[i]->Height; + totalSize = ( baseImage->Height * + baseImage->Width * + baseImage->TexFormat->TexelBytes ); - t->dirty |= (1 << i); - - totalSize += (tObj->Image[i]->Height * - tObj->Image[i]->Width * - tObj->Image[i]->TexFormat->TexelBytes); - - /* Offsets must be 32-byte aligned for host data blits and tiling */ - totalSize = (totalSize + 31) & ~31; - } + totalSize = (totalSize + 31) & ~31; - t->totalSize = totalSize; - t->firstLevel = firstLevel; - t->lastLevel = lastLevel; + t->base.totalSize = totalSize; + t->base.firstLevel = tObj->BaseLevel; + t->base.lastLevel = tObj->BaseLevel; /* Set the texture format */ - t->setup.tex_cntl &= ~(0xf << 16); - t->setup.tex_cntl |= t->textureFormat; - - t->setup.tex_combine_cntl = 0x00000000; /* XXX is this right? */ - - t->setup.tex_size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) | - (log2Size << R128_TEX_SIZE_SHIFT) | - (log2Height << R128_TEX_HEIGHT_SHIFT) | - (log2MinSize << R128_TEX_MIN_SIZE_SHIFT)); - - for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) { - t->setup.tex_offset[i] = 0x00000000; - } - - if (firstLevel == lastLevel) - t->setup.tex_cntl |= R128_MIP_MAP_DISABLE; - else - t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE; - -#else if ( ( baseImage->_BaseFormat == GL_RGBA ) || ( baseImage->_BaseFormat == GL_ALPHA ) || ( baseImage->_BaseFormat == GL_LUMINANCE_ALPHA ) ) { @@ -171,15 +106,9 @@ static void mach64SetTexImages( mach64ContextPtr mmesa, t->hasAlpha = 0; } - totalSize = ( baseImage->Width * baseImage->Height * - baseImage->TexFormat->TexelBytes ); - totalSize = (totalSize + 31) & ~31; - t->size = totalSize; t->widthLog2 = baseImage->WidthLog2; t->heightLog2 = baseImage->HeightLog2; t->maxLog2 = baseImage->MaxLog2; - -#endif } static void mach64UpdateTextureEnv( GLcontext *ctx, int unit ) @@ -387,17 +316,17 @@ static void mach64UpdateTextureUnit( GLcontext *ctx, int unit ) } /* Upload teximages */ - if (t->dirty) { + if (t->base.dirty_images[0]) { mach64SetTexImages( mmesa, tObj ); mmesa->dirty |= (MACH64_UPLOAD_TEX0IMAGE << unit); } /* Bind to the given texture unit */ mmesa->CurrentTexObj[unit] = t; - t->bound |= (1 << unit); + t->base.bound |= (1 << unit); - if ( t->memBlock ) - mach64UpdateTexLRU( mmesa, t ); + if ( t->base.memBlock ) + driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */ /* register setup */ if ( unit == 0 ) { @@ -515,8 +444,8 @@ void mach64UpdateTextureState( GLcontext *ctx ) FALLBACK( mmesa, MACH64_FALLBACK_TEXTURE, GL_FALSE ); /* Unbind any currently bound textures */ - if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->bound = 0; - if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->bound = 0; + if ( mmesa->CurrentTexObj[0] ) mmesa->CurrentTexObj[0]->base.bound = 0; + if ( mmesa->CurrentTexObj[1] ) mmesa->CurrentTexObj[1]->base.bound = 0; mmesa->CurrentTexObj[0] = NULL; mmesa->CurrentTexObj[1] = NULL; @@ -556,3 +485,41 @@ void mach64UpdateTextureState( GLcontext *ctx ) MACH64_UPLOAD_TEXTURE); } + +/* Due to the way we must program texture state into the Rage Pro, + * we must leave these calculations to the absolute last minute. + */ +void mach64EmitTexStateLocked( mach64ContextPtr mmesa, + mach64TexObjPtr t0, + mach64TexObjPtr t1 ) +{ + drm_mach64_sarea_t *sarea = mmesa->sarea; + drm_mach64_context_regs_t *regs = &(mmesa->setup); + + /* for multitex, both textures must be local or AGP */ + if ( t0 && t1 ) + assert(t0->heap == t1->heap); + + if ( t0 ) { + if (t0->heap == MACH64_CARD_HEAP) { +#if ENABLE_PERF_BOXES + mmesa->c_texsrc_card++; +#endif + mmesa->setup.tex_cntl &= ~MACH64_TEX_SRC_AGP; + } else { +#if ENABLE_PERF_BOXES + mmesa->c_texsrc_agp++; +#endif + mmesa->setup.tex_cntl |= MACH64_TEX_SRC_AGP; + } + mmesa->setup.tex_offset = t0->bufAddr; + } + + if ( t1 ) { + mmesa->setup.secondary_tex_off = t1->bufAddr; + } + + memcpy( &sarea->context_state.tex_size_pitch, ®s->tex_size_pitch, + MACH64_NR_TEXTURE_REGS * sizeof(GLuint) ); +} +