home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / src / fxmesa3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  9.0 KB  |  420 lines

  1. /* -*- mode: C; tab-width:8;  -*-
  2.  
  3.              fxmesa3.c - 3Dfx VooDoo texture memory functions
  4. */
  5.  
  6. /*
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Library General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Library General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Library General Public
  18.  * License along with this library; if not, write to the Free
  19.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  * See the file fxmesa1.c for more informations about authors
  22.  *
  23.  */
  24.  
  25. #if defined(FX)
  26.  
  27. #include <limits.h>
  28.  
  29. #include "fxdrv.h"
  30.  
  31. static texmemfreenode *newtexfreenode(FxU32 start, FxU32 end)
  32. {
  33.   texmemfreenode *tmn;
  34.  
  35.   if(!(tmn=malloc(sizeof(texmemfreenode)))) {
  36.     fprintf(stderr,"fx Driver: out of memory !\n");
  37.     fxCloseHardware();
  38.     exit(-1);
  39.   }
  40.  
  41.   tmn->next=NULL;
  42.   tmn->startadr=start;
  43.   tmn->endadr=end;
  44.  
  45.   return tmn;
  46. }
  47.  
  48. void inittmmanager(fxMesaContext fxMesa)
  49. {
  50.   texmemfreenode *tmn,*tmntmp;
  51.   FxU32 start,end,blockstart,blockend;
  52.  
  53.   start=grTexMinAddress(GR_TMU0);
  54.   end=grTexMaxAddress(GR_TMU0);
  55.  
  56.   if(fxMesa->verbose) {
  57.     fprintf(stderr,"Lower texture memory address (%d)\n",start);
  58.     fprintf(stderr,"Higher texture memory address (%d)\n",end);
  59.     fprintf(stderr,"Splitting Texture memory in 2Mb blocks:\n");
  60.   }
  61.  
  62.   fxMesa->tmfree=NULL;
  63.   fxMesa->tmalloc=NULL;
  64.  
  65.   blockstart=start;
  66.   while(blockstart<=end) {
  67.     if(blockstart+0x1fffff>end)
  68.       blockend=end;
  69.     else
  70.       blockend=blockstart+0x1fffff;
  71.  
  72.     if(fxMesa->verbose)
  73.       fprintf(stderr,"  %07d-%07d\n",blockstart,blockend);
  74.  
  75.     tmn=newtexfreenode(blockstart,blockend);
  76.  
  77.     if(fxMesa->tmfree) {
  78.       for(tmntmp=fxMesa->tmfree;tmntmp->next!=NULL;tmntmp=tmntmp->next);
  79.       tmntmp->next=tmn;
  80.     } else
  81.       fxMesa->tmfree=tmn;
  82.  
  83.     blockstart+=0x1fffff+1;
  84.   }
  85.  
  86.   fxMesa->texbindnumber=0;
  87. }
  88.  
  89. static struct gl_texture_object *findoldesttmblock(fxMesaContext fxMesa,
  90.                            texmemallocnode *tmalloc,
  91.                            GLuint texbindnumber)
  92. {
  93.   GLuint age,oldestage,lasttimeused;
  94.   struct gl_texture_object *oldesttexobj;
  95.  
  96.   oldesttexobj=tmalloc->tobj;
  97.   oldestage=0;
  98.  
  99.   while(tmalloc) {
  100.     lasttimeused=((texinfo *)(tmalloc->tobj->DriverData))->tmi.lasttimeused;
  101.  
  102.     if(lasttimeused>texbindnumber)
  103.       age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */
  104.     else
  105.       age=texbindnumber-lasttimeused;
  106.  
  107.     if(age>=oldestage) {
  108.       oldestage=age;
  109.       oldesttexobj=tmalloc->tobj;
  110.     }
  111.  
  112.     tmalloc=tmalloc->next;
  113.   }
  114.  
  115.   return oldesttexobj;
  116. }
  117.  
  118. static GLboolean freeoldtmblock(fxMesaContext fxMesa)
  119. {
  120.   struct gl_texture_object *oldesttexobj;
  121.  
  122.   if(!fxMesa->tmalloc)
  123.     return GL_FALSE;
  124.  
  125.   oldesttexobj=findoldesttmblock(fxMesa,fxMesa->tmalloc,fxMesa->texbindnumber);
  126.  
  127.   moveouttexturememory(fxMesa,oldesttexobj);
  128.  
  129.   return GL_TRUE;
  130. }
  131.  
  132. static texmemfreenode *extracttmfreeblock(texmemfreenode *tmfree, int texmemsize,
  133.                       GLboolean *success, FxU32 *startadr)
  134. {
  135.   int blocksize;
  136.  
  137.   /* TO DO: cut recursion */
  138.  
  139.   if(!tmfree) {
  140.     *success=GL_FALSE;
  141.     return NULL;
  142.   }
  143.  
  144.   blocksize=tmfree->endadr-tmfree->startadr+1;
  145.  
  146.   if(blocksize==texmemsize) {
  147.     texmemfreenode *nexttmfree;
  148.  
  149.     *success=GL_TRUE;
  150.     *startadr=tmfree->startadr;
  151.  
  152.     nexttmfree=tmfree->next;
  153.     free(tmfree);
  154.  
  155.     return nexttmfree;
  156.   }
  157.  
  158.   if(blocksize>texmemsize) {
  159.     *success=GL_TRUE;
  160.     *startadr=tmfree->startadr;
  161.  
  162.     tmfree->startadr+=texmemsize;
  163.  
  164.     return tmfree;
  165.   }
  166.  
  167.   tmfree->next=extracttmfreeblock(tmfree->next,texmemsize,success,startadr);
  168.   return tmfree;
  169. }
  170.  
  171. static texmemallocnode *gettmblock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
  172.                    int texmemsize)
  173. {
  174.   texmemfreenode *newtmfree;
  175.   texmemallocnode *newtmalloc;
  176.   GLboolean success;
  177.   FxU32 startadr;
  178.  
  179.   for(;;) { /* TO DO: improve performaces */
  180.     newtmfree=extracttmfreeblock(fxMesa->tmfree,texmemsize,&success,&startadr);
  181.  
  182.     if(success) {
  183.       fxMesa->tmfree=newtmfree;
  184.  
  185.       if(!(newtmalloc=malloc(sizeof(texmemallocnode)))) {
  186.     fprintf(stderr,"fx Driver: out of memory !\n");
  187.     fxCloseHardware();
  188.     exit(-1);
  189.       }
  190.       
  191.       newtmalloc->next=fxMesa->tmalloc;
  192.       newtmalloc->startadr=startadr;
  193.       newtmalloc->endadr=startadr+texmemsize-1;
  194.       newtmalloc->tobj=tObj;
  195.  
  196.       fxMesa->tmalloc=newtmalloc;
  197.  
  198.       return newtmalloc;
  199.     }
  200.  
  201.     if(!freeoldtmblock(fxMesa)) {
  202.       fprintf(stderr,"fx Driver: internal error in gettmblock()\n");
  203.       fxCloseHardware();
  204.       exit(-1);
  205.     }
  206.   }
  207. }
  208.  
  209. void moveintexturememory(fxMesaContext fxMesa, struct gl_texture_object *tObj)
  210. {
  211.   texinfo *ti=(texinfo *)tObj->DriverData;
  212.   GrLOD_t lodlevel;
  213.   int i;
  214.   int texmemsize;
  215.  
  216. #if defined(DEBUG_FXMESA)
  217.   fprintf(stderr,"fxmesa: moveintexturememory(%d)\n",tObj->Name);
  218. #endif
  219.  
  220.   fxMesa->stats.reqtexupload++;
  221.  
  222.   if(!ti->valid)
  223.     return;
  224.  
  225.   if(ti->tmi.isintexturememory)
  226.     return;
  227.  
  228. #if defined(DEBUG_FXMESA)
  229.   fprintf(stderr,"fxmesa: downloading %d in texture memory\n",tObj->Name);
  230. #endif
  231.  
  232.   texmemsize=grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
  233.  
  234.   ti->tmi.tm=gettmblock(fxMesa,tObj,texmemsize);
  235.  
  236.   texgetinfo(ti->width,ti->height,&lodlevel,NULL,NULL,NULL,NULL,NULL);
  237.  
  238.   for(i=0;i<MAXNUM_MIPMAPLEVELS;i++)
  239.     if(ti->levelsdefined & (1<<i)) {
  240.       grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm->startadr,lodlevel,
  241.                    ti->info.largeLod,ti->info.aspectRatio,
  242.                    ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
  243.                    ti->tmi.mipmaplevel[i]);
  244.  
  245.       lodlevel++; /* TO DO: check if it is right */
  246.     }
  247.  
  248.   fxMesa->stats.texupload++;
  249.   fxMesa->stats.memtexupload+=texmemsize;
  250.  
  251.   ti->tmi.isintexturememory=GL_TRUE;
  252. }
  253.  
  254. void reloadmipmaplevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level)
  255. {
  256.   texinfo *ti=(texinfo *)tObj->DriverData;
  257.   GrLOD_t lodlevel;
  258.  
  259.   moveintexturememory(fxMesa,tObj);
  260.  
  261.   texgetinfo(ti->width,ti->height,&lodlevel,NULL,NULL,NULL,NULL,NULL);
  262.  
  263.   grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm->startadr,lodlevel+level,
  264.                ti->info.largeLod,ti->info.aspectRatio,
  265.                ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
  266.                ti->tmi.mipmaplevel[level]);
  267.  
  268. }
  269.  
  270. static texmemallocnode *freetmallocblock(texmemallocnode *tmalloc, texmemallocnode *tmunalloc)
  271. {
  272.   if(!tmalloc)
  273.     return NULL;
  274.  
  275.   if(tmalloc==tmunalloc) {
  276.     texmemallocnode *newtmalloc;
  277.  
  278.     newtmalloc=tmalloc->next;
  279.     free(tmalloc);
  280.  
  281.     return newtmalloc;
  282.   }
  283.  
  284.   tmalloc->next=freetmallocblock(tmalloc->next,tmunalloc);
  285.  
  286.   return tmalloc;
  287. }
  288.  
  289. static texmemfreenode *addtmfree(texmemfreenode *tmfree, FxU32 startadr, FxU32 endadr)
  290. {
  291.   if(!tmfree)
  292.     return newtexfreenode(startadr,endadr);
  293.  
  294.   if((endadr+1==tmfree->startadr) && (tmfree->startadr & 0x1fffff)) {
  295.     tmfree->startadr=startadr;
  296.  
  297.     return tmfree;
  298.   }
  299.  
  300.   if((startadr-1==tmfree->endadr) && (startadr & 0x1fffff)) {
  301.     tmfree->endadr=endadr;
  302.  
  303.     if((tmfree->next && (endadr+1==tmfree->next->startadr) &&
  304.         (tmfree->next->startadr & 0x1fffff))) {
  305.       texmemfreenode *nexttmfree;
  306.  
  307.       tmfree->endadr=tmfree->next->endadr;
  308.  
  309.       nexttmfree=tmfree->next->next;
  310.       free(tmfree->next);
  311.  
  312.       tmfree->next=nexttmfree;
  313.     }
  314.  
  315.  
  316.     return tmfree;
  317.   }
  318.  
  319.   if(startadr<tmfree->startadr) {
  320.     texmemfreenode *newtmfree;
  321.  
  322.     newtmfree=newtexfreenode(startadr,endadr);
  323.     newtmfree->next=tmfree;
  324.  
  325.     return newtmfree;
  326.   }
  327.  
  328.   tmfree->next=addtmfree(tmfree->next,startadr,endadr);
  329.  
  330.   return tmfree;
  331. }
  332.  
  333. static void freetmblock(fxMesaContext fxMesa, texmemallocnode *tmalloc)
  334. {
  335.   FxU32 startadr,endadr;
  336.  
  337.   startadr=tmalloc->startadr;
  338.   endadr=tmalloc->endadr;
  339.  
  340.   fxMesa->tmalloc=freetmallocblock(fxMesa->tmalloc,tmalloc);
  341.  
  342.   fxMesa->tmfree=addtmfree(fxMesa->tmfree,startadr,endadr);
  343. }
  344.  
  345. void moveouttexturememory(fxMesaContext fxMesa, struct gl_texture_object *tObj)
  346. {
  347.   texinfo *ti=(texinfo *)tObj->DriverData;
  348.  
  349. #if defined(DEBUG_FXMESA)
  350.   fprintf(stderr,"fxmesa: moveouttexturememory(%d)\n",tObj->Name);
  351. #endif
  352.  
  353.   if(!ti->valid)
  354.     return;
  355.  
  356.   if(!ti->tmi.isintexturememory)
  357.     return;
  358.  
  359.   freetmblock(fxMesa,ti->tmi.tm);
  360.  
  361.   ti->tmi.isintexturememory=GL_FALSE;
  362. }
  363.  
  364. void freetexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
  365. {
  366.   texinfo *ti=(texinfo *)tObj->DriverData;
  367.   int i;
  368.  
  369.   moveouttexturememory(fxMesa,tObj);
  370.  
  371.   for(i=0;i<MAXNUM_MIPMAPLEVELS;i++)
  372.     if(ti->levelsdefined & (1<<i))
  373.       free(ti->tmi.mipmaplevel[i]);
  374.  
  375.   ti->valid=GL_FALSE;
  376. }
  377.  
  378. void freeallfreenode(texmemfreenode *fn)
  379. {
  380.   if(!fn)
  381.     return;
  382.  
  383.   if(fn->next)
  384.     freeallfreenode(fn->next);
  385.  
  386.   free(fn);
  387. }
  388.  
  389. void freeallallocnode(texmemallocnode *an)
  390. {
  391.   if(!an)
  392.     return;
  393.  
  394.   if(an->next)
  395.     freeallallocnode(an->next);
  396.  
  397.   free(an);
  398. }
  399.  
  400. void closetmmanager(fxMesaContext fxMesa)
  401. {
  402.   freeallfreenode(fxMesa->tmfree);
  403.   freeallallocnode(fxMesa->tmalloc);
  404. }
  405.  
  406.  
  407. #else
  408.  
  409.  
  410. /*
  411.  * Need this to provide at least one external definition.
  412.  */
  413.  
  414. int gl_fx_dummy_function3(void)
  415. {
  416.   return 0;
  417. }
  418.  
  419. #endif  /* FX */
  420.