From 98ce7146149d170a13ed522226594a4926f706e9 Mon Sep 17 00:00:00 2001 From: Eidolon Date: Mon, 27 Feb 2023 19:49:45 -0600 Subject: [PATCH] hwr2: integrate avrecorder with RHI and legacy GL --- src/d_clisrv.c | 8 +++-- src/d_main.c | 6 ++-- src/f_finale.c | 6 ++-- src/f_wipe.c | 4 ++- src/g_game.c | 4 ++- src/hwr2/pass_screenshot.cpp | 4 +-- src/i_video_common.cpp | 12 +++++-- src/m_avrecorder.cpp | 21 ----------- src/m_avrecorder.h | 3 -- src/m_misc.cpp | 60 +++++++++++++++++++++++++++----- src/media/avrecorder.hpp | 13 ++++--- src/media/avrecorder_impl.hpp | 5 ++- src/media/avrecorder_indexed.cpp | 22 ++++++------ src/media/avrecorder_queue.cpp | 2 +- src/p_setup.c | 4 +-- 15 files changed, 105 insertions(+), 69 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index f251d0c9b..69d400866 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -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]); } diff --git a/src/d_main.c b/src/d_main.c index 5b21248c0..007071e88 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -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 diff --git a/src/f_finale.c b/src/f_finale.c index b78bc4139..49b5f31ce 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -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--; } diff --git a/src/f_wipe.c b/src/f_wipe.c index 1beb29506..2f0350cb7 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -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 } diff --git a/src/g_game.c b/src/g_game.c index ab9783b93..bf2c2761a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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)) { diff --git a/src/hwr2/pass_screenshot.cpp b/src/hwr2/pass_screenshot.cpp index b37409218..64ed1e4be 100644 --- a/src/hwr2/pass_screenshot.cpp +++ b/src/hwr2/pass_screenshot.cpp @@ -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 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_))); } diff --git a/src/i_video_common.cpp b/src/i_video_common.cpp index ef02a7643..ef76d1e58 100644 --- a/src/i_video_common.cpp +++ b/src/i_video_common.cpp @@ -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; diff --git a/src/m_avrecorder.cpp b/src/m_avrecorder.cpp index 7491fb195..7467e388d 100644 --- a/src/m_avrecorder.cpp +++ b/src/m_avrecorder.cpp @@ -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 pal(&pLocalPalette[std::max(st_palette, 0) * 256], 256); - tcb::span 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)); -} diff --git a/src/m_avrecorder.h b/src/m_avrecorder.h index 9cce8349c..21d635c5f 100644 --- a/src/m_avrecorder.h +++ b/src/m_avrecorder.h @@ -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, diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 9862fcf3f..0873a9777 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -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 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 data) +static void M_SaveFrame_GIF(uint32_t width, uint32_t height, tcb::span data) { if (moviemode != MM_GIF) { @@ -1492,6 +1498,44 @@ void M_SaveFrame(uint32_t width, uint32_t height, tcb::span dat GIF_frame_rgb24(width, height, reinterpret_cast(data.data())); } +static void M_SaveFrame_AVRecorder(uint32_t width, uint32_t height, tcb::span 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(data.data()); + auto data_end = reinterpret_cast(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 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 diff --git a/src/media/avrecorder.hpp b/src/media/avrecorder.hpp index fdee91b18..3f2cf684a 100644 --- a/src/media/avrecorder.hpp +++ b/src/media/avrecorder.hpp @@ -58,17 +58,16 @@ public: }; // TODO: remove once hwr2 twodee is finished - struct IndexedVideoFrame + struct StagingVideoFrame { - using instance_t = std::unique_ptr; + using instance_t = std::unique_ptr; - std::array palette; std::vector 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; diff --git a/src/media/avrecorder_impl.hpp b/src/media/avrecorder_impl.hpp index 3fab89df8..bc4338932 100644 --- a/src/media/avrecorder_impl.hpp +++ b/src/media/avrecorder_impl.hpp @@ -53,7 +53,7 @@ public: template struct Traits { - using frame_type = IndexedVideoFrame::instance_t; + using frame_type = StagingVideoFrame::instance_t; }; std::vector::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 <> diff --git a/src/media/avrecorder_indexed.cpp b/src/media/avrecorder_indexed.cpp index 31846b7da..f69008b85 100644 --- a/src/media/avrecorder_indexed.cpp +++ b/src/media/avrecorder_indexed.cpp @@ -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(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 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(width, height, *pts); + return std::make_unique(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(); diff --git a/src/media/avrecorder_queue.cpp b/src/media/avrecorder_queue.cpp index 4a94e1abe..f18c7b8fd 100644 --- a/src/media/avrecorder_queue.cpp +++ b/src/media/avrecorder_queue.cpp @@ -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)); } diff --git a/src/p_setup.c b/src/p_setup.c index a5140cbb2..6ae609536 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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(); \ } \