summaryrefslogtreecommitdiff
path: root/src/renderer/tr_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/renderer/tr_init.c')
-rw-r--r--src/renderer/tr_init.c215
1 files changed, 160 insertions, 55 deletions
diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c
index 89fcf3e3..10ea222c 100644
--- a/src/renderer/tr_init.c
+++ b/src/renderer/tr_init.c
@@ -152,6 +152,9 @@ cvar_t *r_saveFontData;
cvar_t *r_marksOnTriangleMeshes;
+cvar_t *r_aviMotionJpegQuality;
+cvar_t *r_screenshotJpegQuality;
+
cvar_t *r_maxpolys;
int max_polys;
cvar_t *r_maxpolyverts;
@@ -362,15 +365,62 @@ FIXME: the statics don't get a reinit between fs_game changes
/*
==================
+RB_ReadPixels
+
+Reads an image but takes care of alignment issues for reading RGB images.
+
+Reads a minimum offset for where the RGB data starts in the image from
+integer stored at pointer offset. When the function has returned the actual
+offset was written back to address offset. This address will always have an
+alignment of packAlign to ensure efficient copying.
+
+Stores the length of padding after a line of pixels to address padlen
+
+Return value must be freed with ri.Hunk_FreeTempMemory()
+==================
+*/
+
+byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen)
+{
+ byte *buffer, *bufstart;
+ int padwidth, linelen;
+ GLint packAlign;
+
+ qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
+
+ linelen = width * 3;
+ padwidth = PAD(linelen, packAlign);
+
+ // Allocate a few more bytes so that we can choose an alignment we like
+ buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1);
+
+ bufstart = (byte *) PAD((intptr_t) buffer + *offset, packAlign);
+ qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart);
+
+ *offset = bufstart - buffer;
+ *padlen = padwidth - linelen;
+
+ return buffer;
+}
+
+/*
+==================
RB_TakeScreenshot
==================
*/
-void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) {
- byte *buffer;
- int i, c, temp;
+void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName)
+{
+ byte *allbuf, *buffer;
+ byte *srcptr, *destptr;
+ byte *endline, *endmem;
+ byte temp;
+
+ int linelen, padlen;
+ size_t offset = 18, memcount;
- buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18);
-
+ allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen);
+ buffer = allbuf + offset - 18;
+
Com_Memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = width & 255;
@@ -379,47 +429,62 @@ void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) {
buffer[15] = height >> 8;
buffer[16] = 24; // pixel size
- qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 );
+ // swap rgb to bgr and remove padding from line endings
+ linelen = width * 3;
+
+ srcptr = destptr = allbuf + offset;
+ endmem = srcptr + (linelen + padlen) * height;
+
+ while(srcptr < endmem)
+ {
+ endline = srcptr + linelen;
- // swap rgb to bgr
- c = 18 + width * height * 3;
- for (i=18 ; i<c ; i+=3) {
- temp = buffer[i];
- buffer[i] = buffer[i+2];
- buffer[i+2] = temp;
+ while(srcptr < endline)
+ {
+ temp = srcptr[0];
+ *destptr++ = srcptr[2];
+ *destptr++ = srcptr[1];
+ *destptr++ = temp;
+
+ srcptr += 3;
+ }
+
+ // Skip the pad
+ srcptr += padlen;
}
+ memcount = linelen * height;
+
// gamma correct
- if ( glConfig.deviceSupportsGamma ) {
- R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 );
- }
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(allbuf + offset, memcount);
- ri.FS_WriteFile( fileName, buffer, c );
+ ri.FS_WriteFile(fileName, buffer, memcount + 18);
- ri.Hunk_FreeTempMemory( buffer );
+ ri.Hunk_FreeTempMemory(allbuf);
}
/*
==================
RB_TakeScreenshotJPEG
==================
-*/
-void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) {
- byte *buffer;
+*/
- buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);
+void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName)
+{
+ byte *buffer;
+ size_t offset = 0, memcount;
+ int padlen;
- qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer );
+ buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen);
+ memcount = (width * 3 + padlen) * height;
// gamma correct
- if ( glConfig.deviceSupportsGamma ) {
- R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 );
- }
-
- ri.FS_WriteFile( fileName, buffer, 1 ); // create path
- SaveJPG( fileName, 90, glConfig.vidWidth, glConfig.vidHeight, buffer);
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(buffer + offset, memcount);
- ri.Hunk_FreeTempMemory( buffer );
+ RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, buffer + offset, padlen);
+ ri.Hunk_FreeTempMemory(buffer);
}
/*
@@ -525,8 +590,10 @@ the menu system, sampled down from full screen distorted images
void R_LevelShot( void ) {
char checkname[MAX_OSPATH];
byte *buffer;
- byte *source;
+ byte *source, *allsource;
byte *src, *dst;
+ size_t offset = 0;
+ int padlen;
int x, y;
int r, g, b;
float xScale, yScale;
@@ -534,17 +601,16 @@ void R_LevelShot( void ) {
Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName);
- source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 );
+ allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen);
+ source = allsource + offset;
- buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18);
+ buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18);
Com_Memset (buffer, 0, 18);
buffer[2] = 2; // uncompressed type
buffer[12] = 128;
buffer[14] = 128;
buffer[16] = 24; // pixel size
- qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source );
-
// resample from source
xScale = glConfig.vidWidth / 512.0f;
yScale = glConfig.vidHeight / 384.0f;
@@ -553,7 +619,8 @@ void R_LevelShot( void ) {
r = g = b = 0;
for ( yy = 0 ; yy < 3 ; yy++ ) {
for ( xx = 0 ; xx < 4 ; xx++ ) {
- src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) );
+ src = source + (3 * glConfig.vidWidth + padlen) * (int)((y*3 + yy) * yScale) +
+ 3 * (int) ((x*4 + xx) * xScale);
r += src[0];
g += src[1];
b += src[2];
@@ -573,8 +640,8 @@ void R_LevelShot( void ) {
ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 );
- ri.Hunk_FreeTempMemory( buffer );
- ri.Hunk_FreeTempMemory( source );
+ ri.Hunk_FreeTempMemory(buffer);
+ ri.Hunk_FreeTempMemory(allsource);
ri.Printf( PRINT_ALL, "Wrote %s\n", checkname );
}
@@ -707,36 +774,70 @@ RB_TakeVideoFrameCmd
const void *RB_TakeVideoFrameCmd( const void *data )
{
const videoFrameCommand_t *cmd;
- int frameSize;
- int i;
+ byte *cBuf;
+ size_t memcount, linelen;
+ int padwidth, avipadwidth, padlen, avipadlen;
+ GLint packAlign;
cmd = (const videoFrameCommand_t *)data;
- qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA,
- GL_UNSIGNED_BYTE, cmd->captureBuffer );
+ qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign);
+
+ linelen = cmd->width * 3;
+
+ // Alignment stuff for glReadPixels
+ padwidth = PAD(linelen, packAlign);
+ padlen = padwidth - linelen;
+ // AVI line padding
+ avipadwidth = PAD(linelen, AVI_LINE_PADDING);
+ avipadlen = avipadwidth - linelen;
+
+ cBuf = (byte *) PAD((intptr_t) cmd->captureBuffer, packAlign);
+
+ qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB,
+ GL_UNSIGNED_BYTE, cBuf);
+
+ memcount = padwidth * cmd->height;
// gamma correct
- if( glConfig.deviceSupportsGamma )
- R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 );
+ if(glConfig.deviceSupportsGamma)
+ R_GammaCorrect(cBuf, memcount);
- if( cmd->motionJpeg )
+ if(cmd->motionJpeg)
{
- frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 90,
- cmd->width, cmd->height, cmd->captureBuffer );
- ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize );
+ memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height,
+ r_aviMotionJpegQuality->integer,
+ cmd->width, cmd->height, cBuf, padlen);
+ ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount);
}
else
{
- frameSize = cmd->width * cmd->height;
-
- for( i = 0; i < frameSize; i++) // Pack to 24bpp and swap R and B
+ byte *lineend, *memend;
+ byte *srcptr, *destptr;
+
+ srcptr = cBuf;
+ destptr = cmd->encodeBuffer;
+ memend = srcptr + memcount;
+
+ // swap R and B and remove line paddings
+ while(srcptr < memend)
{
- cmd->encodeBuffer[ i*3 ] = cmd->captureBuffer[ i*4 + 2 ];
- cmd->encodeBuffer[ i*3 + 1 ] = cmd->captureBuffer[ i*4 + 1 ];
- cmd->encodeBuffer[ i*3 + 2 ] = cmd->captureBuffer[ i*4 ];
+ lineend = srcptr + linelen;
+ while(srcptr < lineend)
+ {
+ *destptr++ = srcptr[2];
+ *destptr++ = srcptr[1];
+ *destptr++ = srcptr[0];
+ srcptr += 3;
+ }
+
+ Com_Memset(destptr, '\0', avipadlen);
+ destptr += avipadlen;
+
+ srcptr += padlen;
}
-
- ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize * 3 );
+
+ ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height);
}
return (const void *)(cmd + 1);
@@ -932,6 +1033,7 @@ void R_Register( void )
r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH);
+ ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse);
//
// temporary latched variables that can only change over a restart
@@ -1024,6 +1126,9 @@ void R_Register( void )
r_marksOnTriangleMeshes = ri.Cvar_Get("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE);
+ r_aviMotionJpegQuality = ri.Cvar_Get("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE);
+ r_screenshotJpegQuality = ri.Cvar_Get("r_screenshotJpegQuality", "90", CVAR_ARCHIVE);
+
r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0);
r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0);