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