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