57 atlas.entries.emplace_back(atlas_id, uv_rect, bitmap.
texture(), bpp_format,
78 ScopedTimer timer(
"atlas_add_bitmap_bpp_optimized");
85 if (current_bpp == target_bpp) {
91 bitmap.
vector(), current_bpp, target_bpp, bitmap.
width(),
96 converted_data, bitmap.
palette());
114 for (
auto& atlas_entry : atlas->entries) {
115 if (atlas_entry.atlas_id == atlas_id) {
144 const std::vector<RenderCommand>& render_commands) {
145 if (render_commands.empty()) {
152 std::unordered_map<int, std::vector<const RenderCommand*>> atlas_groups;
154 for (
const auto& cmd : render_commands) {
158 for (
size_t i = 0; i <
atlases_.size(); ++i) {
159 for (
const auto& entry :
atlases_[i]->entries) {
160 if (entry.atlas_id == cmd.atlas_id) {
161 atlas_groups[i].push_back(&cmd);
170 for (
const auto& [atlas_index, commands] : atlas_groups) {
171 if (commands.empty())
174 auto& atlas = *
atlases_[atlas_index];
180 for (
const auto* cmd : commands) {
188 SDL_Rect dest_rect = {
static_cast<int>(cmd->x),
static_cast<int>(cmd->y),
189 static_cast<int>(entry->
uv_rect.w * cmd->scale_x),
190 static_cast<int>(entry->
uv_rect.h * cmd->scale_y)};
193 if (std::abs(cmd->rotation) > 0.001F) {
205 const std::vector<RenderCommand>& render_commands,
206 const std::unordered_map<
BppFormat, std::vector<int>>& bpp_groups) {
207 if (render_commands.empty()) {
211 ScopedTimer timer(
"atlas_batch_render_bpp_optimized");
214 for (
const auto& [bpp_format, command_indices] : bpp_groups) {
215 if (command_indices.empty())
219 std::unordered_map<int, std::vector<const RenderCommand*>> atlas_groups;
221 for (
int cmd_index : command_indices) {
222 if (cmd_index >= 0 &&
223 cmd_index <
static_cast<int>(render_commands.size())) {
224 const auto& cmd = render_commands[cmd_index];
227 it->second->bpp_format == bpp_format) {
229 for (
size_t i = 0; i <
atlases_.size(); ++i) {
230 for (
const auto& entry :
atlases_[i]->entries) {
231 if (entry.atlas_id == cmd.atlas_id) {
232 atlas_groups[i].push_back(&cmd);
242 for (
const auto& [atlas_index, commands] : atlas_groups) {
243 if (commands.empty())
246 auto& atlas = *
atlases_[atlas_index];
252 for (
const auto* cmd : commands) {
260 SDL_Rect dest_rect = {
261 static_cast<int>(cmd->x),
static_cast<int>(cmd->y),
262 static_cast<int>(entry->
uv_rect.w * cmd->scale_x),
263 static_cast<int>(entry->
uv_rect.h * cmd->scale_y)};
266 if (std::abs(cmd->rotation) > 0.001F) {
281 for (
const auto& atlas :
atlases_) {
284 std::count_if(atlas->entries.begin(), atlas->entries.end(),
285 [](
const AtlasEntry& entry) { return entry.in_use; });
304 atlas->entries.erase(
305 std::remove_if(atlas->entries.begin(), atlas->entries.end(),
306 [](
const AtlasEntry& entry) { return !entry.in_use; }),
307 atlas->entries.end());
317 if (atlas->texture) {
343 for (
const auto& atlas_entry : atlas->entries) {
344 if (atlas_entry.atlas_id == atlas_id) {
346 SDL_Rect dest_rect = {
static_cast<int>(x),
static_cast<int>(y),
347 static_cast<int>(entry->
uv_rect.w * scale_x),
348 static_cast<int>(entry->
uv_rect.h * scale_y)};
365 return it->second->uv_rect;
370 int width = bitmap.
width();
371 int height = bitmap.
height();
375 if (free_rect.w == 0 || free_rect.h == 0) {
383 uv_rect = {free_rect.x, free_rect.y, width, height};
394 atlases_.push_back(std::make_unique<Atlas>(size));
401 if (!atlas.texture) {
402 SDL_Log(
"Failed to create atlas texture: %s", SDL_GetError());
415 for (
auto& entry : atlas.
entries) {
416 if (entry.in_use && entry.texture) {
427 for (
int y = 0; y <= atlas.
size - height; ++y) {
428 for (
int x = 0; x <= atlas.
size - width; ++x) {
432 for (
int dy = 0; dy < height && can_fit; ++dy) {
433 for (
int dx = 0; dx < width && can_fit; ++dx) {
434 int index = (y + dy) * atlas.
size + (x + dx);
435 if (index >=
static_cast<int>(atlas.
used_regions.size()) ||
443 return {x, y, width, height};
453 for (
int y = rect.y; y < rect.y + rect.h; ++y) {
454 for (
int x = rect.x; x < rect.x + rect.w; ++x) {
455 int index = y * atlas.
size + x;
456 if (index >= 0 && index <
static_cast<int>(atlas.
used_regions.size())) {
Atlas-based rendering system for efficient graphics operations.
SDL_Rect FindFreeRegion(Atlas &atlas, int width, int height)
AtlasStats GetStats() const
Get atlas statistics.
bool PackBitmap(Atlas &atlas, const Bitmap &bitmap, SDL_Rect &uv_rect)
void UpdateBitmap(int atlas_id, const Bitmap &bitmap)
Update a bitmap in the atlas.
std::vector< std::unique_ptr< Atlas > > atlases_
void RebuildAtlas(Atlas &atlas)
void Clear()
Clear all atlases.
int AddBitmapWithBppOptimization(const Bitmap &bitmap, BppFormat target_bpp)
Add a bitmap to the atlas with BPP format optimization.
void RenderBitmap(int atlas_id, float x, float y, float scale_x=1.0f, float scale_y=1.0f)
Render a single bitmap using atlas (convenience method)
void MarkRegionUsed(Atlas &atlas, const SDL_Rect &rect, bool used)
std::unordered_map< int, AtlasEntry * > atlas_lookup_
void RenderBatch(const std::vector< RenderCommand > &render_commands)
Render multiple bitmaps in a single draw call.
void RemoveBitmap(int atlas_id)
Remove a bitmap from the atlas.
void Defragment()
Defragment the atlas to reclaim space.
SDL_Rect GetUVCoordinates(int atlas_id) const
Get UV coordinates for a bitmap in the atlas.
int AddBitmap(const Bitmap &bitmap)
Add a bitmap to the atlas.
static AtlasRenderer & Get()
void Initialize(IRenderer *renderer, int initial_size=1024)
Initialize the atlas renderer.
void RenderBatchWithBppOptimization(const std::vector< RenderCommand > &render_commands, const std::unordered_map< BppFormat, std::vector< int > > &bpp_groups)
Render multiple bitmaps with BPP-aware batching.
Represents a bitmap image optimized for SNES ROM hacking.
const SnesPalette & palette() const
TextureHandle texture() const
const std::vector< uint8_t > & vector() const
void CreateTexture()
Creates the underlying SDL_Texture to be displayed.
Defines an abstract interface for all rendering operations.
virtual TextureHandle CreateTexture(int width, int height)=0
Creates a new, empty texture.
virtual void RenderCopy(TextureHandle texture, const SDL_Rect *srcrect, const SDL_Rect *dstrect)=0
Copies a portion of a texture to the current render target.
virtual void SetDrawColor(SDL_Color color)=0
Sets the color used for drawing operations (e.g., Clear).
virtual void Clear()=0
Clears the entire render target with the current draw color.
virtual void DestroyTexture(TextureHandle texture)=0
Destroys a texture and frees its associated resources.
virtual void SetRenderTarget(TextureHandle texture)=0
Sets the render target for subsequent drawing operations.
RAII timer for automatic timing management.
BppFormat
BPP format enumeration for SNES graphics.
std::vector< AtlasEntry > entries
std::vector< bool > used_regions
float utilization_percent