evictTilesOutsideViewport

fun evictTilesOutsideViewport(visibleHashShorts: Set<String>, protectedAncestorHashShorts: Set<String> = emptySet())

Evicts every cached tile×time whose tile coordinate (x/y/z, ignoring interval) is not in visibleHashShorts and is not a protected zoom-ancestor of one (protectedAncestorHashShorts) — i.e., belongs to a viewport panned away from. Deliberately runs regardless of play state (unlike evictTimesNotIn): rule 7's "never evict" is about the currently visible tiles' full timeline, not every viewport ever visited during a session. Without this, GPU/native memory for stale viewports never comes back, growing unbounded until downloads stall and rendering has no headroom left to animate.

protectedAncestorHashShorts exists because a zoom change was evicting the exact same coarser tiles RenderPass.determinePartial falls back to for the newly-visible (not-yet- downloaded) tiles at the new zoom — this ran every frame via flushPendingGpuEvictions racing the very next draw call, so the ancestor was gone before the fallback could ever use it, and zooming in showed a hard blank instead of a cropped/scaled parent texture. The ancestor set is geometrically small (at most one tile per zoom level per visible tile, shrinking toward zoom 0), so protecting it does not reintroduce the unbounded growth this eviction exists to prevent.