summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/d_surf.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/quake/d_surf.c')
-rw-r--r--apps/plugins/sdl/progs/quake/d_surf.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/d_surf.c b/apps/plugins/sdl/progs/quake/d_surf.c
new file mode 100644
index 0000000000..b09c5f896e
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/d_surf.c
@@ -0,0 +1,335 @@
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
26float surfscale;
27qboolean r_cache_thrash; // set if surface cache is thrashing
28
29int sc_size;
30surfcache_t *sc_rover, *sc_base;
31
32#define GUARDSIZE 4
33
34
35int 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
55void 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
66void 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================
79D_InitCaches
80
81================
82*/
83void D_InitCaches (void *buffer, int size)
84{
85
86 if (!msg_suppress_1)
87 Con_Printf ("%ik surface cache\n", size/1024);
88
89 sc_size = size - GUARDSIZE;
90 sc_base = (surfcache_t *)buffer;
91 sc_rover = sc_base;
92
93 sc_base->next = NULL;
94 sc_base->owner = NULL;
95 sc_base->size = sc_size;
96
97 D_ClearCacheGuard ();
98}
99
100
101/*
102==================
103D_FlushCaches
104==================
105*/
106void D_FlushCaches (void)
107{
108 surfcache_t *c;
109
110 if (!sc_base)
111 return;
112
113 for (c = sc_base ; c ; c = c->next)
114 {
115 if (c->owner)
116 *c->owner = NULL;
117 }
118
119 sc_rover = sc_base;
120 sc_base->next = NULL;
121 sc_base->owner = NULL;
122 sc_base->size = sc_size;
123}
124
125/*
126=================
127D_SCAlloc
128=================
129*/
130surfcache_t *D_SCAlloc (int width, int size)
131{
132 surfcache_t *new;
133 qboolean wrapped_this_time;
134
135 if ((width < 0) || (width > 256))
136 Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
137
138 if ((size <= 0) || (size > 0x10000))
139 Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
140
141 size = (int)&((surfcache_t *)0)->data[size];
142 size = (size + 3) & ~3;
143 if (size > sc_size)
144 Sys_Error ("D_SCAlloc: %i > cache size",size);
145
146// if there is not size bytes after the rover, reset to the start
147 wrapped_this_time = false;
148
149 if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
150 {
151 if (sc_rover)
152 {
153 wrapped_this_time = true;
154 }
155 sc_rover = sc_base;
156 }
157
158// colect and free surfcache_t blocks until the rover block is large enough
159 new = sc_rover;
160 if (sc_rover->owner)
161 *sc_rover->owner = NULL;
162
163 while (new->size < size)
164 {
165 // free another
166 sc_rover = sc_rover->next;
167 if (!sc_rover)
168 Sys_Error ("D_SCAlloc: hit the end of memory");
169 if (sc_rover->owner)
170 *sc_rover->owner = NULL;
171
172 new->size += sc_rover->size;
173 new->next = sc_rover->next;
174 }
175
176// create a fragment out of any leftovers
177 if (new->size - size > 256)
178 {
179 sc_rover = (surfcache_t *)( (byte *)new + size);
180 sc_rover->size = new->size - size;
181 sc_rover->next = new->next;
182 sc_rover->width = 0;
183 sc_rover->owner = NULL;
184 new->next = sc_rover;
185 new->size = size;
186 }
187 else
188 sc_rover = new->next;
189
190 new->width = width;
191// DEBUG
192 if (width > 0)
193 new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
194
195 new->owner = NULL; // should be set properly after return
196
197 if (d_roverwrapped)
198 {
199 if (wrapped_this_time || (sc_rover >= d_initial_rover))
200 r_cache_thrash = true;
201 }
202 else if (wrapped_this_time)
203 {
204 d_roverwrapped = true;
205 }
206
207D_CheckCacheGuard (); // DEBUG
208 return new;
209}
210
211
212/*
213=================
214D_SCDump
215=================
216*/
217void D_SCDump (void)
218{
219 surfcache_t *test;
220
221 for (test = sc_base ; test ; test = test->next)
222 {
223 if (test == sc_rover)
224 Sys_Printf ("ROVER:\n");
225 printf ("%p : %i bytes %i width\n",test, test->size, test->width);
226 }
227}
228
229//=============================================================================
230
231// if the num is not a power of 2, assume it will not repeat
232
233int MaskForNum (int num)
234{
235 if (num==128)
236 return 127;
237 if (num==64)
238 return 63;
239 if (num==32)
240 return 31;
241 if (num==16)
242 return 15;
243 return 255;
244}
245
246int D_log2 (int num)
247{
248 int c;
249
250 c = 0;
251
252 while (num>>=1)
253 c++;
254 return c;
255}
256
257//=============================================================================
258
259/*
260================
261D_CacheSurface
262================
263*/
264surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
265{
266 surfcache_t *cache;
267
268//
269// if the surface is animating or flashing, flush the cache
270//
271 r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
272 r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
273 r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
274 r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
275 r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
276
277//
278// see if the cache holds apropriate data
279//
280 cache = surface->cachespots[miplevel];
281
282 if (cache && !cache->dlight && surface->dlightframe != r_framecount
283 && cache->texture == r_drawsurf.texture
284 && cache->lightadj[0] == r_drawsurf.lightadj[0]
285 && cache->lightadj[1] == r_drawsurf.lightadj[1]
286 && cache->lightadj[2] == r_drawsurf.lightadj[2]
287 && cache->lightadj[3] == r_drawsurf.lightadj[3] )
288 return cache;
289
290//
291// determine shape of surface
292//
293 surfscale = 1.0 / (1<<miplevel);
294 r_drawsurf.surfmip = miplevel;
295 r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
296 r_drawsurf.rowbytes = r_drawsurf.surfwidth;
297 r_drawsurf.surfheight = surface->extents[1] >> miplevel;
298
299//
300// allocate memory if needed
301//
302 if (!cache) // if a texture just animated, don't reallocate it
303 {
304 cache = D_SCAlloc (r_drawsurf.surfwidth,
305 r_drawsurf.surfwidth * r_drawsurf.surfheight);
306 surface->cachespots[miplevel] = cache;
307 cache->owner = &surface->cachespots[miplevel];
308 cache->mipscale = surfscale;
309 }
310
311 if (surface->dlightframe == r_framecount)
312 cache->dlight = 1;
313 else
314 cache->dlight = 0;
315
316 r_drawsurf.surfdat = (pixel_t *)cache->data;
317
318 cache->texture = r_drawsurf.texture;
319 cache->lightadj[0] = r_drawsurf.lightadj[0];
320 cache->lightadj[1] = r_drawsurf.lightadj[1];
321 cache->lightadj[2] = r_drawsurf.lightadj[2];
322 cache->lightadj[3] = r_drawsurf.lightadj[3];
323
324//
325// draw and light the surface texture
326//
327 r_drawsurf.surf = surface;
328
329 c_surf++;
330 R_DrawSurface ();
331
332 return surface->cachespots[miplevel];
333}
334
335