|
|
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.