#ifndef YAZE_APP_GFX_TEXTURE_ATLAS_H #define YAZE_APP_GFX_TEXTURE_ATLAS_H #include #include #include #include "app/gfx/bitmap.h" #include "absl/status/status.h" namespace yaze { namespace gfx { /** * @class TextureAtlas * @brief Manages multiple textures packed into a single large texture for performance * * Future-proof infrastructure for combining multiple room textures into one atlas. * This reduces GPU state changes and improves rendering performance when many rooms are open. * * Benefits: * - Fewer texture binds per frame * - Better memory locality * - Reduced VRAM fragmentation * - Easier batch rendering * * Usage (Future): * TextureAtlas atlas(2048, 2048); * auto region = atlas.AllocateRegion(room_id, 512, 512); * atlas.PackBitmap(room.bg1_buffer().bitmap(), *region); * atlas.DrawRegion(room_id, x, y); */ class TextureAtlas { public: /** * @brief Region within the atlas texture */ struct AtlasRegion { int x = 0; // X position in atlas int y = 0; // Y position in atlas int width = 0; // Region width int height = 0; // Region height int source_id = -1; // ID of source (e.g., room_id) bool in_use = false; // Whether this region is allocated }; /** * @brief Construct texture atlas with specified dimensions * @param width Atlas width in pixels (typically 2048 or 4096) * @param height Atlas height in pixels (typically 2048 or 4096) */ explicit TextureAtlas(int width = 2048, int height = 2048); /** * @brief Allocate a region in the atlas for a source texture * @param source_id Identifier for the source (e.g., room_id) * @param width Required width in pixels * @param height Required height in pixels * @return Pointer to allocated region, or nullptr if no space * * Uses simple rect packing algorithm. Future: implement more efficient packing. */ AtlasRegion* AllocateRegion(int source_id, int width, int height); /** * @brief Pack a bitmap into an allocated region * @param src Source bitmap to pack * @param region Region to pack into (must be pre-allocated) * @return Status of packing operation * * Copies pixel data from source bitmap into atlas at region coordinates. */ absl::Status PackBitmap(const Bitmap& src, const AtlasRegion& region); /** * @brief Draw a region from the atlas to screen coordinates * @param source_id Source identifier (e.g., room_id) * @param dest_x Destination X coordinate * @param dest_y Destination Y coordinate * @return Status of drawing operation * * Future: Integrate with renderer to draw atlas regions. */ absl::Status DrawRegion(int source_id, int dest_x, int dest_y); /** * @brief Free a region and mark it as available * @param source_id Source identifier to free */ void FreeRegion(int source_id); /** * @brief Clear all regions and reset atlas */ void Clear(); /** * @brief Get the atlas bitmap (contains all packed textures) * @return Reference to atlas bitmap */ Bitmap& GetAtlasBitmap() { return atlas_bitmap_; } const Bitmap& GetAtlasBitmap() const { return atlas_bitmap_; } /** * @brief Get region for a specific source * @param source_id Source identifier * @return Pointer to region, or nullptr if not found */ const AtlasRegion* GetRegion(int source_id) const; /** * @brief Get atlas dimensions */ int width() const { return width_; } int height() const { return height_; } /** * @brief Get atlas utilization statistics */ struct AtlasStats { int total_regions = 0; int used_regions = 0; int total_pixels = 0; int used_pixels = 0; float utilization = 0.0f; // Percentage of atlas in use }; AtlasStats GetStats() const; private: int width_; int height_; Bitmap atlas_bitmap_; // Large combined bitmap // Simple linear packing for now (future: more efficient algorithms) int next_x_ = 0; int next_y_ = 0; int row_height_ = 0; // Current row height for packing // Map source_id → region std::map regions_; // Simple rect packing helper bool TryPackRect(int width, int height, int& out_x, int& out_y); }; } // namespace gfx } // namespace yaze #endif // YAZE_APP_GFX_TEXTURE_ATLAS_H