diff options
-rw-r--r-- | src/gl_main.c | 214 | ||||
-rw-r--r-- | src/gl_state.c | 15 | ||||
-rw-r--r-- | src/r_images.c | 216 | ||||
-rw-r--r-- | src/r_shared.h | 20 |
4 files changed, 232 insertions, 233 deletions
diff --git a/src/gl_main.c b/src/gl_main.c index dd8cde8..fc5247d 100644 --- a/src/gl_main.c +++ b/src/gl_main.c @@ -33,15 +33,6 @@ statCounters_t c; int registration_sequence; cvar_t *gl_partscale; -#if USE_JPG || USE_PNG -cvar_t *gl_screenshot_format; -#endif -#if USE_JPG -cvar_t *gl_screenshot_quality; -#endif -#if USE_PNG -cvar_t *gl_screenshot_compression; -#endif #if USE_CELSHADING cvar_t *gl_celshading; #endif @@ -633,176 +624,7 @@ void R_EndFrame( void ) { // qglFinish(); } -/* -============================================================================== - - SCREEN SHOTS - -============================================================================== -*/ - -#if USE_TGA || USE_JPG || USE_PNG -static void make_screenshot( const char *name, const char *ext, - img_save_t func, GLenum format, int param ) -{ - char buffer[MAX_OSPATH]; - byte *pixels; - qerror_t ret; - qhandle_t f; - int i; - - if( name && *name ) { - // save to user supplied name - f = FS_EasyOpenFile( buffer, sizeof( buffer ), FS_MODE_WRITE, - SCREENSHOTS_DIRECTORY "/", name, ext ); - if( !f ) { - return; - } - } else { - // find a file name to save it to - for( i = 0; i < 1000; i++ ) { - Q_snprintf( buffer, sizeof( buffer ), SCREENSHOTS_DIRECTORY "/quake%03d%s", i, ext ); - ret = FS_FOpenFile( buffer, &f, FS_MODE_WRITE|FS_FLAG_EXCL ); - if( f ) { - break; - } - if( ret != Q_ERR_EXIST ) { - Com_EPrintf( "Couldn't exclusively open %s for writing: %s\n", - buffer, Q_ErrorString( ret ) ); - return; - } - } - - if( i == 1000 ) { - Com_EPrintf( "All screenshot slots are full.\n" ); - return; - } - } - - pixels = FS_AllocTempMem( gl_config.vidWidth * gl_config.vidHeight * 3 ); - - qglReadPixels( 0, 0, gl_config.vidWidth, gl_config.vidHeight, format, - GL_UNSIGNED_BYTE, pixels ); - - ret = func( f, buffer, pixels, gl_config.vidWidth, gl_config.vidHeight, param ); - - FS_FreeFile( pixels ); - - FS_FCloseFile( f ); - - if( ret < 0 ) { - Com_EPrintf( "Couldn't write %s: %s\n", buffer, Q_ErrorString( ret ) ); - } else { - Com_Printf( "Wrote %s\n", buffer ); - } -} -#endif - -/* -================== -GL_ScreenShot_f - -Standard function to take a screenshot. Saves in default format unless user -overrides format with a second argument. Screenshot name can't be -specified. This function is always compiled in to give a meaningful warning -if no formats are available. -================== -*/ -static void GL_ScreenShot_f( void ) { -#if USE_JPG || USE_PNG - const char *s; - - if( Cmd_Argc() > 2 ) { - Com_Printf( "Usage: %s [format]\n", Cmd_Argv( 0 ) ); - return; - } - - if( Cmd_Argc() > 1 ) { - s = Cmd_Argv( 1 ); - } else { - s = gl_screenshot_format->string; - } - -#if USE_JPG - if( *s == 'j' ) { - make_screenshot( NULL, ".jpg", IMG_SaveJPG, GL_RGB, - gl_screenshot_quality->integer ); - return; - } -#endif - -#if USE_PNG - if( *s == 'p' ) { - make_screenshot( NULL, ".png", IMG_SavePNG, GL_RGB, - gl_screenshot_compression->integer ); - return; - } -#endif -#endif - -#if USE_TGA - make_screenshot( NULL, ".tga", IMG_SaveTGA, GL_BGR, 0 ); -#else - Com_Printf( "Can't take screenshot, TGA format not available.\n" ); -#endif -} - -/* -================== -GL_ScreenShotXXX_f - -Specialized function to take a screenshot in specified format. Screenshot name -can be also specified, as well as quality and compression options. -================== -*/ -#if USE_TGA -static void GL_ScreenShotTGA_f( void ) { - if( Cmd_Argc() > 2 ) { - Com_Printf( "Usage: %s [name]\n", Cmd_Argv( 0 ) ); - return; - } - - make_screenshot( Cmd_Argv( 1 ), ".tga", IMG_SaveTGA, GL_BGR, 0 ); -} -#endif - -#if USE_JPG -static void GL_ScreenShotJPG_f( void ) { - int quality; - - if( Cmd_Argc() > 3 ) { - Com_Printf( "Usage: %s [name] [quality]\n", Cmd_Argv( 0 ) ); - return; - } - - if( Cmd_Argc() > 2 ) { - quality = atoi( Cmd_Argv( 2 ) ); - } else { - quality = gl_screenshot_quality->integer; - } - - make_screenshot( Cmd_Argv( 1 ), ".jpg", IMG_SaveJPG, GL_RGB, quality ); -} -#endif - -#if USE_PNG -static void GL_ScreenShotPNG_f( void ) { - int compression; - - if( Cmd_Argc() > 3 ) { - Com_Printf( "Usage: %s [name] [compression]\n", Cmd_Argv( 0 ) ); - return; - } - - if( Cmd_Argc() > 2 ) { - compression = atoi( Cmd_Argv( 2 ) ); - } else { - compression = gl_screenshot_compression->integer; - } - - make_screenshot( Cmd_Argv( 1 ), ".png", IMG_SavePNG, GL_RGB, compression ); -} -#endif +// ============================================================================== static void GL_Strings_f( void ) { Com_Printf( "GL_VENDOR: %s\n", gl_config.vendorString ); @@ -818,41 +640,12 @@ static size_t GL_ViewCluster_m( char *buffer, size_t size ) { return Q_scnprintf( buffer, size, "%d", glr.viewcluster1 ); } -// ============================================================================== - -static const cmdreg_t gl_cmd[] = { - { "screenshot", GL_ScreenShot_f }, -#if USE_TGA - { "screenshottga", GL_ScreenShotTGA_f }, -#endif -#if USE_JPG - { "screenshotjpg", GL_ScreenShotJPG_f }, -#endif -#if USE_PNG - { "screenshotpng", GL_ScreenShotPNG_f }, -#endif - { "strings", GL_Strings_f }, - - { NULL } -}; - static void gl_novis_changed( cvar_t *self ) { glr.viewcluster1 = glr.viewcluster2 = -2; } static void GL_Register( void ) { gl_partscale = Cvar_Get( "gl_partscale", "2", 0 ); -#if USE_JPG - gl_screenshot_format = Cvar_Get( "gl_screenshot_format", "jpg", 0 ); -#elif USE_PNG - gl_screenshot_format = Cvar_Get( "gl_screenshot_format", "png", 0 ); -#endif -#if USE_JPG - gl_screenshot_quality = Cvar_Get( "gl_screenshot_quality", "100", 0 ); -#endif -#if USE_PNG - gl_screenshot_compression = Cvar_Get( "gl_screenshot_compression", "6", 0 ); -#endif #if USE_CELSHADING gl_celshading = Cvar_Get( "gl_celshading", "0", 0 ); #endif @@ -892,14 +685,13 @@ static void GL_Register( void ) { gl_showerrors = Cvar_Get( "gl_showerrors", "1", 0 ); gl_fragment_program = Cvar_Get( "gl_fragment_program", "1", 0 ); gl_vertex_buffer_object = Cvar_Get( "gl_vertex_buffer_object", "1", CVAR_FILES ); - - Cmd_Register( gl_cmd ); + Cmd_AddCommand( "strings", GL_Strings_f ); Cmd_AddMacro( "gl_viewcluster", GL_ViewCluster_m ); } static void GL_Unregister( void ) { - Cmd_Deregister( gl_cmd ); + Cmd_RemoveCommand( "strings" ); } static qboolean GL_SetupExtensions( void ) { diff --git a/src/gl_state.c b/src/gl_state.c index 108d30c..c2be393 100644 --- a/src/gl_state.c +++ b/src/gl_state.c @@ -236,6 +236,21 @@ void GL_SetDefaultState( void ) { GL_Bits( GLS_DEFAULT ); } +// for screenshots +byte *IMG_ReadPixels( qboolean reverse, int *width, int *height ) { + byte *pixels; + + pixels = FS_AllocTempMem( gl_config.vidWidth * gl_config.vidHeight * 3 ); + + qglReadPixels( 0, 0, gl_config.vidWidth, gl_config.vidHeight, + reverse ? GL_BGR : GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + *width = gl_config.vidWidth; + *height = gl_config.vidHeight; + + return pixels; +} + void GL_EnableOutlines( void ) { if( gls.fp_enabled ) { qglDisable( GL_FRAGMENT_PROGRAM_ARB ); diff --git a/src/r_images.c b/src/r_images.c index 09121a7..23660ea 100644 --- a/src/r_images.c +++ b/src/r_images.c @@ -48,7 +48,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. const char *filename, byte **pic, int *width, int *height ) #define IMG_SAVE( x ) \ - qerror_t IMG_Save##x( qhandle_t f, const char *filename, \ + static qerror_t IMG_Save##x( qhandle_t f, const char *filename, \ const byte *pic, int width, int height, int param ) /* @@ -1109,6 +1109,188 @@ fail1: /* ========================================================= +SCREEN SHOTS + +========================================================= +*/ + +#if USE_TGA || USE_JPG || USE_PNG + +#if USE_JPG || USE_PNG +static cvar_t *r_screenshot_format; +#endif +#if USE_JPG +static cvar_t *r_screenshot_quality; +#endif +#if USE_PNG +static cvar_t *r_screenshot_compression; +#endif + +static void make_screenshot( const char *name, const char *ext, + qerror_t (*save)( qhandle_t, const char *, const byte *, int, int, int ), + qboolean reverse, int param ) +{ + char buffer[MAX_OSPATH]; + byte *pixels; + qerror_t ret; + qhandle_t f; + int i; + int w, h; + + if( name && *name ) { + // save to user supplied name + f = FS_EasyOpenFile( buffer, sizeof( buffer ), FS_MODE_WRITE, + SCREENSHOTS_DIRECTORY "/", name, ext ); + if( !f ) { + return; + } + } else { + // find a file name to save it to + for( i = 0; i < 1000; i++ ) { + Q_snprintf( buffer, sizeof( buffer ), SCREENSHOTS_DIRECTORY "/quake%03d%s", i, ext ); + ret = FS_FOpenFile( buffer, &f, FS_MODE_WRITE|FS_FLAG_EXCL ); + if( f ) { + break; + } + if( ret != Q_ERR_EXIST ) { + Com_EPrintf( "Couldn't exclusively open %s for writing: %s\n", + buffer, Q_ErrorString( ret ) ); + return; + } + } + + if( i == 1000 ) { + Com_EPrintf( "All screenshot slots are full.\n" ); + return; + } + } + + pixels = IMG_ReadPixels( reverse, &w, &h ); + + ret = save( f, buffer, pixels, w, h, param ); + + FS_FreeFile( pixels ); + + FS_FCloseFile( f ); + + if( ret < 0 ) { + Com_EPrintf( "Couldn't write %s: %s\n", buffer, Q_ErrorString( ret ) ); + } else { + Com_Printf( "Wrote %s\n", buffer ); + } +} + +#endif // USE_TGA || USE_JPG || USE_PNG + +/* +================== +IMG_ScreenShot_f + +Standard function to take a screenshot. Saves in default format unless user +overrides format with a second argument. Screenshot name can't be +specified. This function is always compiled in to give a meaningful warning +if no formats are available. +================== +*/ +static void IMG_ScreenShot_f( void ) { +#if USE_JPG || USE_PNG + const char *s; + + if( Cmd_Argc() > 2 ) { + Com_Printf( "Usage: %s [format]\n", Cmd_Argv( 0 ) ); + return; + } + + if( Cmd_Argc() > 1 ) { + s = Cmd_Argv( 1 ); + } else { + s = r_screenshot_format->string; + } + +#if USE_JPG + if( *s == 'j' ) { + make_screenshot( NULL, ".jpg", IMG_SaveJPG, qfalse, + r_screenshot_quality->integer ); + return; + } +#endif + +#if USE_PNG + if( *s == 'p' ) { + make_screenshot( NULL, ".png", IMG_SavePNG, qfalse, + r_screenshot_compression->integer ); + return; + } +#endif +#endif + +#if USE_TGA + make_screenshot( NULL, ".tga", IMG_SaveTGA, qtrue, 0 ); +#else + Com_Printf( "Can't take screenshot, TGA format not available.\n" ); +#endif +} + +/* +================== +IMG_ScreenShotXXX_f + +Specialized function to take a screenshot in specified format. Screenshot name +can be also specified, as well as quality and compression options. +================== +*/ +#if USE_TGA +static void IMG_ScreenShotTGA_f( void ) { + if( Cmd_Argc() > 2 ) { + Com_Printf( "Usage: %s [name]\n", Cmd_Argv( 0 ) ); + return; + } + + make_screenshot( Cmd_Argv( 1 ), ".tga", IMG_SaveTGA, qtrue, 0 ); +} +#endif + +#if USE_JPG +static void IMG_ScreenShotJPG_f( void ) { + int quality; + + if( Cmd_Argc() > 3 ) { + Com_Printf( "Usage: %s [name] [quality]\n", Cmd_Argv( 0 ) ); + return; + } + + if( Cmd_Argc() > 2 ) { + quality = atoi( Cmd_Argv( 2 ) ); + } else { + quality = r_screenshot_quality->integer; + } + + make_screenshot( Cmd_Argv( 1 ), ".jpg", IMG_SaveJPG, qfalse, quality ); +} +#endif + +#if USE_PNG +static void IMG_ScreenShotPNG_f( void ) { + int compression; + + if( Cmd_Argc() > 3 ) { + Com_Printf( "Usage: %s [name] [compression]\n", Cmd_Argv( 0 ) ); + return; + } + + if( Cmd_Argc() > 2 ) { + compression = atoi( Cmd_Argv( 2 ) ); + } else { + compression = r_screenshot_compression->integer; + } + + make_screenshot( Cmd_Argv( 1 ), ".png", IMG_SavePNG, qfalse, compression ); +} +#endif + +/* +========================================================= + IMAGE MANAGER ========================================================= @@ -1736,6 +1918,22 @@ fail: Com_Error( ERR_FATAL, "Couldn't load %s: %s", colormap, Q_ErrorString( ret ) ); } +static const cmdreg_t img_cmd[] = { + { "imagelist", IMG_List_f }, + { "screenshot", IMG_ScreenShot_f }, +#if USE_TGA + { "screenshottga", IMG_ScreenShotTGA_f }, +#endif +#if USE_JPG + { "screenshotjpg", IMG_ScreenShotJPG_f }, +#endif +#if USE_PNG + { "screenshotpng", IMG_ScreenShotPNG_f }, +#endif + + { NULL } +}; + void IMG_Init( void ) { int i; @@ -1759,9 +1957,21 @@ void IMG_Init( void ) { , 0 ); r_texture_formats->changed = r_texture_formats_changed; r_texture_formats_changed( r_texture_formats ); + +#if USE_JPG + r_screenshot_format = Cvar_Get( "gl_screenshot_format", "jpg", 0 ); +#elif USE_PNG + r_screenshot_format = Cvar_Get( "gl_screenshot_format", "png", 0 ); +#endif +#if USE_JPG + r_screenshot_quality = Cvar_Get( "gl_screenshot_quality", "100", 0 ); #endif +#if USE_PNG + r_screenshot_compression = Cvar_Get( "gl_screenshot_compression", "6", 0 ); +#endif +#endif // USE_PNG || USE_JPG || USE_TGA - Cmd_AddCommand( "imagelist", IMG_List_f ); + Cmd_Register( img_cmd ); for( i = 0; i < RIMAGES_HASH; i++ ) { List_Init( &r_imageHash[i] ); @@ -1772,7 +1982,7 @@ void IMG_Init( void ) { } void IMG_Shutdown( void ) { - Cmd_RemoveCommand( "imagelist" ); + Cmd_Deregister( img_cmd ); r_numImages = 0; } diff --git a/src/r_shared.h b/src/r_shared.h index 84da400..e6a29af 100644 --- a/src/r_shared.h +++ b/src/r_shared.h @@ -139,26 +139,8 @@ qhandle_t R_RegisterSkin( const char *name ); qhandle_t R_RegisterPic( const char *name ); qhandle_t R_RegisterFont( const char *name ); -#if USE_TGA || USE_JPG || USE_PNG -typedef qerror_t (img_save_t)( qhandle_t, const char *, const byte *, int, int, int ); -#endif - -#if USE_TGA -qerror_t IMG_SaveTGA( qhandle_t f, const char *filename, const byte *bgr, - int width, int height, int unused ); -#endif - -#if USE_JPG -qerror_t IMG_SaveJPG( qhandle_t f, const char *filename, const byte *rgb, - int width, int height, int quality ); -#endif - -#if USE_PNG -qerror_t IMG_SavePNG( qhandle_t f, const char *filename, const byte *rgb, - int width, int height, int compression ); -#endif - // these are implemented in [gl,sw]_images.c void IMG_Unload( image_t *image ); void IMG_Load( image_t *image, byte *pic, int width, int height ); +byte *IMG_ReadPixels( qboolean reverse, int *width, int *height ); |