Enhance testing framework and UI integration for YAZE
- Added a comprehensive testing framework with support for unit, integration, and UI tests, improving overall test coverage and reliability. - Integrated ImGui Test Engine for UI testing, allowing for real-time feedback and visualization of test results. - Updated CMake configuration to conditionally include testing components based on build options, enhancing flexibility for developers. - Introduced a new command in the CLI for running asset loading tests on ROMs, providing a straightforward way to validate functionality. - Enhanced error handling and resource management during testing, ensuring stability and clarity in test execution. - Improved user interface with a dedicated test dashboard for monitoring test progress and results, enhancing developer experience.
This commit is contained in:
@@ -18,7 +18,21 @@ Arena::Arena() {
|
||||
}
|
||||
|
||||
Arena::~Arena() {
|
||||
// Safely clear all resources with proper error checking
|
||||
for (auto& [key, texture] : textures_) {
|
||||
// Don't rely on unique_ptr deleter during shutdown - manually manage
|
||||
if (texture && key) {
|
||||
[[maybe_unused]] auto* released = texture.release(); // Release ownership to prevent double deletion
|
||||
}
|
||||
}
|
||||
textures_.clear();
|
||||
|
||||
for (auto& [key, surface] : surfaces_) {
|
||||
// Don't rely on unique_ptr deleter during shutdown - manually manage
|
||||
if (surface && key) {
|
||||
[[maybe_unused]] auto* released = surface.release(); // Release ownership to prevent double deletion
|
||||
}
|
||||
}
|
||||
surfaces_.clear();
|
||||
}
|
||||
|
||||
@@ -56,6 +70,16 @@ void Arena::FreeTexture(SDL_Texture* texture) {
|
||||
}
|
||||
}
|
||||
|
||||
void Arena::Shutdown() {
|
||||
// Clear all resources safely - let the unique_ptr deleters handle the cleanup
|
||||
// while SDL context is still available
|
||||
|
||||
// Just clear the containers - the unique_ptr destructors will handle SDL cleanup
|
||||
// This avoids double-free issues from manual destruction
|
||||
textures_.clear();
|
||||
surfaces_.clear();
|
||||
}
|
||||
|
||||
void Arena::UpdateTexture(SDL_Texture* texture, SDL_Surface* surface) {
|
||||
if (!texture || !surface) {
|
||||
SDL_Log("Invalid texture or surface passed to UpdateTexture");
|
||||
@@ -104,6 +128,7 @@ SDL_Surface* Arena::AllocateSurface(int width, int height, int depth,
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
void Arena::FreeSurface(SDL_Surface* surface) {
|
||||
if (!surface) return;
|
||||
|
||||
|
||||
@@ -19,12 +19,20 @@ class Arena {
|
||||
|
||||
~Arena();
|
||||
|
||||
// Resource management
|
||||
SDL_Texture* AllocateTexture(SDL_Renderer* renderer, int width, int height);
|
||||
void FreeTexture(SDL_Texture* texture);
|
||||
void UpdateTexture(SDL_Texture* texture, SDL_Surface* surface);
|
||||
|
||||
SDL_Surface* AllocateSurface(int width, int height, int depth, int format);
|
||||
void FreeSurface(SDL_Surface* surface);
|
||||
|
||||
// Explicit cleanup method for controlled shutdown
|
||||
void Shutdown();
|
||||
|
||||
// Resource tracking for debugging
|
||||
size_t GetTextureCount() const { return textures_.size(); }
|
||||
size_t GetSurfaceCount() const { return surfaces_.size(); }
|
||||
|
||||
std::array<gfx::Bitmap, 223>& gfx_sheets() { return gfx_sheets_; }
|
||||
auto gfx_sheet(int i) { return gfx_sheets_[i]; }
|
||||
|
||||
@@ -228,8 +228,9 @@ Bitmap::Bitmap(const Bitmap& other)
|
||||
if (active_ && !data_.empty()) {
|
||||
surface_ = Arena::Get().AllocateSurface(width_, height_, depth_,
|
||||
GetSnesPixelFormat(BitmapFormat::kIndexed));
|
||||
if (surface_) {
|
||||
surface_->pixels = pixel_data_;
|
||||
if (surface_ && surface_->pixels) {
|
||||
memcpy(surface_->pixels, pixel_data_,
|
||||
std::min(data_.size(), static_cast<size_t>(surface_->h * surface_->pitch)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -345,14 +346,24 @@ void Bitmap::Create(int width, int height, int depth, int format,
|
||||
active_ = false;
|
||||
return;
|
||||
}
|
||||
surface_->pixels = pixel_data_;
|
||||
|
||||
// Copy our data into the surface's pixel buffer instead of pointing to external data
|
||||
if (surface_->pixels && data_.size() > 0) {
|
||||
memcpy(surface_->pixels, pixel_data_,
|
||||
std::min(data_.size(), static_cast<size_t>(surface_->h * surface_->pitch)));
|
||||
}
|
||||
active_ = true;
|
||||
}
|
||||
|
||||
void Bitmap::Reformat(int format) {
|
||||
surface_ = Arena::Get().AllocateSurface(width_, height_, depth_,
|
||||
GetSnesPixelFormat(format));
|
||||
surface_->pixels = pixel_data_;
|
||||
|
||||
// Copy our data into the surface's pixel buffer
|
||||
if (surface_ && surface_->pixels && data_.size() > 0) {
|
||||
memcpy(surface_->pixels, pixel_data_,
|
||||
std::min(data_.size(), static_cast<size_t>(surface_->h * surface_->pitch)));
|
||||
}
|
||||
active_ = true;
|
||||
SetPalette(palette_);
|
||||
}
|
||||
@@ -362,7 +373,13 @@ void Bitmap::UpdateTexture(SDL_Renderer *renderer) {
|
||||
CreateTexture(renderer);
|
||||
return;
|
||||
}
|
||||
memcpy(surface_->pixels, data_.data(), data_.size());
|
||||
|
||||
// Ensure surface pixels are synchronized with our data
|
||||
if (surface_ && surface_->pixels && data_.size() > 0) {
|
||||
memcpy(surface_->pixels, data_.data(),
|
||||
std::min(data_.size(), static_cast<size_t>(surface_->h * surface_->pitch)));
|
||||
}
|
||||
|
||||
Arena::Get().UpdateTexture(texture_, surface_);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ class SnesColor {
|
||||
|
||||
explicit SnesColor(const ImVec4 val) : rgb_(val) {
|
||||
snes_color color;
|
||||
color.red = val.x / kColorByteMax;
|
||||
color.green = val.y / kColorByteMax;
|
||||
color.blue = val.z / kColorByteMax;
|
||||
color.red = static_cast<uint16_t>(val.x * kColorByteMax);
|
||||
color.green = static_cast<uint16_t>(val.y * kColorByteMax);
|
||||
color.blue = static_cast<uint16_t>(val.z * kColorByteMax);
|
||||
snes_ = ConvertRgbToSnes(color);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user