1 /*
2 Copyright (C) 2003-2006 Andrey Nazarov
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 
21 #include "gl_local.h"
22 
23 drawStatic_t draw;
24 
Draw_SetColor(uint32 flags,const color_t color)25 void Draw_SetColor( uint32 flags, const color_t color ) {
26 	draw.flags &= ~DRAW_COLOR_MASK;
27 
28 	if( flags == DRAW_COLOR_CLEAR ) {
29         *( uint32 * )draw.color = *( uint32 * )colorWhite;
30 		return;
31 	}
32 	if( flags == DRAW_COLOR_ALPHA ) {
33         draw.color[3] = *( float * )color * 255;
34 	} else if( flags == DRAW_COLOR_INDEXED ) {
35 		*( uint32 * )draw.color = d_8to24table[ *( uint32 * )color & 255 ];
36 	} else {
37 		if( flags & DRAW_COLOR_RGB ) {
38 			VectorCopy( color, draw.color );
39 		}
40 		if( flags & DRAW_COLOR_ALPHA ) {
41 			draw.color[3] = color[3];
42 		}
43 	}
44 
45 	draw.flags |= flags;
46 }
47 
Draw_SetClipRect(uint32 flags,const clipRect_t * clip)48 void Draw_SetClipRect( uint32 flags, const clipRect_t *clip ) {
49 	clipRect_t rc;
50 
51 	if( ( draw.flags & DRAW_CLIP_MASK ) == flags ) {
52 		return;
53 	}
54 
55 	GL_Flush2D();
56 
57 	if( flags == DRAW_CLIP_DISABLED ) {
58 		qglDisable( GL_SCISSOR_TEST );
59 		draw.flags &= ~DRAW_CLIP_MASK;
60 		return;
61 	}
62 
63 	rc.left = 0;
64 	rc.top = 0;
65 	if( flags & DRAW_CLIP_LEFT ) {
66 		rc.left = clip->left;
67 	}
68 	if( flags & DRAW_CLIP_TOP ) {
69 		rc.top = clip->top;
70 	}
71 
72 	rc.right = vid.width;
73 	rc.bottom = vid.height;
74 	if( flags & DRAW_CLIP_RIGHT ) {
75 		rc.right = clip->right;
76 	}
77 	if( flags & DRAW_CLIP_BOTTOM ) {
78 		rc.bottom = clip->bottom;
79 	}
80 
81 	qglEnable( GL_SCISSOR_TEST );
82 	qglScissor( rc.left, vid.height - rc.bottom,
83 		rc.right - rc.left, rc.bottom - rc.top );
84 	draw.flags = ( draw.flags & ~DRAW_CLIP_MASK ) | flags;
85 }
86 
Draw_SetScale(float * scale)87 void Draw_SetScale( float *scale ) {
88 	float f = scale ? *scale : 1;
89 
90 	if( draw.scale == f ) {
91 		return;
92 	}
93 
94 	GL_Flush2D();
95 
96 	qglMatrixMode( GL_PROJECTION );
97 	qglLoadIdentity();
98 
99 	qglOrtho( 0, vid.width * f, vid.height * f, 0, -1, 1 );
100 
101 	draw.scale = f;
102 }
103 
Draw_GetPicSize(int * w,int * h,qhandle_t hPic)104 void Draw_GetPicSize( int *w, int *h, qhandle_t hPic ) {
105 	image_t *image;
106 
107 	image = R_ImageForHandle( hPic );
108 	*w = image->upload_width;
109 	*h = image->upload_height;
110 }
111 
Draw_GetFontSize(int * w,int * h,qhandle_t hFont)112 void Draw_GetFontSize( int *w, int *h, qhandle_t hFont ) {
113     *w = 8;
114     *h = 8;
115 }
116 
GL_RegisterFont(const char * name)117 qhandle_t GL_RegisterFont( const char *name ) {
118 	image_t	*image;
119 	char	fullname[MAX_QPATH];
120 
121 	if( name[0] != '/' && name[0] != '\\' ) {
122 		Com_sprintf( fullname, sizeof( fullname ), "pics/%s", name );
123 		COM_DefaultExtension( fullname, ".pcx", sizeof( fullname ) );
124 		image = R_FindImage( fullname, it_charset );
125 	} else {
126 		image = R_FindImage( name + 1, it_charset );
127 	}
128 
129 	if( !image ) {
130 		return 0;
131 	}
132 
133 	return ( image - r_images );
134 }
135 
Draw_StretchPicST(int x,int y,int w,int h,float s1,float t1,float s2,float t2,qhandle_t hPic)136 void Draw_StretchPicST( int x, int y, int w, int h, float s1, float t1,
137         float s2, float t2, qhandle_t hPic )
138 {
139 	/* TODO: scrap support */
140     GL_StretchPic( x, y, w, h, s1, t1, s2, t2, draw.color,
141 		R_ImageForHandle( hPic ) );
142 }
143 
Draw_StretchPic(int x,int y,int w,int h,qhandle_t hPic)144 void Draw_StretchPic( int x, int y, int w, int h, qhandle_t hPic ) {
145 	image_t *image;
146 
147 	image = R_ImageForHandle( hPic );
148     GL_StretchPic( x, y, w, h, image->sl, image->tl, image->sh, image->th,
149 		draw.color, image );
150 }
151 
Draw_Pic(int x,int y,qhandle_t hPic)152 void Draw_Pic( int x, int y, qhandle_t hPic ) {
153 	image_t *image;
154 
155 	image = R_ImageForHandle( hPic );
156     GL_StretchPic( x, y, image->width, image->height,
157 		image->sl, image->tl, image->sh, image->th,
158 			draw.color, image );
159 }
160 
161 #define DOSTRETCH do {							\
162 			tbyte = src[u >> 16];				\
163             *dst++ = gl_static.palette[tbyte];	\
164 			u += ustep;							\
165 		} while( 0 )
166 
Draw_StretchRaw(int x,int y,int w,int h,int cols,int rows,const byte * data)167 void Draw_StretchRaw( int x, int y, int w, int h, int cols,
168         int rows, const byte *data )
169 {
170 	uint32	resampled[256*256];
171 	int width, height;
172 	const byte *src;
173 	byte tbyte;
174 	uint32 *dst;
175 	int u, v, ustep, vstep;
176 
177 	vstep = rows * 0x10000 / 256;
178 	ustep = cols * 0x10000 / 256;
179 
180 	dst = resampled;
181 	v = 0;
182 	height = 256;
183 	do {
184 		src = &data[( v >> 16 ) * cols];
185 
186 		u = 0;
187 		width = 256/8;
188 		do {
189 			DOSTRETCH;
190 			DOSTRETCH;
191 			DOSTRETCH;
192 			DOSTRETCH;
193 			DOSTRETCH;
194 			DOSTRETCH;
195 			DOSTRETCH;
196 			DOSTRETCH;
197 		} while( --width );
198 
199 		v += vstep;
200 	} while( --height );
201 
202 	qglBindTexture( GL_TEXTURE_2D, 0 );
203 	qglTexImage2D( GL_TEXTURE_2D, 0, gl_tex_solid_format, 256, 256, 0,
204             GL_RGBA, GL_UNSIGNED_BYTE, resampled );
205 	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
206 	qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
207 
208 	qglBegin( GL_QUADS );
209 	qglTexCoord2f( 0, 0 ); qglVertex2f( x, y );
210 	qglTexCoord2f( 1, 0 ); qglVertex2f( x + w, y );
211 	qglTexCoord2f( 1, 1 ); qglVertex2f( x + w, y + h );
212 	qglTexCoord2f( 0, 1 ); qglVertex2f( x, y + h );
213 	qglEnd();
214 }
215 
216 #define DIV64	( 1.0f / 64.0f )
217 
Draw_TileClear(int x,int y,int w,int h,qhandle_t hPic)218 void Draw_TileClear( int x, int y, int w, int h, qhandle_t hPic ) {
219 	image_t *image;
220 
221 	if( !( image = R_ImageForHandle( hPic ) ) ) {
222 		GL_StretchPic( x, y, w, h, 0, 0, 1, 1, colorBlack, r_whiteimage );
223 		return;
224 	}
225 	GL_StretchPic( x, y, w, h, x * DIV64, y * DIV64, ( x + w ) * DIV64, ( y + h ) * DIV64, colorWhite, image );
226 }
227 
Draw_Fill(int x,int y,int w,int h,int c)228 void Draw_Fill( int x, int y, int w, int h, int c ) {
229     GL_StretchPic( x, y, w, h, 0, 0, 1, 1, ( byte * )&d_8to24table[c & 255],
230             r_whiteimage );
231 }
232 
Draw_FillEx(int x,int y,int w,int h,const color_t color)233 void Draw_FillEx( int x, int y, int w, int h, const color_t color ) {
234     GL_StretchPic( x, y, w, h, 0, 0, 1, 1, color, r_whiteimage );
235 }
236 
Draw_FadeScreen(void)237 void Draw_FadeScreen( void ) {
238 }
239 
Draw_Char(int x,int y,uint32 flags,int ch,qhandle_t hFont)240 void Draw_Char( int x, int y, uint32 flags, int ch, qhandle_t hFont ) {
241 	float s, t;
242 
243     ch &= 255;
244     s = ( ch & 15 ) * 0.0625f;
245 	t = ( ch >> 4 ) * 0.0625f;
246 
247     GL_StretchPic( x, y, 8, 8, s, t, s + 0.0625f, t + 0.0625f,
248             draw.color, R_ImageForHandle( hFont ) );
249 }
250 
Draw_String(int x,int y,uint32 flags,int maxChars,const char * string,qhandle_t hFont)251 void Draw_String( int x, int y, uint32 flags, int maxChars,
252         const char *string, qhandle_t hFont )
253 {
254     byte c;
255 	float s, t;
256 	image_t *image;
257     color_t colors[2];
258 	int mask;
259 
260 	image = R_ImageForHandle( hFont );
261 
262 	mask = 0;
263 	if( flags & UI_ALTCOLOR ) {
264 		mask |= 128;
265 	}
266 
267     *( uint32 * )colors[0] = *( uint32 * )draw.color;
268 	*( uint32 * )colors[1] = MakeColor( 255, 255, 255, draw.color[3] );
269 	while( maxChars-- && *string ) {
270         if( Q_IsColorString( string ) ) {
271             c = string[1];
272 			if( c == COLOR_ALT ) {
273 				mask |= 128;
274 			} else if( c == COLOR_RESET ) {
275                 *( uint32 * )colors[0] = *( uint32 * )draw.color;
276 				mask = 0;
277 				if( flags & UI_ALTCOLOR ) {
278 					mask |= 128;
279 				}
280             } else {
281                 VectorCopy( colorTable[ ColorIndex( c ) ], colors[0] );
282 				mask = 0;
283             }
284             string += 2;
285             continue;
286         }
287 
288 		c = *string++;
289 		c |= mask;
290 
291         if( ( c & 127 ) == 32 ) {
292             x += 8;
293             continue;
294         }
295 
296 		s = ( c & 15 ) * 0.0625f;
297 		t = ( c >> 4 ) * 0.0625f;
298 
299         GL_StretchPic( x, y, 8, 8, s, t, s + 0.0625f, t + 0.0625f,
300 			colors[ ( c >> 7 ) & 1 ], image );
301 		x += 8;
302     }
303 }
304 
305 image_t *r_charset;
306 
Draw_Stringf(int x,int y,const char * fmt,...)307 void Draw_Stringf( int x, int y, const char *fmt, ... ) {
308 	va_list argptr;
309 	char buffer[MAX_STRING_CHARS];
310 	char *string;
311 	byte c;
312 	float s, t;
313 
314 	va_start( argptr, fmt );
315 	Q_vsnprintf( buffer, sizeof( buffer ), fmt, argptr );
316 	va_end( argptr );
317 
318     if( !r_charset ) {
319         qhandle_t tmp;
320         tmp = GL_RegisterFont( "conchars" );
321         if(!tmp) return;
322         r_charset = R_ImageForHandle( tmp );
323     }
324 
325 	string = buffer;
326 	while( *string ) {
327 		c = *string++;
328 
329 		s = ( c & 15 ) * 0.0625f;
330 		t = ( c >> 4 ) * 0.0625f;
331 
332 #if 0
333 		glBegin( GL_QUADS );
334 			glTexCoord2f( s, t );
335 			glVertex2i( x, y );
336 			glTexCoord2f( s + 0.0625f, t );
337 			glVertex2i( x + 8, y );
338 			glTexCoord2f( s + 0.0625f, t + 0.0625f );
339 			glVertex2i( x + 8, y + 16 );
340 			glTexCoord2f( s, t + 0.0625f );
341 			glVertex2i( x, y + 16 );
342 		glEnd();
343 #endif
344         GL_StretchPic( x, y, 8, 16, s, t, s + 0.0625f, t + 0.0625f,
345                 colorWhite, r_charset );
346 		x += 8;
347 	}
348 
349 }
350 
351 #if 0
352 
353 void Draw_FPS( int x, int y ) {
354 	int time;
355 	static int realtime;
356 	static int frameTimes[4] = { 1 };
357 	static int current;
358 	int fps;
359 
360 	time = sys.Milliseconds();
361 	frameTimes[current & 3] = time - realtime;
362 	current++;
363 	realtime = time;
364 
365 	fps = 4000 / ( frameTimes[0] + frameTimes[1] +
366             frameTimes[2] + frameTimes[3] );
367 	Draw_Stringf( x, y, "FPS: %i", fps );
368 }
369 
370 #else
371 
372 #define FPS_APERTURE    9
373 
SortCmp(const void * v1,const void * v2)374 int SortCmp( const void *v1, const void *v2 ) {
375     int i1 = *( int * )v1;
376     int i2 = *( int * )v2;
377 
378     if( i1 < i2 ) {
379         return -1;
380     }
381     if( i1 > i2 ) {
382         return 1;
383     }
384     return 0;
385 }
386 
Draw_FPS(int x,int y)387 void Draw_FPS( int x, int y ) {
388 	int time;
389 	static int realtime;
390 	static int frameTimes[FPS_APERTURE];
391 	static int current;
392 	int buffer[FPS_APERTURE];
393 	int fps, i;
394 
395 	time = sys.Milliseconds();
396 	frameTimes[current % FPS_APERTURE] = time - realtime;
397 	current++;
398 	realtime = time;
399 
400     for( i = 0; i < FPS_APERTURE; i++ ) {
401         buffer[i] = frameTimes[i];
402     }
403 
404     qsort( buffer, FPS_APERTURE, sizeof( buffer[0] ), SortCmp );
405     if( buffer[4] ) {
406 	    fps = 1000 / buffer[4];
407     	Draw_Stringf( x, y, "FPS: %i", fps );
408     }
409 }
410 #endif
411 
412 
Draw_Stats(void)413 void Draw_Stats( void ) {
414 	int x, y;
415 	//const char *orderStr[2] = { "unordered", "inorder" };
416 	//const char *enableStr[2] = { "disabled", "enabled" };
417 	//const char *algStr[2] = { "mergesort", "quicksort" };
418     statCounters_t st = c;
419 
420 #if 0
421     GL_Flush2D();
422    // GL_StretchPic( 0, 0, vid.width, vid.height, -0.5f, -0.5f, 1.5f, 1.5f,
423     GL_StretchPic( 0, 0, vid.width, vid.height, 0, 0, 1, 1,
424             colorWhite, r_beamtexture );
425    // qglBlendFunc( GL_ONE, GL_ONE );
426     //
427 #endif
428 
429 	y = 16;
430 	x = 16;
431 
432 	Draw_FPS( vid.width - 80, y );
433 //    qglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
434     //GL_Flush2D();
435 
436 	Draw_Stringf( x, y, "Nodes visible  : %i", st.nodesVisible ); y += 16;
437 	Draw_Stringf( x, y, "Nodes culled   : %i", st.nodesCulled ); y += 16;
438 	//Draw_String( x, y, "Nodes drawn  : %i", c_nodesDrawn ); y += 16;
439 	//Draw_String( x, y, "Faces marked : %i", c_facesMarked ); y += 16;
440 	Draw_Stringf( x, y, "Faces drawn    : %i", st.facesDrawn ); y += 16;
441     if( st.facesCulled ) {
442     	Draw_Stringf( x, y, "Faces culled   : %i", st.facesCulled ); y += 16;
443     }
444     if( st.boxesCulled ) {
445     	Draw_Stringf( x, y, "Boxes culled   : %i", st.boxesCulled ); y += 16;
446     }
447 	if( st.spheresCulled ) {
448     	Draw_Stringf( x, y, "Spheres culled : %i", st.spheresCulled ); y += 16;
449     }
450 	if( st.rotatedBoxesCulled ) {
451 		Draw_Stringf( x, y, "RtBoxes culled : %i", st.rotatedBoxesCulled ); y += 16;
452     }
453 	Draw_Stringf( x, y, "Tris drawn   : %i", st.trisDrawn ); y += 16;
454 	Draw_Stringf( x, y, "Tex switches : %i", st.texSwitches ); y += 16;
455     if( st.batchesDrawn ) {
456     	Draw_Stringf( x, y, "Batches drawn: %i", st.batchesDrawn ); y += 16;
457     	Draw_Stringf( x, y, "Faces / batch: %i", st.facesDrawn / st.batchesDrawn );
458         y += 16;
459     	Draw_Stringf( x, y, "Tris / batch : %i", st.trisDrawn / st.batchesDrawn );
460         y += 16;
461     }
462 
463 	y += 16;
464     /*
465 	Draw_String( x, y, "Drawing order: %s", orderStr[r_drawOrder] ); y += 16;
466 	Draw_String( x, y, "Depth test   : %s", enableStr[r_depthTest] ); y += 16;
467 	Draw_String( x, y, "Faces culling: %s", enableStr[r_cullFace] ); y += 16;
468 	Draw_String( x, y, "Faces sorting: %s", enableStr[enableSort] ); y += 16;
469 	Draw_String( x, y, "Algorithm    : %s", algStr[doMergeSort] ); y += 16;
470     */
471 
472 	y += 16;
473 }
474 
475