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