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