Refactor software renderer (#6621)

This commit is contained in:
GPUCode 2023-06-24 01:59:18 +03:00 committed by GitHub
parent 7198243319
commit 9b82de6b24
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 1815 additions and 1796 deletions

View file

@ -344,11 +344,14 @@ int main(int argc, char** argv) {
return -1;
}
auto& system = Core::System::GetInstance();
auto& movie = Core::Movie::GetInstance();
if (!movie_record.empty()) {
Core::Movie::GetInstance().PrepareForRecording();
movie.PrepareForRecording();
}
if (!movie_play.empty()) {
Core::Movie::GetInstance().PrepareForPlayback(movie_play);
movie.PrepareForPlayback(movie_play);
}
// Apply the command line arguments
@ -361,13 +364,13 @@ int main(int argc, char** argv) {
EmuWindow_SDL2::InitializeSDL2();
const auto create_emu_window = [](bool fullscreen,
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
const auto create_emu_window = [&](bool fullscreen,
bool is_secondary) -> std::unique_ptr<EmuWindow_SDL2> {
switch (Settings::values.graphics_api.GetValue()) {
case Settings::GraphicsAPI::OpenGL:
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
case Settings::GraphicsAPI::Software:
return std::make_unique<EmuWindow_SDL2_SW>(fullscreen, is_secondary);
return std::make_unique<EmuWindow_SDL2_SW>(system, fullscreen, is_secondary);
}
LOG_ERROR(Frontend, "Invalid Graphics API, using OpenGL");
return std::make_unique<EmuWindow_SDL2_GL>(fullscreen, is_secondary);
@ -385,7 +388,6 @@ int main(int argc, char** argv) {
Common::g_scm_desc);
Settings::LogSettings();
Core::System& system = Core::System::GetInstance();
const Core::System::ResultStatus load_result{
system.Load(*emu_window, filepath, secondary_window.get())};
@ -437,21 +439,21 @@ int main(int argc, char** argv) {
}
if (!movie_play.empty()) {
auto metadata = Core::Movie::GetInstance().GetMovieMetadata(movie_play);
auto metadata = movie.GetMovieMetadata(movie_play);
LOG_INFO(Movie, "Author: {}", metadata.author);
LOG_INFO(Movie, "Rerecord count: {}", metadata.rerecord_count);
LOG_INFO(Movie, "Input count: {}", metadata.input_count);
Core::Movie::GetInstance().StartPlayback(movie_play);
movie.StartPlayback(movie_play);
}
if (!movie_record.empty()) {
Core::Movie::GetInstance().StartRecording(movie_record, movie_record_author);
movie.StartRecording(movie_record, movie_record_author);
}
if (!dump_video.empty() && DynamicLibrary::FFmpeg::LoadFFmpeg()) {
Layout::FramebufferLayout layout{Layout::FrameLayoutFromResolutionScale(
VideoCore::g_renderer->GetResolutionScaleFactor())};
const auto layout{
Layout::FrameLayoutFromResolutionScale(system.Renderer().GetResolutionScaleFactor())};
auto dumper = std::make_shared<VideoDumper::FFmpegBackend>();
if (dumper->StartDumping(dump_video, layout)) {
Core::System::GetInstance().RegisterVideoDumper(dumper);
system.RegisterVideoDumper(dumper);
}
}
@ -494,7 +496,7 @@ int main(int argc, char** argv) {
main_render_thread.join();
secondary_render_thread.join();
Core::Movie::GetInstance().Shutdown();
movie.Shutdown();
auto video_dumper = system.GetVideoDumper();
if (video_dumper && video_dumper->IsDumping()) {

View file

@ -9,18 +9,16 @@
#include <SDL.h>
#include <SDL_rect.h>
#include "citra/emu_window/emu_window_sdl2_sw.h"
#include "common/color.h"
#include "common/scm_rev.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/frontend/emu_window.h"
#include "core/hw/gpu.h"
#include "core/memory.h"
#include "video_core/video_core.h"
#include "video_core/renderer_software/renderer_software.h"
class DummyContext : public Frontend::GraphicsContext {};
EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{is_secondary} {
EmuWindow_SDL2_SW::EmuWindow_SDL2_SW(Core::System& system_, bool fullscreen, bool is_secondary)
: EmuWindow_SDL2{is_secondary}, system{system_} {
std::string window_title = fmt::format("Citra {} | {}-{}", Common::g_build_fullname,
Common::g_scm_branch, Common::g_scm_desc);
render_window =
@ -67,6 +65,8 @@ void EmuWindow_SDL2_SW::Present() {
const auto layout{Layout::DefaultFrameLayout(
Core::kScreenTopWidth, Core::kScreenTopHeight + Core::kScreenBottomHeight, false, false)};
using VideoCore::ScreenId;
while (IsOpen()) {
SDL_SetRenderDrawColor(renderer,
static_cast<Uint8>(Settings::values.bg_red.GetValue() * 255),
@ -74,62 +74,34 @@ void EmuWindow_SDL2_SW::Present() {
static_cast<Uint8>(Settings::values.bg_blue.GetValue() * 255), 0xFF);
SDL_RenderClear(renderer);
const auto draw_screen = [&](int fb_id) {
const auto dst_rect = fb_id == 0 ? layout.top_screen : layout.bottom_screen;
const auto draw_screen = [&](ScreenId screen_id) {
const auto dst_rect =
screen_id == ScreenId::TopLeft ? layout.top_screen : layout.bottom_screen;
SDL_Rect sdl_rect{static_cast<int>(dst_rect.left), static_cast<int>(dst_rect.top),
static_cast<int>(dst_rect.GetWidth()),
static_cast<int>(dst_rect.GetHeight())};
SDL_Surface* screen = LoadFramebuffer(fb_id);
SDL_Surface* screen = LoadFramebuffer(screen_id);
SDL_BlitSurface(screen, nullptr, window_surface, &sdl_rect);
SDL_FreeSurface(screen);
};
draw_screen(0);
draw_screen(1);
draw_screen(ScreenId::TopLeft);
draw_screen(ScreenId::Bottom);
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(render_window);
}
}
SDL_Surface* EmuWindow_SDL2_SW::LoadFramebuffer(int fb_id) {
const auto& framebuffer = GPU::g_regs.framebuffer_config[fb_id];
const PAddr framebuffer_addr =
framebuffer.active_fb == 0 ? framebuffer.address_left1 : framebuffer.address_left2;
Memory::RasterizerFlushRegion(framebuffer_addr, framebuffer.stride * framebuffer.height);
const u8* framebuffer_data = VideoCore::g_memory->GetPhysicalPointer(framebuffer_addr);
const int width = framebuffer.height;
const int height = framebuffer.width;
const int bpp = GPU::Regs::BytesPerPixel(framebuffer.color_format);
SDL_Surface* EmuWindow_SDL2_SW::LoadFramebuffer(VideoCore::ScreenId screen_id) {
const auto& renderer = static_cast<SwRenderer::RendererSoftware&>(system.Renderer());
const auto& info = renderer.Screen(screen_id);
const int width = static_cast<int>(info.width);
const int height = static_cast<int>(info.height);
SDL_Surface* surface =
SDL_CreateRGBSurfaceWithFormat(0, width, height, 0, SDL_PIXELFORMAT_ABGR8888);
SDL_LockSurface(surface);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
const u8* pixel = framebuffer_data + (x * height + height - y) * bpp;
const Common::Vec4 color = [&] {
switch (framebuffer.color_format) {
case GPU::Regs::PixelFormat::RGBA8:
return Common::Color::DecodeRGBA8(pixel);
case GPU::Regs::PixelFormat::RGB8:
return Common::Color::DecodeRGB8(pixel);
case GPU::Regs::PixelFormat::RGB565:
return Common::Color::DecodeRGB565(pixel);
case GPU::Regs::PixelFormat::RGB5A1:
return Common::Color::DecodeRGB5A1(pixel);
case GPU::Regs::PixelFormat::RGBA4:
return Common::Color::DecodeRGBA4(pixel);
}
UNREACHABLE();
}();
u8* dst_pixel = reinterpret_cast<u8*>(surface->pixels) + (y * width + x) * 4;
std::memcpy(dst_pixel, color.AsArray(), sizeof(color));
}
}
std::memcpy(surface->pixels, info.pixels.data(), info.pixels.size());
SDL_UnlockSurface(surface);
return surface;
}

View file

@ -10,9 +10,17 @@
struct SDL_Renderer;
struct SDL_Surface;
namespace VideoCore {
enum class ScreenId : u32;
}
namespace Core {
class System;
}
class EmuWindow_SDL2_SW : public EmuWindow_SDL2 {
public:
explicit EmuWindow_SDL2_SW(bool fullscreen, bool is_secondary);
explicit EmuWindow_SDL2_SW(Core::System& system, bool fullscreen, bool is_secondary);
~EmuWindow_SDL2_SW();
void Present() override;
@ -22,7 +30,10 @@ public:
private:
/// Loads a framebuffer to an SDL surface
SDL_Surface* LoadFramebuffer(int fb_id);
SDL_Surface* LoadFramebuffer(VideoCore::ScreenId screen_id);
/// The system class.
Core::System& system;
/// The SDL software renderer
SDL_Renderer* renderer;