home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / d_surf.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  7.4 KB  |  341 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. #ifdef AMIGA
  46.   size = SURFCACHE_SIZE_AT_320X200 * 2;  /* phx */
  47. #else
  48.   size = SURFCACHE_SIZE_AT_320X200;
  49. #endif
  50.  
  51.   pix = width*height;
  52.   if (pix > 64000)
  53.     size += (pix-64000)*3;
  54.     
  55.  
  56.   return size;
  57. }
  58.  
  59. void D_CheckCacheGuard (void)
  60. {
  61.   byte    *s;
  62.   int             i;
  63.  
  64.   s = (byte *)sc_base + sc_size;
  65.   for (i=0 ; i<GUARDSIZE ; i++)
  66.     if (s[i] != (byte)i)
  67.       Sys_Error ("D_CheckCacheGuard: failed");
  68. }
  69.  
  70. void D_ClearCacheGuard (void)
  71. {
  72.   byte    *s;
  73.   int             i;
  74.   
  75.   s = (byte *)sc_base + sc_size;
  76.   for (i=0 ; i<GUARDSIZE ; i++)
  77.     s[i] = (byte)i;
  78. }
  79.  
  80.  
  81. /*
  82. ================
  83. D_InitCaches
  84.  
  85. ================
  86. */
  87. void D_InitCaches (void *buffer, int size)
  88. {
  89.  
  90.   if (!msg_suppress_1)
  91.     Con_Printf ("%ik surface cache\n", size/1024);
  92.  
  93.   sc_size = size - GUARDSIZE;
  94.   sc_base = (surfcache_t *)buffer;
  95.   sc_rover = sc_base;
  96.   
  97.   sc_base->next = NULL;
  98.   sc_base->owner = NULL;
  99.   sc_base->size = sc_size;
  100.   
  101.   D_ClearCacheGuard ();
  102. }
  103.  
  104.  
  105. /*
  106. ==================
  107. D_FlushCaches
  108. ==================
  109. */
  110. void D_FlushCaches (void)
  111. {
  112.   surfcache_t     *c;
  113.   
  114.   if (!sc_base)
  115.     return;
  116.  
  117.   for (c = sc_base ; c ; c = c->next)
  118.   {
  119.     if (c->owner)
  120.       *c->owner = NULL;
  121.   }
  122.   
  123.   sc_rover = sc_base;
  124.   sc_base->next = NULL;
  125.   sc_base->owner = NULL;
  126.   sc_base->size = sc_size;
  127. }
  128.  
  129. /*
  130. =================
  131. D_SCAlloc
  132. =================
  133. */
  134. surfcache_t     *D_SCAlloc (int width, int size)
  135. {
  136.   surfcache_t             *new;
  137.   qboolean                wrapped_this_time;
  138.  
  139.   if ((width < 0) || (width > 256))
  140.     Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
  141.  
  142.   if ((size <= 0) || (size > 0x10000))
  143.     Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
  144.   
  145.   size = (int)&((surfcache_t *)0)->data[size];
  146.   size = (size + 3) & ~3;
  147.   if (size > sc_size)
  148.     Sys_Error ("D_SCAlloc: %i > cache size",size);
  149.  
  150. // if there is not size bytes after the rover, reset to the start
  151.   wrapped_this_time = false;
  152.  
  153.   if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
  154.   {
  155.     if (sc_rover)
  156.     {
  157.       wrapped_this_time = true;
  158.     }
  159.     sc_rover = sc_base;
  160.   }
  161.     
  162. // colect and free surfcache_t blocks until the rover block is large enough
  163.   new = sc_rover;
  164.   if (sc_rover->owner)
  165.     *sc_rover->owner = NULL;
  166.   
  167.   while (new->size < size)
  168.   {
  169.   // free another
  170.     sc_rover = sc_rover->next;
  171.     if (!sc_rover)
  172.       Sys_Error ("D_SCAlloc: hit the end of memory");
  173.     if (sc_rover->owner)
  174.       *sc_rover->owner = NULL;
  175.       
  176.     new->size += sc_rover->size;
  177.     new->next = sc_rover->next;
  178.   }
  179.  
  180. // create a fragment out of any leftovers
  181.   if (new->size - size > 256)
  182.   {
  183.     sc_rover = (surfcache_t *)( (byte *)new + size);
  184.     sc_rover->size = new->size - size;
  185.     sc_rover->next = new->next;
  186.     sc_rover->width = 0;
  187.     sc_rover->owner = NULL;
  188.     new->next = sc_rover;
  189.     new->size = size;
  190.   }
  191.   else
  192.     sc_rover = new->next;
  193.   
  194.   new->width = width;
  195. // DEBUG
  196.   if (width > 0)
  197.     new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
  198.  
  199.   new->owner = NULL;              // should be set properly after return
  200.  
  201.   if (d_roverwrapped)
  202.   {
  203.     if (wrapped_this_time || (sc_rover >= d_initial_rover))
  204.       r_cache_thrash = true;
  205.   }
  206.   else if (wrapped_this_time)
  207.   {       
  208.     d_roverwrapped = true;
  209.   }
  210.  
  211. D_CheckCacheGuard ();   // DEBUG
  212.   return new;
  213. }
  214.  
  215.  
  216. /*
  217. =================
  218. D_SCDump
  219. =================
  220. */
  221. void D_SCDump (void)
  222. {
  223.   surfcache_t             *test;
  224.  
  225.   for (test = sc_base ; test ; test = test->next)
  226.   {
  227.     if (test == sc_rover)
  228.       Sys_Printf ("ROVER:\n");
  229.     printf ("%p : %i bytes     %i width\n",(void *)test,
  230.             test->size, (int)test->width);
  231.   }
  232. }
  233.  
  234. //=============================================================================
  235.  
  236. // if the num is not a power of 2, assume it will not repeat
  237.  
  238. int     MaskForNum (int num)
  239. {
  240.   if (num==128)
  241.     return 127;
  242.   if (num==64)
  243.     return 63;
  244.   if (num==32)
  245.     return 31;
  246.   if (num==16)
  247.     return 15;
  248.   return 255;
  249. }
  250.  
  251. int D_log2 (int num)
  252. {
  253.   int     c;
  254.   
  255.   c = 0;
  256.   
  257.   while (num>>=1)
  258.     c++;
  259.   return c;
  260. }
  261.  
  262. //=============================================================================
  263.  
  264. #ifndef PPCASM
  265. /*
  266. ================
  267. D_CacheSurface
  268. ================
  269. */
  270. surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
  271. {
  272.   surfcache_t     *cache;
  273.  
  274. //
  275. // if the surface is animating or flashing, flush the cache
  276. //
  277.   r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
  278.   r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
  279.   r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
  280.   r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
  281.   r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
  282.   
  283. //
  284. // see if the cache holds apropriate data
  285. //
  286.   cache = surface->cachespots[miplevel];
  287.  
  288.   if (cache && !cache->dlight && surface->dlightframe != r_framecount
  289.       && cache->texture == r_drawsurf.texture
  290.       && cache->lightadj[0] == r_drawsurf.lightadj[0]
  291.       && cache->lightadj[1] == r_drawsurf.lightadj[1]
  292.       && cache->lightadj[2] == r_drawsurf.lightadj[2]
  293.       && cache->lightadj[3] == r_drawsurf.lightadj[3] )
  294.     return cache;
  295.  
  296. //
  297. // determine shape of surface
  298. //
  299.   surfscale = 1.0 / (1<<miplevel);
  300.   r_drawsurf.surfmip = miplevel;
  301.   r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
  302.   r_drawsurf.rowbytes = r_drawsurf.surfwidth;
  303.   r_drawsurf.surfheight = surface->extents[1] >> miplevel;
  304.   
  305. //
  306. // allocate memory if needed
  307. //
  308.   if (!cache)     // if a texture just animated, don't reallocate it
  309.   {
  310.     cache = D_SCAlloc (r_drawsurf.surfwidth,
  311.                r_drawsurf.surfwidth * r_drawsurf.surfheight);
  312.     surface->cachespots[miplevel] = cache;
  313.     cache->owner = &surface->cachespots[miplevel];
  314.     cache->mipscale = surfscale;
  315.   }
  316.   
  317.   if (surface->dlightframe == r_framecount)
  318.     cache->dlight = 1;
  319.   else
  320.     cache->dlight = 0;
  321.  
  322.   r_drawsurf.surfdat = (pixel_t *)cache->data;
  323.   
  324.   cache->texture = r_drawsurf.texture;
  325.   cache->lightadj[0] = r_drawsurf.lightadj[0];
  326.   cache->lightadj[1] = r_drawsurf.lightadj[1];
  327.   cache->lightadj[2] = r_drawsurf.lightadj[2];
  328.   cache->lightadj[3] = r_drawsurf.lightadj[3];
  329.  
  330. //
  331. // draw and light the surface texture
  332. //
  333.   r_drawsurf.surf = surface;
  334.  
  335.   c_surf++;
  336.   R_DrawSurface ();
  337.  
  338.   return surface->cachespots[miplevel];
  339. }
  340. #endif
  341.