Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 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
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
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
 
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
==================
103
D_FlushCaches
104
==================
105
*/
106
void 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
=================
127
D_SCAlloc
128
=================
129
*/
130
surfcache_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
 
207
D_CheckCacheGuard ();   // DEBUG
208
	return new;
209
}
210
 
211
 
212
/*
213
=================
214
D_SCDump
215
=================
216
*/
217
void 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
 
233
int     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
 
246
int 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
================
261
D_CacheSurface
262
================
263
*/
264
surfcache_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<
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