Perform layer::Stack::merge before rendering

This commit is contained in:
Héctor Ramón Jiménez 2025-08-18 20:51:57 +02:00
parent ab4fdaf91d
commit fb5ac7dcb0
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
3 changed files with 35 additions and 34 deletions

View file

@ -103,27 +103,7 @@ impl<T: Layer> Stack<T> {
pub fn pop_clip(&mut self) {
self.flush();
let previous = self.previous.pop().unwrap();
// Try to merge contiguous layers
if previous + 1 == self.current {
let (head, tail) = self.layers.split_at_mut(previous + 1);
let previous_layer = &mut head[previous];
let current_layer = &mut tail[0];
if previous_layer.end() <= current_layer.start()
&& previous_layer.bounds() == current_layer.bounds()
{
previous_layer.merge(current_layer);
// We can reuse the last layer
if self.current + 1 == self.active_count {
self.active_count -= 1;
}
}
}
self.current = previous;
self.current = self.previous.pop().unwrap();
}
/// Pushes a new [`Transformation`] in the [`Stack`].
@ -142,13 +122,6 @@ impl<T: Layer> Stack<T> {
let _ = self.transformations.pop();
}
/// Returns an iterator over mutable references to the layers in the [`Stack`].
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
self.flush();
self.layers[..self.active_count].iter_mut()
}
/// Returns an iterator over immutable references to the layers in the [`Stack`].
pub fn iter(&self) -> impl Iterator<Item = &T> {
self.layers[..self.active_count].iter()
@ -159,11 +132,37 @@ impl<T: Layer> Stack<T> {
&self.layers[..self.active_count]
}
/// Flushes and settles any primitives in the current layer of the [`Stack`].
/// Flushes and settles any primitives in the [`Stack`].
pub fn flush(&mut self) {
self.layers[self.current].flush();
}
/// Performs layer merging wherever possible.
///
/// Flushes and settles any primitives in the [`Stack`].
pub fn merge(&mut self) {
self.flush();
let mut current = 0;
while current < self.active_count {
let (head, tail) = self.layers.split_at_mut(current + 1);
let layer = &mut head[current];
let mut candidate = 0;
while let Some(next_layer) = tail.get_mut(candidate)
&& layer.end() <= next_layer.start()
&& layer.bounds() == next_layer.bounds()
{
layer.merge(next_layer);
candidate += 1;
}
current += candidate + 1;
}
}
/// Clears the layers of the [`Stack`], allowing reuse.
///
/// It resizes the base layer bounds to the `new_bounds`.

View file

@ -301,7 +301,7 @@ impl graphics::Layer for Layer {
return 0;
}
if !self.triangles.is_empty() || !self.pending_meshes.is_empty() {
if !self.triangles.is_empty() {
return 1;
}
@ -313,7 +313,7 @@ impl graphics::Layer for Layer {
return 3;
}
if !self.text.is_empty() || !self.pending_text.is_empty() {
if !self.text.is_empty() {
return 4;
}
@ -321,7 +321,7 @@ impl graphics::Layer for Layer {
}
fn end(&self) -> usize {
if !self.text.is_empty() || !self.pending_text.is_empty() {
if !self.text.is_empty() {
return 4;
}
@ -333,7 +333,7 @@ impl graphics::Layer for Layer {
return 2;
}
if !self.triangles.is_empty() || !self.pending_meshes.is_empty() {
if !self.triangles.is_empty() {
return 1;
}

View file

@ -311,7 +311,9 @@ impl Renderer {
viewport.physical_size(),
));
for layer in self.layers.iter_mut() {
self.layers.merge();
for layer in self.layers.iter() {
if physical_bounds
.intersection(&(layer.bounds * scale_factor))
.and_then(Rectangle::snap)