5 #include "cl_collision.h"
7 cvar_t scr_viewsize = {CVAR_SAVE, "viewsize","100"};
8 cvar_t scr_fov = {CVAR_SAVE, "fov","90"}; // 1 - 170
9 cvar_t scr_conspeed = {CVAR_SAVE, "scr_conspeed","900"}; // LordHavoc: quake used 300
10 cvar_t scr_conalpha = {CVAR_SAVE, "scr_conalpha", "1"};
11 cvar_t scr_conbrightness = {CVAR_SAVE, "scr_conbrightness", "0.2"};
12 cvar_t scr_conforcewhiledisconnected = {CVAR_SAVE, "scr_conforcewhiledisconnected", "1"};
13 cvar_t scr_centertime = {0, "scr_centertime","2"};
14 cvar_t scr_showram = {CVAR_SAVE, "showram","1"};
15 cvar_t scr_showturtle = {CVAR_SAVE, "showturtle","0"};
16 cvar_t scr_showpause = {CVAR_SAVE, "showpause","1"};
17 cvar_t scr_showbrand = {0, "showbrand","0"};
18 cvar_t scr_printspeed = {0, "scr_printspeed","8"};
19 cvar_t vid_conwidth = {CVAR_SAVE, "vid_conwidth", "640"};
20 cvar_t vid_conheight = {CVAR_SAVE, "vid_conheight", "480"};
21 cvar_t vid_pixelaspect = {CVAR_SAVE, "vid_pixelaspect", "1"};
22 cvar_t scr_screenshot_jpeg = {CVAR_SAVE, "scr_screenshot_jpeg","1"};
23 cvar_t scr_screenshot_jpeg_quality = {CVAR_SAVE, "scr_screenshot_jpeg_quality","0.9"};
24 cvar_t scr_screenshot_gamma = {CVAR_SAVE, "scr_screenshot_gamma","2.2"};
25 cvar_t scr_screenshot_name = {0, "scr_screenshot_name","dp"};
26 cvar_t cl_capturevideo = {0, "cl_capturevideo", "0"};
27 cvar_t cl_capturevideo_sound = {0, "cl_capturevideo_sound", "0"};
28 cvar_t cl_capturevideo_fps = {0, "cl_capturevideo_fps", "30"};
29 cvar_t cl_capturevideo_rawrgb = {0, "cl_capturevideo_rawrgb", "0"};
30 cvar_t cl_capturevideo_rawyv12 = {0, "cl_capturevideo_rawyv12", "0"};
31 cvar_t r_textshadow = {0, "r_textshadow", "0"};
32 cvar_t r_letterbox = {0, "r_letterbox", "0"};
34 int jpeg_supported = false;
36 qboolean scr_initialized; // ready to draw
38 float scr_con_current;
40 extern int con_vislines;
42 void DrawCrosshair(int num);
43 static void SCR_ScreenShot_f (void);
44 static void R_Envmap_f (void);
47 void R_ClearScreen(void);
50 static vec4_t string_colors[] =
53 // LordHavoc: why on earth is cyan before magenta in Quake3?
54 // LordHavoc: note: Doom3 uses white for [0] and [7]
55 {0.0, 0.0, 0.0, 1.0}, // black
56 {1.0, 0.0, 0.0, 1.0}, // red
57 {0.0, 1.0, 0.0, 1.0}, // green
58 {1.0, 1.0, 0.0, 1.0}, // yellow
59 {0.0, 0.0, 1.0, 1.0}, // blue
60 {0.0, 1.0, 1.0, 1.0}, // cyan
61 {1.0, 0.0, 1.0, 1.0}, // magenta
62 {1.0, 1.0, 1.0, 1.0}, // white
63 // [515]'s BX_COLOREDTEXT extension
64 {1.0, 1.0, 1.0, 0.5}, // half transparent
65 {0.5, 0.5, 0.5, 1.0} // half brightness
66 // Black's color table
67 //{1.0, 1.0, 1.0, 1.0},
68 //{1.0, 0.0, 0.0, 1.0},
69 //{0.0, 1.0, 0.0, 1.0},
70 //{0.0, 0.0, 1.0, 1.0},
71 //{1.0, 1.0, 0.0, 1.0},
72 //{0.0, 1.0, 1.0, 1.0},
73 //{1.0, 0.0, 1.0, 1.0},
74 //{0.1, 0.1, 0.1, 1.0}
77 #define STRING_COLORS_COUNT (sizeof(string_colors) / sizeof(vec4_t))
79 // color is read and changed in the end
80 void DrawQ_ColoredString( float x, float y, const char *text, int maxlen, float scalex, float scaley, float basered, float basegreen, float baseblue, float basealpha, int flags, int *outcolor )
85 const char *start, *current;
87 if( !outcolor || *outcolor == -1 ) {
88 colorindex = STRING_COLOR_DEFAULT;
90 colorindex = *outcolor;
92 color = string_colors[colorindex];
95 len = (int)strlen( text );
97 len = min( maxlen, (int) strlen( text ) );
99 start = current = text;
101 // check for color control char
102 if( *current == STRING_COLOR_TAG ) {
109 // display the tag char?
110 if( *current == STRING_COLOR_TAG ) {
111 // only display one of the two
116 } else if( '0' <= *current && *current <= '9' ) {
119 colorindex = colorindex * 10 + (*current - '0');
120 // only read as long as it makes a valid index
121 if( colorindex >= (int)STRING_COLORS_COUNT ) {
122 // undo the last operation
128 } while( len > 0 && '0' <= *current && *current <= '9' );
130 color = string_colors[colorindex];
131 // we jump over the color tag
135 // go on and read normal text in until the next control char
136 while( len > 0 && *current != STRING_COLOR_TAG ) {
141 if( start != current ) {
143 DrawQ_String( x, y, start, current - start, scalex, scaley, basered * color[0], basegreen * color[1], baseblue * color[2], basealpha * color[3], flags );
144 // update x to be at the new start position
145 x += (current - start) * scalex;
146 // set start accordingly
151 // return the last colorindex
153 *outcolor = colorindex;
158 ===============================================================================
162 ===============================================================================
165 char scr_centerstring[1024];
166 float scr_centertime_start; // for slow victory printing
167 float scr_centertime_off;
168 int scr_center_lines;
170 int scr_erase_center;
176 Called for important messages that should stay in the center of the screen
180 void SCR_CenterPrint(char *str)
182 strlcpy (scr_centerstring, str, sizeof (scr_centerstring));
183 scr_centertime_off = scr_centertime.value;
184 scr_centertime_start = cl.time;
186 // count the number of lines for centering
187 scr_center_lines = 1;
197 void SCR_DrawCenterString (void)
205 // the finale prints the characters one at a time
207 remaining = scr_printspeed.value * (cl.time - scr_centertime_start);
211 scr_erase_center = 0;
212 start = scr_centerstring;
214 if (scr_center_lines <= 4)
215 y = vid_conheight.integer*0.35;
222 // scan the width of the line
223 for (l=0 ; l<vid_conwidth.integer/8 ; l++)
224 if (start[l] == '\n' || !start[l])
226 x = (vid_conwidth.integer - l*8)/2;
231 DrawQ_ColoredString(x, y, start, l, 8, 8, 1, 1, 1, 1, 0, &color);
239 while (*start && *start != '\n')
244 start++; // skip the \n
248 void SCR_CheckDrawCenterString (void)
250 if (scr_center_lines > scr_erase_lines)
251 scr_erase_lines = scr_center_lines;
253 scr_centertime_off -= host_frametime;
255 // don't draw if this is a normal stats-screen intermission,
256 // only if it is not an intermission, or a finale intermission
257 if (cl.intermission == 1)
259 if (scr_centertime_off <= 0 && !cl.intermission)
261 if (key_dest != key_game)
264 SCR_DrawCenterString ();
272 void SCR_DrawTurtle (void)
276 if (cls.state != ca_connected)
279 if (!scr_showturtle.integer)
282 if (host_frametime < 0.1)
292 DrawQ_Pic (0, 0, "gfx/turtle", 0, 0, 1, 1, 1, 1, 0);
300 void SCR_DrawNet (void)
302 if (cls.state != ca_connected)
304 if (realtime - cl.last_received_message < 0.3)
306 if (cls.demoplayback)
309 DrawQ_Pic (64, 0, "gfx/net", 0, 0, 1, 1, 1, 1, 0);
317 void SCR_DrawPause (void)
321 if (cls.state != ca_connected)
324 if (!scr_showpause.integer) // turn off for screenshots
330 pic = Draw_CachePic ("gfx/pause", true);
331 DrawQ_Pic ((vid_conwidth.integer - pic->width)/2, (vid_conheight.integer - pic->height)/2, "gfx/pause", 0, 0, 1, 1, 1, 1, 0);
339 void SCR_DrawBrand (void)
344 if (!scr_showbrand.value)
347 pic = Draw_CachePic ("gfx/brand", true);
349 switch ((int)scr_showbrand.value)
351 case 1: // bottom left
353 y = vid_conheight.integer - pic->height;
355 case 2: // bottom centre
356 x = (vid_conwidth.integer - pic->width) / 2;
357 y = vid_conheight.integer - pic->height;
359 case 3: // bottom right
360 x = vid_conwidth.integer - pic->width;
361 y = vid_conheight.integer - pic->height;
363 case 4: // centre right
364 x = vid_conwidth.integer - pic->width;
365 y = (vid_conheight.integer - pic->height) / 2;
368 x = vid_conwidth.integer - pic->width;
371 case 6: // top centre
372 x = (vid_conwidth.integer - pic->width) / 2;
379 case 8: // centre left
381 y = (vid_conheight.integer - pic->height) / 2;
387 DrawQ_Pic (x, y, "gfx/brand", 0, 0, 1, 1, 1, 1, 0);
390 //=============================================================================
395 SCR_SetUpToDrawConsole
398 void SCR_SetUpToDrawConsole (void)
400 // lines of console to display
405 if (key_dest == key_game && cls.signon != SIGNONS && scr_conforcewhiledisconnected.integer)
406 key_consoleactive |= KEY_CONSOLEACTIVE_FORCED;
408 key_consoleactive &= ~KEY_CONSOLEACTIVE_FORCED;
410 // decide on the height of the console
411 if (key_consoleactive & KEY_CONSOLEACTIVE_USER)
412 conlines = vid_conheight.integer/2; // half screen
414 conlines = 0; // none visible
416 if (scr_conspeed.value)
418 if (scr_con_current > conlines)
420 scr_con_current -= scr_conspeed.value*host_realframetime;
421 if (scr_con_current < conlines)
422 scr_con_current = conlines;
425 else if (scr_con_current < conlines)
427 scr_con_current += scr_conspeed.value*host_realframetime;
428 if (scr_con_current > conlines)
429 scr_con_current = conlines;
433 scr_con_current = conlines;
441 void SCR_DrawConsole (void)
443 if (key_consoleactive & KEY_CONSOLEACTIVE_FORCED)
446 Con_DrawConsole (vid_conheight.integer);
448 else if (scr_con_current)
449 Con_DrawConsole (scr_con_current);
453 if (key_dest == key_game || key_dest == key_message)
454 Con_DrawNotify (); // only draw notify in game
460 SCR_BeginLoadingPlaque
464 void SCR_BeginLoadingPlaque (void)
468 SCR_UpdateLoadingScreen();
471 //=============================================================================
473 char r_speeds_string[1024];
474 int speedstringcount, r_timereport_active;
475 double r_timereport_temp = 0, r_timereport_current = 0, r_timereport_start = 0;
477 void R_TimeReport(char *desc)
483 if (!r_timereport_active || r_showtrispass)
486 r_timereport_temp = r_timereport_current;
487 r_timereport_current = Sys_DoubleTime();
488 t = (int) ((r_timereport_current - r_timereport_temp) * 1000000.0);
490 dpsnprintf(tempbuf, sizeof(tempbuf), "%8i %s", t, desc);
491 length = (int)strlen(tempbuf);
493 tempbuf[length++] = ' ';
495 if (speedstringcount + length > (vid_conwidth.integer / 8))
497 strlcat(r_speeds_string, "\n", sizeof(r_speeds_string));
498 speedstringcount = 0;
500 // skip the space at the beginning if it's the first on the line
501 if (speedstringcount == 0)
503 strlcat(r_speeds_string, tempbuf + 1, sizeof(r_speeds_string));
504 speedstringcount = length - 1;
508 strlcat(r_speeds_string, tempbuf, sizeof(r_speeds_string));
509 speedstringcount += length;
513 void R_TimeReport_Start(void)
515 r_timereport_active = r_speeds.integer && cls.signon == SIGNONS && cls.state == ca_connected;
516 r_speeds_string[0] = 0;
517 if (r_timereport_active)
519 speedstringcount = 0;
520 sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], r_viewforward[0], r_viewforward[1], r_viewforward[2]);
521 sprintf(r_speeds_string + strlen(r_speeds_string), "world:%6i faces%6i nodes%6i leafs%6i dlitwalls\n", c_faces, c_nodes, c_leafs, c_light_polys);
522 sprintf(r_speeds_string + strlen(r_speeds_string), "%5i models%5i bmodels%5i sprites%6i particles%4i dlights\n", c_models, c_bmodels, c_sprites, c_particles, c_dlights);
523 sprintf(r_speeds_string + strlen(r_speeds_string), "%6i modeltris%6i meshs%6i meshtris\n", c_alias_polys, c_meshs, c_meshelements / 3);
524 sprintf(r_speeds_string + strlen(r_speeds_string), "bloom %s: %i copies (%i pixels) %i draws (%i pixels)\n", c_bloom ? "active" : "inactive", c_bloomcopies, c_bloomcopypixels, c_bloomdraws, c_bloomdrawpixels);
525 sprintf(r_speeds_string + strlen(r_speeds_string), "realtime lighting:%4i lights%4i clears%4i scissored\n", c_rt_lights, c_rt_clears, c_rt_scissored);
526 sprintf(r_speeds_string + strlen(r_speeds_string), "dynamic: %6i shadowmeshes%6i shadowtris%6i lightmeshes%6i lighttris\n", c_rt_shadowmeshes, c_rt_shadowtris, c_rt_lightmeshes, c_rt_lighttris);
527 sprintf(r_speeds_string + strlen(r_speeds_string), "precomputed: %6i shadowmeshes%6i shadowtris\n", c_rtcached_shadowmeshes, c_rtcached_shadowtris);
544 c_rt_shadowmeshes = 0;
546 c_rt_lightmeshes = 0;
548 c_rtcached_shadowmeshes = 0;
549 c_rtcached_shadowtris = 0;
552 c_bloomcopypixels = 0;
554 c_bloomdrawpixels = 0;
556 r_timereport_start = Sys_DoubleTime();
560 void R_TimeReport_End(void)
562 r_timereport_current = r_timereport_start;
563 R_TimeReport("total");
565 if (r_timereport_active)
569 for (i = 0;r_speeds_string[i];i++)
570 if (r_speeds_string[i] == '\n')
572 y = vid_conheight.integer - sb_lines - lines * 8;
574 DrawQ_Fill(0, y, vid_conwidth.integer, lines * 8, 0, 0, 0, 0.5, 0);
575 while (r_speeds_string[i])
578 while (r_speeds_string[i] && r_speeds_string[i] != '\n')
581 DrawQ_String(0, y, r_speeds_string + j, i - j, 8, 8, 1, 1, 1, 1, 0);
582 if (r_speeds_string[i] == '\n')
596 void SCR_SizeUp_f (void)
598 Cvar_SetValue ("viewsize",scr_viewsize.value+10);
609 void SCR_SizeDown_f (void)
611 Cvar_SetValue ("viewsize",scr_viewsize.value-10);
614 void CL_Screen_Init(void)
616 Cvar_RegisterVariable (&scr_fov);
617 Cvar_RegisterVariable (&scr_viewsize);
618 Cvar_RegisterVariable (&scr_conspeed);
619 Cvar_RegisterVariable (&scr_conalpha);
620 Cvar_RegisterVariable (&scr_conbrightness);
621 Cvar_RegisterVariable (&scr_conforcewhiledisconnected);
622 Cvar_RegisterVariable (&scr_showram);
623 Cvar_RegisterVariable (&scr_showturtle);
624 Cvar_RegisterVariable (&scr_showpause);
625 Cvar_RegisterVariable (&scr_showbrand);
626 Cvar_RegisterVariable (&scr_centertime);
627 Cvar_RegisterVariable (&scr_printspeed);
628 Cvar_RegisterVariable (&vid_conwidth);
629 Cvar_RegisterVariable (&vid_conheight);
630 Cvar_RegisterVariable (&vid_pixelaspect);
631 Cvar_RegisterVariable (&scr_screenshot_jpeg);
632 Cvar_RegisterVariable (&scr_screenshot_jpeg_quality);
633 Cvar_RegisterVariable (&scr_screenshot_gamma);
634 Cvar_RegisterVariable (&cl_capturevideo);
635 Cvar_RegisterVariable (&cl_capturevideo_sound);
636 Cvar_RegisterVariable (&cl_capturevideo_fps);
637 Cvar_RegisterVariable (&cl_capturevideo_rawrgb);
638 Cvar_RegisterVariable (&cl_capturevideo_rawyv12);
639 Cvar_RegisterVariable (&r_textshadow);
640 Cvar_RegisterVariable (&r_letterbox);
642 Cmd_AddCommand ("sizeup",SCR_SizeUp_f);
643 Cmd_AddCommand ("sizedown",SCR_SizeDown_f);
644 Cmd_AddCommand ("screenshot",SCR_ScreenShot_f);
645 Cmd_AddCommand ("envmap", R_Envmap_f);
647 scr_initialized = true;
650 void DrawQ_Clear(void)
652 r_refdef.drawqueuesize = 0;
655 static int picelements[6] = {0, 1, 2, 0, 2, 3};
656 void DrawQ_Pic(float x, float y, const char *picname, float width, float height, float red, float green, float blue, float alpha, int flags)
658 DrawQ_SuperPic(x,y,picname,width,height,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
661 void DrawQ_String_Real(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
666 if (alpha < (1.0f / 255.0f))
669 len = (int)strlen(string);
671 for (len = 0;len < maxlen && string[len];len++);
672 for (;len > 0 && string[0] == ' ';string++, x += scalex, len--);
673 for (;len > 0 && string[len - 1] == ' ';len--);
676 if (x >= vid_conwidth.integer || y >= vid_conheight.integer || x < (-scalex * len) || y < (-scaley))
678 size = sizeof(*dq) + ((len + 1 + 3) & ~3);
679 if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize)
681 red = bound(0, red, 1);
682 green = bound(0, green, 1);
683 blue = bound(0, blue, 1);
684 alpha = bound(0, alpha, 1);
685 dq = (void *)(r_refdef.drawqueue + r_refdef.drawqueuesize);
687 dq->command = DRAWQUEUE_STRING;
689 dq->color = ((unsigned int) (red * 255.0f) << 24) | ((unsigned int) (green * 255.0f) << 16) | ((unsigned int) (blue * 255.0f) << 8) | ((unsigned int) (alpha * 255.0f));
694 out = (char *)(dq + 1);
695 memcpy(out, string, len);
697 r_refdef.drawqueuesize += dq->size;
700 void DrawQ_String(float x, float y, const char *string, int maxlen, float scalex, float scaley, float red, float green, float blue, float alpha, int flags)
702 if (r_textshadow.integer)
703 DrawQ_String_Real(x+scalex*0.25,y+scaley*0.25,string,maxlen,scalex,scaley,0,0,0,alpha*0.8,flags);
705 DrawQ_String_Real(x,y,string,maxlen,scalex,scaley,red,green,blue,alpha,flags);
710 void DrawQ_Fill (float x, float y, float w, float h, float red, float green, float blue, float alpha, int flags)
712 DrawQ_SuperPic(x,y,NULL,w,h,0,0,red,green,blue,alpha,1,0,red,green,blue,alpha,0,1,red,green,blue,alpha,1,1,red,green,blue,alpha,flags);
715 void DrawQ_SuperPic(float x, float y, const char *picname, float width, float height, float s1, float t1, float r1, float g1, float b1, float a1, float s2, float t2, float r2, float g2, float b2, float a2, float s3, float t3, float r3, float g3, float b3, float a3, float s4, float t4, float r4, float g4, float b4, float a4, int flags)
719 drawqueuemesh_t mesh;
720 memset(&mesh, 0, sizeof(mesh));
721 if (picname && picname[0])
723 pic = Draw_CachePic(picname, false);
727 height = pic->height;
728 mesh.texture = pic->tex;
730 mesh.num_triangles = 2;
731 mesh.num_vertices = 4;
732 mesh.data_element3i = picelements;
733 mesh.data_vertex3f = floats;
734 mesh.data_texcoord2f = floats + 12;
735 mesh.data_color4f = floats + 20;
736 memset(floats, 0, sizeof(floats));
737 mesh.data_vertex3f[0] = mesh.data_vertex3f[9] = x;
738 mesh.data_vertex3f[1] = mesh.data_vertex3f[4] = y;
739 mesh.data_vertex3f[3] = mesh.data_vertex3f[6] = x + width;
740 mesh.data_vertex3f[7] = mesh.data_vertex3f[10] = y + height;
741 mesh.data_texcoord2f[0] = s1;mesh.data_texcoord2f[1] = t1;mesh.data_color4f[ 0] = r1;mesh.data_color4f[ 1] = g1;mesh.data_color4f[ 2] = b1;mesh.data_color4f[ 3] = a1;
742 mesh.data_texcoord2f[2] = s2;mesh.data_texcoord2f[3] = t2;mesh.data_color4f[ 4] = r2;mesh.data_color4f[ 5] = g2;mesh.data_color4f[ 6] = b2;mesh.data_color4f[ 7] = a2;
743 mesh.data_texcoord2f[4] = s4;mesh.data_texcoord2f[5] = t4;mesh.data_color4f[ 8] = r4;mesh.data_color4f[ 9] = g4;mesh.data_color4f[10] = b4;mesh.data_color4f[11] = a4;
744 mesh.data_texcoord2f[6] = s3;mesh.data_texcoord2f[7] = t3;mesh.data_color4f[12] = r3;mesh.data_color4f[13] = g3;mesh.data_color4f[14] = b3;mesh.data_color4f[15] = a3;
745 DrawQ_Mesh (&mesh, flags);
748 void DrawQ_Mesh (drawqueuemesh_t *mesh, int flags)
755 size += sizeof(drawqueuemesh_t);
756 size += sizeof(int[3]) * mesh->num_triangles;
757 size += sizeof(float[3]) * mesh->num_vertices;
758 size += sizeof(float[2]) * mesh->num_vertices;
759 size += sizeof(float[4]) * mesh->num_vertices;
760 if (r_refdef.drawqueuesize + size > r_refdef.maxdrawqueuesize)
762 dq = (void *)(r_refdef.drawqueue + r_refdef.drawqueuesize);
764 dq->command = DRAWQUEUE_MESH;
771 p = (void *)(dq + 1);
772 m = p;p = (qbyte*)p + sizeof(drawqueuemesh_t);
773 m->num_triangles = mesh->num_triangles;
774 m->num_vertices = mesh->num_vertices;
775 m->texture = mesh->texture;
776 m->data_element3i = p;memcpy(m->data_element3i , mesh->data_element3i , m->num_triangles * sizeof(int[3]));p = (qbyte*)p + m->num_triangles * sizeof(int[3]);
777 m->data_vertex3f = p;memcpy(m->data_vertex3f , mesh->data_vertex3f , m->num_vertices * sizeof(float[3]));p = (qbyte*)p + m->num_vertices * sizeof(float[3]);
778 m->data_texcoord2f = p;memcpy(m->data_texcoord2f, mesh->data_texcoord2f, m->num_vertices * sizeof(float[2]));p = (qbyte*)p + m->num_vertices * sizeof(float[2]);
779 m->data_color4f = p;memcpy(m->data_color4f , mesh->data_color4f , m->num_vertices * sizeof(float[4]));p = (qbyte*)p + m->num_vertices * sizeof(float[4]);
780 r_refdef.drawqueuesize += dq->size;
783 void DrawQ_SetClipArea(float x, float y, float width, float height)
786 if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize)
788 Con_DPrint("DrawQueue full !\n");
791 dq = (void*) (r_refdef.drawqueue + r_refdef.drawqueuesize);
792 dq->size = sizeof(*dq);
793 dq->command = DRAWQUEUE_SETCLIP;
801 r_refdef.drawqueuesize += dq->size;
804 void DrawQ_ResetClipArea(void)
807 if(r_refdef.drawqueuesize + (int)sizeof(*dq) > r_refdef.maxdrawqueuesize)
809 Con_DPrint("DrawQueue full !\n");
812 dq = (void*) (r_refdef.drawqueue + r_refdef.drawqueuesize);
813 dq->size = sizeof(*dq);
814 dq->command = DRAWQUEUE_RESETCLIP;
822 r_refdef.drawqueuesize += dq->size;
830 void SCR_ScreenShot_f (void)
832 static int shotnumber;
833 static char oldname[MAX_QPATH];
834 char base[MAX_QPATH];
835 char filename[MAX_QPATH];
839 qboolean jpeg = (scr_screenshot_jpeg.integer != 0);
841 sprintf (base, "screenshots/%s", scr_screenshot_name.string);
843 if (strcmp (oldname, scr_screenshot_name.string))
845 sprintf(oldname, "%s", scr_screenshot_name.string);
849 // find a file name to save it to
850 for (;shotnumber < 1000000;shotnumber++)
851 if (!FS_SysFileExists(va("%s/%s%06d.tga", fs_gamedir, base, shotnumber)) && !FS_SysFileExists(va("%s/%s%06d.jpg", fs_gamedir, base, shotnumber)))
853 if (shotnumber >= 1000000)
855 Con_Print("SCR_ScreenShot_f: Couldn't create the image file\n");
859 sprintf(filename, "%s%06d.%s", base, shotnumber, jpeg ? "jpg" : "tga");
861 buffer1 = Mem_Alloc(tempmempool, vid.width * vid.height * 3);
862 buffer2 = Mem_Alloc(tempmempool, vid.width * vid.height * 3);
863 buffer3 = Mem_Alloc(tempmempool, vid.width * vid.height * 3 + 18);
865 if (SCR_ScreenShot (filename, buffer1, buffer2, buffer3, 0, 0, vid.width, vid.height, false, false, false, jpeg, true))
866 Con_Printf("Wrote %s\n", filename);
868 Con_Printf("unable to write %s\n", filename);
877 typedef enum capturevideoformat_e
879 CAPTUREVIDEOFORMAT_TARGA,
880 CAPTUREVIDEOFORMAT_JPEG,
881 CAPTUREVIDEOFORMAT_RAWRGB,
882 CAPTUREVIDEOFORMAT_RAWYV12
884 capturevideoformat_t;
886 qboolean cl_capturevideo_active = false;
887 capturevideoformat_t cl_capturevideo_format;
888 static double cl_capturevideo_starttime = 0;
889 double cl_capturevideo_framerate = 0;
890 static int cl_capturevideo_soundrate = 0;
891 static int cl_capturevideo_frame = 0;
892 static qbyte *cl_capturevideo_buffer = NULL;
893 static qfile_t *cl_capturevideo_videofile = NULL;
894 qfile_t *cl_capturevideo_soundfile = NULL;
895 static short cl_capturevideo_rgbtoyuvscaletable[3][3][256];
896 static unsigned char cl_capturevideo_yuvnormalizetable[3][256];
897 //static unsigned char cl_capturevideo_rgbgammatable[3][256];
899 void SCR_CaptureVideo_BeginVideo(void)
904 if (cl_capturevideo_active)
906 // soundrate is figured out on the first SoundFrame
907 cl_capturevideo_active = true;
908 cl_capturevideo_starttime = Sys_DoubleTime();
909 cl_capturevideo_framerate = bound(1, cl_capturevideo_fps.value, 1000);
910 cl_capturevideo_soundrate = 0;
911 cl_capturevideo_frame = 0;
912 cl_capturevideo_buffer = Mem_Alloc(tempmempool, vid.width * vid.height * (3+3+3) + 18);
913 gamma = 1.0/scr_screenshot_gamma.value;
916 for (i = 0;i < 256;i++)
918 unsigned char j = (unsigned char)bound(0, 255*pow(i/255.0, gamma), 255);
919 cl_capturevideo_rgbgammatable[0][i] = j;
920 cl_capturevideo_rgbgammatable[1][i] = j;
921 cl_capturevideo_rgbgammatable[2][i] = j;
925 R = Y + 1.4075 * (Cr - 128);
926 G = Y + -0.3455 * (Cb - 128) + -0.7169 * (Cr - 128);
927 B = Y + 1.7790 * (Cb - 128);
928 Y = R * .299 + G * .587 + B * .114;
929 Cb = R * -.169 + G * -.332 + B * .500 + 128.;
930 Cr = R * .500 + G * -.419 + B * -.0813 + 128.;
932 for (i = 0;i < 256;i++)
934 g = 255*pow(i/255.0, gamma);
935 // Y weights from RGB
936 cl_capturevideo_rgbtoyuvscaletable[0][0][i] = (short)(g * 0.299);
937 cl_capturevideo_rgbtoyuvscaletable[0][1][i] = (short)(g * 0.587);
938 cl_capturevideo_rgbtoyuvscaletable[0][2][i] = (short)(g * 0.114);
939 // Cb weights from RGB
940 cl_capturevideo_rgbtoyuvscaletable[1][0][i] = (short)(g * -0.169);
941 cl_capturevideo_rgbtoyuvscaletable[1][1][i] = (short)(g * -0.332);
942 cl_capturevideo_rgbtoyuvscaletable[1][2][i] = (short)(g * 0.500);
943 // Cr weights from RGB
944 cl_capturevideo_rgbtoyuvscaletable[2][0][i] = (short)(g * 0.500);
945 cl_capturevideo_rgbtoyuvscaletable[2][1][i] = (short)(g * -0.419);
946 cl_capturevideo_rgbtoyuvscaletable[2][2][i] = (short)(g * -0.0813);
947 // range reduction of YCbCr to valid signal range
948 cl_capturevideo_yuvnormalizetable[0][i] = 16 + i * (236-16) / 256;
949 cl_capturevideo_yuvnormalizetable[1][i] = 16 + i * (240-16) / 256;
950 cl_capturevideo_yuvnormalizetable[2][i] = 16 + i * (240-16) / 256;
953 if (cl_capturevideo_rawrgb.integer)
955 cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWRGB;
956 cl_capturevideo_videofile = FS_Open ("video/dpvideo.rgb", "wb", false, true);
958 else if (cl_capturevideo_rawyv12.integer)
960 cl_capturevideo_format = CAPTUREVIDEOFORMAT_RAWYV12;
961 cl_capturevideo_videofile = FS_Open ("video/dpvideo.yv12", "wb", false, true);
963 else if (scr_screenshot_jpeg.integer)
965 cl_capturevideo_format = CAPTUREVIDEOFORMAT_JPEG;
966 cl_capturevideo_videofile = NULL;
970 cl_capturevideo_format = CAPTUREVIDEOFORMAT_TARGA;
971 cl_capturevideo_videofile = NULL;
974 if (cl_capturevideo_sound.integer)
976 cl_capturevideo_soundfile = FS_Open ("video/dpvideo.wav", "wb", false, true);
977 // wave header will be filled out when video ends
979 FS_Write (cl_capturevideo_soundfile, out, 44);
982 cl_capturevideo_soundfile = NULL;
985 void SCR_CaptureVideo_EndVideo(void)
989 if (!cl_capturevideo_active)
991 cl_capturevideo_active = false;
993 if (cl_capturevideo_videofile)
995 FS_Close(cl_capturevideo_videofile);
996 cl_capturevideo_videofile = NULL;
999 // finish the wave file
1000 if (cl_capturevideo_soundfile)
1002 i = (int)FS_Tell (cl_capturevideo_soundfile);
1003 //"RIFF", (int) unknown (chunk size), "WAVE",
1004 //"fmt ", (int) 16 (chunk size), (short) format 1 (uncompressed PCM), (short) 2 channels, (int) unknown rate, (int) unknown bytes per second, (short) 4 bytes per sample (channels * bytes per channel), (short) 16 bits per channel
1005 //"data", (int) unknown (chunk size)
1006 memcpy (out, "RIFF****WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00********\x04\x00\x10\0data****", 44);
1007 // the length of the whole RIFF chunk
1009 out[4] = (n) & 0xFF;
1010 out[5] = (n >> 8) & 0xFF;
1011 out[6] = (n >> 16) & 0xFF;
1012 out[7] = (n >> 24) & 0xFF;
1014 n = cl_capturevideo_soundrate;
1015 out[24] = (n) & 0xFF;
1016 out[25] = (n >> 8) & 0xFF;
1017 out[26] = (n >> 16) & 0xFF;
1018 out[27] = (n >> 24) & 0xFF;
1019 // bytes per second (rate * channels * bytes per channel)
1020 n = cl_capturevideo_soundrate * 2 * 2;
1021 out[28] = (n) & 0xFF;
1022 out[29] = (n >> 8) & 0xFF;
1023 out[30] = (n >> 16) & 0xFF;
1024 out[31] = (n >> 24) & 0xFF;
1025 // the length of the data chunk
1027 out[40] = (n) & 0xFF;
1028 out[41] = (n >> 8) & 0xFF;
1029 out[42] = (n >> 16) & 0xFF;
1030 out[43] = (n >> 24) & 0xFF;
1031 FS_Seek (cl_capturevideo_soundfile, 0, SEEK_SET);
1032 FS_Write (cl_capturevideo_soundfile, out, 44);
1033 FS_Close (cl_capturevideo_soundfile);
1034 cl_capturevideo_soundfile = NULL;
1037 if (cl_capturevideo_buffer)
1039 Mem_Free (cl_capturevideo_buffer);
1040 cl_capturevideo_buffer = NULL;
1043 cl_capturevideo_starttime = 0;
1044 cl_capturevideo_framerate = 0;
1045 cl_capturevideo_frame = 0;
1048 qboolean SCR_CaptureVideo_VideoFrame(int newframenum)
1050 int x = 0, y = 0, width = vid.width, height = vid.height;
1051 unsigned char *b, *out;
1053 int outoffset = (width/2)*(height/2);
1054 //return SCR_ScreenShot(filename, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.width * vid.height * 3, cl_capturevideo_buffer + vid.width * vid.height * 6, 0, 0, vid.width, vid.height, false, false, false, jpeg, true);
1055 // speed is critical here, so do saving as directly as possible
1056 switch (cl_capturevideo_format)
1058 case CAPTUREVIDEOFORMAT_RAWYV12:
1059 // FIXME: width/height must be multiple of 2, enforce this?
1060 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1062 // process one line at a time, and CbCr every other line at 2 pixel intervals
1063 for (y = 0;y < height;y++)
1066 for (b = cl_capturevideo_buffer + (height-1-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + y*width, x = 0;x < width;x++, b += 3, out++)
1067 *out = cl_capturevideo_yuvnormalizetable[0][cl_capturevideo_rgbtoyuvscaletable[0][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[0][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[0][2][b[2]]];
1070 // 2x2 Cb and Cr planes
1072 // low quality, no averaging
1073 for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
1076 out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[2][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[2][2][b[2]] + 128];
1078 out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][b[0]] + cl_capturevideo_rgbtoyuvscaletable[1][1][b[1]] + cl_capturevideo_rgbtoyuvscaletable[1][2][b[2]] + 128];
1081 // high quality, averaging
1082 int inpitch = width*3;
1083 for (b = cl_capturevideo_buffer + (height-2-y)*width*3, out = cl_capturevideo_buffer + width*height*3 + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
1085 int blockr, blockg, blockb;
1086 blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
1087 blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
1088 blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
1090 out[0 ] = cl_capturevideo_yuvnormalizetable[2][cl_capturevideo_rgbtoyuvscaletable[2][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[2][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[2][2][blockb] + 128];
1092 out[outoffset] = cl_capturevideo_yuvnormalizetable[1][cl_capturevideo_rgbtoyuvscaletable[1][0][blockr] + cl_capturevideo_rgbtoyuvscaletable[1][1][blockg] + cl_capturevideo_rgbtoyuvscaletable[1][2][blockb] + 128];
1097 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1098 if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer + width*height*3, width*height+(width/2)*(height/2)*2))
1101 case CAPTUREVIDEOFORMAT_RAWRGB:
1102 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1104 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1105 if (!FS_Write (cl_capturevideo_videofile, cl_capturevideo_buffer, width*height*3))
1108 case CAPTUREVIDEOFORMAT_JPEG:
1109 qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, cl_capturevideo_buffer);
1111 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1113 sprintf(filename, "video/dp%06d.jpg", cl_capturevideo_frame);
1114 if (!JPEG_SaveImage_preflipped (filename, width, height, cl_capturevideo_buffer))
1118 case CAPTUREVIDEOFORMAT_TARGA:
1119 //return Image_WriteTGARGB_preflipped (filename, width, height, cl_capturevideo_buffer, cl_capturevideo_buffer + vid.width * vid.height * 3, );
1120 memset (cl_capturevideo_buffer, 0, 18);
1121 cl_capturevideo_buffer[2] = 2; // uncompressed type
1122 cl_capturevideo_buffer[12] = (width >> 0) & 0xFF;
1123 cl_capturevideo_buffer[13] = (width >> 8) & 0xFF;
1124 cl_capturevideo_buffer[14] = (height >> 0) & 0xFF;
1125 cl_capturevideo_buffer[15] = (height >> 8) & 0xFF;
1126 cl_capturevideo_buffer[16] = 24; // pixel size
1127 qglReadPixels (x, y, width, height, GL_BGR, GL_UNSIGNED_BYTE, cl_capturevideo_buffer + 18);
1129 for (;cl_capturevideo_frame < newframenum;cl_capturevideo_frame++)
1131 sprintf(filename, "video/dp%06d.tga", cl_capturevideo_frame);
1132 if (!FS_WriteFile (filename, cl_capturevideo_buffer, width*height*3 + 18))
1141 void SCR_CaptureVideo_SoundFrame(qbyte *bufstereo16le, size_t length, int rate)
1143 if (!cl_capturevideo_soundfile)
1145 cl_capturevideo_soundrate = rate;
1146 if (FS_Write (cl_capturevideo_soundfile, bufstereo16le, 4 * length) < (fs_offset_t)(4 * length))
1148 Cvar_SetValueQuick(&cl_capturevideo, 0);
1149 Con_Printf("video sound saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame);
1150 SCR_CaptureVideo_EndVideo();
1154 void SCR_CaptureVideo(void)
1157 if (cl_capturevideo.integer && r_render.integer)
1159 if (!cl_capturevideo_active)
1160 SCR_CaptureVideo_BeginVideo();
1161 if (cl_capturevideo_framerate != cl_capturevideo_fps.value)
1163 Con_Printf("You can not change the video framerate while recording a video.\n");
1164 Cvar_SetValueQuick(&cl_capturevideo_fps, cl_capturevideo_framerate);
1166 if (cl_capturevideo_soundfile)
1168 // preserve sound sync by duplicating frames when running slow
1169 newframenum = (Sys_DoubleTime() - cl_capturevideo_starttime) * cl_capturevideo_framerate;
1172 newframenum = cl_capturevideo_frame + 1;
1173 // if falling behind more than one second, stop
1174 if (newframenum - cl_capturevideo_frame > (int)ceil(cl_capturevideo_framerate))
1176 Cvar_SetValueQuick(&cl_capturevideo, 0);
1177 Con_Printf("video saving failed on frame %i, your machine is too slow for this capture speed.\n", cl_capturevideo_frame);
1178 SCR_CaptureVideo_EndVideo();
1182 if (!SCR_CaptureVideo_VideoFrame(newframenum))
1184 Cvar_SetValueQuick(&cl_capturevideo, 0);
1185 Con_Printf("video saving failed on frame %i, out of disk space? stopping video capture.\n", cl_capturevideo_frame);
1186 SCR_CaptureVideo_EndVideo();
1189 else if (cl_capturevideo_active)
1190 SCR_CaptureVideo_EndVideo();
1197 Grab six views for environment mapping tests
1204 qboolean flipx, flipy, flipdiagonaly;
1208 {{ 0, 0, 0}, "rt", false, false, false},
1209 {{ 0, 270, 0}, "ft", false, false, false},
1210 {{ 0, 180, 0}, "lf", false, false, false},
1211 {{ 0, 90, 0}, "bk", false, false, false},
1212 {{-90, 180, 0}, "up", true, true, false},
1213 {{ 90, 180, 0}, "dn", true, true, false},
1215 {{ 0, 0, 0}, "px", true, true, true},
1216 {{ 0, 90, 0}, "py", false, true, false},
1217 {{ 0, 180, 0}, "nx", false, false, true},
1218 {{ 0, 270, 0}, "ny", true, false, false},
1219 {{-90, 180, 0}, "pz", false, false, true},
1220 {{ 90, 180, 0}, "nz", false, false, true}
1223 static void R_Envmap_f (void)
1226 char filename[256], basename[256];
1231 if (Cmd_Argc() != 3)
1233 Con_Print("envmap <basename> <size>: save out 6 cubic environment map images, usable with loadsky, note that size must one of 128, 256, 512, or 1024 and can't be bigger than your current resolution\n");
1237 strlcpy (basename, Cmd_Argv(1), sizeof (basename));
1238 size = atoi(Cmd_Argv(2));
1239 if (size != 128 && size != 256 && size != 512 && size != 1024)
1241 Con_Print("envmap: size must be one of 128, 256, 512, or 1024\n");
1244 if (size > vid.width || size > vid.height)
1246 Con_Print("envmap: your resolution is not big enough to render that size\n");
1254 r_refdef.width = size;
1255 r_refdef.height = size;
1257 r_refdef.fov_x = 90;
1258 r_refdef.fov_y = 90;
1260 buffer1 = Mem_Alloc(tempmempool, size * size * 3);
1261 buffer2 = Mem_Alloc(tempmempool, size * size * 3);
1262 buffer3 = Mem_Alloc(tempmempool, size * size * 3 + 18);
1264 for (j = 0;j < 12;j++)
1266 sprintf(filename, "env/%s%s.tga", basename, envmapinfo[j].name);
1267 Matrix4x4_CreateFromQuakeEntity(&r_refdef.viewentitymatrix, r_vieworigin[0], r_vieworigin[1], r_vieworigin[2], envmapinfo[j].angles[0], envmapinfo[j].angles[1], envmapinfo[j].angles[2], 1);
1272 SCR_ScreenShot(filename, buffer1, buffer2, buffer3, 0, vid.height - (r_refdef.y + r_refdef.height), size, size, envmapinfo[j].flipx, envmapinfo[j].flipy, envmapinfo[j].flipdiagonaly, false, false);
1282 //=============================================================================
1284 // LordHavoc: SHOWLMP stuff
1285 #define SHOWLMP_MAXLABELS 256
1286 typedef struct showlmp_s
1296 showlmp_t showlmp[SHOWLMP_MAXLABELS];
1298 void SHOWLMP_decodehide(void)
1302 lmplabel = MSG_ReadString();
1303 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1304 if (showlmp[i].isactive && strcmp(showlmp[i].label, lmplabel) == 0)
1306 showlmp[i].isactive = false;
1311 void SHOWLMP_decodeshow(void)
1314 qbyte lmplabel[256], picname[256];
1316 strlcpy (lmplabel,MSG_ReadString(), sizeof (lmplabel));
1317 strlcpy (picname, MSG_ReadString(), sizeof (picname));
1318 if (gamemode == GAME_NEHAHRA) // LordHavoc: nasty old legacy junk
1325 x = MSG_ReadShort();
1326 y = MSG_ReadShort();
1329 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1330 if (showlmp[i].isactive)
1332 if (strcmp(showlmp[i].label, lmplabel) == 0)
1335 break; // drop out to replace it
1338 else if (k < 0) // find first empty one to replace
1341 return; // none found to replace
1342 // change existing one
1343 showlmp[k].isactive = true;
1344 strlcpy (showlmp[k].label, lmplabel, sizeof (showlmp[k].label));
1345 strlcpy (showlmp[k].pic, picname, sizeof (showlmp[k].pic));
1350 void SHOWLMP_drawall(void)
1353 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1354 if (showlmp[i].isactive)
1355 DrawQ_Pic(showlmp[i].x, showlmp[i].y, showlmp[i].pic, 0, 0, 1, 1, 1, 1, 0);
1358 void SHOWLMP_clear(void)
1361 for (i = 0;i < SHOWLMP_MAXLABELS;i++)
1362 showlmp[i].isactive = false;
1365 void CL_SetupScreenSize(void)
1367 float conwidth, conheight;
1369 VID_UpdateGamma(false);
1371 conwidth = bound(320, vid_conwidth.value, 2048);
1372 conheight = bound(200, vid_conheight.value, 1536);
1373 if (vid_conwidth.value != conwidth)
1374 Cvar_SetValue("vid_conwidth", conwidth);
1375 if (vid_conheight.value != conheight)
1376 Cvar_SetValue("vid_conheight", conheight);
1378 vid_conwidth.integer = vid_conwidth.integer;
1379 vid_conheight.integer = vid_conheight.integer;
1381 SCR_SetUpToDrawConsole();
1384 extern void R_Shadow_EditLights_DrawSelectedLightProperties(void);
1385 void CL_UpdateScreen(void)
1387 if (!scr_initialized || !con_initialized || vid_hidden)
1388 return; // not initialized yet
1390 // don't allow cheats in multiplayer
1391 if (!cl.islocalgame && cl.worldmodel)
1393 if (r_fullbright.integer != 0)
1394 Cvar_Set ("r_fullbright", "0");
1395 if (r_ambient.value != 0)
1396 Cvar_Set ("r_ambient", "0");
1400 if (scr_viewsize.value < 30)
1401 Cvar_Set ("viewsize","30");
1402 if (scr_viewsize.value > 120)
1403 Cvar_Set ("viewsize","120");
1405 // bound field of view
1406 if (scr_fov.value < 1)
1407 Cvar_Set ("fov","1");
1408 if (scr_fov.value > 170)
1409 Cvar_Set ("fov","170");
1411 // intermission is always full screen
1412 if (cl.intermission)
1416 if (scr_viewsize.value >= 120)
1417 sb_lines = 0; // no status bar at all
1418 else if (scr_viewsize.value >= 110)
1419 sb_lines = 24; // no inventory
1424 r_refdef.colormask[0] = 1;
1425 r_refdef.colormask[1] = 1;
1426 r_refdef.colormask[2] = 1;
1430 if (cls.signon == SIGNONS)
1431 R_TimeReport("other");
1433 CL_SetupScreenSize();
1437 if (cls.signon == SIGNONS)
1438 R_TimeReport("setup");
1440 //FIXME: force menu if nothing else to look at?
1441 //if (key_dest == key_game && cls.signon != SIGNONS && cls.state == ca_disconnected)
1443 if (cls.signon == SIGNONS)
1448 if (!r_letterbox.value)
1451 SCR_CheckDrawCenterString();
1457 if (cls.signon == SIGNONS)
1461 R_TimeReport_Start();
1463 R_Shadow_EditLights_DrawSelectedLightProperties();
1472 void CL_Screen_NewMap(void)