1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
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 // r_misc.c
21 
22 #include "gl_local.h"
23 #include <jpeglib.h> //Heffo - JPEG Screenshots
24 
25 /*
26 ==================
27 R_InitParticleTexture
28 ==================
29 */
30 
SetParticlePicture(int num,char * name)31 void SetParticlePicture (int num, char *name)
32 {
33 	r_particletextures[num] = GL_FindImage(name, it_part);
34 	if (!r_particletextures[num])
35 		r_particletextures[num] = r_notexture;
36 }
37 
38 byte	notexture[8][8] =
39 {
40 	{	075,	075,	075,	075,	255,	255,	255,	255	},
41 	{	075,	075,	075,	075,	255,	255,	255,	255	},
42 	{	075,	075,	075,	075,	255,	255,	255,	255	},
43 	{	075,	075,	075,	075,	255,	255,	255,	255	},
44 	{	255,	255,	255,	255,	175,	175,	175,	175	},
45 	{	255,	255,	255,	255,	175,	175,	175,	175	},
46 	{	255,	255,	255,	255,	175,	175,	175,	175	},
47 	{	255,	255,	255,	255,	175,	175,	175,	175	},
48 };
49 
50 #define CEL_SIZE 32
51 
52 const byte celcolors [CEL_SIZE][2] =
53 {
54 	//3 (3)
55 	0,		255,
56 	0,		255,
57 	0,		255,
58 
59 	//5 (8)
60 	0,		170,
61 	0,		170,
62 	0,		170,
63 	0,		170,
64 	0,		170,
65 
66 	//8 (16)
67 	0,		85,
68 	0,		85,
69 	0,		85,
70 	0,		85,
71 	0,		85,
72 	0,		85,
73 	0,		85,
74 	0,		85,
75 
76 	//16 (32)
77 	0,		0,
78 	0,		0,
79 	0,		0,
80 	0,		0,
81 	0,		0,
82 	0,		0,
83 	0,		0,
84 	0,		0,
85 	255,	0,
86 	255,	0,
87 	255,	0,
88 	255,	0,
89 	255,	0,
90 	255,	0,
91 	255,	0,
92 	255,	0,
93 };
94 
R_InitParticleTexture(void)95 void R_InitParticleTexture (void)
96 {
97 	int		x,y;
98 	byte	no_data[8][8][4];
99 	byte	cel_data[CEL_SIZE][CEL_SIZE][4];
100 	byte	env_data[256*256*4];
101 
102 	//
103 	// also use this for bad textures, but without alpha
104 	//
105 	for (x=0 ; x<8 ; x++)
106 		for (y=0 ; y<8 ; y++)
107 		{
108 			no_data[y][x][0] = notexture[y][x];
109 			no_data[y][x][1] = notexture[y][x];
110 			no_data[y][x][2] = notexture[y][x];
111 			no_data[y][x][3] = 255;
112 		}
113 
114 	r_notexture = GL_FindImage("textures/notexture.png", it_part);
115 	if (!r_notexture)
116 		r_notexture = GL_LoadPic ("***r_notexture***", (byte *)no_data, 8, 8, it_wall, 32);
117 
118 	r_particlebeam = GL_FindImage("particles/beam.png", it_part);
119 	if (!r_particlebeam)
120 		r_particlebeam = r_notexture;
121 
122 	for (x=0 ; x<PARTICLE_TYPES ; x++)
123 		r_particletextures[x] = NULL;
124 
125 	memset((void *)env_data, 0, 256*256*4);
126 	r_dynamicimage = GL_LoadPic ("***r_dynamicimage***", (byte *)env_data, 256, 256, it_wall, 32);
127 	r_lblendimage = GL_LoadPic ("***r_lblendimage***", (byte *)env_data, 256, 256, it_wall, 32);
128 	r_motionblurimage = GL_LoadPic ("***r_motionblurimage***", (byte *)env_data, 256, 256, it_wall, 32);
129 	r_motionblurscreenimage = GL_LoadPic ("***r_motionblurscreenimage***", (byte *)env_data, 256, 256, it_wall, 32);
130 
131 	for (x=0 ; x<CEL_SIZE ; x++)
132 		for (y=0 ; y<CEL_SIZE ; y++)
133 		{
134 			cel_data[y][x][0] = (byte)celcolors[x][0];
135 			cel_data[y][x][1] = (byte)celcolors[x][0];
136 			cel_data[y][x][2] = (byte)celcolors[x][0];
137 			cel_data[y][x][3] = (byte)celcolors[x][1];
138 		}
139 
140 	//set texture mode too
141 	r_celtexture = GL_LoadPic ("***r_celtexture***", (byte *)cel_data, CEL_SIZE, CEL_SIZE, it_pic, 32);
142 	GL_Bind (r_celtexture->texnum);
143 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
144 		qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
145 
146 	ri.SetParticlePics();
147 }
148 
149 
150 /*
151 ==============================================================================
152 
153 						SCREEN SHOTS
154 
155 ==============================================================================
156 */
157 
158 typedef struct _TargaHeader {
159 	unsigned char 	id_length, colormap_type, image_type;
160 	unsigned short	colormap_index, colormap_length;
161 	unsigned char	colormap_size;
162 	unsigned short	x_origin, y_origin, width, height;
163 	unsigned char	pixel_size, attributes;
164 } TargaHeader;
165 
166 void GL_ScreenShot_PNG (void);
167 
168 /*
169 ==================
170 GL_ScreenShot_JPG
171 By Robert 'Heffo' Heffernan
172 ==================
173 */
GL_ScreenShot_JPG(void)174 void GL_ScreenShot_JPG (void)
175 {
176 	struct jpeg_compress_struct		cinfo;
177 	struct jpeg_error_mgr			jerr;
178 	byte							*rgbdata;
179 	JSAMPROW						s[1];
180 	FILE							*file;
181 	char							picname[80], checkname[MAX_OSPATH];
182 	int								i, offset;
183 
184 	// Create the scrnshots directory if it doesn't exist
185 	Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
186 	Sys_Mkdir (checkname);
187 
188 	for (i=0 ; i<=999 ; i++)
189 	{
190 		Com_sprintf (picname, sizeof(picname), "quake2max%i%i%i.jpg", (int)(i/100)%10, (int)(i/10)%10, i%10);
191 		Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), picname);
192 		file = fopen (checkname, "rb");
193 		if (!file)
194 			break;	// file doesn't exist
195 		fclose (file);
196 	}
197 	if (i==1000)
198 	{
199 		ri.Con_Printf (PRINT_ALL, "SCR_JPGScreenShot_f: Couldn't create a file\n");
200 		return;
201  	}
202 
203 	// Open the file for Binary Output
204 	file = fopen(checkname, "wb");
205 	if(!file)
206 	{
207 		ri.Con_Printf (PRINT_ALL, "SCR_JPGScreenShot_f: Couldn't create a file\n");
208 		return;
209  	}
210 
211 	// Allocate room for a copy of the framebuffer
212 	rgbdata = malloc(vid.width * vid.height * 3);
213 	if(!rgbdata)
214 	{
215 		fclose(file);
216 		return;
217 	}
218 
219 	// Read the framebuffer into our storage
220 	qglReadPixels(0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, rgbdata);
221 
222 	// Initialise the JPEG compression object
223 	cinfo.err = jpeg_std_error(&jerr);
224 	jpeg_create_compress(&cinfo);
225 	jpeg_stdio_dest(&cinfo, file);
226 
227 	// Setup JPEG Parameters
228 	cinfo.image_width = vid.width;
229 	cinfo.image_height = vid.height;
230 	cinfo.in_color_space = JCS_RGB;
231 	cinfo.input_components = 3;
232 	jpeg_set_defaults(&cinfo);
233 
234 	if((gl_screenshot_quality->value > 100) || (gl_screenshot_quality->value <= 0))
235 		ri.Cvar_Set("gl_screenshot_quality", "85");
236 
237 	jpeg_set_quality(&cinfo, gl_screenshot_quality->value, TRUE);
238 
239 	// Start Compression
240 	jpeg_start_compress(&cinfo, true);
241 
242 	// Feed Scanline data
243 	offset = (cinfo.image_width * cinfo.image_height * 3) - (cinfo.image_width * 3);
244 	while(cinfo.next_scanline < cinfo.image_height)
245 	{
246 		s[0] = &rgbdata[offset - (cinfo.next_scanline * (cinfo.image_width * 3))];
247 		jpeg_write_scanlines(&cinfo, s, 1);
248 	}
249 
250 	// Finish Compression
251 	jpeg_finish_compress(&cinfo);
252 
253 	// Destroy JPEG object
254 	jpeg_destroy_compress(&cinfo);
255 
256 	// Close File
257 	fclose(file);
258 
259 	// Free Temp Framebuffer
260 	free(rgbdata);
261 
262 	// Done!
263 	ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname);
264 }
265 
266 /*
267 ==================
268 GL_ScreenShot_f
269 ==================
270 */
GL_ScreenShot_f(void)271 void GL_ScreenShot_f (void)
272 {
273 	byte		*buffer;
274 	char		picname[80];
275 	char		checkname[MAX_OSPATH];
276 	int			i, c, temp;
277 	FILE		*f;
278 
279 	if (ri.Cmd_Argc()>1)
280 	{
281 		if (!strcmp ("tga", ri.Cmd_Argv(1)))
282 		{
283 			//now we continue
284 		}
285 		else if (!strcmp ("png", ri.Cmd_Argv(1)))
286 		{
287 			GL_ScreenShot_PNG();
288 			return;
289 		}
290 		else if (!strcmp ("jpg", ri.Cmd_Argv(1)))
291 		{
292 			GL_ScreenShot_JPG();
293 			return;
294 		}
295 		else //bad params
296 		{
297 			return;
298 		}
299 	}
300 	else //default is jpg
301 	{
302 		GL_ScreenShot_JPG();
303 		return;
304 	}
305 
306 	//
307 	// find a file name to save it to
308 	//
309 
310 	// create the scrnshots directory if it doesn't exist
311 	Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot", ri.FS_Gamedir());
312 	Sys_Mkdir (checkname);
313 
314 	for (i=0 ; i<=999 ; i++)
315 	{
316 		Com_sprintf (picname, sizeof(picname), "quake2max%i%i%i.tga", (int)(i/100)%10, (int)(i/10)%10, i%10);
317 		Com_sprintf (checkname, sizeof(checkname), "%s/scrnshot/%s", ri.FS_Gamedir(), picname);
318 		f = fopen (checkname, "rb");
319 		if (!f)
320 			break;	// file doesn't exist
321 		fclose (f);
322 	}
323 	if (i==1000)
324 	{
325 		ri.Con_Printf (PRINT_ALL, "SCR_ScreenShot_f: Couldn't create a file\n");
326 		return;
327  	}
328 
329 	buffer = malloc(vid.width*vid.height*3 + 18);
330 	memset (buffer, 0, 18);
331 	buffer[2] = 2;		// uncompressed type
332 	buffer[12] = vid.width&255;
333 	buffer[13] = vid.width>>8;
334 	buffer[14] = vid.height&255;
335 	buffer[15] = vid.height>>8;
336 	buffer[16] = 24;	// pixel size
337 
338 	qglReadPixels (0, 0, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );
339 
340 	// swap rgb to bgr
341 	c = 18+vid.width*vid.height*3;
342 	for (i=18 ; i<c ; i+=3)
343 	{
344 		temp = buffer[i];
345 		buffer[i] = buffer[i+2];
346 		buffer[i+2] = temp;
347 	}
348 
349 	f = fopen (checkname, "wb");
350 	fwrite (buffer, 1, c, f);
351 	fclose (f);
352 
353 	free (buffer);
354 	ri.Con_Printf (PRINT_ALL, "Wrote %s\n", picname);
355 }
356 
357 /*
358 ** GL_Strings_f
359 */
GL_Strings_f(void)360 void GL_Strings_f( void )
361 {
362 	ri.Con_Printf (PRINT_ALL, "GL_VENDOR: %s\n", gl_config.vendor_string );
363 	ri.Con_Printf (PRINT_ALL, "GL_RENDERER: %s\n", gl_config.renderer_string );
364 	ri.Con_Printf (PRINT_ALL, "GL_VERSION: %s\n", gl_config.version_string );
365 	ri.Con_Printf (PRINT_ALL, "GL_EXTENSIONS: %s\n", gl_config.extensions_string );
366 }
367 
368 /*
369 ** GL_SetDefaultState
370 */
GL_SetDefaultState(void)371 void GL_SetDefaultState( void )
372 {
373 	qglClearColor (1,0, 0.5 , 0.5);
374 	qglCullFace(GL_FRONT);
375 	qglEnable(GL_TEXTURE_2D);
376 
377 	qglEnable( GL_ALPHA_TEST);
378 	qglAlphaFunc(GL_GREATER, 0.666);
379 	gl_state.alpha_test=true;
380 
381 	qglDisable (GL_DEPTH_TEST);
382 	qglDisable (GL_CULL_FACE);
383 	qglDisable (GL_BLEND);
384 	gl_state.blend=false;
385 
386 	qglColor4f (1,1,1,1);
387 
388 	qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
389 	GL_ShadeModel (GL_FLAT);
390 
391 	GL_TextureMode( gl_texturemode->string );
392 	GL_TextureAlphaMode( gl_texturealphamode->string );
393 	GL_TextureSolidMode( gl_texturesolidmode->string );
394 
395 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
396 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
397 
398 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
399 	qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
400 
401 	GL_BlendFunction (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
402 
403 	GL_TexEnv( GL_REPLACE );
404 
405 	GL_UpdateSwapInterval();
406 }
407 
GL_UpdateSwapInterval(void)408 void GL_UpdateSwapInterval( void )
409 {
410 	if ( gl_swapinterval->modified )
411 	{
412 		gl_swapinterval->modified = false;
413 
414 		if ( !gl_state.stereo_enabled )
415 		{
416 #ifdef _WIN32
417 			if ( qwglSwapIntervalEXT )
418 				qwglSwapIntervalEXT( gl_swapinterval->value );
419 #endif
420 		}
421 	}
422 }
423