mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 04:21:51 +00:00
[renderer] Make screen capture support asynchronous operation
This fixes (*ahem*) the vulkan renderer segfaulting when attempting to take a screenshot. However, the image is upside down. Also, remote snapshots and demo capture are broken for the moment.
This commit is contained in:
parent
a29836cc2c
commit
acffacc59b
15 changed files with 183 additions and 266 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
glsl_main.c
|
||||
|
||||
GLSL rendering
|
||||
|
||||
Copyright (C) 2011 Bill Currie <bill@taniwha.org>
|
||||
|
||||
Author: Bill Currie <bill@taniwha.org>
|
||||
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 <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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 <stdlib.h>
|
||||
|
||||
#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;
|
||||
}
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue