home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / d_surf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  7.4 KB  |  340 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // d_surf.c: rasterization driver surface heap manager
  21.  
  22. #include "quakedef.h"
  23. #include "d_local.h"
  24. #include "r_local.h"
  25.  
  26. float           surfscale;
  27. qboolean        r_cache_thrash;         // set if surface cache is thrashing
  28.  
  29. int                                     sc_size;
  30. surfcache_t                     *sc_rover, *sc_base;
  31.  
  32. #define GUARDSIZE       4
  33.  
  34.  
  35. int     D_SurfaceCacheForRes (int width, int height)
  36. {
  37.   int             size, pix;
  38.  
  39.   if (COM_CheckParm ("-surfcachesize"))
  40.   {
  41.     size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
  42.     return size;
  43.   }
  44.   
  45.   size = SURFCACHE_SIZE_AT_320X200;
  46.  
  47.   pix = width*height;
  48.   if (pix > 64000)
  49.     size += (pix-64000)*3;
  50.     
  51.  
  52.   return size;
  53. }
  54.  
  55. void D_CheckCacheGuard (void)
  56. {
  57.   byte    *s;
  58.   int             i;
  59.  
  60.   s = (byte *)sc_base + sc_size;
  61.   for (i=0 ; i<GUARDSIZE ; i++)
  62.     if (s[i] != (byte)i)
  63.       Sys_Error ("D_CheckCacheGuard: failed");
  64. }
  65.  
  66. void D_ClearCacheGuard (void)
  67. {
  68.   byte    *s;
  69.   int             i;
  70.   
  71.   s = (byte *)sc_base + sc_size;
  72.   for (i=0 ; i<GUARDSIZE ; i++)
  73.     s[i] = (byte)i;
  74. }
  75.  
  76.  
  77. /*
  78. ================
  79. D_InitCaches
  80.  
  81. ================
  82. */
  83. void D_InitCaches (void *buffer, int size)
  84. {
  85. //  if (!msg_suppress_1)
  86. //    Con_Printf ("%ik surface cache\n", size/1024);
  87.  
  88.   sc_size = size - GUARDSIZE;
  89.   sc_base = (surfcache_t *)buffer;
  90.   sc_rover = sc_base;
  91.   
  92.   sc_base->next = NULL;
  93.   sc_base->owner = NULL;
  94.   sc_base->size = sc_size;
  95.   
  96.   D_ClearCacheGuard ();
  97. }
  98.  
  99.  
  100. /*
  101. ==================
  102. D_FlushCaches
  103. ==================
  104. */
  105. void D_FlushCaches (void)
  106. {
  107.   surfcache_t     *c;
  108.   
  109.   if (!sc_base)
  110.     return;
  111.  
  112.   for (c = sc_base ; c ; c = c->next)
  113.   {
  114.     if (c->owner)
  115.       *c->owner = NULL;
  116.   }
  117.   
  118.   sc_rover = sc_base;
  119.   sc_base->next = NULL;
  120.   sc_base->owner = NULL;
  121.   sc_base->size = sc_size;
  122. }
  123.  
  124. /*
  125. =================
  126. D_SCAlloc
  127. =================
  128. */
  129. surfcache_t     *D_SCAlloc (int width, int size)
  130. {
  131.   surfcache_t             *new;
  132.   qboolean                wrapped_this_time;
  133.  
  134.   if ((width < 0) || (width > 256))
  135.     Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
  136.  
  137.   if ((size <= 0) || (size > 0x10000))
  138.     Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
  139.   
  140. #ifdef __alpha__
  141.   size = (int)((long)&((surfcache_t *)0)->data[size]);
  142. #else
  143.   size = (int)&((surfcache_t *)0)->data[size];
  144. #endif
  145.   size = (size + 3) & ~3;
  146.   if (size > sc_size)
  147.     Sys_Error ("D_SCAlloc: %i > cache size",size);
  148.  
  149. // if there is not size bytes after the rover, reset to the start
  150.   wrapped_this_time = false;
  151.  
  152.   if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
  153.   {
  154.     if (sc_rover)
  155.     {
  156.       wrapped_this_time = true;
  157.     }
  158.     sc_rover = sc_base;
  159.   }
  160.     
  161. // colect and free surfcache_t blocks until the rover block is large enough
  162.   new = sc_rover;
  163.   if (sc_rover->owner)
  164.     *sc_rover->owner = NULL;
  165.   
  166.   while (new->size < size)
  167.   {
  168.   // free another
  169.     sc_rover = sc_rover->next;
  170.     if (!sc_rover)
  171.       Sys_Error ("D_SCAlloc: hit the end of memory");
  172.     if (sc_rover->owner)
  173.       *sc_rover->owner = NULL;
  174.       
  175.     new->size += sc_rover->size;
  176.     new->next = sc_rover->next;
  177.   }
  178.  
  179. // create a fragment out of any leftovers
  180.   if (new->size - size > 256)
  181.   {
  182.     sc_rover = (surfcache_t *)( (byte *)new + size);
  183.     sc_rover->size = new->size - size;
  184.     sc_rover->next = new->next;
  185.     sc_rover->width = 0;
  186.     sc_rover->owner = NULL;
  187.     new->next = sc_rover;
  188.     new->size = size;
  189.   }
  190.   else
  191.     sc_rover = new->next;
  192.   
  193.   new->width = width;
  194. // DEBUG
  195.   if (width > 0)
  196.     new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
  197.  
  198.   new->owner = NULL;              // should be set properly after return
  199.  
  200.   if (d_roverwrapped)
  201.   {
  202.     if (wrapped_this_time || (sc_rover >= d_initial_rover))
  203.       r_cache_thrash = true;
  204.   }
  205.   else if (wrapped_this_time)
  206.   {       
  207.     d_roverwrapped = true;
  208.   }
  209.  
  210. D_CheckCacheGuard ();   // DEBUG
  211.   return new;
  212. }
  213.  
  214.  
  215. /*
  216. =================
  217. D_SCDump
  218. =================
  219. */
  220. void D_SCDump (void)
  221. {
  222.   surfcache_t             *test;
  223.  
  224.   for (test = sc_base ; test ; test = test->next)
  225.   {
  226.     if (test == sc_rover)
  227.       Sys_Printf ("ROVER:\n");
  228.     printf ("%p : %i bytes     %i width\n",
  229.             (void *)test, test->size, (int)test->width);
  230.   }
  231. }
  232.  
  233. //=============================================================================
  234.  
  235. // if the num is not a power of 2, assume it will not repeat
  236.  
  237. int     MaskForNum (int num)
  238. {
  239.   if (num==128)
  240.     return 127;
  241.   if (num==64)
  242.     return 63;
  243.   if (num==32)
  244.     return 31;
  245.   if (num==16)
  246.     return 15;
  247.   return 255;
  248. }
  249.  
  250. int D_log2 (int num)
  251. {
  252.   int     c;
  253.   
  254.   c = 0;
  255.   
  256.   while (num>>=1)
  257.     c++;
  258.   return c;
  259. }
  260.  
  261. //=============================================================================
  262.  
  263. #ifndef PPCASM
  264. /*
  265. ================
  266. D_CacheSurface
  267. ================
  268. */
  269. surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
  270. {
  271.   surfcache_t     *cache;
  272.  
  273. //
  274. // if the surface is animating or flashing, flush the cache
  275. //
  276.   r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
  277.   r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
  278.   r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
  279.   r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
  280.   r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
  281.   
  282. //
  283. // see if the cache holds apropriate data
  284. //
  285.   cache = surface->cachespots[miplevel];
  286.  
  287.   if (cache && !cache->dlight && surface->dlightframe != r_framecount
  288.       && cache->texture == r_drawsurf.texture
  289.       && cache->lightadj[0] == r_drawsurf.lightadj[0]
  290.       && cache->lightadj[1] == r_drawsurf.lightadj[1]
  291.       && cache->lightadj[2] == r_drawsurf.lightadj[2]
  292.       && cache->lightadj[3] == r_drawsurf.lightadj[3] )
  293.     return cache;
  294.  
  295. //
  296. // determine shape of surface
  297. //
  298.   surfscale = 1.0 / (1<<miplevel);
  299.   r_drawsurf.surfmip = miplevel;
  300.   r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
  301.   r_drawsurf.rowbytes = r_drawsurf.surfwidth;
  302.   r_drawsurf.surfheight = surface->extents[1] >> miplevel;
  303.   
  304. //
  305. // allocate memory if needed
  306. //
  307.   if (!cache)     // if a texture just animated, don't reallocate it
  308.   {
  309.     cache = D_SCAlloc (r_drawsurf.surfwidth,
  310.                r_drawsurf.surfwidth * r_drawsurf.surfheight);
  311.     surface->cachespots[miplevel] = cache;
  312.     cache->owner = &surface->cachespots[miplevel];
  313.     cache->mipscale = surfscale;
  314.   }
  315.   
  316.   if (surface->dlightframe == r_framecount)
  317.     cache->dlight = 1;
  318.   else
  319.     cache->dlight = 0;
  320.  
  321.   r_drawsurf.surfdat = (pixel_t *)cache->data;
  322.   
  323.   cache->texture = r_drawsurf.texture;
  324.   cache->lightadj[0] = r_drawsurf.lightadj[0];
  325.   cache->lightadj[1] = r_drawsurf.lightadj[1];
  326.   cache->lightadj[2] = r_drawsurf.lightadj[2];
  327.   cache->lightadj[3] = r_drawsurf.lightadj[3];
  328.  
  329. //
  330. // draw and light the surface texture
  331. //
  332.   r_drawsurf.surf = surface;
  333.  
  334.   c_surf++;
  335.   R_DrawSurface ();
  336.  
  337.   return surface->cachespots[miplevel];
  338. }
  339. #endif
  340.