Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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