Quake II RTX doxygen  1.0 dev
surf.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (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. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 // r_surf.c: surface-related refresh code
19 
20 #include "sw.h"
21 
23 
24 static int sourcetstep;
25 static void *prowdestbase;
26 static byte *pbasesource;
27 static int surfrowbytes;
28 static unsigned *r_lightptr;
29 static int r_stepback;
30 static int r_lightwidth;
32 static byte *r_source, *r_sourcemax;
33 
34 static void R_DrawSurfaceBlock8_mip0(void);
35 static void R_DrawSurfaceBlock8_mip1(void);
36 static void R_DrawSurfaceBlock8_mip2(void);
37 static void R_DrawSurfaceBlock8_mip3(void);
38 
39 static void (*surfmiptable[4])(void) = {
44 };
45 
46 static int sc_size;
48 
49 /*
50 ===============
51 R_TextureAnimation
52 
53 Returns the proper texture for a given time and base texture
54 ===============
55 */
56 static image_t *R_TextureAnimation(mtexinfo_t *tex)
57 {
58  int c;
59 
60  if (!tex->next)
61  return tex->image;
62 
63  c = currententity->frame % tex->numframes;
64  while (c) {
65  tex = tex->next;
66  c--;
67  }
68 
69  return tex->image;
70 }
71 
72 /*
73 ===============
74 R_DrawSurface
75 ===============
76 */
77 static void R_DrawSurface(void)
78 {
79  byte *basetptr;
80  int smax, tmax, twidth;
81  int u;
82  int soffset, toffset;
83  int horzblockstep;
84  byte *pcolumndest;
85  void (*pblockdrawer)(void);
86  image_t *mt;
87  int blocksize;
88  int blockdivshift;
89 
91 
92  mt = r_drawsurf.image;
93 
94  r_source = mt->pixels[r_drawsurf.surfmip];
95 
96  twidth = (mt->upload_width >> r_drawsurf.surfmip) * TEX_BYTES;
97 
98  blocksize = 16 >> r_drawsurf.surfmip;
99  blockdivshift = 4 - r_drawsurf.surfmip;
100 
102 
103  r_numhblocks = r_drawsurf.surfwidth >> blockdivshift;
104  r_numvblocks = r_drawsurf.surfheight >> blockdivshift;
105 
106  pblockdrawer = surfmiptable[r_drawsurf.surfmip];
107 // TODO: only needs to be set when there is a display settings change
108  horzblockstep = blocksize * TEX_BYTES;
109 
110  smax = mt->upload_width >> r_drawsurf.surfmip;
111  tmax = mt->upload_height >> r_drawsurf.surfmip;
112  sourcetstep = twidth;
113  r_stepback = tmax * twidth;
114 
115  r_sourcemax = r_source + tmax * smax * TEX_BYTES;
116 
117  soffset = r_drawsurf.surf->texturemins[0];
118  toffset = r_drawsurf.surf->texturemins[1];
119 
120 // << 16 components are to guarantee positive values for %
121  soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax;
122  toffset = ((toffset >> r_drawsurf.surfmip) + (tmax << 16)) % tmax;
123 
124  basetptr = &r_source[toffset * twidth];
125 
126  pcolumndest = r_drawsurf.surfdat;
127 
128  for (u = 0; u < r_numhblocks; u++) {
129  r_lightptr = (unsigned *)blocklights + u * LIGHTMAP_BYTES;
130 
131  prowdestbase = pcolumndest;
132 
133  pbasesource = basetptr + soffset * TEX_BYTES;
134 
135  (*pblockdrawer)();
136 
137  soffset += blocksize;
138  if (soffset >= smax)
139  soffset = 0;
140 
141  pcolumndest += horzblockstep;
142  }
143 }
144 
145 //=============================================================================
146 
147 #define BLOCK_FUNC R_DrawSurfaceBlock8_mip0
148 #define BLOCK_SHIFT 4
149 #include "block.h"
150 
151 #define BLOCK_FUNC R_DrawSurfaceBlock8_mip1
152 #define BLOCK_SHIFT 3
153 #include "block.h"
154 
155 #define BLOCK_FUNC R_DrawSurfaceBlock8_mip2
156 #define BLOCK_SHIFT 2
157 #include "block.h"
158 
159 #define BLOCK_FUNC R_DrawSurfaceBlock8_mip3
160 #define BLOCK_SHIFT 1
161 #include "block.h"
162 
163 //============================================================================
164 
165 
166 /*
167 ================
168 R_InitCaches
169 
170 ================
171 */
172 void R_InitCaches(void)
173 {
174  int size;
175  int pix;
176 
177  // calculate size to allocate
178  if (sw_surfcacheoverride->integer) {
182  } else {
184 
185  pix = vid.width * vid.height;
186  if (pix > 64000)
187  size += (pix - 64000) * 3;
188  }
189 
190  size *= TEX_BYTES;
191 
192  // round up to page size
193  size = (size + 8191) & ~8191;
194 
195  Com_DPrintf("%ik surface cache\n", size / 1024);
196 
197  sc_size = size;
198  sc_base = (surfcache_t *)R_Malloc(size);
199  sc_rover = sc_base;
200 
201  sc_base->next = NULL;
202  sc_base->owner = NULL;
203  sc_base->size = sc_size;
204 }
205 
206 void R_FreeCaches(void)
207 {
208  if (sc_base) {
209  Z_Free(sc_base);
210  sc_base = NULL;
211  }
212 
213  sc_size = 0;
214  sc_rover = NULL;
215 }
216 
217 /*
218 ==================
219 D_FlushCaches
220 ==================
221 */
222 void D_FlushCaches(void)
223 {
224  surfcache_t *c;
225 
226  if (!sc_base)
227  return;
228 
229  for (c = sc_base; c; c = c->next) {
230  if (c->owner) {
231  *c->owner = NULL;
232  }
233  }
234 
235  sc_rover = sc_base;
236  sc_base->next = NULL;
237  sc_base->owner = NULL;
238  sc_base->size = sc_size;
239 }
240 
241 /*
242 =================
243 D_SCAlloc
244 =================
245 */
246 static surfcache_t *D_SCAlloc(int width, int size)
247 {
248  surfcache_t *new;
249 
250  if ((width < 0) || (width > 256))
251  Com_Error(ERR_FATAL, "D_SCAlloc: bad cache width %d\n", width);
252 
253  if ((size <= 0) || (size > 0x10000 * TEX_BYTES))
254  Com_Error(ERR_FATAL, "D_SCAlloc: bad cache size %d\n", size);
255 
256  size += sizeof(surfcache_t) - 4;
257  size = (size + 3) & ~3;
258  if (size > sc_size)
259  Com_Error(ERR_FATAL, "D_SCAlloc: %i > cache size of %i", size, sc_size);
260 
261 // if there is not size bytes after the rover, reset to the start
262  if (!sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) {
263  sc_rover = sc_base;
264  }
265 
266 // colect and free surfcache_t blocks until the rover block is large enough
267  new = sc_rover;
268  if (sc_rover->owner)
269  *sc_rover->owner = NULL;
270 
271  while (new->size < size) {
272  // free another
274  if (!sc_rover)
275  Com_Error(ERR_FATAL, "D_SCAlloc: hit the end of memory");
276  if (sc_rover->owner)
277  *sc_rover->owner = NULL;
278 
279  new->size += sc_rover->size;
280  new->next = sc_rover->next;
281  }
282 
283 // create a fragment out of any leftovers
284  if (new->size - size > 256) {
285  sc_rover = (surfcache_t *)((byte *)new + size);
286  sc_rover->size = new->size - size;
287  sc_rover->next = new->next;
288  sc_rover->width = 0;
289  sc_rover->owner = NULL;
290  new->next = sc_rover;
291  new->size = size;
292  } else
293  sc_rover = new->next;
294 
295  new->width = width;
296 // DEBUG
297  if (width > 0)
298  new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
299 
300  new->owner = NULL; // should be set properly after return
301 
302  return new;
303 }
304 
305 
306 /*
307 =================
308 D_SCDump
309 =================
310 */
311 void D_SCDump_f(void)
312 {
313  surfcache_t *test;
314 
315  for (test = sc_base; test; test = test->next) {
316  if (test == sc_rover)
317  Com_Printf("ROVER:\n");
318  Com_Printf("%p : %i bytes %i width\n", test, test->size,
319  test->width);
320  }
321 }
322 
323 //=============================================================================
324 
325 /*
326 ================
327 D_CacheSurface
328 ================
329 */
330 surfcache_t *D_CacheSurface(mface_t *surface, int miplevel)
331 {
332  surfcache_t *cache;
333  float surfscale;
334 
335 //
336 // if the surface is animating or flashing, flush the cache
337 //
338  r_drawsurf.image = R_TextureAnimation(surface->texinfo);
339  r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white * sw_modulate->value * 256;
340  r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white * sw_modulate->value * 256;
341  r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white * sw_modulate->value * 256;
342  r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white * sw_modulate->value * 256;
343 
344 //
345 // see if the cache holds apropriate data
346 //
347  cache = surface->cachespots[miplevel];
348 
349  if (cache && !cache->dlight && surface->dlightframe != r_framecount
350  && cache->image == r_drawsurf.image
351  && cache->lightadj[0] == r_drawsurf.lightadj[0]
352  && cache->lightadj[1] == r_drawsurf.lightadj[1]
353  && cache->lightadj[2] == r_drawsurf.lightadj[2]
354  && cache->lightadj[3] == r_drawsurf.lightadj[3])
355  return cache;
356 
357 //
358 // determine shape of surface
359 //
360  surfscale = 1.0 / (1 << miplevel);
362  r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
364  r_drawsurf.surfheight = surface->extents[1] >> miplevel;
365 
366 //
367 // allocate memory if needed
368 //
369  if (!cache) { // if a texture just animated, don't reallocate it
372  surface->cachespots[miplevel] = cache;
373  cache->owner = &surface->cachespots[miplevel];
374  cache->mipscale = surfscale;
375  }
376 
377  if (surface->dlightframe == r_framecount)
378  cache->dlight = 1;
379  else
380  cache->dlight = 0;
381 
382  r_drawsurf.surfdat = (pixel_t *)cache->data;
383 
384  cache->image = r_drawsurf.image;
385  cache->lightadj[0] = r_drawsurf.lightadj[0];
386  cache->lightadj[1] = r_drawsurf.lightadj[1];
387  cache->lightadj[2] = r_drawsurf.lightadj[2];
388  cache->lightadj[3] = r_drawsurf.lightadj[3];
389 
390 //
391 // draw and light the surface texture
392 //
393  r_drawsurf.surf = surface;
394 
395  c_surf++;
396 
397  // calculate the lightings
398  R_BuildLightMap();
399 
400  // rasterize the surface into the cache
401  R_DrawSurface();
402 
403  return cache;
404 }
405 
406 
sc_base
static surfcache_t * sc_base
Definition: surf.c:47
drawsurf_s
Definition: sw.h:176
block.h
surfcache_s::size
int size
Definition: sw.h:212
r_numvblocks
static int r_numvblocks
Definition: surf.c:31
drawsurf_s::surfheight
int surfheight
Definition: sw.h:184
pbasesource
static byte * pbasesource
Definition: surf.c:26
r_newrefdef
refdef_t r_newrefdef
Definition: main.c:28
r_lightwidth
static int r_lightwidth
Definition: surf.c:30
miplevel
static int miplevel
Definition: edge.c:61
R_DrawSurfaceBlock8_mip2
static void R_DrawSurfaceBlock8_mip2(void)
surfcache_s
Definition: sw.h:207
image_t
struct image_s image_t
Definition: material.h:27
sc_size
static int sc_size
Definition: surf.c:46
R_DrawSurfaceBlock8_mip1
static void R_DrawSurfaceBlock8_mip1(void)
R_TextureAnimation
static image_t * R_TextureAnimation(mtexinfo_t *tex)
Definition: surf.c:56
TEX_BYTES
#define TEX_BYTES
Definition: sw.h:50
surfmiptable
static void(* surfmiptable[4])(void)
Definition: surf.c:39
viddef_t::width
int width
Definition: sw.h:127
D_SCDump_f
void D_SCDump_f(void)
Definition: surf.c:311
surfcache_s::lightadj
int lightadj[MAX_LIGHTMAPS]
Definition: sw.h:210
sw_surfcacheoverride
cvar_t * sw_surfcacheoverride
Definition: main.c:84
r_framecount
int r_framecount
Definition: main.c:64
r_lightptr
static unsigned * r_lightptr
Definition: surf.c:28
viddef_t::height
int height
Definition: sw.h:128
prowdestbase
static void * prowdestbase
Definition: surf.c:25
c_surf
int c_surf
Definition: main.c:42
surfcache_s::image
image_t * image
Definition: sw.h:216
R_DrawSurfaceBlock8_mip3
static void R_DrawSurfaceBlock8_mip3(void)
r_sourcemax
static byte * r_sourcemax
Definition: surf.c:32
blocklights
static float blocklights[MAX_BLOCKLIGHTS *3]
Definition: surf.c:112
surfcache_t
struct surfcache_s surfcache_t
width
static int width
Definition: physical_sky.c:38
currententity
entity_t * currententity
Definition: bsp.c:26
drawsurf_s::surf
mface_t * surf
Definition: sw.h:179
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
R_BuildLightMap
void R_BuildLightMap(void)
Definition: light.c:290
pixel_t
unsigned char pixel_t
Definition: sw.h:121
drawsurf_s::lightadj
fixed8_t lightadj[MAX_LIGHTMAPS]
Definition: sw.h:180
sw.h
drawsurf_s::rowbytes
int rowbytes
Definition: sw.h:178
surfcache_s::mipscale
float mipscale
Definition: sw.h:215
Z_Free
void Z_Free(void *ptr)
Definition: zone.c:147
R_InitCaches
void R_InitCaches(void)
Definition: surf.c:172
drawsurf_s::image
image_t * image
Definition: sw.h:181
surfcache_s::owner
struct surfcache_s ** owner
Definition: sw.h:209
void
void(APIENTRY *qwglDrawBuffer)(GLenum mode)
r_source
static byte * r_source
Definition: surf.c:32
sc_rover
static surfcache_t * sc_rover
Definition: surf.c:47
r_numhblocks
static int r_numhblocks
Definition: surf.c:31
drawsurf_s::surfmip
int surfmip
Definition: sw.h:182
D_SCAlloc
static surfcache_t * D_SCAlloc(int width, int size)
Definition: surf.c:246
c
statCounters_t c
Definition: main.c:30
sw_modulate
cvar_t * sw_modulate
Definition: main.c:87
LIGHTMAP_BYTES
#define LIGHTMAP_BYTES
Definition: sw.h:203
D_FlushCaches
void D_FlushCaches(void)
Definition: surf.c:222
Cvar_ClampInteger
int Cvar_ClampInteger(cvar_t *var, int min, int max)
Definition: cvar.c:549
r_drawsurf
drawsurf_t r_drawsurf
Definition: surf.c:22
drawsurf_s::surfwidth
int surfwidth
Definition: sw.h:183
surfcache_s::data
byte data[4]
Definition: sw.h:217
r_stepback
static int r_stepback
Definition: surf.c:29
sourcetstep
static int sourcetstep
Definition: surf.c:24
drawsurf_s::surfdat
byte * surfdat
Definition: sw.h:177
R_DrawSurface
static void R_DrawSurface(void)
Definition: surf.c:77
D_CacheSurface
surfcache_t * D_CacheSurface(mface_t *surface, int miplevel)
Definition: surf.c:330
surfcache_s::dlight
int dlight
Definition: sw.h:211
R_FreeCaches
void R_FreeCaches(void)
Definition: surf.c:206
surfcache_s::width
unsigned width
Definition: sw.h:213
vid
viddef_t vid
Definition: main.c:22
surfcache_s::next
struct surfcache_s * next
Definition: sw.h:208
surfrowbytes
static int surfrowbytes
Definition: surf.c:27
R_DrawSurfaceBlock8_mip0
static void R_DrawSurfaceBlock8_mip0(void)
SURFCACHE_SIZE_AT_320X240
#define SURFCACHE_SIZE_AT_320X240
Definition: sw.h:94