epic: refactor SDL2_Renderer usage to IRenderer and queued texture rendering
- Updated the testing guide to clarify the testing framework's organization and execution methods, improving user understanding. - Refactored CMakeLists to include new platform-specific files, ensuring proper integration of the rendering backend. - Modified main application files to utilize the new IRenderer interface, enhancing flexibility in rendering operations. - Implemented deferred texture management in various components, allowing for more efficient graphics handling and improved performance. - Introduced new methods for texture creation and updates, streamlining the rendering process across the application. - Enhanced logging and error handling in the rendering pipeline to facilitate better debugging and diagnostics.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#if __APPLE__
|
||||
#include "app/core/platform/app_delegate.h"
|
||||
#include "app/platform/app_delegate.h"
|
||||
#endif
|
||||
|
||||
#include <SDL.h>
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "absl/flags/parse.h"
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/rom.h"
|
||||
#include "app/gfx/backend/irenderer.h"
|
||||
#include "app/gfx/backend/sdl2_renderer.h"
|
||||
#include "util/sdl_deleter.h"
|
||||
|
||||
ABSL_FLAG(std::string, emu_rom, "", "Path to the ROM file to load.");
|
||||
@@ -86,17 +88,13 @@ int main(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
std::unique_ptr<SDL_Renderer, SDL_Deleter> renderer_(
|
||||
SDL_CreateRenderer(window_.get(), -1,
|
||||
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
|
||||
SDL_Deleter());
|
||||
if (!renderer_) {
|
||||
printf("SDL_CreateRenderer failed: %s\n", SDL_GetError());
|
||||
SDL_Quit();
|
||||
return EXIT_FAILURE;
|
||||
// Create and initialize the renderer
|
||||
auto renderer = std::make_unique<yaze::gfx::SDL2Renderer>();
|
||||
if (!renderer->Initialize(window_.get())) {
|
||||
printf("Failed to initialize renderer\n");
|
||||
SDL_Quit();
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
SDL_SetRenderDrawBlendMode(renderer_.get(), SDL_BLENDMODE_BLEND);
|
||||
SDL_SetRenderDrawColor(renderer_.get(), 0x00, 0x00, 0x00, 0xFF);
|
||||
|
||||
// Initialize audio system
|
||||
constexpr int kAudioFrequency = 48000;
|
||||
@@ -120,10 +118,7 @@ int main(int argc, char **argv) {
|
||||
SDL_PauseAudioDevice(audio_device, 0);
|
||||
|
||||
// Create PPU texture for rendering
|
||||
SDL_Texture* ppu_texture = SDL_CreateTexture(renderer_.get(),
|
||||
SDL_PIXELFORMAT_RGBX8888,
|
||||
SDL_TEXTUREACCESS_STREAMING,
|
||||
512, 480);
|
||||
void* ppu_texture = renderer->CreateTexture(512, 480);
|
||||
if (!ppu_texture) {
|
||||
printf("SDL_CreateTexture failed: %s\n", SDL_GetError());
|
||||
SDL_CloseAudioDevice(audio_device);
|
||||
@@ -271,20 +266,17 @@ int main(int argc, char **argv) {
|
||||
// Render PPU output to texture
|
||||
void *ppu_pixels = nullptr;
|
||||
int ppu_pitch = 0;
|
||||
if (SDL_LockTexture(ppu_texture, nullptr, &ppu_pixels, &ppu_pitch) != 0) {
|
||||
printf("Failed to lock texture: %s\n", SDL_GetError());
|
||||
running = false;
|
||||
break;
|
||||
if (renderer->LockTexture(ppu_texture, nullptr, &ppu_pixels, &ppu_pitch)) {
|
||||
snes_.SetPixels(static_cast<uint8_t*>(ppu_pixels));
|
||||
renderer->UnlockTexture(ppu_texture);
|
||||
}
|
||||
snes_.SetPixels(static_cast<uint8_t*>(ppu_pixels));
|
||||
SDL_UnlockTexture(ppu_texture);
|
||||
}
|
||||
}
|
||||
|
||||
// Present rendered frame
|
||||
SDL_RenderClear(renderer_.get());
|
||||
SDL_RenderCopy(renderer_.get(), ppu_texture, nullptr, nullptr);
|
||||
SDL_RenderPresent(renderer_.get());
|
||||
renderer->Clear();
|
||||
renderer->RenderCopy(ppu_texture, nullptr, nullptr);
|
||||
renderer->Present();
|
||||
}
|
||||
|
||||
// === Cleanup SDL resources (in reverse order of initialization) ===
|
||||
@@ -292,7 +284,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
// Clean up texture
|
||||
if (ppu_texture) {
|
||||
SDL_DestroyTexture(ppu_texture);
|
||||
renderer->DestroyTexture(ppu_texture);
|
||||
ppu_texture = nullptr;
|
||||
}
|
||||
|
||||
@@ -302,7 +294,7 @@ int main(int argc, char **argv) {
|
||||
SDL_CloseAudioDevice(audio_device);
|
||||
|
||||
// Clean up renderer and window (done automatically by unique_ptr destructors)
|
||||
renderer_.reset();
|
||||
renderer->Shutdown();
|
||||
window_.reset();
|
||||
|
||||
// Quit SDL subsystems
|
||||
|
||||
@@ -5,7 +5,7 @@ if (NOT YAZE_MINIMAL_BUILD AND APPLE)
|
||||
MACOSX_BUNDLE
|
||||
app/main.cc
|
||||
app/rom.cc
|
||||
app/core/platform/app_delegate.mm
|
||||
app/platform/app_delegate.mm
|
||||
${YAZE_APP_EMU_SRC}
|
||||
${YAZE_APP_CORE_SRC}
|
||||
${YAZE_APP_EDITOR_SRC}
|
||||
|
||||
@@ -49,21 +49,24 @@ using ImGui::Separator;
|
||||
using ImGui::TableNextColumn;
|
||||
using ImGui::Text;
|
||||
|
||||
void Emulator::Initialize(gfx::IRenderer* renderer, const std::vector<uint8_t>& rom_data) {
|
||||
renderer_ = renderer;
|
||||
rom_data_ = rom_data;
|
||||
snes_.Init(rom_data_);
|
||||
initialized_ = true;
|
||||
}
|
||||
|
||||
void Emulator::Run(Rom* rom) {
|
||||
static bool loaded = false;
|
||||
if (!snes_.running() && rom->is_loaded()) {
|
||||
// Use ARGB8888 format to match PPU output (XBGR layout with format=1)
|
||||
// Add better error handling and texture optimization
|
||||
ppu_texture_ = SDL_CreateTexture(core::Renderer::Get().renderer(),
|
||||
SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STREAMING, 512, 480);
|
||||
ppu_texture_ = renderer_->CreateTexture(512, 480);
|
||||
if (ppu_texture_ == NULL) {
|
||||
printf("Failed to create texture: %s\n", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimize texture for better performance
|
||||
SDL_SetTextureBlendMode(ppu_texture_, SDL_BLENDMODE_NONE);
|
||||
// renderer_->SetTextureBlendMode(ppu_texture_, SDL_BLENDMODE_NONE);
|
||||
rom_data_ = rom->vector();
|
||||
snes_.Init(rom_data_);
|
||||
|
||||
@@ -149,10 +152,9 @@ void Emulator::Run(Rom* rom) {
|
||||
// Update PPU texture only on rendered frames
|
||||
void* ppu_pixels_;
|
||||
int ppu_pitch_;
|
||||
if (SDL_LockTexture(ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_) ==
|
||||
0) {
|
||||
if (renderer_->LockTexture(ppu_texture_, NULL, &ppu_pixels_, &ppu_pitch_)) {
|
||||
snes_.SetPixels(static_cast<uint8_t*>(ppu_pixels_));
|
||||
SDL_UnlockTexture(ppu_texture_);
|
||||
renderer_->UnlockTexture(ppu_texture_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
|
||||
#include "app/emu/snes.h"
|
||||
#include "app/rom.h"
|
||||
#include "imgui/imgui.h"
|
||||
|
||||
namespace yaze {
|
||||
namespace gfx {
|
||||
class IRenderer;
|
||||
} // namespace gfx
|
||||
|
||||
/**
|
||||
* @namespace yaze::emu
|
||||
@@ -39,6 +41,7 @@ class Emulator {
|
||||
public:
|
||||
Emulator() = default;
|
||||
~Emulator() = default;
|
||||
void Initialize(gfx::IRenderer* renderer, const std::vector<uint8_t>& rom_data);
|
||||
void Run(Rom* rom);
|
||||
|
||||
auto snes() -> Snes& { return snes_; }
|
||||
@@ -129,7 +132,9 @@ class Emulator {
|
||||
SDL_AudioDeviceID audio_device_;
|
||||
|
||||
Snes snes_;
|
||||
SDL_Texture* ppu_texture_;
|
||||
bool initialized_ = false;
|
||||
gfx::IRenderer* renderer_ = nullptr;
|
||||
void* ppu_texture_ = nullptr;
|
||||
|
||||
std::vector<uint8_t> rom_data_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user