1 /*
2 screen.c
3
4 master for refresh, status bar, console, chat, notify, etc
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #define NH_DEFINE
32 #include "namehack.h"
33
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40
41 #include <time.h>
42
43 #include "QF/cvar.h"
44 #include "QF/draw.h"
45 #include "QF/dstring.h"
46 #include "QF/image.h"
47 #include "QF/pcx.h"
48 #include "QF/quakefs.h"
49 #include "QF/render.h"
50 #include "QF/screen.h"
51 #include "QF/sys.h"
52 #include "QF/va.h"
53
54 #include "compat.h"
55 #include "r_internal.h"
56 #include "vid_internal.h"
57
58 /* SCREEN SHOTS */
59
60 tex_t *
sw32_SCR_CaptureBGR(void)61 sw32_SCR_CaptureBGR (void)
62 {
63 int count, x, y;
64 tex_t *tex;
65 const byte *src;
66 byte *dst;
67
68 count = vid.width * vid.height;
69 tex = malloc (field_offset (tex_t, data[count * 3]));
70 SYS_CHECKMEM (tex);
71 tex->width = vid.width;
72 tex->height = vid.height;
73 tex->format = tex_rgb;
74 tex->palette = 0;
75 sw32_D_EnableBackBufferAccess ();
76 src = vid.buffer;
77 for (y = 0; y < tex->height; y++) {
78 dst = tex->data + (tex->height - 1 - y) * tex->width * 3;
79 for (x = 0; x < tex->width; x++) {
80 *dst++ = vid.basepal[*src * 3 + 2]; // blue
81 *dst++ = vid.basepal[*src * 3 + 1]; // green
82 *dst++ = vid.basepal[*src * 3 + 0]; // red
83 src++;
84 }
85 }
86 sw32_D_DisableBackBufferAccess ();
87 return tex;
88 }
89
90 tex_t *
sw32_SCR_ScreenShot(int width,int height)91 sw32_SCR_ScreenShot (int width, int height)
92 {
93 return 0;
94 }
95
96 void
sw32_SCR_ScreenShot_f(void)97 sw32_SCR_ScreenShot_f (void)
98 {
99 dstring_t *pcxname = dstring_new ();
100 pcx_t *pcx = 0;
101 int pcx_len;
102
103 // find a file name to save it to
104 if (!QFS_NextFilename (pcxname,
105 va ("%s/qf", qfs_gamedir->dir.shots), ".pcx")) {
106 Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PCX");
107 } else {
108 // enable direct drawing of console to back buffer
109 sw32_D_EnableBackBufferAccess ();
110
111 // save the pcx file
112 switch(sw32_r_pixbytes) {
113 case 1:
114 pcx = EncodePCX (vid.buffer, vid.width, vid.height, vid.rowbytes,
115 vid.basepal, false, &pcx_len);
116 break;
117 case 2:
118 Sys_Printf("SCR_ScreenShot_f: FIXME - add 16bit support\n");
119 break;
120 case 4:
121 Sys_Printf("SCR_ScreenShot_f: FIXME - add 32bit support\n");
122 break;
123 default:
124 Sys_Error("SCR_ScreenShot_f: unsupported r_pixbytes %i", sw32_r_pixbytes);
125 }
126
127 // for adapters that can't stay mapped in for linear writes all the time
128 sw32_D_DisableBackBufferAccess ();
129
130 if (pcx) {
131 QFS_WriteFile (pcxname->str, pcx, pcx_len);
132 Sys_Printf ("Wrote %s/%s\n", qfs_userpath, pcxname->str);
133 }
134 }
135 dstring_delete (pcxname);
136 }
137
138 /*
139 SCR_UpdateScreen
140
141 This is called every frame, and can also be called explicitly to flush
142 text to the screen.
143
144 WARNING: be very careful calling this from elsewhere, because the refresh
145 needs almost the entire 256k of stack space!
146 */
147 void
sw32_SCR_UpdateScreen(double realtime,SCR_Func scr_3dfunc,SCR_Func * scr_funcs)148 sw32_SCR_UpdateScreen (double realtime, SCR_Func scr_3dfunc, SCR_Func *scr_funcs)
149 {
150 vrect_t vrect;
151
152 if (scr_skipupdate)
153 return;
154
155 vr_data.realtime = realtime;
156
157 scr_copytop = 0;
158 vr_data.scr_copyeverything = 0;
159
160 if (!scr_initialized)
161 return; // not initialized yet
162
163 if (oldfov != scr_fov->value) { // determine size of refresh window
164 oldfov = scr_fov->value;
165 vid.recalc_refdef = true;
166 }
167
168 if (vid.recalc_refdef)
169 SCR_CalcRefdef ();
170
171 // do 3D refresh drawing, and then update the screen
172 sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing
173 // directly
174
175 if (vr_data.scr_fullupdate++ < vid.numpages) { // clear the entire screen
176 vr_data.scr_copyeverything = 1;
177 sw32_Draw_TileClear (0, 0, vid.width, vid.height);
178 }
179
180 pconupdate = NULL;
181
182 SCR_SetUpToDrawConsole ();
183
184 sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped
185 // in for linear writes all the time
186 VID_LockBuffer ();
187 scr_3dfunc ();
188 VID_UnlockBuffer ();
189
190 sw32_D_EnableBackBufferAccess (); // of all overlay stuff if drawing
191 // directly
192
193 while (*scr_funcs) {
194 (*scr_funcs)();
195 scr_funcs++;
196 }
197
198 sw32_D_DisableBackBufferAccess (); // for adapters that can't stay mapped
199 // in for linear writes all the time
200 if (pconupdate) {
201 sw32_D_UpdateRects (pconupdate);
202 }
203
204 // update one of three areas
205 if (vr_data.scr_copyeverything) {
206 vrect.x = 0;
207 vrect.y = 0;
208 vrect.width = vid.width;
209 vrect.height = vid.height;
210 vrect.next = 0;
211 } else if (scr_copytop) {
212 vrect.x = 0;
213 vrect.y = 0;
214 vrect.width = vid.width;
215 vrect.height = vid.height - vr_data.lineadj;
216 vrect.next = 0;
217 } else {
218 vrect.x = scr_vrect.x;
219 vrect.y = scr_vrect.y;
220 vrect.width = scr_vrect.width;
221 vrect.height = scr_vrect.height;
222 vrect.next = 0;
223 }
224 VID_Update (&vrect);
225 }
226