From fe4716765ce4c0ea48160d64f44ab61995dc47ce Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Wed, 21 Jan 2026 13:11:01 +0300 Subject: [PATCH] Added screen space cache --- src/DrawingProgram/DrawingProgram.cpp | 3 +- src/DrawingProgram/DrawingProgramCache.cpp | 82 ++++++++++++++++++++++ src/DrawingProgram/DrawingProgramCache.hpp | 17 ++++- 3 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/DrawingProgram/DrawingProgram.cpp b/src/DrawingProgram/DrawingProgram.cpp index 804c966..d4f7100 100644 --- a/src/DrawingProgram/DrawingProgram.cpp +++ b/src/DrawingProgram/DrawingProgram.cpp @@ -604,8 +604,7 @@ void DrawingProgram::draw(SkCanvas* canvas, const DrawData& drawData) { else { canvas->saveLayer(nullptr, nullptr); canvas->clear(SkColor4f{0.0f, 0.0f, 0.0f, 0.0f}); - drawCache.refresh_all_draw_cache(drawData); - drawCache.draw_components_to_canvas(canvas, drawData, {}); + drawCache.update_and_draw_cached_canvas(canvas, drawData); canvas->saveLayer(nullptr, nullptr); selection.draw_components(canvas, drawData); canvas->restore(); diff --git a/src/DrawingProgram/DrawingProgramCache.cpp b/src/DrawingProgram/DrawingProgramCache.cpp index 8f48b00..2332bbf 100644 --- a/src/DrawingProgram/DrawingProgramCache.cpp +++ b/src/DrawingProgram/DrawingProgramCache.cpp @@ -12,6 +12,7 @@ #endif std::unordered_map, DrawingProgramCache::NodeCache> DrawingProgramCache::nodeCacheMap; +DrawingProgramCache::WindowCache DrawingProgramCache::windowCache; DrawingProgramCache::DrawingProgramCache(DrawingProgram& initDrawP): drawP(initDrawP) @@ -44,6 +45,14 @@ void DrawingProgramCache::invalidate_cache_at_aabb(const SCollision::AABB& cC) { @@ -303,6 +314,77 @@ void DrawingProgramCache::refresh_draw_cache(const std::shared_ptr cameraSpaceInvalidAABB = drawData.cam.c.world_collider_to_coords>(iBounds); + SCollision::AABB clipRectBoundAABB{cameraSpaceInvalidAABB.min - Vector2f{4, 4}, cameraSpaceInvalidAABB.max + Vector2f{4, 4}}; + + SkIRect clipRect = SkIRect::MakeLTRB(clipRectBoundAABB.min.x(), + clipRectBoundAABB.min.y(), + clipRectBoundAABB.max.x(), + clipRectBoundAABB.max.y()); + + SCollision::AABB clipRectBoundAABBWorld = drawData.cam.c.collider_to_world>(clipRectBoundAABB); + + SkCanvas* cacheCanvas = windowCache.surface->getCanvas(); + cacheCanvas->save(); + cacheCanvas->clipIRect(clipRect); + cacheCanvas->clear(SkColor4f{0, 0, 0, 0}); + draw_components_to_canvas(cacheCanvas, drawData, clipRectBoundAABBWorld); + cacheCanvas->restore(); + windowCache.invalidBounds = std::nullopt; +} + +void DrawingProgramCache::window_cache_complete_refresh(const DrawData& drawData) { + SkCanvas* cacheCanvas = windowCache.surface->getCanvas(); + cacheCanvas->save(); + cacheCanvas->clear(SkColor4f{0, 0, 0, 0}); + draw_components_to_canvas(cacheCanvas, drawData, std::nullopt); + cacheCanvas->restore(); + windowCache.attachedDrawingProgramCache = this; + windowCache.coords = drawData.cam.c; +} + +void DrawingProgramCache::update_and_draw_cached_canvas(SkCanvas* canvas, const DrawData& drawData) { + if(windowCache.surface == nullptr || drawData.main->window.size != windowCache.size) { + allocate_window_cache_area(); + refresh_all_draw_cache(drawData); + window_cache_complete_refresh(drawData); + } + else if(windowCache.attachedDrawingProgramCache != this || drawData.cam.c != windowCache.coords) { + refresh_all_draw_cache(drawData); + window_cache_complete_refresh(drawData); + } + else if(windowCache.invalidBounds.has_value()) { + refresh_all_draw_cache(drawData); + update_window_cache_invalid_bounds(drawData); + } + canvas->drawImage(windowCache.surface->makeTemporaryImage(), 0, 0, {SkFilterMode::kNearest, SkMipmapMode::kNone}, nullptr); +} + void DrawingProgramCache::draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::optional>& drawBounds) { if(drawP.layerMan.layer_tree_root_exists()) { std::vector> cachedNodesToDraw; diff --git a/src/DrawingProgram/DrawingProgramCache.hpp b/src/DrawingProgram/DrawingProgramCache.hpp index 4bcf05c..ea4ad72 100644 --- a/src/DrawingProgram/DrawingProgramCache.hpp +++ b/src/DrawingProgram/DrawingProgramCache.hpp @@ -31,10 +31,12 @@ class DrawingProgramCache { void node_loop_erase_if_components(const std::shared_ptr& bvhNode, std::function f); void node_loop_components(const std::shared_ptr& bvhNode, std::function f); bool should_rebuild() const; + void update_and_draw_cached_canvas(SkCanvas* canvas, const DrawData& drawData); void draw_components_to_canvas(SkCanvas* canvas, const DrawData& drawData, const std::optional>& drawBounds); bool unsorted_components_exist() const; void invalidate_cache_at_aabb(const SCollision::AABB& aabb); - void refresh_all_draw_cache(const DrawData& drawData); + void set_clear_window_cache(); + CanvasComponentContainer::ObjInfo* get_front_object_colliding_with_in_editing_layer(const SCollision::ColliderCollection& cC); ~DrawingProgramCache(); private: @@ -46,6 +48,19 @@ class DrawingProgramCache { }; static std::unordered_map, NodeCache> nodeCacheMap; + struct WindowCache { + sk_sp surface; + DrawingProgramCache* attachedDrawingProgramCache = nullptr; + std::optional> invalidBounds; + Vector2i size = {0, 0}; + CoordSpaceHelper coords; + }; + static WindowCache windowCache; + + void refresh_all_draw_cache(const DrawData& drawData); + void update_window_cache_invalid_bounds(const DrawData& drawData); + void window_cache_complete_refresh(const DrawData& drawData); + void allocate_window_cache_area(); void internal_build(std::vector componentsToBuild, const std::unordered_set& objsToNotInclude); void build_bvh_node(const std::shared_ptr& bvhNode, const std::vector& components); void build_bvh_node_coords_and_resolution(DrawingProgramCacheBVHNode& node);