Retain surface textures for animations
This commit is contained in:
parent
3540cdc4be
commit
fba9d65ba1
8 changed files with 365 additions and 19 deletions
182
src/renderer.rs
182
src/renderer.rs
|
|
@ -1,7 +1,8 @@
|
|||
use {
|
||||
crate::{
|
||||
animation::{RetainedContent, RetainedSurface, RetainedToplevel},
|
||||
cmm::cmm_render_intent::RenderIntent,
|
||||
gfx_api::{AcquireSync, AlphaMode, GfxApiOpt, ReleaseSync, SampleRect},
|
||||
gfx_api::{AcquireSync, AlphaMode, BufferResv, GfxApiOpt, ReleaseSync, SampleRect},
|
||||
ifs::wl_surface::{
|
||||
SurfaceBuffer, WlSurface,
|
||||
x_surface::xwindow::Xwindow,
|
||||
|
|
@ -467,6 +468,167 @@ impl Renderer<'_> {
|
|||
visual.move_(-container.abs_x1.get(), -container.abs_y1.get())
|
||||
}
|
||||
|
||||
fn render_child_or_snapshot(
|
||||
&mut self,
|
||||
child: &Rc<dyn ToplevelNode>,
|
||||
x: i32,
|
||||
y: i32,
|
||||
bounds: Option<&Rect>,
|
||||
) {
|
||||
if let Some(retained) = self
|
||||
.state
|
||||
.animations
|
||||
.retained_snapshot(child.node_id(), self.state.now_nsec())
|
||||
{
|
||||
self.render_retained_toplevel(&retained, x, y, bounds);
|
||||
} else {
|
||||
child.node_render(self, x, y, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_retained_toplevel(
|
||||
&mut self,
|
||||
retained: &RetainedToplevel,
|
||||
x: i32,
|
||||
y: i32,
|
||||
bounds: Option<&Rect>,
|
||||
) {
|
||||
let (x, y) = self
|
||||
.base
|
||||
.scale_point(x + retained.offset.0, y + retained.offset.1);
|
||||
self.render_retained_surface_scaled(&retained.surface, x, y, None, bounds);
|
||||
}
|
||||
|
||||
fn render_retained_surface_scaled(
|
||||
&mut self,
|
||||
retained: &RetainedSurface,
|
||||
x: i32,
|
||||
y: i32,
|
||||
pos_rel: Option<(i32, i32)>,
|
||||
bounds: Option<&Rect>,
|
||||
) {
|
||||
let stretch = self.stretch.take();
|
||||
let corner_radius = self.corner_radius.take();
|
||||
let mut size = retained.size;
|
||||
if let Some((x_rel, y_rel)) = pos_rel {
|
||||
let (x, y) = self.base.scale_point(x_rel, y_rel);
|
||||
let (w, h) = self.base.scale_point(x_rel + size.0, y_rel + size.1);
|
||||
size = (w - x, h - y);
|
||||
} else {
|
||||
size = self.base.scale_point(size.0, size.1);
|
||||
}
|
||||
let mut stretched_source = None;
|
||||
if let Some(s) = stretch {
|
||||
if let RetainedContent::Texture { source, .. } = &retained.content {
|
||||
let mut source = *source;
|
||||
if size.0 > 0 && size.1 > 0 {
|
||||
let sx = s.0 as f32 / size.0 as f32;
|
||||
let sy = s.1 as f32 / size.1 as f32;
|
||||
source.x2 *= sx;
|
||||
source.y2 *= sy;
|
||||
}
|
||||
stretched_source = Some(source);
|
||||
}
|
||||
size = s;
|
||||
}
|
||||
for child in &retained.below {
|
||||
let (x1, y1) = self.base.scale_point(child.offset.0, child.offset.1);
|
||||
self.render_retained_surface_scaled(child, x + x1, y + y1, Some(child.offset), bounds);
|
||||
}
|
||||
self.corner_radius = corner_radius;
|
||||
self.render_retained_content(retained, stretched_source, x, y, size, bounds);
|
||||
for child in &retained.above {
|
||||
let (x1, y1) = self.base.scale_point(child.offset.0, child.offset.1);
|
||||
self.render_retained_surface_scaled(child, x + x1, y + y1, Some(child.offset), bounds);
|
||||
}
|
||||
}
|
||||
|
||||
fn render_retained_content(
|
||||
&mut self,
|
||||
retained: &RetainedSurface,
|
||||
stretched_source: Option<SampleRect>,
|
||||
x: i32,
|
||||
y: i32,
|
||||
size: (i32, i32),
|
||||
bounds: Option<&Rect>,
|
||||
) {
|
||||
let corner_radius = self.corner_radius.take();
|
||||
match &retained.content {
|
||||
RetainedContent::Texture {
|
||||
texture,
|
||||
buffer,
|
||||
source,
|
||||
alpha,
|
||||
color_description,
|
||||
render_intent,
|
||||
alpha_mode,
|
||||
opaque,
|
||||
} => {
|
||||
let source = stretched_source.unwrap_or(*source);
|
||||
if let Some(cr) = corner_radius {
|
||||
self.base.render_rounded_texture(
|
||||
texture,
|
||||
*alpha,
|
||||
x,
|
||||
y,
|
||||
Some(source),
|
||||
Some(size),
|
||||
self.base.scale,
|
||||
bounds,
|
||||
Some(buffer.clone() as Rc<dyn BufferResv>),
|
||||
AcquireSync::Unnecessary,
|
||||
buffer.release_sync,
|
||||
color_description,
|
||||
*render_intent,
|
||||
*alpha_mode,
|
||||
cr,
|
||||
);
|
||||
} else {
|
||||
self.base.render_texture(
|
||||
texture,
|
||||
*alpha,
|
||||
x,
|
||||
y,
|
||||
Some(source),
|
||||
Some(size),
|
||||
self.base.scale,
|
||||
bounds,
|
||||
Some(buffer.clone() as Rc<dyn BufferResv>),
|
||||
AcquireSync::Unnecessary,
|
||||
buffer.release_sync,
|
||||
*opaque,
|
||||
color_description,
|
||||
*render_intent,
|
||||
*alpha_mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
RetainedContent::Color {
|
||||
color,
|
||||
alpha,
|
||||
color_description,
|
||||
render_intent,
|
||||
} => {
|
||||
if let Some(rect) = Rect::new_sized(x, y, size.0, size.1) {
|
||||
let rect = match bounds {
|
||||
None => rect,
|
||||
Some(bounds) => rect.intersect(*bounds),
|
||||
};
|
||||
if !rect.is_empty() {
|
||||
self.base.sync();
|
||||
self.base.fill_scaled_boxes(
|
||||
&[rect],
|
||||
color,
|
||||
*alpha,
|
||||
&color_description.linear,
|
||||
*render_intent,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
|
||||
self.render_container_decorations(container, x, y);
|
||||
|
||||
|
|
@ -526,9 +688,12 @@ impl Renderer<'_> {
|
|||
self.corner_radius = Some(inner_cr);
|
||||
}
|
||||
}
|
||||
child
|
||||
.node
|
||||
.node_render(self, x + content.x1(), y + content.y1(), Some(&body));
|
||||
self.render_child_or_snapshot(
|
||||
&child.node,
|
||||
x + content.x1(),
|
||||
y + content.y1(),
|
||||
Some(&body),
|
||||
);
|
||||
self.stretch = None;
|
||||
self.corner_radius = None;
|
||||
} else {
|
||||
|
|
@ -579,9 +744,12 @@ impl Renderer<'_> {
|
|||
}
|
||||
let body = body.move_(x, y);
|
||||
let body = self.base.scale_rect(body);
|
||||
child
|
||||
.node
|
||||
.node_render(self, x + content.x1(), y + content.y1(), Some(&body));
|
||||
self.render_child_or_snapshot(
|
||||
&child.node,
|
||||
x + content.x1(),
|
||||
y + content.y1(),
|
||||
Some(&body),
|
||||
);
|
||||
self.stretch = None;
|
||||
self.corner_radius = None;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue