2025-07-06 20:43:53 +03:00
# pragma once
# include "ResourceDisplay.hpp"
# include <include/core/SkImage.h>
# include <vector>
2025-10-10 18:41:08 +03:00
# include <thread>
# include <include/codec/SkCodec.h>
2026-02-19 15:21:47 +03:00
# include <queue>
2025-07-06 20:43:53 +03:00
class ImageResourceDisplay : public ResourceDisplay {
public :
virtual void update ( World & w ) override ;
2026-02-19 15:21:47 +03:00
virtual bool load ( ResourceManager & rMan , const std : : string & fileName , const std : : shared_ptr < std : : string > & fileData ) override ;
2025-07-06 20:43:53 +03:00
virtual bool update_draw ( ) const override ;
virtual void draw ( SkCanvas * canvas , const DrawData & drawData , const SkRect & imRect ) override ;
virtual Vector2f get_dimensions ( ) const override ;
virtual float get_dimension_scale ( ) const override ;
2025-10-09 16:56:05 +03:00
virtual Type get_type ( ) const override ;
2026-02-19 15:21:47 +03:00
virtual void camera_view_update ( const CoordSpaceHelper & compCoords , const SCollision : : AABB < WorldScalar > & compAABB , const DrawData & drawData , const SkRect & imRect ) override ;
2026-02-19 22:29:24 +03:00
virtual void clear_cache ( ) override ;
2025-10-10 18:41:08 +03:00
virtual ~ ImageResourceDisplay ( ) override ;
2026-02-19 15:21:47 +03:00
static int IMAGE_LOAD_THREAD_COUNT_MAX ;
2025-07-06 20:43:53 +03:00
private :
2026-02-19 15:21:47 +03:00
static constexpr int SMALLEST_MIPMAP_RESOLUTION = 128 ;
2025-07-06 20:43:53 +03:00
struct FrameData {
2026-02-19 15:21:47 +03:00
// Mipmap level calculation is done using the smaller dimension, not the bigger one, to ensure that the dimensions are never invalid
std : : vector < sk_sp < SkImage > > mipmapLevels ;
sk_sp < SkImage > smallestMipmapLevel ; // Smaller dimension of this should be around SMALLEST_MIPMAP_RESOLUTION pixels. Is always allocated and used when cachedMipmapLevel is unavailable or when the image is viewed from far away
float duration = - 1.0f ;
2025-07-06 20:43:53 +03:00
} ;
2026-02-19 15:21:47 +03:00
static std : : unordered_map < std : : shared_ptr < std : : string > , sk_sp < SkImage > > screenshotCache ;
static std : : atomic < int > imageLoadThreadCount ;
2025-07-06 20:43:53 +03:00
std : : vector < FrameData > frames ;
2025-10-10 18:41:08 +03:00
2026-02-19 15:21:47 +03:00
enum class MipmapLevelStatus {
UNALLOCATED ,
ALLOCATED_JUST_SET ,
ALLOCATED_WILL_REMOVE
} ;
2025-10-10 18:41:08 +03:00
2026-02-19 15:21:47 +03:00
std : : vector < std : : atomic < MipmapLevelStatus > > mipmapLevelsStatus ;
std : : atomic < bool > smallestMipmapLevelLoaded = false ;
2025-10-10 18:41:08 +03:00
2026-02-19 15:21:47 +03:00
std : : shared_ptr < std : : string > fileData ;
SkImageInfo imageInfo ;
2025-10-10 18:41:08 +03:00
2025-07-06 20:43:53 +03:00
float currentTime = 0.0f ;
2026-02-19 22:02:18 +03:00
unsigned frameIndex = 0 ;
2026-02-19 15:21:47 +03:00
bool mustUpdateDraw = false ;
std : : unique_ptr < std : : thread > loadThread ;
std : : atomic < bool > shutdownLoadThread = false ;
std : : atomic < bool > mustUpdateDrawLoadThread = false ;
2026-02-19 22:02:18 +03:00
unsigned get_exact_mipmap_level_for_image_component ( const DrawData & drawData , const CoordSpaceHelper & compCoords , const SkRect & imRect ) ;
unsigned get_exact_mipmap_level_for_dimensions ( const Vector2i & dim ) ;
unsigned get_best_allocated_mipmap_level ( unsigned mipmapLevel ) ;
unsigned get_smallest_mipmap_level ( ) const ;
Vector2i get_mipmap_level_image_dimensions ( unsigned mipmapLevel ) const ;
unsigned calculate_smallest_mipmap_level ( ) ;
void load_thread_func ( unsigned mipmapLevel ) ;
void attempt_load_mipmap_in_separate_thread ( unsigned mipmapLevel ) ;
2026-02-19 15:21:47 +03:00
sk_sp < SkImage > load_frame_with_codec ( const std : : unique_ptr < SkCodec > & codec , unsigned width , unsigned height , unsigned frameIndexToLoad ) ;
2025-07-06 20:43:53 +03:00
} ;