diff --git a/include/QF/plugin/vid_render.h b/include/QF/plugin/vid_render.h index c0ad899c9..19ed1e394 100644 --- a/include/QF/plugin/vid_render.h +++ b/include/QF/plugin/vid_render.h @@ -76,6 +76,9 @@ typedef struct vid_model_funcs_s { void (*Skin_InitTranslations) (void); } vid_model_funcs_t; +struct tex_s; +typedef void (*capfunc_t) (struct tex_s *screencap, void *data); + typedef struct vid_render_funcs_s { void (*init) (void); void (*Draw_Character) (int x, int y, unsigned ch); @@ -99,7 +102,6 @@ typedef struct vid_render_funcs_s { void (*Draw_Picf) (float x, float y, qpic_t *pic); void (*Draw_SubPic) (int x, int y, qpic_t *pic, int srcx, int srcy, int width, int height); - struct tex_s *(*SCR_CaptureBGR) (void); struct psystem_s *(*ParticleSystem) (void); void (*R_Init) (void); @@ -124,6 +126,8 @@ typedef struct vid_render_funcs_s { // x and y are tan(f/2) for fov_x and fov_y void (*set_fov) (float x, float y); + void (*capture_screen) (capfunc_t callback, void *data); + vid_model_funcs_t *model_funcs; } vid_render_funcs_t; diff --git a/include/vid_gl.h b/include/vid_gl.h index 6249790dd..c073837bc 100644 --- a/include/vid_gl.h +++ b/include/vid_gl.h @@ -32,9 +32,6 @@ typedef struct gl_framebuffer_s { extern gl_ctx_t *gl_ctx; extern gl_ctx_t *glsl_ctx; -struct tex_s *gl_SCR_CaptureBGR (void); -struct tex_s *glsl_SCR_CaptureBGR (void); - void gl_Fog_SetupFrame (void); void gl_Fog_EnableGFog (void); void gl_Fog_DisableGFog (void); diff --git a/include/vid_sw.h b/include/vid_sw.h index ed2f21a1a..913052242 100644 --- a/include/vid_sw.h +++ b/include/vid_sw.h @@ -20,6 +20,4 @@ typedef struct sw_framebuffer_s { extern sw_ctx_t *sw_ctx; -struct tex_s *sw_SCR_CaptureBGR (void); - #endif//__vid_sw_h diff --git a/include/vid_vulkan.h b/include/vid_vulkan.h index 66d394181..56aa8c3f3 100644 --- a/include/vid_vulkan.h +++ b/include/vid_vulkan.h @@ -79,6 +79,9 @@ typedef struct vulkan_ctx_s { struct qfv_capture_s *capture; void (*capture_callback) (const byte *data, int width, int height); + // make a queue? + void *capture_complete;// really capfunc_t + void *capture_complete_data; struct qfv_tex_s *default_black; struct qfv_tex_s *default_white; diff --git a/libs/video/renderer/Makemodule.am b/libs/video/renderer/Makemodule.am index c19d5bcdb..bc48a77e2 100644 --- a/libs/video/renderer/Makemodule.am +++ b/libs/video/renderer/Makemodule.am @@ -80,7 +80,6 @@ libs_video_renderer_librender_gl_la_SOURCES = \ libs/video/renderer/gl/gl_rmain.c \ libs/video/renderer/gl/gl_rmisc.c \ libs/video/renderer/gl/gl_rsurf.c \ - libs/video/renderer/gl/gl_screen.c \ libs/video/renderer/gl/gl_sky.c \ libs/video/renderer/gl/gl_sky_clip.c \ libs/video/renderer/gl/gl_textures.c \ @@ -116,7 +115,6 @@ libs_video_renderer_librender_glsl_la_SOURCES = \ libs/video/renderer/glsl/glsl_lightmap.c \ libs/video/renderer/glsl/glsl_main.c \ libs/video/renderer/glsl/glsl_particles.c \ - libs/video/renderer/glsl/glsl_screen.c \ libs/video/renderer/glsl/glsl_shader.c \ libs/video/renderer/glsl/glsl_sprite.c \ libs/video/renderer/glsl/glsl_textures.c \ @@ -158,7 +156,6 @@ libs_video_renderer_librender_sw_la_SOURCES = \ libs/video/renderer/sw/fpu.c \ libs/video/renderer/sw/fpua.S \ libs/video/renderer/sw/nonintel.c \ - libs/video/renderer/sw/screen.c \ libs/video/renderer/sw/surf8.S \ libs/video/renderer/sw/sw_fisheye.c \ libs/video/renderer/sw/sw_graph.c \ diff --git a/libs/video/renderer/gl/gl_screen.c b/libs/video/renderer/gl/gl_screen.c deleted file mode 100644 index 8bd6c462d..000000000 --- a/libs/video/renderer/gl/gl_screen.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - gl_screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "QF/GL/defines.h" -#include "QF/GL/funcs.h" -#include "QF/GL/qf_rmain.h" - -#include "r_internal.h" -#include "vid_gl.h" - -/* SCREEN SHOTS */ - -tex_t * -gl_SCR_CaptureBGR (void) -{ - int count; - tex_t *tex; - - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; - tex->format = tex_rgb; - tex->palette = 0; - qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT, - GL_UNSIGNED_BYTE, tex->data); - return tex; -} diff --git a/libs/video/renderer/glsl/glsl_screen.c b/libs/video/renderer/glsl/glsl_screen.c deleted file mode 100644 index 4848b9018..000000000 --- a/libs/video/renderer/glsl/glsl_screen.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - glsl_main.c - - GLSL rendering - - Copyright (C) 2011 Bill Currie - - Author: Bill Currie - Date: 2011/12/23 - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "QF/GLSL/defines.h" -#include "QF/GLSL/funcs.h" - -#include "r_internal.h" -#include "vid_gl.h" - -tex_t * -glsl_SCR_CaptureBGR (void) -{ - byte *r, *b; - int count, i; - tex_t *tex; - - count = vid.width * vid.height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = vid.width; - tex->height = vid.height; - tex->format = tex_rgb; - tex->palette = 0; - qfeglReadPixels (0, 0, vid.width, vid.height, GL_RGB, - GL_UNSIGNED_BYTE, tex->data); - for (i = 0, r = tex->data, b = tex->data + 2; i < count; - i++, r += 3, b += 3) { - byte t = *b; - *b = *r; - *r = t; - } - return tex; -} diff --git a/libs/video/renderer/r_screen.c b/libs/video/renderer/r_screen.c index d9380affd..31ebcbf0d 100644 --- a/libs/video/renderer/r_screen.c +++ b/libs/video/renderer/r_screen.c @@ -357,6 +357,28 @@ SCR_SetBottomMargin (int lines) update_vrect (); } +typedef struct scr_capture_s { + dstring_t *name; + QFile *file; +} scr_capture_t; + +static void +scr_write_caputre (tex_t *tex, void *data) +{ + scr_capture_t *cap = data; + + if (tex) { + WritePNG (cap->file, tex->data, tex->width, tex->height); + free (tex); + Sys_Printf ("Wrote %s/%s\n", qfs_userpath, cap->name->str); + } else { + Sys_Printf ("Capture failed\n"); + } + Qclose (cap->file); + dstring_delete (cap->name); + free (cap); +} + static void ScreenShot_f (void) { @@ -368,16 +390,13 @@ ScreenShot_f (void) ".png"))) { Sys_Printf ("SCR_ScreenShot_f: Couldn't create a PNG file: %s\n", name->str); + dstring_delete (name); } else { - tex_t *tex; - - tex = r_funcs->SCR_CaptureBGR (); - WritePNG (file, tex->data, tex->width, tex->height); - free (tex); - Qclose (file); - Sys_Printf ("Wrote %s/%s\n", qfs_userpath, name->str); + scr_capture_t *cap = malloc (sizeof (scr_capture_t)); + cap->file = file; + cap->name = name; + r_funcs->capture_screen (scr_write_caputre, cap); } - dstring_delete (name); } /* @@ -463,6 +482,7 @@ SCR_DrawPause (void) /* Find closest color in the palette for named color */ +#if 0 static int MipColor (int r, int g, int b) { @@ -495,6 +515,7 @@ MipColor (int r, int g, int b) lastbest = best; return best; } +#endif // in draw.c @@ -542,6 +563,8 @@ SCR_DrawStringToSnap (const char *s, tex_t *tex, int x, int y) tex_t * SCR_SnapScreen (unsigned width, unsigned height) { + return 0; +#if 0 byte *src, *dest; float fracw, frach; unsigned count, dex, dey, dx, dy, nx, r, g, b, x, y, w, h; @@ -599,6 +622,7 @@ SCR_SnapScreen (unsigned width, unsigned height) free (snap); return tex; +#endif } static void diff --git a/libs/video/renderer/sw/screen.c b/libs/video/renderer/sw/screen.c deleted file mode 100644 index 543d831f1..000000000 --- a/libs/video/renderer/sw/screen.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - screen.c - - master for refresh, status bar, console, chat, notify, etc - - Copyright (C) 1996-1997 Id Software, Inc. - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - - Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA - -*/ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include "QF/image.h" -#include "QF/sys.h" - -#include "r_internal.h" -#include "vid_sw.h" - -/* SCREEN SHOTS */ - -tex_t * -sw_SCR_CaptureBGR (void) -{ - int count, x, y; - tex_t *tex; - const byte *src; - byte *dst; - framebuffer_t *fb = sw_ctx->framebuffer; - - count = fb->width * fb->height; - tex = malloc (sizeof (tex_t) + count * 3); - tex->data = (byte *) (tex + 1); - SYS_CHECKMEM (tex); - tex->width = fb->width; - tex->height = fb->height; - tex->format = tex_rgb; - tex->palette = 0; - src = ((sw_framebuffer_t *) fb->buffer)->color; - int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; - for (y = 0; y < tex->height; y++) { - dst = tex->data + (tex->height - 1 - y) * tex->width * 3; - for (x = 0; x < tex->width; x++) { - byte c = src[x]; - *dst++ = vid.basepal[c * 3 + 2]; // blue - *dst++ = vid.basepal[c * 3 + 1]; // green - *dst++ = vid.basepal[c * 3 + 0]; // red - } - src += rowbytes; - } - return tex; -} diff --git a/libs/video/renderer/vid_render_gl.c b/libs/video/renderer/vid_render_gl.c index 687f8765e..761854407 100644 --- a/libs/video/renderer/vid_render_gl.c +++ b/libs/video/renderer/vid_render_gl.c @@ -29,6 +29,7 @@ #endif #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -458,6 +459,26 @@ gl_set_fov (float x, float y) mmulf (gl_ctx->projection, depth_range, proj); } +static void +gl_capture_screen (capfunc_t callback, void *data) +{ + int count; + tex_t *tex; + + count = vid.width * vid.height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = vid.width; + tex->height = vid.height; + tex->format = tex_rgb; + tex->palette = 0; + qfglReadPixels (0, 0, tex->width, tex->height, GL_BGR_EXT, + GL_UNSIGNED_BYTE, tex->data); + } + callback (tex, data); +} + vid_render_funcs_t gl_vid_render_funcs = { gl_vid_render_init, gl_Draw_Character, @@ -481,8 +502,6 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_Draw_Picf, gl_Draw_SubPic, - gl_SCR_CaptureBGR, - gl_ParticleSystem, gl_R_Init, gl_R_ClearState, @@ -504,6 +523,8 @@ vid_render_funcs_t gl_vid_render_funcs = { gl_set_viewport, gl_set_fov, + gl_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_glsl.c b/libs/video/renderer/vid_render_glsl.c index 669cedab9..1860f2ba7 100644 --- a/libs/video/renderer/vid_render_glsl.c +++ b/libs/video/renderer/vid_render_glsl.c @@ -29,6 +29,7 @@ #endif #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -405,6 +406,35 @@ glsl_set_fov (float x, float y) mmulf (glsl_ctx->projection, depth_range, proj); } +static void +glsl_capture_screen (capfunc_t callback, void *data) +{ + byte *r, *b; + int count, i; + tex_t *tex; + + count = vid.width * vid.height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = vid.width; + tex->height = vid.height; + tex->format = tex_rgb; + tex->palette = 0; + qfeglReadPixels (0, 0, tex->width, tex->height, GL_RGB, + GL_UNSIGNED_BYTE, tex->data); + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back + for (i = 0, r = tex->data, b = tex->data + 2; i < count; + i++, r+= 3, b += 3) { + byte t = *b; + *b = *r; + *r = t; + } + } + callback (tex, data); +} + vid_render_funcs_t glsl_vid_render_funcs = { glsl_vid_render_init, glsl_Draw_Character, @@ -428,8 +458,6 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_Draw_Picf, glsl_Draw_SubPic, - glsl_SCR_CaptureBGR, - glsl_ParticleSystem, glsl_R_Init, glsl_R_ClearState, @@ -451,6 +479,8 @@ vid_render_funcs_t glsl_vid_render_funcs = { glsl_set_viewport, glsl_set_fov, + glsl_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_sw.c b/libs/video/renderer/vid_render_sw.c index 23a920a36..43c1dfc1d 100644 --- a/libs/video/renderer/vid_render_sw.c +++ b/libs/video/renderer/vid_render_sw.c @@ -31,6 +31,7 @@ #include #include "QF/cvar.h" +#include "QF/image.h" #include "QF/plugin/general.h" #include "QF/plugin/vid_render.h" @@ -411,6 +412,41 @@ sw_set_fov (float x, float y) r_resfudge = r_aliastransadj->value * res_scale; } +static void +sw_capture_screen (capfunc_t callback, void *data) +{ + int count, x, y; + tex_t *tex; + const byte *src; + byte *dst; + framebuffer_t *fb = sw_ctx->framebuffer; + + count = fb->width * fb->height; + tex = malloc (sizeof (tex_t) + count * 3); + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = fb->width; + tex->height = fb->height; + tex->format = tex_rgb; + tex->palette = 0; + src = ((sw_framebuffer_t *) fb->buffer)->color; + int rowbytes = ((sw_framebuffer_t *) fb->buffer)->rowbytes; + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back + for (y = 0; y < tex->height; y++) { + dst = tex->data + (tex->height - 1 - y) * tex->width * 3; + for (x = 0; x < tex->width; x++) { + byte c = src[x]; + *dst++ = vid.basepal[c * 3 + 2]; // blue + *dst++ = vid.basepal[c * 3 + 1]; // green + *dst++ = vid.basepal[c * 3 + 0]; // red + } + src += rowbytes; + } + } + callback (tex, data); +} + vid_render_funcs_t sw_vid_render_funcs = { sw_vid_render_init, Draw_Character, @@ -434,8 +470,6 @@ vid_render_funcs_t sw_vid_render_funcs = { Draw_Picf, Draw_SubPic, - sw_SCR_CaptureBGR, - sw_ParticleSystem, sw_R_Init, R_ClearState, @@ -457,6 +491,8 @@ vid_render_funcs_t sw_vid_render_funcs = { sw_set_viewport, sw_set_fov, + sw_capture_screen, + &model_funcs }; diff --git a/libs/video/renderer/vid_render_vulkan.c b/libs/video/renderer/vid_render_vulkan.c index 0a8c786ab..5cb1acf5c 100644 --- a/libs/video/renderer/vid_render_vulkan.c +++ b/libs/video/renderer/vid_render_vulkan.c @@ -462,60 +462,69 @@ vulkan_set_fov (float x, float y) mctx->dirty = mctx->frames.size; } -#if 0 + static int is_bgr (VkFormat format) { return (format >= VK_FORMAT_B8G8R8A8_UNORM && format <= VK_FORMAT_B8G8R8A8_SRGB); } -#endif + static void capture_screenshot (const byte *data, int width, int height) { -#if 0 - dstring_t *name = dstring_new (); - // find a file name to save it to - if (!QFS_NextFilename (name, va (vulkan_ctx->va_ctx, "%s/qf", - qfs_gamedir->dir.shots), - ".ppm")) { - Sys_Printf ("SCR_ScreenShot_f: Couldn't create a ppm file\n"); - } else { - QFile *file = QFS_Open (name->str, "wb"); - if (!file) { - Sys_Printf ("Couldn't open %s\n", name->str); - } else { - Qprintf (file, "P6\n%d\n%d\n255\n", width, height); - if (vulkan_ctx->capture->canBlit || - !is_bgr (vulkan_ctx->swapchain->format)) { - for (int count = width * height; count-- > 0; ) { - Qwrite (file, data, 3); - data += 4; - } - } else { - for (int count = width * height; count-- > 0; ) { - byte rgb[] = { data[2], data[1], data[0] }; - Qwrite (file, rgb, 3); - data += 4; - } + int count = width * height; + tex_t *tex = malloc (sizeof (tex_t) + count * 3); + + if (tex) { + tex->data = (byte *) (tex + 1); + tex->width = width; + tex->height = height; + tex->format = tex_rgb; + tex->palette = 0; + + //FIXME shouldn't have to swap between rgb and bgr since WritePNG + //swaps back (ie, it can work with either) + //can it auto-convert RGBA to RGB? + if (!vulkan_ctx->capture->canBlit || + is_bgr (vulkan_ctx->swapchain->format)) { + const byte *src = data; + byte *dst = tex->data; + for (int count = width * height; count-- > 0; ) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; + } + } else { + const byte *src = data; + byte *dst = tex->data; + for (int count = width * height; count-- > 0; ) { + byte r = *src++; + byte g = *src++; + byte b = *src++; + *dst++ = b; + *dst++ = g; + *dst++ = r; + src++; } - Qclose (file); } } - dstring_delete (name); -#endif + capfunc_t callback = vulkan_ctx->capture_complete; + callback (tex, vulkan_ctx->capture_complete_data);; } -static tex_t * -vulkan_SCR_CaptureBGR (void) +static void +vulkan_capture_screen (capfunc_t callback, void *data) { if (!vulkan_ctx->capture) { Sys_Printf ("Capture not supported\n"); - return 0; + callback (0, data); + return; } vulkan_ctx->capture_callback = capture_screenshot; - //FIXME async process - return 0; + vulkan_ctx->capture_complete = callback; + vulkan_ctx->capture_complete_data = data; } static void @@ -727,8 +736,6 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_Draw_Picf, vulkan_Draw_SubPic, - vulkan_SCR_CaptureBGR, - vulkan_ParticleSystem, vulkan_R_Init, vulkan_R_ClearState, @@ -750,6 +757,8 @@ vid_render_funcs_t vulkan_vid_render_funcs = { vulkan_set_viewport, vulkan_set_fov, + vulkan_capture_screen, + &model_funcs }; diff --git a/nq/source/host.c b/nq/source/host.c index 6b17ddc12..b34feedde 100644 --- a/nq/source/host.c +++ b/nq/source/host.c @@ -699,7 +699,7 @@ _Host_Frame (float time) Host_ClientFrame (); else host_time += host_frametime; //FIXME is this needed? vcr stuff - +#if 0 if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); QFile *file = Qopen (va (0, "%s/qfmv%06d.png", @@ -711,7 +711,7 @@ _Host_Frame (float time) } free (tex); } - +#endif host_framecount++; fps_count++; } diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index f0207396c..ea89cb825 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -1749,7 +1749,7 @@ Host_Frame (float time) Sys_Printf ("%3i tot %3i server %3i gfx %3i snd\n", pass1 + pass2 + pass3, pass1, pass2, pass3); } - +#if 0 if (cls.demo_capture) { tex_t *tex = r_funcs->SCR_CaptureBGR (); QFile *file = Qopen (va (0, "%s/qfmv%06d.png", @@ -1761,7 +1761,7 @@ Host_Frame (float time) } free (tex); } - +#endif host_framecount++; fps_count++; }