home *** CD-ROM | disk | FTP | other *** search
- /* -*- mode: C; tab-width:8; -*-
-
- fxmesa3.c - 3Dfx VooDoo texture memory functions
- */
-
- /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * See the file fxmesa1.c for more informations about authors
- *
- */
-
- #if defined(FX)
-
- #include <limits.h>
-
- #include "fxdrv.h"
-
- static texmemfreenode *newtexfreenode(FxU32 start, FxU32 end)
- {
- texmemfreenode *tmn;
-
- if(!(tmn=malloc(sizeof(texmemfreenode)))) {
- fprintf(stderr,"fx Driver: out of memory !\n");
- fxCloseHardware();
- exit(-1);
- }
-
- tmn->next=NULL;
- tmn->startadr=start;
- tmn->endadr=end;
-
- return tmn;
- }
-
- void inittmmanager(fxMesaContext fxMesa)
- {
- texmemfreenode *tmn,*tmntmp;
- FxU32 start,end,blockstart,blockend;
-
- start=grTexMinAddress(GR_TMU0);
- end=grTexMaxAddress(GR_TMU0);
-
- if(fxMesa->verbose) {
- fprintf(stderr,"Lower texture memory address (%d)\n",start);
- fprintf(stderr,"Higher texture memory address (%d)\n",end);
- fprintf(stderr,"Splitting Texture memory in 2Mb blocks:\n");
- }
-
- fxMesa->tmfree=NULL;
- fxMesa->tmalloc=NULL;
-
- blockstart=start;
- while(blockstart<=end) {
- if(blockstart+0x1fffff>end)
- blockend=end;
- else
- blockend=blockstart+0x1fffff;
-
- if(fxMesa->verbose)
- fprintf(stderr," %07d-%07d\n",blockstart,blockend);
-
- tmn=newtexfreenode(blockstart,blockend);
-
- if(fxMesa->tmfree) {
- for(tmntmp=fxMesa->tmfree;tmntmp->next!=NULL;tmntmp=tmntmp->next);
- tmntmp->next=tmn;
- } else
- fxMesa->tmfree=tmn;
-
- blockstart+=0x1fffff+1;
- }
-
- fxMesa->texbindnumber=0;
- }
-
- static struct gl_texture_object *findoldesttmblock(fxMesaContext fxMesa,
- texmemallocnode *tmalloc,
- GLuint texbindnumber)
- {
- GLuint age,oldestage,lasttimeused;
- struct gl_texture_object *oldesttexobj;
-
- oldesttexobj=tmalloc->tobj;
- oldestage=0;
-
- while(tmalloc) {
- lasttimeused=((texinfo *)(tmalloc->tobj->DriverData))->tmi.lasttimeused;
-
- if(lasttimeused>texbindnumber)
- age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */
- else
- age=texbindnumber-lasttimeused;
-
- if(age>=oldestage) {
- oldestage=age;
- oldesttexobj=tmalloc->tobj;
- }
-
- tmalloc=tmalloc->next;
- }
-
- return oldesttexobj;
- }
-
- static GLboolean freeoldtmblock(fxMesaContext fxMesa)
- {
- struct gl_texture_object *oldesttexobj;
-
- if(!fxMesa->tmalloc)
- return GL_FALSE;
-
- oldesttexobj=findoldesttmblock(fxMesa,fxMesa->tmalloc,fxMesa->texbindnumber);
-
- moveouttexturememory(fxMesa,oldesttexobj);
-
- return GL_TRUE;
- }
-
- static texmemfreenode *extracttmfreeblock(texmemfreenode *tmfree, int texmemsize,
- GLboolean *success, FxU32 *startadr)
- {
- int blocksize;
-
- /* TO DO: cut recursion */
-
- if(!tmfree) {
- *success=GL_FALSE;
- return NULL;
- }
-
- blocksize=tmfree->endadr-tmfree->startadr+1;
-
- if(blocksize==texmemsize) {
- texmemfreenode *nexttmfree;
-
- *success=GL_TRUE;
- *startadr=tmfree->startadr;
-
- nexttmfree=tmfree->next;
- free(tmfree);
-
- return nexttmfree;
- }
-
- if(blocksize>texmemsize) {
- *success=GL_TRUE;
- *startadr=tmfree->startadr;
-
- tmfree->startadr+=texmemsize;
-
- return tmfree;
- }
-
- tmfree->next=extracttmfreeblock(tmfree->next,texmemsize,success,startadr);
- return tmfree;
- }
-
- static texmemallocnode *gettmblock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
- int texmemsize)
- {
- texmemfreenode *newtmfree;
- texmemallocnode *newtmalloc;
- GLboolean success;
- FxU32 startadr;
-
- for(;;) { /* TO DO: improve performaces */
- newtmfree=extracttmfreeblock(fxMesa->tmfree,texmemsize,&success,&startadr);
-
- if(success) {
- fxMesa->tmfree=newtmfree;
-
- if(!(newtmalloc=malloc(sizeof(texmemallocnode)))) {
- fprintf(stderr,"fx Driver: out of memory !\n");
- fxCloseHardware();
- exit(-1);
- }
-
- newtmalloc->next=fxMesa->tmalloc;
- newtmalloc->startadr=startadr;
- newtmalloc->endadr=startadr+texmemsize-1;
- newtmalloc->tobj=tObj;
-
- fxMesa->tmalloc=newtmalloc;
-
- return newtmalloc;
- }
-
- if(!freeoldtmblock(fxMesa)) {
- fprintf(stderr,"fx Driver: internal error in gettmblock()\n");
- fxCloseHardware();
- exit(-1);
- }
- }
- }
-
- void moveintexturememory(fxMesaContext fxMesa, struct gl_texture_object *tObj)
- {
- texinfo *ti=(texinfo *)tObj->DriverData;
- GrLOD_t lodlevel;
- int i;
- int texmemsize;
-
- #if defined(DEBUG_FXMESA)
- fprintf(stderr,"fxmesa: moveintexturememory(%d)\n",tObj->Name);
- #endif
-
- fxMesa->stats.reqtexupload++;
-
- if(!ti->valid)
- return;
-
- if(ti->tmi.isintexturememory)
- return;
-
- #if defined(DEBUG_FXMESA)
- fprintf(stderr,"fxmesa: downloading %d in texture memory\n",tObj->Name);
- #endif
-
- texmemsize=grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
-
- ti->tmi.tm=gettmblock(fxMesa,tObj,texmemsize);
-
- texgetinfo(ti->width,ti->height,&lodlevel,NULL,NULL,NULL,NULL,NULL);
-
- for(i=0;i<MAXNUM_MIPMAPLEVELS;i++)
- if(ti->levelsdefined & (1<<i)) {
- grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm->startadr,lodlevel,
- ti->info.largeLod,ti->info.aspectRatio,
- ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
- ti->tmi.mipmaplevel[i]);
-
- lodlevel++; /* TO DO: check if it is right */
- }
-
- fxMesa->stats.texupload++;
- fxMesa->stats.memtexupload+=texmemsize;
-
- ti->tmi.isintexturememory=GL_TRUE;
- }
-
- void reloadmipmaplevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level)
- {
- texinfo *ti=(texinfo *)tObj->DriverData;
- GrLOD_t lodlevel;
-
- moveintexturememory(fxMesa,tObj);
-
- texgetinfo(ti->width,ti->height,&lodlevel,NULL,NULL,NULL,NULL,NULL);
-
- grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm->startadr,lodlevel+level,
- ti->info.largeLod,ti->info.aspectRatio,
- ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
- ti->tmi.mipmaplevel[level]);
-
- }
-
- static texmemallocnode *freetmallocblock(texmemallocnode *tmalloc, texmemallocnode *tmunalloc)
- {
- if(!tmalloc)
- return NULL;
-
- if(tmalloc==tmunalloc) {
- texmemallocnode *newtmalloc;
-
- newtmalloc=tmalloc->next;
- free(tmalloc);
-
- return newtmalloc;
- }
-
- tmalloc->next=freetmallocblock(tmalloc->next,tmunalloc);
-
- return tmalloc;
- }
-
- static texmemfreenode *addtmfree(texmemfreenode *tmfree, FxU32 startadr, FxU32 endadr)
- {
- if(!tmfree)
- return newtexfreenode(startadr,endadr);
-
- if((endadr+1==tmfree->startadr) && (tmfree->startadr & 0x1fffff)) {
- tmfree->startadr=startadr;
-
- return tmfree;
- }
-
- if((startadr-1==tmfree->endadr) && (startadr & 0x1fffff)) {
- tmfree->endadr=endadr;
-
- if((tmfree->next && (endadr+1==tmfree->next->startadr) &&
- (tmfree->next->startadr & 0x1fffff))) {
- texmemfreenode *nexttmfree;
-
- tmfree->endadr=tmfree->next->endadr;
-
- nexttmfree=tmfree->next->next;
- free(tmfree->next);
-
- tmfree->next=nexttmfree;
- }
-
-
- return tmfree;
- }
-
- if(startadr<tmfree->startadr) {
- texmemfreenode *newtmfree;
-
- newtmfree=newtexfreenode(startadr,endadr);
- newtmfree->next=tmfree;
-
- return newtmfree;
- }
-
- tmfree->next=addtmfree(tmfree->next,startadr,endadr);
-
- return tmfree;
- }
-
- static void freetmblock(fxMesaContext fxMesa, texmemallocnode *tmalloc)
- {
- FxU32 startadr,endadr;
-
- startadr=tmalloc->startadr;
- endadr=tmalloc->endadr;
-
- fxMesa->tmalloc=freetmallocblock(fxMesa->tmalloc,tmalloc);
-
- fxMesa->tmfree=addtmfree(fxMesa->tmfree,startadr,endadr);
- }
-
- void moveouttexturememory(fxMesaContext fxMesa, struct gl_texture_object *tObj)
- {
- texinfo *ti=(texinfo *)tObj->DriverData;
-
- #if defined(DEBUG_FXMESA)
- fprintf(stderr,"fxmesa: moveouttexturememory(%d)\n",tObj->Name);
- #endif
-
- if(!ti->valid)
- return;
-
- if(!ti->tmi.isintexturememory)
- return;
-
- freetmblock(fxMesa,ti->tmi.tm);
-
- ti->tmi.isintexturememory=GL_FALSE;
- }
-
- void freetexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
- {
- texinfo *ti=(texinfo *)tObj->DriverData;
- int i;
-
- moveouttexturememory(fxMesa,tObj);
-
- for(i=0;i<MAXNUM_MIPMAPLEVELS;i++)
- if(ti->levelsdefined & (1<<i))
- free(ti->tmi.mipmaplevel[i]);
-
- ti->valid=GL_FALSE;
- }
-
- void freeallfreenode(texmemfreenode *fn)
- {
- if(!fn)
- return;
-
- if(fn->next)
- freeallfreenode(fn->next);
-
- free(fn);
- }
-
- void freeallallocnode(texmemallocnode *an)
- {
- if(!an)
- return;
-
- if(an->next)
- freeallallocnode(an->next);
-
- free(an);
- }
-
- void closetmmanager(fxMesaContext fxMesa)
- {
- freeallfreenode(fxMesa->tmfree);
- freeallallocnode(fxMesa->tmalloc);
- }
-
-
- #else
-
-
- /*
- * Need this to provide at least one external definition.
- */
-
- int gl_fx_dummy_function3(void)
- {
- return 0;
- }
-
- #endif /* FX */
-