fixed picmip simpleitems issue.

fixed double picmip bug.
use pbos for videocapture, for extra speed. mwahaha.
fix issues with 2d batching. including drawflags.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4962 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2015-08-14 02:46:38 +00:00
parent 5f7243c6dc
commit a26a373d15
19 changed files with 424 additions and 175 deletions

View File

@ -3686,7 +3686,7 @@ void CL_LinkPacketEntities (void)
Q_snprintfz(name, sizeof(name), "textures/bmodels/simple_%s_%i.tga", basename, ent->skinnum);
else
Q_snprintfz(name, sizeof(name), "textures/models/simple_%s_%i.tga", basename, ent->skinnum);
model->simpleskin[ent->skinnum] = R_RegisterShader(name, 0, va("{\nprogram defaultsprite\nsurfaceparm noshadows\nsurfaceparm nodlight\nsort seethrough\n{\nmap \"%s\"\nalphafunc ge128\n}\n}\n", name));
model->simpleskin[ent->skinnum] = R_RegisterShader(name, 0, va("{\nnomipmaps\nprogram defaultsprite\nsurfaceparm noshadows\nsurfaceparm nodlight\nsort seethrough\n{\nmap \"%s\"\nalphafunc ge128\n}\n}\n", name));
}
VectorCopy(le->angles, angles);

View File

@ -2031,13 +2031,96 @@ typedef struct _TargaHeader {
#if defined(AVAIL_JPEGLIB) && !defined(NO_JPEG)
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight);
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight, enum uploadfmt fmt);
#endif
#ifdef AVAIL_PNGLIB
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height);
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height, enum uploadfmt fmt);
#endif
void WriteBMPFile(char *filename, enum fs_relative fsroot, qbyte *in, int width, int height);
qboolean WriteTGA(char *filename, enum fs_relative fsroot, qbyte *rgb_buffer, int width, int height, enum uploadfmt fmt)
{
size_t c, i;
vfsfile_t *vfs;
if (fmt != TF_BGRA32 && fmt != TF_RGB24 && fmt != TF_RGBA32 && fmt != TF_BGR24)
return false;
FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs)
{
unsigned char header[18];
memset (header, 0, 18);
header[2] = 2; // uncompressed type
header[12] = width&255;
header[13] = width>>8;
header[14] = height&255;
header[15] = height>>8;
header[16] = 24; // pixel size
if (fmt == TF_BGRA32)
{
#if 0
header[16] = 32;
#else
qbyte tmp[3];
// compact+swap
c = width*height;
for (i=0 ; i<c ; i++)
{
tmp[0] = rgb_buffer[i*4+0];
tmp[1] = rgb_buffer[i*4+1];
tmp[2] = rgb_buffer[i*4+2];
rgb_buffer[i*3+0] = tmp[0];
rgb_buffer[i*3+1] = tmp[1];
rgb_buffer[i*3+2] = tmp[2];
}
c *= 3;
#endif
}
else if (fmt == TF_BGR24)
c = width*height*3;
else if (fmt == TF_RGBA32)
{
int s = 3;
qbyte tmp[3];
#if 0
s = 4;
header[16] = s*8;
#endif
// compact+swap
c = width*height;
for (i=0 ; i<c ; i++)
{
tmp[0] = rgb_buffer[i*4+0];
tmp[1] = rgb_buffer[i*4+1];
tmp[2] = rgb_buffer[i*4+2];
rgb_buffer[i*s+0] = tmp[2];
rgb_buffer[i*s+1] = tmp[1];
rgb_buffer[i*s+2] = tmp[0];
}
c *= s;
}
else if (fmt == TF_RGB24)
{
qbyte temp;
// swap r+b in place
c = width*height*3;
for (i=0 ; i<c ; i+=3)
{
temp = rgb_buffer[i];
rgb_buffer[i] = rgb_buffer[i+2];
rgb_buffer[i+2] = temp;
}
}
else
c = 0;
VFS_WRITE(vfs, header, sizeof(header));
VFS_WRITE(vfs, rgb_buffer, c);
VFS_CLOSE(vfs);
}
return true;
}
/*
Find closest color in the palette for named color
*/
@ -2071,9 +2154,8 @@ int MipColor(int r, int g, int b)
return best;
}
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height)
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height, enum uploadfmt fmt)
{
int i, c, temp;
#if defined(AVAIL_PNGLIB) || defined(AVAIL_JPEGLIB)
extern cvar_t scr_sshot_compression;
#endif
@ -2088,70 +2170,66 @@ qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buff
#ifdef AVAIL_PNGLIB
if (!Q_strcasecmp(ext, "png"))
{
return Image_WritePNG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
//png can do bgr+rgb
//rgba bgra will result in an extra alpha chan
return Image_WritePNG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height, fmt);
}
else
#endif
#ifdef AVAIL_JPEGLIB
if (!Q_strcasecmp(ext, "jpeg") || !Q_strcasecmp(ext, "jpg"))
{
return screenshotJPEG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height);
return screenshotJPEG(filename, fsroot, scr_sshot_compression.value, rgb_buffer, width, height, fmt);
}
else
#endif
/* if (!Q_strcasecmp(ext, "bmp"))
{
WriteBMPFile(pcxname, rgb_buffer, width, height);
return WriteBMPFile(pcxname, rgb_buffer, width, height);
}
else*/
if (!Q_strcasecmp(ext, "pcx"))
{
int y, x;
int y, x, s;
qbyte *src, *dest;
qbyte *newbuf = rgb_buffer;
// convert in-place to eight bit
for (y = 0; y < height; y++)
if (fmt == TF_RGB24 || fmt == TF_RGBA32)
{
src = newbuf + (width * 3 * y);
dest = newbuf + (width * y);
s = (fmt == TF_RGB24)?3:4;
// convert in-place to eight bit
for (y = 0; y < height; y++)
{
src = newbuf + (width * s * y);
dest = newbuf + (width * y);
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[0], src[1], src[2]);
src += 3;
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[0], src[1], src[2]);
src += s;
}
}
}
else if (fmt == TF_BGR24 || fmt == TF_BGRA32)
{
s = (fmt == TF_BGR24)?3:4;
// convert in-place to eight bit
for (y = 0; y < height; y++)
{
src = newbuf + (width * s * y);
dest = newbuf + (width * y);
for (x = 0; x < width; x++) {
*dest++ = MipColor(src[2], src[1], src[0]);
src += s;
}
}
}
else
return false;
WritePCXfile (filename, fsroot, newbuf, width, height, width, host_basepal, false);
}
else if (!Q_strcasecmp(ext, "tga")) //tga
{
vfsfile_t *vfs;
FS_CreatePath(filename, fsroot);
vfs = FS_OpenVFS(filename, "wb", fsroot);
if (vfs)
{
unsigned char header[18];
memset (header, 0, 18);
header[2] = 2; // uncompressed type
header[12] = width&255;
header[13] = width>>8;
header[14] = height&255;
header[15] = height>>8;
header[16] = 24; // pixel size
VFS_WRITE(vfs, header, sizeof(header));
// swap rgb to bgr
c = width*height*3;
for (i=0 ; i<c ; i+=3)
{
temp = ((qbyte*)rgb_buffer)[i];
((qbyte*)rgb_buffer)[i] = ((qbyte*)rgb_buffer)[i+2];
((qbyte*)rgb_buffer)[i+2] = temp;
}
VFS_WRITE(vfs, rgb_buffer, c);
VFS_CLOSE(vfs);
}
}
return WriteTGA(filename, fsroot, rgb_buffer, width, height, fmt);
else //extension / type not recognised.
return false;
return true;
@ -2170,6 +2248,7 @@ void SCR_ScreenShot_f (void)
vfsfile_t *vfs;
void *rgbbuffer;
int width, height;
enum uploadmfmt fmt;
if (!VID_GetRGBInfo)
{
@ -2213,10 +2292,10 @@ void SCR_ScreenShot_f (void)
FS_NativePath(pcxname, FS_GAMEONLY, sysname, sizeof(sysname));
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
rgbbuffer = VID_GetRGBInfo(&width, &height, &fmt);
if (rgbbuffer)
{
if (SCR_ScreenShot(pcxname, FS_GAMEONLY, rgbbuffer, width, height))
if (SCR_ScreenShot(pcxname, FS_GAMEONLY, rgbbuffer, width, height, fmt))
{
Con_Printf ("Wrote %s\n", sysname);
BZ_Free(rgbbuffer);
@ -2233,6 +2312,7 @@ void SCR_ScreenShot_Mega_f(void)
int height;
qbyte *rgbbuffer;
char filename[MAX_QPATH];
enum uploadfmt fmt;
//poke the various modes into redrawing the screen (without huds), to avoid any menus or console drawn over the top of the current backbuffer.
//FIXME: clear-to-black first
@ -2286,10 +2366,10 @@ void SCR_ScreenShot_Mega_f(void)
//okay, we drew something, we're good to save a screeny.
if (okay)
{
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
rgbbuffer = VID_GetRGBInfo(&width, &height, &fmt);
if (rgbbuffer)
{
if (SCR_ScreenShot(filename, FS_GAMEONLY, rgbbuffer, width, height))
if (SCR_ScreenShot(filename, FS_GAMEONLY, rgbbuffer, width, height, fmt))
{
char sysname[1024];
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
@ -2374,6 +2454,7 @@ qboolean SCR_RSShot (void)
float fracw, frach;
char st[80];
time_t now;
enum uploadfmt fmt;
if (!scr_allowsnap.ival)
return false;
@ -2394,7 +2475,15 @@ qboolean SCR_RSShot (void)
//
// save the pcx file
//
newbuf = VID_GetRGBInfo(0, &truewidth, &trueheight);
newbuf = VID_GetRGBInfo(&truewidth, &trueheight, &fmt);
if (fmt == TF_INVALID)
return false;
if (fmt != TF_RGB24)
{
BZ_Free(newbuf);
return false;
}
w = RSSHOT_WIDTH;
h = RSSHOT_HEIGHT;

View File

@ -1572,7 +1572,7 @@ typedef struct
typedef struct {
char *drivername;
void *(VARGS *capture_begin) (char *streamname, int videorate, int width, int height, int *sndkhz, int *sndchannels, int *sndbits);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height);
void (VARGS *capture_video) (void *ctx, void *data, int frame, int width, int height, enum uploadfmt fmt);
void (VARGS *capture_audio) (void *ctx, void *data, int bytes);
void (VARGS *capture_end) (void *ctx);
} media_encoder_funcs_t;

View File

@ -720,6 +720,7 @@ void (PNGAPI *qpng_set_expand_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)) PST
#else
void (PNGAPI *qpng_set_gray_1_2_4_to_8) PNGARG((png_structp png_ptr)) PSTATIC(png_set_gray_1_2_4_to_8);
#endif
void (PNGAPI *qpng_set_bgr) PNGARG((png_structp png_ptr)) PSTATIC(png_set_bgr);
void (PNGAPI *qpng_set_filler) PNGARG((png_structp png_ptr, png_uint_32 filler, int flags)) PSTATIC(png_set_filler);
void (PNGAPI *qpng_set_palette_to_rgb) PNGARG((png_structp png_ptr)) PSTATIC(png_set_palette_to_rgb);
png_uint_32 (PNGAPI *qpng_get_IHDR) PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, png_uint_32 *height,
@ -767,6 +768,7 @@ qboolean LibPNG_Init(void)
#else
{(void **) &qpng_set_gray_1_2_4_to_8, "png_set_gray_1_2_4_to_8"},
#endif
{(void **) &qpng_set_bgr, "png_set_bgr"},
{(void **) &qpng_set_filler, "png_set_filler"},
{(void **) &qpng_set_palette_to_rgb, "png_set_palette_to_rgb"},
{(void **) &qpng_get_IHDR, "png_get_IHDR"},
@ -979,7 +981,7 @@ error:
#ifndef NPFTE
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height)
int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qbyte *pixels, int width, int height, enum uploadfmt fmt)
{
char name[MAX_OSPATH];
int i;
@ -988,6 +990,7 @@ int Image_WritePNG (char *filename, enum fs_relative fsroot, int compression, qb
png_infop info_ptr;
png_byte **row_pointers;
struct pngerr errctx;
int pxsize;
if (!FS_NativePath(filename, fsroot, name, sizeof(name)))
return false;
@ -1036,14 +1039,25 @@ err:
#endif
qpng_set_compression_level(png_ptr, Z_NO_COMPRESSION + (compression*(Z_BEST_COMPRESSION-Z_NO_COMPRESSION))/100);
qpng_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
if (fmt == TF_BGR24 || fmt == TF_BGRA32)
qpng_set_bgr(png_ptr);
if (fmt == TF_RGBA32 || fmt == TF_BGRA32)
{
pxsize = 4;
qpng_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
}
else
{
pxsize = 3;
qpng_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
}
qpng_write_info(png_ptr, info_ptr);
row_pointers = BZ_Malloc (sizeof(png_byte *) * height);
if (!row_pointers)
goto err;
for (i = 0; i < height; i++)
row_pointers[height - i - 1] = pixels + i * width * 3;
row_pointers[height - i - 1] = pixels + i * width * pxsize;
qpng_write_image(png_ptr, row_pointers);
qpng_write_end(png_ptr, info_ptr);
BZ_Free(row_pointers);
@ -1463,6 +1477,19 @@ badjpeg:
/*end read*/
#ifndef NPFTE
/*begin write*/
#ifndef DYNAMIC_LIBJPEG
#define qjpeg_std_error jpeg_std_error
#define qjpeg_destroy_compress jpeg_destroy_compress
#define qjpeg_CreateCompress jpeg_CreateCompress
#define qjpeg_set_defaults jpeg_set_defaults
#define qjpeg_set_quality jpeg_set_quality
#define qjpeg_start_compress jpeg_start_compress
#define qjpeg_write_scanlines jpeg_write_scanlines
#define qjpeg_finish_compress jpeg_finish_compress
#define qjpeg_destroy_compress jpeg_destroy_compress
#endif
#define OUTPUT_BUF_SIZE 4096
typedef struct {
struct jpeg_error_mgr pub;
@ -1535,7 +1562,7 @@ METHODDEF(void) jpeg_error_exit (j_common_ptr cinfo)
{
longjmp(((jpeg_error_mgr_wrapper *) cinfo->err)->setjmp_buffer, 1);
}
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight) //input is rgb NOT rgba
qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression, qbyte *screendata, int screenwidth, int screenheight, enum uploadfmt fmt)
{
qbyte *buffer;
vfsfile_t *outfile;
@ -1543,6 +1570,9 @@ qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression
struct jpeg_compress_struct cinfo;
JSAMPROW row_pointer[1];
if (fmt != TF_RGB24)
return false;
if (!LIBJPEG_LOADED())
return false;
@ -1556,29 +1586,17 @@ qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression
}
}
#ifdef DYNAMIC_LIBJPEG
cinfo.err = qjpeg_std_error(&jerr.pub);
#else
cinfo.err = jpeg_std_error(&jerr.pub);
#endif
cinfo.err = qjpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
#ifdef DYNAMIC_LIBJPEG
qjpeg_destroy_compress(&cinfo);
#else
jpeg_destroy_compress(&cinfo);
#endif
qjpeg_destroy_compress(&cinfo);
VFS_CLOSE(outfile);
FS_Remove(filename, FS_GAME);
Con_Printf("Failed to create jpeg\n");
return false;
}
#ifdef DYNAMIC_LIBJPEG
qjpeg_create_compress(&cinfo);
#else
jpeg_create_compress(&cinfo);
#endif
qjpeg_create_compress(&cinfo);
buffer = screendata;
@ -1587,42 +1605,18 @@ qboolean screenshotJPEG(char *filename, enum fs_relative fsroot, int compression
cinfo.image_height = screenheight;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
#ifdef DYNAMIC_LIBJPEG
qjpeg_set_defaults(&cinfo);
#else
jpeg_set_defaults(&cinfo);
#endif
#ifdef DYNAMIC_LIBJPEG
qjpeg_set_quality (&cinfo, bound(0, compression, 100), true);
#else
jpeg_set_quality (&cinfo, bound(0, compression, 100), true);
#endif
#ifdef DYNAMIC_LIBJPEG
qjpeg_start_compress(&cinfo, true);
#else
jpeg_start_compress(&cinfo, true);
#endif
qjpeg_set_defaults(&cinfo);
qjpeg_set_quality (&cinfo, bound(0, compression, 100), true);
qjpeg_start_compress(&cinfo, true);
while (cinfo.next_scanline < cinfo.image_height)
{
*row_pointer = &buffer[(cinfo.image_height - cinfo.next_scanline - 1) * cinfo.image_width * 3];
#ifdef DYNAMIC_LIBJPEG
qjpeg_write_scanlines(&cinfo, row_pointer, 1);
#else
jpeg_write_scanlines(&cinfo, row_pointer, 1);
#endif
qjpeg_write_scanlines(&cinfo, row_pointer, 1);
}
#ifdef DYNAMIC_LIBJPEG
qjpeg_finish_compress(&cinfo);
#else
jpeg_finish_compress(&cinfo);
#endif
qjpeg_finish_compress(&cinfo);
VFS_CLOSE(outfile);
#ifdef DYNAMIC_LIBJPEG
qjpeg_destroy_compress(&cinfo);
#else
jpeg_destroy_compress(&cinfo);
#endif
qjpeg_destroy_compress(&cinfo);
return true;
}
#endif
@ -3155,21 +3149,24 @@ static void Image_RoundDimensions(int *scaled_width, int *scaled_height, unsigne
}
}
if (flags & IF_NOMIPMAP)
if (!(flags & IF_NOPICMIP))
{
if (gl_picmip2d.ival > 0)
if (flags & IF_NOMIPMAP)
{
*scaled_width >>= gl_picmip2d.ival;
*scaled_height >>= gl_picmip2d.ival;
if (gl_picmip2d.ival > 0)
{
*scaled_width >>= gl_picmip2d.ival;
*scaled_height >>= gl_picmip2d.ival;
}
}
}
else
{
if (gl_picmip.ival > 0)
else
{
TRACE(("dbg: GL_RoundDimensions: %f\n", gl_picmip.value));
*scaled_width >>= gl_picmip.ival;
*scaled_height >>= gl_picmip.ival;
if (gl_picmip.ival > 0)
{
TRACE(("dbg: GL_RoundDimensions: %f\n", gl_picmip.value));
*scaled_width >>= gl_picmip.ival;
*scaled_height >>= gl_picmip.ival;
}
}
}
@ -3500,6 +3497,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case TF_MIP4_LUM8:
//8bit opaque data
Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags);
flags |= IF_NOPICMIP;
if (mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight)
{
unsigned int pixels =
@ -3537,6 +3535,7 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag
case TF_MIP4_SOLID8:
//8bit opaque data
Image_RoundDimensions(&mips->mip[0].width, &mips->mip[0].height, flags);
flags |= IF_NOPICMIP;
if (mips->mip[0].width == imgwidth && mips->mip[0].height == imgheight && sh_config.texfmt[PTI_RGBX8])
{
unsigned int pixels =

View File

@ -697,7 +697,6 @@ void Media_LoadTrackNames (char *listname);
void M_Media_Draw (menu_t *menu)
{
mpic_t *p;
mediatrack_t *track;
int y;
int op, i;
@ -2672,6 +2671,12 @@ int captureoldfbo;
qboolean capturingfbo;
texid_t capturetexture;
qboolean captureframeforce;
#ifdef GLQUAKE
//ring buffer
int pbo_handles[4];
enum uploadfmt pbo_format;
#endif
int pbo_oldest;
qboolean capturepaused;
extern cvar_t vid_conautoscale;
@ -2751,13 +2756,13 @@ static void *QDECL capture_raw_begin (char *streamname, int videorate, int width
}
return ctx;
}
static void QDECL capture_raw_video (void *vctx, void *data, int frame, int width, int height)
static void QDECL capture_raw_video (void *vctx, void *data, int frame, int width, int height, enum uploadfmt fmt)
{
struct capture_raw_ctx *ctx = vctx;
char filename[MAX_OSPATH];
ctx->frames = frame+1;
Q_snprintfz(filename, sizeof(filename), "%s%8.8i.%s", ctx->videonameprefix, frame, ctx->videonameextension);
SCR_ScreenShot(filename, ctx->fsroot, data, width, height);
SCR_ScreenShot(filename, ctx->fsroot, data, width, height, fmt);
}
static void QDECL capture_raw_audio (void *vctx, void *data, int bytes)
{
@ -2949,19 +2954,39 @@ static void *QDECL capture_avi_begin (char *streamname, int videorate, int width
return ctx;
}
static void QDECL capture_avi_video(void *vctx, void *vdata, int frame, int width, int height)
static void QDECL capture_avi_video(void *vctx, void *vdata, int frame, int width, int height, enum uploadfmt fmt)
{
struct capture_avi_ctx *ctx = vctx;
qbyte *data = vdata;
int c, i;
qbyte temp;
// swap rgb to bgr
c = width*height*3;
for (i=0 ; i<c ; i+=3)
if (fmt == TF_BGRA32)
{
temp = data[i];
data[i] = data[i+2];
data[i+2] = temp;
// truncate bgra to bgr
c = width*height;
for (i=0 ; i<c ; i++)
{
data[i*3+0] = data[i*4+0];
data[i*3+1] = data[i*4+1];
data[i*3+2] = data[i*4+2];
}
}
else if (fmt == TF_RGB24)
{
// swap rgb to bgr
c = width*height*3;
for (i=0 ; i<c ; i+=3)
{
temp = data[i];
data[i] = data[i+2];
data[i+2] = temp;
}
}
else if (fmt != TF_BGR24)
{
Con_Printf("Unsupported image format\n");
return;
}
//write it
if (FAILED(qAVIStreamWrite(avi_video_stream(ctx), frame, 1, data, width*height * 3, ((frame%15) == 0)?AVIIF_KEYFRAME:0, NULL, NULL)))
@ -2993,7 +3018,7 @@ static void *QDECL capture_null_begin (char *streamname, int videorate, int widt
{
return (void*)~0;
}
static void QDECL capture_null_video(void *vctx, void *vdata, int frame, int width, int height)
static void QDECL capture_null_video(void *vctx, void *vdata, int frame, int width, int height, enum uploadfmt fmt)
{
}
static void QDECL capture_null_audio(void *vctx, void *data, int bytes)
@ -3098,6 +3123,7 @@ void Media_RecordFrame (void)
{
char *buffer;
int truewidth, trueheight;
enum uploadfmt fmt;
if (!currentcapture_funcs)
return;
@ -3162,17 +3188,65 @@ void Media_RecordFrame (void)
if (R2D_Flush)
R2D_Flush();
//submit the current video frame. audio will be mixed to match.
buffer = VID_GetRGBInfo(0, &truewidth, &trueheight);
if (buffer)
#ifdef GLQUAKE
if (pbo_format != TF_INVALID)
{
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, captureframe, truewidth, trueheight);
capturelastvideotime += captureframeinterval;
captureframe++;
BZ_Free (buffer);
int imagesize = vid.fbpwidth * vid.fbpheight * 4;
while (pbo_oldest + countof(pbo_handles) <= captureframe)
{
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[pbo_oldest%countof(pbo_handles)]);
buffer = qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
if (buffer)
{
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, pbo_format);
qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
}
pbo_oldest++;
}
if (!pbo_handles[captureframe%countof(pbo_handles)])
{
qglGenBuffersARB(1, &pbo_handles[captureframe%countof(pbo_handles)]);
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[captureframe%countof(pbo_handles)]);
qglBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, imagesize, NULL, GL_STATIC_READ_ARB);
}
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[captureframe%countof(pbo_handles)]);
switch(pbo_format)
{
case TF_BGR24:
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_BGR_EXT, GL_UNSIGNED_BYTE, 0);
break;
case TF_BGRA32:
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
break;
case TF_RGB24:
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_RGB, GL_UNSIGNED_BYTE, 0);
break;
case TF_RGBA32:
qglReadPixels(0, 0, vid.fbpwidth, vid.fbpheight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
break;
}
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
}
else
Con_DPrintf("Unable to grab video image\n");
#endif
{
pbo_oldest = captureframe+1;
//submit the current video frame. audio will be mixed to match.
buffer = VID_GetRGBInfo(&truewidth, &trueheight, &fmt);
if (buffer)
{
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, captureframe, truewidth, trueheight, fmt);
BZ_Free (buffer);
}
else
{
Con_DPrintf("Unable to grab video image\n");
currentcapture_funcs->capture_video(currentcapture_ctx, NULL, captureframe, 0, 0, TF_INVALID);
}
}
captureframe++;
capturelastvideotime += captureframeinterval;
captureframeforce = false;
@ -3358,6 +3432,35 @@ void Media_InitFakeSoundDevice (int speed, int channels, int samplebits)
void Media_StopRecordFilm_f (void)
{
#ifdef GLQUAKE
if (pbo_format)
{
int i;
int imagesize = vid.fbpwidth * vid.fbpheight * 4;
while (pbo_oldest < captureframe)
{
qbyte *buffer;
qglBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pbo_handles[pbo_oldest%countof(pbo_handles)]);
buffer = qglMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
if (buffer)
{
currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, TF_BGR24);
// currentcapture_funcs->capture_video(currentcapture_ctx, buffer, pbo_oldest, vid.fbpwidth, vid.fbpheight, TF_BGRA32);
qglUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
}
pbo_oldest++;
}
for (i = 0; i < countof(pbo_handles); i++)
{
if (pbo_handles[i])
qglDeleteBuffersARB(1, &pbo_handles[i]);
pbo_handles[i] = 0;
}
}
#endif
if (capture_fakesounddevice)
S_ShutdownCard(capture_fakesounddevice);
capture_fakesounddevice = NULL;
@ -3401,7 +3504,7 @@ static void Media_RecordFilm (char *recordingname, qboolean demo)
Con_ClearNotify();
captureframe = 0;
captureframe = pbo_oldest = 0;
for (i = 0; i < sizeof(pluginencodersfunc)/sizeof(pluginencodersfunc[0]); i++)
{
if (pluginencodersfunc[i])
@ -3438,11 +3541,17 @@ static void Media_RecordFilm (char *recordingname, qboolean demo)
{
capturingfbo = true;
capturetexture = R2D_RT_Configure("$democapture", capturewidth.ival, captureheight.ival, TF_BGRA32);
captureoldfbo = GLBE_FBO_Update(&capturefbo, FBO_RB_DEPTH, &capturetexture, 1, r_nulltex, capturewidth.ival, captureheight.ival, 0);
captureoldfbo = GLBE_FBO_Update(&capturefbo, FBO_RB_DEPTH|(Sh_StencilShadowsActive()?FBO_RB_STENCIL:0), &capturetexture, 1, r_nulltex, capturewidth.ival, captureheight.ival, 0);
vid.fbpwidth = capturewidth.ival;
vid.fbpheight = captureheight.ival;
vid.framebuffer = capturetexture;
}
pbo_format = TF_INVALID;
if (qrenderer == QR_OPENGL && !gl_config.gles && gl_config.glversion >= 2.1)
{ //both tgas and vfw favour bgr24, so lets get the gl drivers to suffer instead of us.
pbo_format = TF_BGR24;
}
#endif
recordingdemo = demo;

View File

@ -101,7 +101,7 @@ extern void (*R_RenderView) (void); // must set r_refdef first
extern qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette);
extern void (*VID_DeInit) (void);
extern char *(*VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
extern char *(*VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt);
extern void (*VID_SetWindowCaption) (char *msg);
extern void SCR_Init (void);
@ -413,7 +413,7 @@ typedef struct rendererinfo_s {
void (*VID_DestroyCursor) (void *cursor); //may be null
void (*VID_SetWindowCaption) (char *msg);
char *(*VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
char *(*VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt);
void (*SCR_UpdateScreen) (void);

View File

@ -55,6 +55,9 @@ void QCBUILTIN PF_CL_drawfill (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
void QCBUILTIN PF_CL_drawsetcliparea (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
srect_t srect;
if (R2D_Flush)
R2D_Flush();
csqc_dp_lastwas3d = false;
srect.x = G_FLOAT(OFS_PARM0) / (float)vid.fbvwidth;
@ -71,6 +74,9 @@ void QCBUILTIN PF_CL_drawsetcliparea (pubprogfuncs_t *prinst, struct globalvars_
//void drawresetcliparea(void) = #459;
void QCBUILTIN PF_CL_drawresetcliparea (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
if (R2D_Flush)
R2D_Flush();
csqc_dp_lastwas3d = false;
BE_Scissor(NULL);

View File

@ -31,6 +31,7 @@ shader_t *shader_polyblend;
shader_t *shader_menutint;
#define DRAW_QUADS 128
static int draw_active_flags;
static shader_t *draw_active_shader;
static avec4_t draw_active_colour;
static mesh_t draw_mesh;
@ -576,7 +577,7 @@ void R2D_ImageAtlas(float x, float y, float w, float h, float s1, float t1, floa
void R2D_ImageFlush(void)
{
BE_DrawMesh_Single(draw_active_shader, &draw_mesh, NULL, r2d_be_flags);
BE_DrawMesh_Single(draw_active_shader, &draw_mesh, NULL, draw_active_flags);
R2D_Flush = NULL;
draw_active_shader = NULL;
@ -597,12 +598,13 @@ void R2D_Image(float x, float y, float w, float h, float s1, float t1, float s2,
return;
}
if (draw_active_shader != pic || draw_mesh.numvertexes+4 > DRAW_QUADS)
if (draw_active_shader != pic || draw_active_flags != r2d_be_flags || draw_mesh.numvertexes+4 > DRAW_QUADS)
{
if (R2D_Flush)
R2D_Flush();
draw_active_shader = pic;
draw_active_flags = r2d_be_flags;
R2D_Flush = R2D_ImageFlush;
draw_mesh.numindexes = 0;
@ -663,12 +665,13 @@ void R2D_FillBlock(float x, float y, float w, float h)
pic = shader_draw_fill_trans;
else
pic = shader_draw_fill;
if (draw_active_shader != pic || draw_mesh.numvertexes+4 > DRAW_QUADS)
if (draw_active_shader != pic || draw_active_flags != r2d_be_flags || draw_mesh.numvertexes+4 > DRAW_QUADS)
{
if (R2D_Flush)
R2D_Flush();
draw_active_shader = pic;
draw_active_flags = r2d_be_flags;
R2D_Flush = R2D_ImageFlush;
draw_mesh.numindexes = 0;

View File

@ -856,7 +856,7 @@ void (*R_RenderView) (void); // must set r_refdef first
qboolean (*VID_Init) (rendererstate_t *info, unsigned char *palette);
void (*VID_DeInit) (void);
char *(*VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
char *(*VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt);
void (*VID_SetWindowCaption) (char *msg);
void (*SCR_UpdateScreen) (void);

View File

@ -80,7 +80,8 @@ void SCR_ShowPic_Remove_f(void);
//a header is better than none...
void Draw_TextBox (int x, int y, int width, int lines);
enum fs_relative;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height);
enum uploadfmt;
qboolean SCR_ScreenShot (char *filename, enum fs_relative fsroot, void *rgb_buffer, int width, int height, enum uploadfmt fmt);
void SCR_DrawTwoDimensional(int uimenu, qboolean nohud);

View File

@ -110,6 +110,6 @@ int GLVID_SetMode (rendererstate_t *info, unsigned char *palette);
qboolean GLVID_Is8bit(void);
void GLVID_SwapBuffers(void);
char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight);
char *GLVID_GetRGBInfo(int *truewidth, int *trueheight, enum uploadfmt *fmt);
void GLVID_SetCaption(char *caption);
#endif

View File

@ -163,8 +163,9 @@ static qboolean Headless_VID_ApplyGammaRamps (unsigned short *ramps)
static void Headless_VID_SetWindowCaption (char *msg)
{
}
static char *Headless_VID_GetRGBInfo (int prepad, int *truevidwidth, int *truevidheight)
static char *Headless_VID_GetRGBInfo (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
{
*fmt = TF_INVALID;
*truevidwidth = *truevidheight = 0;
return NULL;
}

View File

@ -802,7 +802,7 @@ qboolean D3D9_VID_ApplyGammaRamps (unsigned short *ramps)
IDirect3DDevice9_SetGammaRamp(pD3DDev9, 0, D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP *)ramps);
return true;
}
static char *(D3D9_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight)
static char *(D3D9_VID_GetRGBInfo) (int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
{
IDirect3DSurface9 *backbuf, *surf;
D3DLOCKED_RECT rect;
@ -828,14 +828,16 @@ static char *(D3D9_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevi
if (!FAILED(IDirect3DDevice9_GetRenderTargetData(pD3DDev9, backbuf, surf)))
if (!FAILED(IDirect3DSurface9_LockRect(surf, &rect, NULL, D3DLOCK_NO_DIRTY_UPDATE|D3DLOCK_READONLY|D3DLOCK_NOSYSLOCK)))
{
ret = BZ_Malloc(prepad + desc.Width*desc.Height*3);
ret = BZ_Malloc(desc.Width*desc.Height*3);
if (ret)
{
*fmt = TF_RGB24;
// read surface rect and convert 32 bgra to 24 rgb and flip
c = prepad+desc.Width*desc.Height*3;
c = desc.Width*desc.Height*3;
p = (qbyte *)rect.pBits;
for (i=c-(3*desc.Width); i>=prepad; i-=(3*desc.Width))
for (i=c-(3*desc.Width); i>=0; i-=(3*desc.Width))
{
for (j=0; j<desc.Width; j++)
{
@ -1239,7 +1241,6 @@ qboolean (D3D9_VID_Init) (rendererstate_t *info, unsigned char *palette);
void (D3D9_VID_DeInit) (void);
void (D3D9_VID_SetPalette) (unsigned char *palette);
void (D3D9_VID_ShiftPalette) (unsigned char *palette);
char *(D3D9_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight);
void (D3D9_VID_SetWindowCaption) (char *msg);
void (D3D9_SCR_UpdateScreen) (void);

View File

@ -1102,7 +1102,7 @@ static qboolean D3D11_VID_ApplyGammaRamps(unsigned short *ramps)
}
return false;
}
static char *D3D11_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidheight)
static char *D3D11_VID_GetRGBInfo(int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
{
//don't directly map the frontbuffer, as that can hold other things.
//create a texture, copy the (gpu)backbuffer to that (cpu)texture
@ -1132,8 +1132,7 @@ static char *D3D11_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidhei
ID3D11Resource_Release(backbuffer);
if (!FAILED(ID3D11DeviceContext_Map(d3ddevctx, (ID3D11Resource*)texture, 0, D3D11_MAP_READ, 0, &lock)))
{
r = rgb = BZ_Malloc(prepad + 3 * vid.pixelwidth * vid.pixelheight);
r += prepad;
r = rgb = BZ_Malloc(3 * vid.pixelwidth * vid.pixelheight);
for (y = vid.pixelheight; y-- > 0; )
{
in = lock.pData;
@ -1150,6 +1149,7 @@ static char *D3D11_VID_GetRGBInfo(int prepad, int *truevidwidth, int *truevidhei
ID3D11Texture2D_Release(texture);
*truevidwidth = vid.pixelwidth;
*truevidheight = vid.pixelheight;
*fmt = TF_RGB24;
return r;
}
static void (D3D11_VID_SetWindowCaption) (char *msg)

View File

@ -28,6 +28,7 @@ int Font_LineBreaks(conchar_t *start, conchar_t *end, int maxpixelwidth, int max
struct font_s *font_default;
struct font_s *font_console;
struct font_s *font_tiny;
static int font_be_flags;
extern unsigned int r2d_be_flags;
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
@ -409,10 +410,10 @@ static void Font_Flush(void)
font_backmesh.numvertexes = font_foremesh.numvertexes;
font_backmesh.istrifan = font_foremesh.istrifan;
BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, r2d_be_flags);
BE_DrawMesh_Single(fontplanes.backshader, &font_backmesh, NULL, font_be_flags);
}
TEXASSIGN(fontplanes.shader->defaulttextures->base, font_texture);
BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, r2d_be_flags);
BE_DrawMesh_Single(fontplanes.shader, &font_foremesh, NULL, font_be_flags);
font_foremesh.numindexes = 0;
font_foremesh.numvertexes = 0;
}
@ -1523,10 +1524,10 @@ void Font_Free(struct font_s *f)
//maps a given virtual screen coord to a pixel coord, which matches the font's height/width values
void Font_BeginString(struct font_s *font, float vx, float vy, int *px, int *py)
{
if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font))
if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font || font_be_flags != r2d_be_flags))
R2D_Flush();
R2D_Flush = Font_Flush;
font_be_flags = r2d_be_flags;
curfont = font;
*px = (vx*(int)vid.rotpixelwidth) / (float)vid.width;
*py = (vy*(int)vid.rotpixelheight) / (float)vid.height;
@ -1544,10 +1545,10 @@ void Font_Transform(float vx, float vy, int *px, int *py)
}
void Font_BeginScaledString(struct font_s *font, float vx, float vy, float szx, float szy, float *px, float *py)
{
if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font))
if (R2D_Flush && (R2D_Flush != Font_Flush || curfont != font || font_be_flags != r2d_be_flags))
R2D_Flush();
R2D_Flush = Font_Flush;
font_be_flags = r2d_be_flags;
curfont = font;
*px = (vx*(float)vid.rotpixelwidth) / (float)vid.width;
*py = (vy*(float)vid.rotpixelheight) / (float)vid.height;

View File

@ -243,7 +243,7 @@ void GLSCR_UpdateScreen (void)
}
char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
char *GLVID_GetRGBInfo(int *truewidth, int *trueheight, enum uploadfmt *fmt)
{ //returns a BZ_Malloced array
extern qboolean gammaworks;
int i, c;
@ -259,14 +259,14 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
p = BZ_Malloc(vid.pixelwidth*vid.pixelheight*sizeof(float));
qglReadPixels (0, 0, vid.pixelwidth, vid.pixelheight, GL_DEPTH_COMPONENT, GL_FLOAT, p);
ret = BZ_Malloc(prepadbytes + vid.pixelwidth*vid.pixelheight*3);
ret = BZ_Malloc(vid.pixelwidth*vid.pixelheight*3);
c = vid.pixelwidth*vid.pixelheight;
for (i = 1; i < c; i++)
{
ret[prepadbytes+i*3+0]=p[i]*p[i]*p[i]*255;
ret[prepadbytes+i*3+1]=p[i]*p[i]*p[i]*255;
ret[prepadbytes+i*3+2]=p[i]*p[i]*p[i]*255;
ret[i*3+0]=p[i]*p[i]*p[i]*255;
ret[i*3+1]=p[i]*p[i]*p[i]*255;
ret[i*3+2]=p[i]*p[i]*p[i]*255;
}
BZ_Free(p);
}
@ -274,30 +274,46 @@ char *GLVID_GetRGBInfo(int prepadbytes, int *truewidth, int *trueheight)
{
qbyte *p;
// gles only guarantees GL_RGBA/GL_UNSIGNED_BYTE so downconvert and resize
ret = BZ_Malloc(prepadbytes + (*truewidth)*(*trueheight)*4);
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGBA, GL_UNSIGNED_BYTE, ret + prepadbytes);
//gles:
//Only two format/type parameter pairs are accepted.
//GL_RGBA/GL_UNSIGNED_BYTE is always accepted, and the other acceptable pair can be discovered by querying GL_IMPLEMENTATION_COLOR_READ_FORMAT and GL_IMPLEMENTATION_COLOR_READ_TYPE.
//thus its simpler to only use GL_RGBA/GL_UNSIGNED_BYTE
//desktopgl:
//total line byte length must be aligned to GL_PACK_ALIGNMENT. by reading rgba instead of rgb, we can ensure the line is a multiple of 4 bytes.
ret = BZ_Malloc((*truewidth)*(*trueheight)*4);
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGBA, GL_UNSIGNED_BYTE, ret);
*fmt = TF_RGB24;
c = (*truewidth)*(*trueheight);
p = ret + prepadbytes;
p = ret;
for (i = 1; i < c; i++)
{
p[i*3+0]=p[i*4+0];
p[i*3+1]=p[i*4+1];
p[i*3+2]=p[i*4+2];
}
ret = BZ_Realloc(ret, prepadbytes + (*truewidth)*(*trueheight)*3);
ret = BZ_Realloc(ret, (*truewidth)*(*trueheight)*3);
}
#ifdef _DEBUG
else if (!gl_config.gles && gl_config.glversion >= 1.2)
{
*fmt = TF_BGRA32;
ret = BZ_Malloc((*truewidth)*(*trueheight)*4);
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_BGRA_EXT, GL_UNSIGNED_INT_8_8_8_8_REV, ret);
}
#endif
else
{
ret = BZ_Malloc(prepadbytes + (*truewidth)*(*trueheight)*3);
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGB, GL_UNSIGNED_BYTE, ret + prepadbytes);
*fmt = TF_RGB24;
ret = BZ_Malloc((*truewidth)*(*trueheight)*3);
qglReadPixels (0, 0, (*truewidth), (*trueheight), GL_RGB, GL_UNSIGNED_BYTE, ret);
}
if (gammaworks)
{
c = prepadbytes+(*truewidth)*(*trueheight)*3;
for (i=prepadbytes ; i<c ; i+=3)
c = (*truewidth)*(*trueheight)*3;
for (i=0 ; i<c ; i+=3)
{
extern qbyte gammatable[256];
ret[i+0] = gammatable[ret[i+0]];

View File

@ -612,6 +612,10 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
#define GL_FRAMEBUFFER_SRGB 0x8DB9
#endif
#ifndef GL_ARB_pixel_buffer_object
#define GL_PIXEL_PACK_BUFFER_ARB 0x88EB
#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
#endif
#ifndef GL_ARB_vertex_buffer_object
#define GL_BUFFER_SIZE_ARB 0x8764

View File

@ -1221,10 +1221,11 @@ void SV_Savegame (char *savename)
//okay, we drew something, we're good to save a screeny.
if (okay)
{
rgbbuffer = VID_GetRGBInfo(0, &width, &height);
enum uploadfmt fmt;
rgbbuffer = VID_GetRGBInfo(&width, &height, &fmt);
if (rgbbuffer)
{
SCR_ScreenShot(savefilename, FS_GAMEONLY, rgbbuffer, width, height);
SCR_ScreenShot(savefilename, FS_GAMEONLY, rgbbuffer, width, height, fmt);
BZ_Free(rgbbuffer);

View File

@ -115,20 +115,38 @@ void close_video(struct encctx *ctx)
}
av_free(ctx->video_outbuf);
}
static void AVEnc_Video (void *vctx, void *data, int frame, int width, int height)
static void AVEnc_Video (void *vctx, void *data, int frame, int width, int height, enum uploadfmt qpfmt)
{
struct encctx *ctx = vctx;
//weird maths to flip it.
const uint8_t *srcslices[2] = {(uint8_t*)data + (height-1)*width*3, NULL};
int srcstride[2] = {-width*3, 0};
const uint8_t *srcslices[2];
int srcstride[2];
int success;
AVPacket pkt;
int avpfmt;
int inbpp;
if (!ctx->video_st)
return;
switch(qpfmt)
{
case TF_BGRA32: avpfmt = AV_PIX_FMT_BGRA; inbpp = 4; break;
case TF_RGBA32: avpfmt = AV_PIX_FMT_RGBA; inbpp = 4; break;
case TF_BGR24: avpfmt = AV_PIX_FMT_BGR24; inbpp = 3; break;
case TF_RGB24: avpfmt = AV_PIX_FMT_RGB24; inbpp = 3; break;
default:
return;
}
//weird maths to flip it.
srcslices[0] = (uint8_t*)data + (height-1)*width*inbpp;
srcstride[0] = -width*inbpp;
srcslices[1] = NULL;
srcstride[1] = 0;
//convert RGB to whatever the codec needs (ie: yuv...).
ctx->scale_ctx = sws_getCachedContext(ctx->scale_ctx, width, height, AV_PIX_FMT_RGB24, ctx->picture->width, ctx->picture->height, ctx->video_st->codec->pix_fmt, SWS_POINT, 0, 0, 0);
//also rescales, but only if the user resizes the video while recording. which is a stupid thing to do.
ctx->scale_ctx = sws_getCachedContext(ctx->scale_ctx, width, height, qpfmt, ctx->picture->width, ctx->picture->height, ctx->video_st->codec->pix_fmt, SWS_POINT, 0, 0, 0);
sws_scale(ctx->scale_ctx, srcslices, srcstride, 0, height, ctx->picture->data, ctx->picture->linesize);
av_init_packet(&pkt);