yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
arena.cc
Go to the documentation of this file.
1#include "app/gfx/arena.h"
2
3#include <SDL.h>
4#include <algorithm>
5
7#include "util/log.h"
8#include "util/sdl_deleter.h"
9
10namespace yaze {
11namespace gfx {
12
13void Arena::Initialize(IRenderer* renderer) { renderer_ = renderer; }
14
16 static Arena instance;
17 return instance;
18}
19
21 layer1_buffer_.fill(0);
22 layer2_buffer_.fill(0);
23}
24
26 // Use the safe shutdown method that handles cleanup properly
27 Shutdown();
28}
29
30
31
33 texture_command_queue_.push_back({type, bitmap});
34}
35
37 // Use provided renderer if available, otherwise use stored renderer
38 IRenderer* active_renderer = renderer ? renderer : renderer_;
39
40 if (!active_renderer) {
41 // Arena not initialized yet - defer processing
42 return;
43 }
44
45 if (texture_command_queue_.empty()) {
46 return;
47 }
48
49 // Performance optimization: Batch process textures with limits
50 // Process up to 8 texture operations per frame to avoid frame drops
51 constexpr size_t kMaxTexturesPerFrame = 8;
52 size_t processed = 0;
53
54 auto it = texture_command_queue_.begin();
55 while (it != texture_command_queue_.end() && processed < kMaxTexturesPerFrame) {
56 const auto& command = *it;
57 bool should_remove = true;
58
59 // CRITICAL: Replicate the exact short-circuit evaluation from working code
60 // We MUST check command.bitmap AND command.bitmap->surface() in one expression
61 // to avoid dereferencing invalid pointers
62
63 switch (command.type) {
65 // Create a new texture and update it with bitmap data
66 // Use short-circuit evaluation - if bitmap is invalid, never call ->surface()
67 if (command.bitmap && command.bitmap->surface() &&
68 command.bitmap->surface()->format &&
69 command.bitmap->is_active() &&
70 command.bitmap->width() > 0 && command.bitmap->height() > 0) {
71
72 try {
73 auto texture = active_renderer->CreateTexture(command.bitmap->width(),
74 command.bitmap->height());
75 if (texture) {
76 command.bitmap->set_texture(texture);
77 active_renderer->UpdateTexture(texture, *command.bitmap);
78 processed++;
79 } else {
80 should_remove = false; // Retry next frame
81 }
82 } catch (...) {
83 LOG_ERROR("Arena", "Exception during texture creation");
84 should_remove = true; // Remove bad command
85 }
86 }
87 break;
88 }
90 // Update existing texture with current bitmap data
91 if (command.bitmap->texture() &&
92 command.bitmap->surface() && command.bitmap->surface()->format &&
93 command.bitmap->is_active()) {
94 try {
95 active_renderer->UpdateTexture(command.bitmap->texture(), *command.bitmap);
96 processed++;
97 } catch (...) {
98 LOG_ERROR("Arena", "Exception during texture update");
99 }
100 }
101 break;
102 }
104 if (command.bitmap->texture()) {
105 try {
106 active_renderer->DestroyTexture(command.bitmap->texture());
107 command.bitmap->set_texture(nullptr);
108 processed++;
109 } catch (...) {
110 LOG_ERROR("Arena", "Exception during texture destruction");
111 }
112 }
113 break;
114 }
115 }
116
117 if (should_remove) {
118 it = texture_command_queue_.erase(it);
119 } else {
120 ++it;
121 }
122 }
123}
124
125SDL_Surface* Arena::AllocateSurface(int width, int height, int depth, int format) {
126 // Try to get a surface from the pool first
127 for (auto it = surface_pool_.available_surfaces_.begin();
128 it != surface_pool_.available_surfaces_.end(); ++it) {
129 auto& info = surface_pool_.surface_info_[*it];
130 if (std::get<0>(info) == width && std::get<1>(info) == height &&
131 std::get<2>(info) == depth && std::get<3>(info) == format) {
132 SDL_Surface* surface = *it;
134 return surface;
135 }
136 }
137
138 // Create new surface if none available in pool
139 Uint32 sdl_format = GetSnesPixelFormat(format);
140 SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, sdl_format);
141
142 if (surface) {
143 auto surface_ptr = std::unique_ptr<SDL_Surface, util::SDL_Surface_Deleter>(surface);
144 surfaces_[surface] = std::move(surface_ptr);
145 surface_pool_.surface_info_[surface] = std::make_tuple(width, height, depth, format);
146 }
147
148 return surface;
149}
150
151void Arena::FreeSurface(SDL_Surface* surface) {
152 if (!surface) return;
153
154 // Return surface to pool if space available
156 surface_pool_.available_surfaces_.push_back(surface);
157 } else {
158 // Remove from tracking maps
159 surface_pool_.surface_info_.erase(surface);
160 surfaces_.erase(surface);
161 }
162}
163
165 // Process any remaining batch updates before shutdown
167
168 // Clear pool references first to prevent reuse during shutdown
173
174 // CRITICAL FIX: Clear containers in reverse order to prevent cleanup issues
175 // This ensures that dependent resources are freed before their dependencies
176 textures_.clear();
177 surfaces_.clear();
178
179 // Clear any remaining queue items
181}
182
183void Arena::NotifySheetModified(int sheet_index) {
184 if (sheet_index < 0 || sheet_index >= 223) {
185 LOG_WARN("Arena", "Invalid sheet index %d, ignoring notification", sheet_index);
186 return;
187 }
188
189 auto& sheet = gfx_sheets_[sheet_index];
190 if (!sheet.is_active() || !sheet.surface()) {
191 LOG_DEBUG("Arena", "Sheet %d not active or no surface, skipping notification", sheet_index);
192 return;
193 }
194
195 // Queue texture update so changes are visible in all editors
196 if (sheet.texture()) {
198 LOG_DEBUG("Arena", "Queued texture update for modified sheet %d", sheet_index);
199 } else {
200 // Create texture if it doesn't exist
202 LOG_DEBUG("Arena", "Queued texture creation for modified sheet %d", sheet_index);
203 }
204}
205
206
207} // namespace gfx
208} // namespace yaze
Resource management arena for efficient graphics memory handling.
Definition arena.h:44
IRenderer * renderer_
Definition arena.h:157
std::unordered_map< SDL_Surface *, std::unique_ptr< SDL_Surface, util::SDL_Surface_Deleter > > surfaces_
Definition arena.h:141
void Initialize(IRenderer *renderer)
Definition arena.cc:13
struct yaze::gfx::Arena::TexturePool texture_pool_
SDL_Surface * AllocateSurface(int width, int height, int depth, int format)
Definition arena.cc:125
std::unordered_map< TextureHandle, std::unique_ptr< SDL_Texture, util::SDL_Texture_Deleter > > textures_
Definition arena.h:137
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Definition arena.cc:32
std::array< uint16_t, kTotalTiles > layer2_buffer_
Definition arena.h:131
void FreeSurface(SDL_Surface *surface)
Definition arena.cc:151
void ProcessTextureQueue(IRenderer *renderer)
Definition arena.cc:36
std::array< gfx::Bitmap, 223 > gfx_sheets_
Definition arena.h:133
std::vector< TextureCommand > texture_command_queue_
Definition arena.h:156
std::array< uint16_t, kTotalTiles > layer1_buffer_
Definition arena.h:130
void NotifySheetModified(int sheet_index)
Notify Arena that a graphics sheet has been modified.
Definition arena.cc:183
struct yaze::gfx::Arena::SurfacePool surface_pool_
void Shutdown()
Definition arena.cc:164
static Arena & Get()
Definition arena.cc:15
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:66
Defines an abstract interface for all rendering operations.
Definition irenderer.h:35
virtual TextureHandle CreateTexture(int width, int height)=0
Creates a new, empty texture.
virtual void UpdateTexture(TextureHandle texture, const Bitmap &bitmap)=0
Updates a texture with the pixel data from a Bitmap.
virtual void DestroyTexture(TextureHandle texture)=0
Destroys a texture and frees its associated resources.
#define LOG_DEBUG(category, format,...)
Definition log.h:104
#define LOG_ERROR(category, format,...)
Definition log.h:110
#define LOG_WARN(category, format,...)
Definition log.h:108
Uint32 GetSnesPixelFormat(int format)
Convert bitmap format enum to SDL pixel format.
Definition bitmap.cc:34
Main namespace for the application.
static constexpr size_t MAX_POOL_SIZE
Definition arena.h:153
std::vector< SDL_Surface * > available_surfaces_
Definition arena.h:151
std::unordered_map< SDL_Surface *, std::tuple< int, int, int, int > > surface_info_
Definition arena.h:152
std::vector< TextureHandle > available_textures_
Definition arena.h:145
std::unordered_map< TextureHandle, std::pair< int, int > > texture_sizes_
Definition arena.h:146