Add method to mark image override textures as dirty

Followup to #1558, which caches images. There's a risk that we'll render stale cached date from dynamic external textures, so we provide a method to mark those as dirty.
diff --git a/vello/src/lib.rs b/vello/src/lib.rs
index 91b92f7..81bb357 100644
--- a/vello/src/lib.rs
+++ b/vello/src/lib.rs
@@ -544,6 +544,15 @@
         }
     }
 
+    /// Marks `image` as dirty in the atlas cache, so its override texture will be re-copied on
+    /// the next render.
+    ///
+    /// Call this each frame for any `image` whose override texture has changed since the last
+    /// render. Otherwise, it's possible stale image data from the atlas will be used.
+    pub fn mark_override_image_dirty(&mut self, image: &ImageData) {
+        self.resolver.mark_image_dirty(image);
+    }
+
     /// Register a [`wgpu::Texture`] with Vello, to allow drawing GPU-resident data.
     ///
     /// The returned `Image` can be used in [`Scene`]s (only those rendered with this `Renderer`)
diff --git a/vello_encoding/src/image_cache.rs b/vello_encoding/src/image_cache.rs
index cdda269..d894ff5 100644
--- a/vello_encoding/src/image_cache.rs
+++ b/vello_encoding/src/image_cache.rs
@@ -158,6 +158,12 @@
             && image.height <= self.atlas.size().height as u32
     }
 
+    pub(crate) fn mark_dirty(&mut self, image: &ImageData) {
+        if let Some(resident) = self.map.get_mut(&image.data.id()) {
+            resident.dirty = true;
+        }
+    }
+
     pub(crate) fn evict_stale_entries(&mut self) -> bool {
         if self.evicted_in_resolve != 0 {
             return false;
diff --git a/vello_encoding/src/resolve.rs b/vello_encoding/src/resolve.rs
index 442f604..d605101 100644
--- a/vello_encoding/src/resolve.rs
+++ b/vello_encoding/src/resolve.rs
@@ -170,6 +170,11 @@
         Self::default()
     }
 
+    /// Marks the atlas entry for `image` as dirty, forcing it to be re-uploaded on the next resolve.
+    pub fn mark_image_dirty(&mut self, image: &ImageData) {
+        self.image_cache.mark_dirty(image);
+    }
+
     /// Resolves late bound resources and packs an encoding. Returns the packed
     /// layout and computed ramp data.
     pub fn resolve<'a>(