if (loc)
sprintf(r_speeds_string + strlen(r_speeds_string), "Location: %s\n", loc->name);
sprintf(r_speeds_string + strlen(r_speeds_string), "org:'%+8.2f %+8.2f %+8.2f' dir:'%+2.3f %+2.3f %+2.3f'\n", r_view.origin[0], r_view.origin[1], r_view.origin[2], r_view.forward[0], r_view.forward[1], r_view.forward[2]);
- sprintf(r_speeds_string + strlen(r_speeds_string), "%5i entities%6i surfaces%6i triangles%5i leafs%5i portals%6i particles\n", r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles, r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "%7i surfaces%7i triangles %5i entities (%7i surfaces%7i triangles)\n", r_refdef.stats.world_surfaces, r_refdef.stats.world_triangles, r_refdef.stats.entities, r_refdef.stats.entities_surfaces, r_refdef.stats.entities_triangles);
+ sprintf(r_speeds_string + strlen(r_speeds_string), "%5ileafs%5i portals%6i particles%6i decals\n", r_refdef.stats.world_leafs, r_refdef.stats.world_portals, r_refdef.stats.particles, r_refdef.stats.decals);
sprintf(r_speeds_string + strlen(r_speeds_string), "%4i lights%4i clears%4i scissored%7i light%7i shadow%7i dynamic\n", r_refdef.stats.lights, r_refdef.stats.lights_clears, r_refdef.stats.lights_scissored, r_refdef.stats.lights_lighttriangles, r_refdef.stats.lights_shadowtriangles, r_refdef.stats.lights_dynamicshadowtriangles);
if (r_refdef.stats.bloom)
sprintf(r_speeds_string + strlen(r_speeds_string), "rendered%6i meshes%8i triangles bloompixels%8i copied%8i drawn\n", r_refdef.stats.meshes, r_refdef.stats.meshes_elements / 3, r_refdef.stats.bloom_copypixels, r_refdef.stats.bloom_drawpixels);
SCR_CaptureVideo_RIFF_Write32(nMatching); // nEntriesInUse
SCR_CaptureVideo_RIFF_WriteFourCC(dwChunkId); // dwChunkId
SCR_CaptureVideo_RIFF_Write32(cls.capturevideo.videofile_ix_movistart & (fs_offset_t) 0xFFFFFFFFu);
- SCR_CaptureVideo_RIFF_Write32(((long long) cls.capturevideo.videofile_ix_movistart) >> 32);
+ SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) cls.capturevideo.videofile_ix_movistart) >> 32);
SCR_CaptureVideo_RIFF_Write32(0); // dwReserved
for(i = 0; i < cls.capturevideo.riffindexbuffer.cursize; i += 16)
FS_Seek(cls.capturevideo.videofile, masteridx_start + 16 * *masteridx_count, SEEK_SET);
SCR_CaptureVideo_RIFF_Write32(ix & (fs_offset_t) 0xFFFFFFFFu);
- SCR_CaptureVideo_RIFF_Write32(((long long) ix) >> 32);
+ SCR_CaptureVideo_RIFF_Write32(((fs_offset_t) ix) >> 32);
SCR_CaptureVideo_RIFF_Write32(pos - ix);
SCR_CaptureVideo_RIFF_Write32(nMatching);
SCR_CaptureVideo_RIFF_Flush();
cls.capturevideo.frame = 0;
cls.capturevideo.soundsampleframe = 0;
cls.capturevideo.realtime = cl_capturevideo_realtime.integer != 0;
- cls.capturevideo.screenbuffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 3);
- cls.capturevideo.outbuffer = (unsigned char *)Mem_Alloc(tempmempool, width * height * (3+3+3) + 18);
+ cls.capturevideo.screenbuffer = (unsigned char *)Mem_Alloc(tempmempool, vid.width * vid.height * 4);
+ cls.capturevideo.outbuffer = (unsigned char *)Mem_Alloc(tempmempool, width * height * (4+4) + 18);
gamma = 1.0/scr_screenshot_gammaboost.value;
dpsnprintf(cls.capturevideo.basename, sizeof(cls.capturevideo.basename), "video/dpvideo%03i", cl_capturevideo_number.integer);
Cvar_SetValueQuick(&cl_capturevideo_number, cl_capturevideo_number.integer + 1);
memset(&cls.capturevideo, 0, sizeof(cls.capturevideo));
}
-// converts from RGB24 to I420 colorspace (identical to YV12 except chroma plane order is reversed), this colorspace is handled by the Intel(r) 4:2:0 codec on Windows
-void SCR_CaptureVideo_ConvertFrame_RGB_to_I420_flip(int width, int height, unsigned char *instart, unsigned char *outstart)
+// converts from BGRA32 to I420 colorspace (identical to YV12 except chroma plane order is reversed), this colorspace is handled by the Intel(r) 4:2:0 codec on Windows
+void SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(int width, int height, unsigned char *instart, unsigned char *outstart)
{
int x, y;
+ int blockr, blockg, blockb;
int outoffset = (width/2)*(height/2);
unsigned char *b, *out;
// process one line at a time, and CbCr every other line at 2 pixel intervals
for (y = 0;y < height;y++)
{
// 1x1 Y
- for (b = instart + (height-1-y)*width*3, out = outstart + y*width, x = 0;x < width;x++, b += 3, out++)
- *out = cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][b[0]] + cls.capturevideo.rgbtoyuvscaletable[0][1][b[1]] + cls.capturevideo.rgbtoyuvscaletable[0][2][b[2]]];
+ for (b = instart + (height-1-y)*width*4, out = outstart + y*width, x = 0;x < width;x++, b += 4, out++)
+ {
+ blockr = b[2];
+ blockg = b[1];
+ blockb = b[0];
+ *out = cls.capturevideo.yuvnormalizetable[0][cls.capturevideo.rgbtoyuvscaletable[0][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[0][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[0][2][blockb]];
+ }
if ((y & 1) == 0)
{
// 2x2 Cr and Cb planes
-#if 0
- // low quality, no averaging
- for (b = instart + (height-2-y)*width*3, out = outstart + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
- {
- // Cr
- out[0 ] = cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][b[0]] + cls.capturevideo.rgbtoyuvscaletable[1][1][b[1]] + cls.capturevideo.rgbtoyuvscaletable[1][2][b[2]] + 128];
- // Cb
- out[outoffset] = cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][b[0]] + cls.capturevideo.rgbtoyuvscaletable[2][1][b[1]] + cls.capturevideo.rgbtoyuvscaletable[2][2][b[2]] + 128];
- }
-#else
- // high quality, averaging
- int inpitch = width*3;
- for (b = instart + (height-2-y)*width*3, out = outstart + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 6, out++)
+ int inpitch = width*4;
+ for (b = instart + (height-2-y)*width*4, out = outstart + width*height + (y/2)*(width/2), x = 0;x < width/2;x++, b += 8, out++)
{
- int blockr, blockg, blockb;
- blockr = (b[0] + b[3] + b[inpitch+0] + b[inpitch+3]) >> 2;
- blockg = (b[1] + b[4] + b[inpitch+1] + b[inpitch+4]) >> 2;
- blockb = (b[2] + b[5] + b[inpitch+2] + b[inpitch+5]) >> 2;
+ blockr = (b[2] + b[6] + b[inpitch+2] + b[inpitch+6]) >> 2;
+ blockg = (b[1] + b[5] + b[inpitch+1] + b[inpitch+5]) >> 2;
+ blockb = (b[0] + b[4] + b[inpitch+0] + b[inpitch+4]) >> 2;
// Cr
out[0 ] = cls.capturevideo.yuvnormalizetable[1][cls.capturevideo.rgbtoyuvscaletable[1][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[1][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[1][2][blockb] + 128];
// Cb
out[outoffset] = cls.capturevideo.yuvnormalizetable[2][cls.capturevideo.rgbtoyuvscaletable[2][0][blockr] + cls.capturevideo.rgbtoyuvscaletable[2][1][blockg] + cls.capturevideo.rgbtoyuvscaletable[2][2][blockb] + 128];
}
-#endif
}
}
}
-static void SCR_ScaleDown(unsigned char *in, int inw, int inh, unsigned char *out, int outw, int outh)
+static void SCR_ScaleDownBGRA(unsigned char *in, int inw, int inh, unsigned char *out, int outw, int outh)
{
// TODO optimize this function
// memcpy is faster than me
if(inw == outw && inh == outh)
{
- memcpy(out, in, 3 * inw * inh);
+ memcpy(out, in, 4 * inw * inh);
return;
}
{
float inx0 = x / (float)outw * inw; int inx0_i = floor(inx0);
float inx1 = (x+1) / (float)outw * inw; int inx1_i = ceil(inx1);
- float r = 0, g = 0, b = 0;
+ float r = 0, g = 0, b = 0, alpha = 0;
int xx, yy;
for(yy = iny0_i; yy < iny1_i; ++yy)
for(xx = inx0_i; xx < inx1_i; ++xx)
{
float a = ya * (min(xx+1, inx1) - max(inx0, xx));
- r += a * in[3*(xx + inw * yy)+0];
- g += a * in[3*(xx + inw * yy)+1];
- b += a * in[3*(xx + inw * yy)+2];
+ r += a * in[4*(xx + inw * yy)+0];
+ g += a * in[4*(xx + inw * yy)+1];
+ b += a * in[4*(xx + inw * yy)+2];
+ alpha += a * in[4*(xx + inw * yy)+3];
}
}
- out[3*(x + outw * y)+0] = r * area;
- out[3*(x + outw * y)+1] = g * area;
- out[3*(x + outw * y)+2] = b * area;
+ out[4*(x + outw * y)+0] = r * area;
+ out[4*(x + outw * y)+1] = g * area;
+ out[4*(x + outw * y)+2] = b * area;
+ out[4*(x + outw * y)+3] = alpha * area;
}
}
}
if (!cls.capturevideo.videofile)
return false;
// FIXME: width/height must be multiple of 2, enforce this?
- qglReadPixels (x, y, vid.width, vid.height, GL_RGB, GL_UNSIGNED_BYTE, cls.capturevideo.screenbuffer);CHECKGLERROR
- SCR_ScaleDown (cls.capturevideo.screenbuffer, vid.width, vid.height, cls.capturevideo.outbuffer, width, height);
+ qglReadPixels (x, y, vid.width, vid.height, GL_BGRA, GL_UNSIGNED_BYTE, cls.capturevideo.screenbuffer);CHECKGLERROR
+ SCR_ScaleDownBGRA (cls.capturevideo.screenbuffer, vid.width, vid.height, cls.capturevideo.outbuffer, width, height);
in = cls.capturevideo.outbuffer;
- out = cls.capturevideo.outbuffer + width*height*3;
- SCR_CaptureVideo_ConvertFrame_RGB_to_I420_flip(width, height, in, out);
+ out = cls.capturevideo.outbuffer + width*height*4;
+ SCR_CaptureVideo_ConvertFrame_BGRA_to_I420_flip(width, height, in, out);
x = width*height+(width/2)*(height/2)*2;
SCR_CaptureVideo_RIFF_OverflowCheck(8 + x);
for (;cls.capturevideo.frame < newframenum;cls.capturevideo.frame++)
return false;
CHECKGLERROR
- qglReadPixels (x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer1);CHECKGLERROR
+ qglReadPixels (x, y, width, height, jpeg ? GL_RGB : GL_BGR, GL_UNSIGNED_BYTE, buffer1);CHECKGLERROR
if (scr_screenshot_gammaboost.value != 1 && gammacorrect)
{
if (jpeg)
ret = JPEG_SaveImage_preflipped (filename, width, height, buffer2);
else
- ret = Image_WriteTGARGB_preflipped (filename, width, height, buffer2, buffer3);
+ ret = Image_WriteTGABGR_preflipped (filename, width, height, buffer2, buffer3);
return ret;
}