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