home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / d_surf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  7.4 KB  |  339 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",test, test->size, test->width);
  229.     }
  230. }
  231.  
  232. //=============================================================================
  233.  
  234. // if the num is not a power of 2, assume it will not repeat
  235.  
  236. int     MaskForNum (int num)
  237. {
  238.     if (num==128)
  239.         return 127;
  240.     if (num==64)
  241.         return 63;
  242.     if (num==32)
  243.         return 31;
  244.     if (num==16)
  245.         return 15;
  246.     return 255;
  247. }
  248.  
  249. int D_log2 (int num)
  250. {
  251.     int     c;
  252.     
  253.     c = 0;
  254.     
  255.     while (num>>=1)
  256.         c++;
  257.     return c;
  258. }
  259.  
  260. //=============================================================================
  261.  
  262. /*
  263. ================
  264. D_CacheSurface
  265. ================
  266. */
  267. surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
  268. {
  269.     surfcache_t     *cache;
  270.  
  271. //
  272. // if the surface is animating or flashing, flush the cache
  273. //
  274.     r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
  275.     r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
  276.     r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
  277.     r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
  278.     r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
  279.     
  280. //
  281. // see if the cache holds apropriate data
  282. //
  283.     cache = surface->cachespots[miplevel];
  284.  
  285.     if (cache && !cache->dlight && surface->dlightframe != r_framecount
  286.             && cache->texture == r_drawsurf.texture
  287.             && cache->lightadj[0] == r_drawsurf.lightadj[0]
  288.             && cache->lightadj[1] == r_drawsurf.lightadj[1]
  289.             && cache->lightadj[2] == r_drawsurf.lightadj[2]
  290.             && cache->lightadj[3] == r_drawsurf.lightadj[3] )
  291.         return cache;
  292.  
  293. //
  294. // determine shape of surface
  295. //
  296.     surfscale = 1.0 / (1<<miplevel);
  297.     r_drawsurf.surfmip = miplevel;
  298.     r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
  299.     r_drawsurf.rowbytes = r_drawsurf.surfwidth;
  300.     r_drawsurf.surfheight = surface->extents[1] >> miplevel;
  301.     
  302. //
  303. // allocate memory if needed
  304. //
  305.     if (!cache)     // if a texture just animated, don't reallocate it
  306.     {
  307.         cache = D_SCAlloc (r_drawsurf.surfwidth,
  308.                            r_drawsurf.surfwidth * r_drawsurf.surfheight);
  309.         surface->cachespots[miplevel] = cache;
  310.         cache->owner = &surface->cachespots[miplevel];
  311.         cache->mipscale = surfscale;
  312.     }
  313.     
  314.     if (surface->dlightframe == r_framecount)
  315.         cache->dlight = 1;
  316.     else
  317.         cache->dlight = 0;
  318.  
  319.     r_drawsurf.surfdat = (pixel_t *)cache->data;
  320.     
  321.     cache->texture = r_drawsurf.texture;
  322.     cache->lightadj[0] = r_drawsurf.lightadj[0];
  323.     cache->lightadj[1] = r_drawsurf.lightadj[1];
  324.     cache->lightadj[2] = r_drawsurf.lightadj[2];
  325.     cache->lightadj[3] = r_drawsurf.lightadj[3];
  326.  
  327. //
  328. // draw and light the surface texture
  329. //
  330.     r_drawsurf.surf = surface;
  331.  
  332.     c_surf++;
  333.     R_DrawSurface ();
  334.  
  335.     return surface->cachespots[miplevel];
  336. }
  337.  
  338.  
  339.