mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-12-31 12:13:16 +00:00
hwr2: integrate avrecorder with RHI and legacy GL
This commit is contained in:
parent
a19b476d3d
commit
98ce714614
15 changed files with 105 additions and 69 deletions
|
|
@ -1879,7 +1879,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
return false;
|
||||
}
|
||||
case CL_LOADFILES:
|
||||
if (CL_LoadServerFiles())
|
||||
if (CL_LoadServerFiles())
|
||||
cl_mode = CL_SETUPFILES;
|
||||
|
||||
break;
|
||||
|
|
@ -2021,8 +2021,10 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
|
|||
#endif
|
||||
}
|
||||
I_UpdateNoVsync(); // page flip or blit buffer
|
||||
if (moviemode)
|
||||
#ifdef HWRENDER
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
#endif
|
||||
S_UpdateSounds();
|
||||
S_UpdateClosedCaptions();
|
||||
}
|
||||
|
|
@ -2540,7 +2542,7 @@ void CL_ClearPlayer(INT32 playernum)
|
|||
if (gamestate == GS_LEVEL)
|
||||
{
|
||||
if (players[playernum].follower)
|
||||
{
|
||||
{
|
||||
K_RemoveFollower(&players[playernum]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -871,10 +871,10 @@ void D_SRB2Loop(void)
|
|||
D_Display();
|
||||
}
|
||||
|
||||
// Only take screenshots after drawing.
|
||||
if (moviemode)
|
||||
M_LegacySaveFrame();
|
||||
#ifdef HWRENDER
|
||||
// Only take screenshots after drawing.
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
if (rendermode == render_opengl && takescreenshot)
|
||||
M_DoLegacyGLScreenShot();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -437,8 +437,10 @@ void F_IntroTicker(void)
|
|||
#endif
|
||||
I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001
|
||||
|
||||
if (moviemode) // make sure we save frames for the white hold too
|
||||
#ifdef HWRENDER
|
||||
if (moviemode && rendermode == render_opengl) // make sure we save frames for the white hold too
|
||||
M_LegacySaveFrame();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -464,7 +466,7 @@ void F_IntroTicker(void)
|
|||
// check for skipping
|
||||
if (keypressed)
|
||||
keypressed = false;
|
||||
|
||||
|
||||
if (animtimer > 0)
|
||||
animtimer--;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -525,8 +525,10 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean r
|
|||
g_wipeskiprender = true;
|
||||
}
|
||||
|
||||
if (moviemode)
|
||||
#ifdef HWRENDER
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
#endif
|
||||
|
||||
NetKeepAlive(); // Update the network so we don't cause timeouts
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1601,8 +1601,10 @@ void G_PreLevelTitleCard(void)
|
|||
I_FinishUpdate(); // page flip or blit buffer
|
||||
NetKeepAlive(); // Prevent timeouts
|
||||
|
||||
if (moviemode)
|
||||
#ifdef HWRENDER
|
||||
if (moviemode && rendermode == render_opengl)
|
||||
M_LegacySaveFrame();
|
||||
#endif
|
||||
|
||||
while (!((nowtime = I_GetTime()) - lasttime))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ void ScreenshotPass::prepass(Rhi& rhi)
|
|||
);
|
||||
}
|
||||
|
||||
doing_screenshot_ = takescreenshot || moviemode == MM_GIF;
|
||||
doing_screenshot_ = takescreenshot || moviemode != MM_OFF;
|
||||
}
|
||||
|
||||
void ScreenshotPass::transfer(Rhi& rhi, Handle<TransferContext> ctx)
|
||||
|
|
@ -68,7 +68,7 @@ void ScreenshotPass::postpass(Rhi& rhi)
|
|||
M_DoScreenShot(width_, height_, tcb::as_bytes(tcb::span(pixel_data_)));
|
||||
}
|
||||
|
||||
if (moviemode == MM_GIF)
|
||||
if (moviemode != MM_OFF)
|
||||
{
|
||||
M_SaveFrame(width_, height_, tcb::as_bytes(tcb::span(pixel_data_)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ static InternalPassData build_pass_manager()
|
|||
framebuffer_manager->swap_post();
|
||||
pp_simple_blit_pass->set_texture(framebuffer_manager->main_color(), vid.width, vid.height);
|
||||
pp_simple_blit_pass
|
||||
->set_output(framebuffer_manager->current_post_color(), vid.width, vid.height, false, true);
|
||||
->set_output(framebuffer_manager->current_post_color(), vid.width, vid.height, false, false);
|
||||
}
|
||||
);
|
||||
basic_rendering->insert("pp_final_simple_blit", pp_simple_blit_pass);
|
||||
|
|
@ -211,7 +211,7 @@ static InternalPassData build_pass_manager()
|
|||
[final_composite_pass, framebuffer_manager](PassManager&, Rhi&)
|
||||
{
|
||||
final_composite_pass->set_texture(framebuffer_manager->current_post_color(), vid.width, vid.height);
|
||||
final_composite_pass->set_output(kNullHandle, vid.realwidth, vid.realheight, true, true);
|
||||
final_composite_pass->set_output(kNullHandle, vid.realwidth, vid.realheight, true, false);
|
||||
}
|
||||
);
|
||||
composite_present_rendering->insert("final_composite", final_composite_pass);
|
||||
|
|
@ -305,6 +305,14 @@ static InternalPassData build_pass_manager()
|
|||
}
|
||||
);
|
||||
wipe_rendering->insert("pp_final_wipe", pp_wipe_pass);
|
||||
wipe_rendering->insert(
|
||||
"screenshot_prepare",
|
||||
[screenshot_pass, framebuffer_manager](PassManager&, Rhi&)
|
||||
{
|
||||
screenshot_pass->set_source(framebuffer_manager->current_post_color(), vid.width, vid.height);
|
||||
}
|
||||
);
|
||||
wipe_rendering->insert("screenshot", screenshot_pass);
|
||||
wipe_rendering->insert("composite_present_rendering", composite_present_rendering);
|
||||
|
||||
InternalPassData ret;
|
||||
|
|
|
|||
|
|
@ -229,24 +229,3 @@ void M_AVRecorder_DrawFrameRate(void)
|
|||
|
||||
g_av_recorder->draw_statistics();
|
||||
}
|
||||
|
||||
// TODO: remove once hwr2 twodee is finished
|
||||
void M_AVRecorder_CopySoftwareScreen(void)
|
||||
{
|
||||
SRB2_ASSERT(g_av_recorder != nullptr);
|
||||
|
||||
auto frame = g_av_recorder->new_indexed_video_frame(vid.width, vid.height);
|
||||
|
||||
if (!frame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tcb::span<RGBA_t> pal(&pLocalPalette[std::max(st_palette, 0) * 256], 256);
|
||||
tcb::span<uint8_t> scr(screens[0], vid.width * vid.height);
|
||||
|
||||
std::copy(pal.begin(), pal.end(), frame->palette.begin());
|
||||
std::copy(scr.begin(), scr.end(), frame->screen.begin());
|
||||
|
||||
g_av_recorder->push_indexed_video_frame(std::move(frame));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ void M_AVRecorder_PrintCurrentConfiguration(void);
|
|||
|
||||
void M_AVRecorder_DrawFrameRate(void);
|
||||
|
||||
// TODO: remove once hwr2 twodee is finished
|
||||
void M_AVRecorder_CopySoftwareScreen(void);
|
||||
|
||||
extern consvar_t
|
||||
cv_movie_custom_resolution,
|
||||
cv_movie_duration,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
#include "m_anigif.h"
|
||||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||
#include "m_avrecorder.h"
|
||||
#include "m_avrecorder.hpp"
|
||||
#endif
|
||||
|
||||
// So that the screenshot menu auto-updates...
|
||||
|
|
@ -1384,6 +1385,8 @@ void M_StartMovie(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void M_SaveFrame_AVRecorder(uint32_t width, uint32_t height, tcb::span<const std::byte> data);
|
||||
|
||||
void M_LegacySaveFrame(void)
|
||||
{
|
||||
#if NUMSCREENS > 2
|
||||
|
|
@ -1402,17 +1405,11 @@ void M_LegacySaveFrame(void)
|
|||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||
if (moviemode == MM_AVRECORDER)
|
||||
{
|
||||
// TODO: replace once hwr2 twodee is finished
|
||||
if (rendermode == render_soft)
|
||||
{
|
||||
M_AVRecorder_CopySoftwareScreen();
|
||||
}
|
||||
|
||||
if (M_AVRecorder_IsExpired())
|
||||
{
|
||||
M_StopMovie();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1464,6 +1461,15 @@ void M_LegacySaveFrame(void)
|
|||
}
|
||||
#else
|
||||
moviemode = MM_OFF;
|
||||
#endif
|
||||
return;
|
||||
case MM_AVRECORDER:
|
||||
#if defined(SRB2_CONFIG_ENABLE_WEBM_MOVIES) && defined(HWRENDER)
|
||||
{
|
||||
UINT8 *linear = HWR_GetScreenshot();
|
||||
M_SaveFrame_AVRecorder(vid.width, vid.height, tcb::as_bytes(tcb::span(linear, 3 * vid.width * vid.height)));
|
||||
free(linear);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
default:
|
||||
|
|
@ -1472,7 +1478,7 @@ void M_LegacySaveFrame(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
void M_SaveFrame(uint32_t width, uint32_t height, tcb::span<const std::byte> data)
|
||||
static void M_SaveFrame_GIF(uint32_t width, uint32_t height, tcb::span<const std::byte> data)
|
||||
{
|
||||
if (moviemode != MM_GIF)
|
||||
{
|
||||
|
|
@ -1492,6 +1498,44 @@ void M_SaveFrame(uint32_t width, uint32_t height, tcb::span<const std::byte> dat
|
|||
GIF_frame_rgb24(width, height, reinterpret_cast<const uint8_t*>(data.data()));
|
||||
}
|
||||
|
||||
static void M_SaveFrame_AVRecorder(uint32_t width, uint32_t height, tcb::span<const std::byte> data)
|
||||
{
|
||||
#ifdef SRB2_CONFIG_ENABLE_WEBM_MOVIES
|
||||
if (M_AVRecorder_IsExpired())
|
||||
{
|
||||
M_StopMovie();
|
||||
return;
|
||||
}
|
||||
|
||||
auto frame = g_av_recorder->new_staging_video_frame(width, height);
|
||||
if (!frame)
|
||||
{
|
||||
// Not time to submit a frame!
|
||||
return;
|
||||
}
|
||||
|
||||
auto data_begin = reinterpret_cast<const uint8_t*>(data.data());
|
||||
auto data_end = reinterpret_cast<const uint8_t*>(data.data() + data.size_bytes());
|
||||
std::copy(data_begin, data_end, frame->screen.begin());
|
||||
g_av_recorder->push_staging_video_frame(std::move(frame));
|
||||
#endif
|
||||
}
|
||||
|
||||
void M_SaveFrame(uint32_t width, uint32_t height, tcb::span<const std::byte> data)
|
||||
{
|
||||
switch (moviemode)
|
||||
{
|
||||
case MM_GIF:
|
||||
M_SaveFrame_GIF(width, height, data);
|
||||
break;
|
||||
case MM_AVRECORDER:
|
||||
M_SaveFrame_AVRecorder(width, height, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void M_StopMovie(void)
|
||||
{
|
||||
#if NUMSCREENS > 2
|
||||
|
|
|
|||
|
|
@ -58,17 +58,16 @@ public:
|
|||
};
|
||||
|
||||
// TODO: remove once hwr2 twodee is finished
|
||||
struct IndexedVideoFrame
|
||||
struct StagingVideoFrame
|
||||
{
|
||||
using instance_t = std::unique_ptr<IndexedVideoFrame>;
|
||||
using instance_t = std::unique_ptr<StagingVideoFrame>;
|
||||
|
||||
std::array<RGBA_t, 256> palette;
|
||||
std::vector<uint8_t> screen;
|
||||
uint32_t width, height;
|
||||
int pts;
|
||||
|
||||
IndexedVideoFrame(uint32_t width_, uint32_t height_, int pts_) :
|
||||
screen(width_ * height_), width(width_), height(height_), pts(pts_)
|
||||
StagingVideoFrame(uint32_t width_, uint32_t height_, int pts_) :
|
||||
screen(width_ * height_ * 3), width(width_), height(height_), pts(pts_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
|
@ -87,9 +86,9 @@ public:
|
|||
|
||||
// May return nullptr in case called between units of
|
||||
// Config::frame_rate
|
||||
IndexedVideoFrame::instance_t new_indexed_video_frame(uint32_t width, uint32_t height);
|
||||
StagingVideoFrame::instance_t new_staging_video_frame(uint32_t width, uint32_t height);
|
||||
|
||||
void push_indexed_video_frame(IndexedVideoFrame::instance_t frame);
|
||||
void push_staging_video_frame(StagingVideoFrame::instance_t frame);
|
||||
|
||||
// Proper name of the container format.
|
||||
const char* format_name() const;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public:
|
|||
template <typename _>
|
||||
struct Traits<VideoEncoder, _>
|
||||
{
|
||||
using frame_type = IndexedVideoFrame::instance_t;
|
||||
using frame_type = StagingVideoFrame::instance_t;
|
||||
};
|
||||
|
||||
std::vector<typename Traits<T>::frame_type> vec_;
|
||||
|
|
@ -151,8 +151,7 @@ private:
|
|||
|
||||
void container_dtor_handler(const MediaContainer& container) const;
|
||||
|
||||
// TODO: remove once hwr2 twodee is finished
|
||||
VideoFrame::instance_t convert_indexed_video_frame(const IndexedVideoFrame& indexed);
|
||||
VideoFrame::instance_t convert_staging_video_frame(const StagingVideoFrame& indexed);
|
||||
};
|
||||
|
||||
template <>
|
||||
|
|
|
|||
|
|
@ -21,34 +21,36 @@ using namespace srb2::media;
|
|||
|
||||
using Impl = AVRecorder::Impl;
|
||||
|
||||
VideoFrame::instance_t Impl::convert_indexed_video_frame(const IndexedVideoFrame& indexed)
|
||||
VideoFrame::instance_t Impl::convert_staging_video_frame(const StagingVideoFrame& staging)
|
||||
{
|
||||
VideoFrame::instance_t frame = video_encoder_->new_frame(indexed.width, indexed.height, indexed.pts);
|
||||
VideoFrame::instance_t frame = video_encoder_->new_frame(staging.width, staging.height, staging.pts);
|
||||
|
||||
SRB2_ASSERT(frame != nullptr);
|
||||
|
||||
const VideoFrame::Buffer& buffer = frame->rgba_buffer();
|
||||
|
||||
const uint8_t* s = indexed.screen.data();
|
||||
const uint8_t* s = staging.screen.data();
|
||||
uint8_t* p = buffer.plane.data();
|
||||
|
||||
// Convert from RGB8 to RGBA8
|
||||
for (int y = 0; y < frame->height(); ++y)
|
||||
{
|
||||
for (int x = 0; x < frame->width(); ++x)
|
||||
{
|
||||
const RGBA_t& c = indexed.palette[s[x]];
|
||||
|
||||
reinterpret_cast<uint32_t*>(p)[x] = c.rgba;
|
||||
p[x * 4] = s[x * 3];
|
||||
p[x * 4 + 1] = s[x * 3 + 1];
|
||||
p[x * 4 + 2] = s[x * 3 + 2];
|
||||
p[x * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
s += indexed.width;
|
||||
s += staging.width * 3;
|
||||
p += buffer.row_stride;
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
AVRecorder::IndexedVideoFrame::instance_t AVRecorder::new_indexed_video_frame(uint32_t width, uint32_t height)
|
||||
AVRecorder::StagingVideoFrame::instance_t AVRecorder::new_staging_video_frame(uint32_t width, uint32_t height)
|
||||
{
|
||||
std::optional<int> pts = impl_->advance_video_pts();
|
||||
|
||||
|
|
@ -57,10 +59,10 @@ AVRecorder::IndexedVideoFrame::instance_t AVRecorder::new_indexed_video_frame(ui
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<IndexedVideoFrame>(width, height, *pts);
|
||||
return std::make_unique<StagingVideoFrame>(width, height, *pts);
|
||||
}
|
||||
|
||||
void AVRecorder::push_indexed_video_frame(IndexedVideoFrame::instance_t frame)
|
||||
void AVRecorder::push_staging_video_frame(StagingVideoFrame::instance_t frame)
|
||||
{
|
||||
auto _ = impl_->queue_guard();
|
||||
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ Impl::QueueState Impl::encode_queues()
|
|||
{
|
||||
for (auto& p : copy)
|
||||
{
|
||||
auto frame = convert_indexed_video_frame(*p);
|
||||
auto frame = convert_staging_video_frame(*p);
|
||||
|
||||
video_encoder_->encode(std::move(frame));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,7 +380,7 @@ void P_DeleteFlickies(INT16 i)
|
|||
static void P_ClearSingleMapHeaderInfo(INT16 num)
|
||||
{
|
||||
UINT8 i = 0;
|
||||
|
||||
|
||||
mapheaderinfo[num]->lvlttl[0] = '\0';
|
||||
mapheaderinfo[num]->subttl[0] = '\0';
|
||||
mapheaderinfo[num]->zonttl[0] = '\0';
|
||||
|
|
@ -7570,7 +7570,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
I_UpdateTime(cv_timescale.value); \
|
||||
} \
|
||||
lastwipetic = nowtime; \
|
||||
if (moviemode) \
|
||||
if (moviemode && rendermode == render_opengl) \
|
||||
M_LegacySaveFrame(); \
|
||||
NetKeepAlive(); \
|
||||
} \
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue