|
|
1.1 ! root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.