micro optimization fixes

This commit is contained in:
Samuel Onoja committed 2026-10-01 20:47:05 +01:00
1 parent 0d7203f84b
commit da60ecb719
36 files changed
+1781 -521

No files matched your search

+24 -24
View File
@@ -130,7 +130,7 @@ pub(super) fn window_border_element(
let context = renderer.context_id().erased();
let buffers = &mut resources.windows.entry(id).or_default().borders;
if !buffers.contexts.contains_key(&context) {
let element = PixelShaderElement::new(
let element = SharedPixelShaderElement::new(
programs.border.clone(),
geometry,
None,
@@ -164,16 +164,16 @@ pub(super) fn window_border_element(
pub(super) fn border_uniforms(parameters: &BorderParameters) -> Vec<Uniform<'static>> {
vec![
Uniform::new("clip_rect", parameters.clip_rect).into_owned(),
Uniform::new("radius", parameters.radius).into_owned(),
Uniform::new("border_width", parameters.width).into_owned(),
Uniform::new("border_color", parameters.color).into_owned(),
Uniform::new("border_color_to", parameters.color_to).into_owned(),
Uniform::new("gradient_line", parameters.gradient_line).into_owned(),
Uniform::new("focus_color", parameters.focus_color).into_owned(),
Uniform::new("focus_color_to", parameters.focus_color_to).into_owned(),
Uniform::new("focus_gradient_line", parameters.focus_gradient_line).into_owned(),
Uniform::new("focus_mix", parameters.focus_mix).into_owned(),
Uniform::new("clip_rect", parameters.clip_rect),
Uniform::new("radius", parameters.radius),
Uniform::new("border_width", parameters.width),
Uniform::new("border_color", parameters.color),
Uniform::new("border_color_to", parameters.color_to),
Uniform::new("gradient_line", parameters.gradient_line),
Uniform::new("focus_color", parameters.focus_color),
Uniform::new("focus_color_to", parameters.focus_color_to),
Uniform::new("focus_gradient_line", parameters.focus_gradient_line),
Uniform::new("focus_mix", parameters.focus_mix),
]
}
@@ -213,12 +213,12 @@ pub(super) fn window_tint_element(
};
let uniforms = |p: &BorderParameters| {
vec![
Uniform::new("visible_rect", p.clip_rect).into_owned(),
Uniform::new("material_radius", p.radius).into_owned(),
Uniform::new("tint", p.color).into_owned(),
Uniform::new("paint_mode", 0.0_f32).into_owned(),
Uniform::new("shadow_rect", p.clip_rect).into_owned(),
Uniform::new("shadow_values", [0.0_f32; 2]).into_owned(),
Uniform::new("visible_rect", p.clip_rect),
Uniform::new("material_radius", p.radius),
Uniform::new("tint", p.color),
Uniform::new("paint_mode", 0.0_f32),
Uniform::new("shadow_rect", p.clip_rect),
Uniform::new("shadow_values", [0.0_f32; 2]),
]
};
let context = renderer.context_id().erased();
@@ -228,7 +228,7 @@ pub(super) fn window_tint_element(
&mut resources.windows.entry(id).or_default().dim
};
let cached = buffers.contexts.entry(context).or_insert_with(|| CachedBorder {
element: PixelShaderElement::new(
element: SharedPixelShaderElement::new(
program.0,
geometry,
None,
@@ -293,7 +293,7 @@ pub(super) fn window_shadow_element(
let context = renderer.context_id().erased();
let buffers = &mut resources.windows.entry(id).or_default().shadow;
if !buffers.contexts.contains_key(&context) {
let element = PixelShaderElement::new(
let element = SharedPixelShaderElement::new(
programs.shadow.clone(),
bounds,
None,
@@ -331,11 +331,11 @@ pub(super) fn window_shadow_element(
pub(super) fn shadow_uniforms(parameters: &ShadowParameters) -> Vec<Uniform<'static>> {
vec![
Uniform::new("shadow_rect", parameters.shadow_rect).into_owned(),
Uniform::new("radius", parameters.radius).into_owned(),
Uniform::new("blur", parameters.blur).into_owned(),
Uniform::new("opacity", parameters.opacity).into_owned(),
Uniform::new("shadow_color", parameters.color).into_owned(),
Uniform::new("shadow_rect", parameters.shadow_rect),
Uniform::new("radius", parameters.radius),
Uniform::new("blur", parameters.blur),
Uniform::new("opacity", parameters.opacity),
Uniform::new("shadow_color", parameters.color),
]
}
+16 -16
View File
@@ -248,7 +248,7 @@ pub(super) fn material_element(
capture.dirty.clone(),
))
} else {
MaterialElement::Fill(PixelShaderElement::new(
MaterialElement::Fill(SharedPixelShaderElement::new(
program.0.clone(),
geometry,
parameters.opaque.then(|| vec![Rectangle::from_size(geometry.size)]),
@@ -264,7 +264,7 @@ pub(super) fn material_element(
.or_insert_with(|| CachedMaterial {
element: make_element(),
parameters: parameters.clone(),
shadow: PixelShaderElement::new(
shadow: SharedPixelShaderElement::new(
program.0.clone(),
parameters.shadow_bounds,
None,
@@ -356,14 +356,14 @@ pub(super) fn blur_uniform_names() -> [UniformName<'static>; 8] {
pub(super) fn blur_uniforms(p: &MaterialParameters) -> Vec<Uniform<'static>> {
vec![
Uniform::new("visible_rect", p.visible_framebuffer).into_owned(),
Uniform::new("material_radius", p.radius).into_owned(),
Uniform::new("texture_size", [p.sample_framebuffer[2], p.sample_framebuffer[3]]).into_owned(),
Uniform::new("capture_origin", [p.sample_framebuffer[0], p.sample_framebuffer[1]]).into_owned(),
Uniform::new("blur_radius", p.blur).into_owned(),
Uniform::new("presentation_alpha", p.presentation_alpha).into_owned(),
Uniform::new("background_opacity", p.background_opacity).into_owned(),
Uniform::new("tint", p.tint).into_owned(),
Uniform::new("visible_rect", p.visible_framebuffer),
Uniform::new("material_radius", p.radius),
Uniform::new("texture_size", [p.sample_framebuffer[2], p.sample_framebuffer[3]]),
Uniform::new("capture_origin", [p.sample_framebuffer[0], p.sample_framebuffer[1]]),
Uniform::new("blur_radius", p.blur),
Uniform::new("presentation_alpha", p.presentation_alpha),
Uniform::new("background_opacity", p.background_opacity),
Uniform::new("tint", p.tint),
]
}
@@ -426,12 +426,12 @@ pub(super) fn material_uniforms(parameters: &MaterialParameters) -> Vec<Uniform<
pub(super) fn decoration_uniforms(parameters: &MaterialParameters, paint_mode: f32) -> Vec<Uniform<'static>> {
vec![
Uniform::new("paint_mode", paint_mode).into_owned(),
Uniform::new("shadow_rect", parameters.shadow_rect).into_owned(),
Uniform::new("shadow_values", parameters.shadow_values).into_owned(),
Uniform::new("visible_rect", parameters.visible_framebuffer).into_owned(),
Uniform::new("material_radius", parameters.radius).into_owned(),
Uniform::new("tint", parameters.tint).into_owned(),
Uniform::new("paint_mode", paint_mode),
Uniform::new("shadow_rect", parameters.shadow_rect),
Uniform::new("shadow_values", parameters.shadow_values),
Uniform::new("visible_rect", parameters.visible_framebuffer),
Uniform::new("material_radius", parameters.radius),
Uniform::new("tint", parameters.tint),
]
}
+10 -9
View File
@@ -4,6 +4,7 @@ mod materials;
mod overview;
mod resources;
mod scene;
mod shader;
use std::collections::HashMap;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
@@ -18,6 +19,7 @@ use scene::cursor_elements;
pub(crate) use scene::{
animated_window_elements, frame_effect_metrics, layer_surfaces, output_elements, sampled_output_elements,
};
pub(crate) use shader::SharedPixelShaderElement;
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::memory::MemoryRenderBufferRenderElement;
use smithay::backend::renderer::element::solid::SolidColorRenderElement;
@@ -31,7 +33,6 @@ use smithay::backend::renderer::element::utils::{
use smithay::backend::renderer::element::{
Element, Id, Kind as RenderElementKind, RenderElement, UnderlyingStorage, render_elements,
};
use smithay::backend::renderer::gles::element::PixelShaderElement;
use smithay::backend::renderer::gles::{
GlesError, GlesFrame, GlesPixelProgram, GlesRenderer, GlesTexProgram, GlesTexture, Uniform, UniformName,
UniformType,
@@ -66,7 +67,7 @@ render_elements! {
Memory=MemoryRenderElement,
Solid=SolidColorRenderElement,
LockSurface=WaylandSurfaceRenderElement<GlesRenderer>,
Border=PixelShaderElement,
Border=SharedPixelShaderElement,
Blur=BlurRenderElement,
Effect=PhysicalShaderElement,
Native=NativeTextureElement,
@@ -132,7 +133,7 @@ struct BlurRenderElement {
commit: CommitCounter,
geometry: Rectangle<i32, Logical>,
capture_rect: [i32; 4],
uniforms: Vec<Uniform<'static>>,
uniforms: Arc<[Uniform<'static>]>,
}
impl BlurRenderElement {
@@ -150,7 +151,7 @@ impl BlurRenderElement {
commit: CommitCounter::default(),
geometry: parameters.sample_geometry,
capture_rect: framebuffer_capture_rect(parameters.sample_framebuffer),
uniforms: blur_uniforms(parameters),
uniforms: blur_uniforms(parameters).into(),
}
}
@@ -158,7 +159,7 @@ impl BlurRenderElement {
self.capture_dirty.store(true, Ordering::Relaxed);
self.geometry = parameters.sample_geometry;
self.capture_rect = framebuffer_capture_rect(parameters.sample_framebuffer);
self.uniforms = blur_uniforms(parameters);
self.uniforms = blur_uniforms(parameters).into();
self.commit.increment();
}
}
@@ -327,7 +328,7 @@ struct MaterialParameters {
#[derive(Clone, Debug)]
enum MaterialElement {
Fill(PixelShaderElement),
Fill(SharedPixelShaderElement),
Blur(BlurRenderElement),
}
@@ -335,7 +336,7 @@ enum MaterialElement {
struct CachedMaterial {
element: MaterialElement,
parameters: MaterialParameters,
shadow: PixelShaderElement,
shadow: SharedPixelShaderElement,
}
#[derive(Debug, Default)]
@@ -361,7 +362,7 @@ struct BorderParameters {
#[derive(Debug)]
struct CachedBorder {
element: PixelShaderElement,
element: SharedPixelShaderElement,
parameters: BorderParameters,
}
@@ -382,7 +383,7 @@ struct ShadowParameters {
#[derive(Debug)]
struct CachedShadow {
element: PixelShaderElement,
element: SharedPixelShaderElement,
parameters: ShadowParameters,
}
+17 -19
View File
@@ -40,12 +40,12 @@ pub(super) fn overview_chrome_element(
border_uniforms(p)
} else {
vec![
Uniform::new("visible_rect", p.clip_rect).into_owned(),
Uniform::new("material_radius", p.radius).into_owned(),
Uniform::new("tint", p.color).into_owned(),
Uniform::new("paint_mode", 0.0_f32).into_owned(),
Uniform::new("shadow_rect", p.clip_rect).into_owned(),
Uniform::new("shadow_values", [0.0_f32; 2]).into_owned(),
Uniform::new("visible_rect", p.clip_rect),
Uniform::new("material_radius", p.radius),
Uniform::new("tint", p.color),
Uniform::new("paint_mode", 0.0_f32),
Uniform::new("shadow_rect", p.clip_rect),
Uniform::new("shadow_values", [0.0_f32; 2]),
]
}
};
@@ -61,7 +61,7 @@ pub(super) fn overview_chrome_element(
.or_default()
.entry(context)
.or_insert_with(|| CachedBorder {
element: PixelShaderElement::new(
element: SharedPixelShaderElement::new(
program,
geometry,
None,
@@ -119,33 +119,31 @@ pub(super) fn overview_strip_elements(
.opacity;
let mut elements = Vec::new();
let programs = rounded_clip_program(&mut state.render, renderer);
// Resolve IDs once per strip, rather than scanning all managed windows
// separately for every miniature. Own the handles so rendering can mutate state.
let windows_by_id: std::collections::HashMap<_, _> = state
.windows
.ids()
state.retain_overview_labels();
let card_ids = cards
.iter()
.map(|(window, id)| (*id, window.clone()))
.collect();
.map(|card| card.workspace.0)
.collect::<std::collections::HashSet<_>>();
if let Some(output_id) = state.output_id(output)
&& let Some(cache) = state.render.outputs.get_mut(&output_id)
{
cache.chrome.retain(|(id, part), _| match part {
OverviewChromePart::Caption => windows_by_id.keys().any(|window| window.0 == *id),
OverviewChromePart::Card | OverviewChromePart::Outline => cards.iter().any(|card| card.workspace.0 == *id),
OverviewChromePart::Caption => state.windows.window(ferese_layout::WindowId(*id)).is_some(),
OverviewChromePart::Card | OverviewChromePart::Outline => card_ids.contains(id),
OverviewChromePart::Strip => true,
});
}
// Cached title textures are independent of window content and stay readable
// when thumbnails are small. Their pills use the shell's material and radius.
for (id, window) in &windows_by_id {
for id in frame.windows.keys() {
if !state.window_belongs_to_output(*id, output) {
continue;
}
let Some(rect) = frame.windows.get(id).map(|sample| sample.rect) else {
continue;
};
let Some((buffer, size)) = state.overview_window_label(window, scale, rect.width) else {
let Some((buffer, size)) = state.overview_window_label(*id, scale, rect.width) else {
continue;
};
let width = (f64::from(size.w) / scale + 16.0).min(rect.width);
@@ -222,7 +220,7 @@ pub(super) fn overview_strip_elements(
}
if let Some(programs) = &programs {
for (id, rect) in &card.windows {
if let Some(window) = windows_by_id.get(id) {
if let Some(window) = state.windows.window(*id) {
elements.extend(rounded_window_elements(
renderer,
window,
+40 -38
View File
@@ -1,3 +1,5 @@
use smithay::desktop::Window;
use super::*;
pub(crate) fn animated_window_elements(
@@ -109,39 +111,42 @@ pub(crate) fn sampled_output_elements(
frame,
));
}
let mut candidates = if state.overview.is_active() {
state.windows.ids().keys().cloned().collect::<Vec<_>>()
let prepare_window = |window: &Window| {
// Configure immediately, but present the frame/shadow only after
// the first buffer commit has settled the actual client geometry.
if !state.window_content_ready(window) {
return None;
}
let id = *state.windows.ids().get(window)?;
// Scrolling columns may sit outside their monitor's rectangle.
// They must not reappear on a neighboring output just because
// their global animated coordinates overlap it.
if !state.window_belongs_to_output(id, output) {
return None;
}
let sample = frame.windows.get(&id)?;
let visual = scaled_visual_rect(sample.rect, sample.close_scale);
let close_alpha = sample.close_alpha;
let decoration_progress = sample.geometry.decorations.clamp(0.0, 1.0);
Some((window.clone(), id, sample, visual, decoration_progress, close_alpha))
};
let windows = if state.overview.is_active() {
state
.windows
.overview_windows()
.filter_map(prepare_window)
.collect::<Vec<_>>()
} else {
state.space.elements().rev().cloned().collect::<Vec<_>>()
state
.space
.elements()
.rev()
.filter_map(prepare_window)
.collect::<Vec<_>>()
};
if state.overview.is_active() {
candidates.sort_by_key(|window| std::cmp::Reverse(state.windows.ids().get(window).map_or(0, |id| id.0)));
}
let windows = candidates
.iter()
.filter_map(|window| {
// Configure immediately, but present the frame/shadow only after
// the first buffer commit has settled the actual client geometry.
if !state.window_content_ready(window) {
return None;
}
let id = *state.windows.ids().get(window)?;
// Scrolling columns may sit outside their monitor's rectangle.
// They must not reappear on a neighboring output just because
// their global animated coordinates overlap it.
if !state.window_belongs_to_output(id, output) {
return None;
}
let sample = frame.windows.get(&id)?;
let visual = scaled_visual_rect(sample.rect, sample.close_scale);
let close_alpha = sample.close_alpha;
let decoration_progress = sample.geometry.decorations.clamp(0.0, 1.0);
Some((window.clone(), id, visual, decoration_progress, close_alpha))
})
.collect::<Vec<_>>();
for (window, id, visual, decoration_progress, close_alpha) in windows {
for (window, id, sample, visual, decoration_progress, close_alpha) in windows {
let constrain = rounded_visual_rect(visual, output_geometry.loc);
let material_surface = window
.toplevel()
@@ -158,10 +163,10 @@ pub(crate) fn sampled_output_elements(
let corners = RoundedRect::new(visual, output_geometry.loc, scale, window_radius);
let pixels = corners.rect;
// Only overview/close intentionally scale the complete application.
let scale_content = frame.overview.is_presenting() || frame.windows[&id].close_scale != 1.0;
let scale_content = frame.overview.is_presenting() || sample.close_scale != 1.0;
let behavior = resize_content_behavior(scale_content);
let dim = frame.windows[&id].dim;
let dim = sample.dim;
if let Some(overlay) = window_tint_element(
&mut state.render,
renderer,
@@ -182,7 +187,7 @@ pub(crate) fn sampled_output_elements(
let shadow_blur = state.theme_settings.shadow_blur;
let shadow_opacity = state.theme_settings.shadow_opacity;
let shadow_color = state.theme_settings.shadow_color.0;
let focus = frame.windows[&id].focus;
let focus = sample.focus;
let border_width = state.theme_settings.border_width
+ (state.theme_settings.focus_ring_width - state.theme_settings.border_width) * focus;
let border_color = state.theme_settings.border_color.0;
@@ -245,10 +250,7 @@ pub(crate) fn sampled_output_elements(
))),
alpha: crate::presentation::handoff_alpha(snapshot.elapsed) * close_alpha,
program: Some(programs.texture.clone()),
uniforms: vec![
Uniform::new("clip_rect", clip).into_owned(),
Uniform::new("radius", corners.radius).into_owned(),
],
uniforms: vec![Uniform::new("clip_rect", clip), Uniform::new("radius", corners.radius)],
}
.into(),
);
@@ -260,7 +262,7 @@ pub(crate) fn sampled_output_elements(
corners,
scale,
close_alpha,
frame.windows[&id].geometry.presentation_changed,
sample.geometry.presentation_changed,
output,
programs.clone(),
behavior,
+231
View File
@@ -0,0 +1,231 @@
//! Static uniform names stay borrowed; cached frame elements share their state.
//! Copy on write preserves the ID and commit seen by an already sampled frame.
use std::sync::Arc;
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement};
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesPixelProgram, GlesRenderer, Uniform};
use smithay::backend::renderer::utils::{CommitCounter, OpaqueRegions};
use smithay::utils::{Buffer, Logical, Physical, Rectangle, Scale, Transform};
#[derive(Clone, Debug)]
pub(crate) struct SharedPixelShaderElement {
shader: GlesPixelProgram,
state: Arc<ShaderState>,
}
#[derive(Clone, Debug)]
struct ShaderState {
id: Id,
commit: CommitCounter,
area: Rectangle<i32, Logical>,
opaque: Vec<Rectangle<i32, Logical>>,
alpha: f32,
uniforms: Vec<Uniform<'static>>,
kind: Kind,
}
impl SharedPixelShaderElement {
pub(crate) fn new(
shader: GlesPixelProgram,
area: Rectangle<i32, Logical>,
opaque: Option<Vec<Rectangle<i32, Logical>>>,
alpha: f32,
uniforms: Vec<Uniform<'static>>,
kind: Kind,
) -> Self {
Self {
shader,
state: Arc::new(ShaderState {
id: Id::new(),
commit: CommitCounter::default(),
area,
opaque: opaque.unwrap_or_default(),
alpha,
uniforms,
kind,
}),
}
}
pub(crate) fn resize(&mut self, area: Rectangle<i32, Logical>, opaque: Option<Vec<Rectangle<i32, Logical>>>) {
let opaque = opaque.unwrap_or_default();
if self.state.area != area || self.state.opaque != opaque {
let state = Arc::make_mut(&mut self.state);
state.area = area;
state.opaque = opaque;
state.commit.increment();
}
}
pub(crate) fn update_uniforms(&mut self, uniforms: Vec<Uniform<'static>>) {
let state = Arc::make_mut(&mut self.state);
state.uniforms = uniforms;
state.commit.increment();
}
}
impl Element for SharedPixelShaderElement {
fn id(&self) -> &Id {
&self.state.id
}
fn current_commit(&self) -> CommitCounter {
self.state.commit
}
fn src(&self) -> Rectangle<f64, Buffer> {
Rectangle::from_size(self.state.area.size.to_f64().to_buffer(1.0, Transform::Normal))
}
fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
self.state.area.to_physical_precise_round(scale)
}
fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
self.state
.opaque
.iter()
.map(|region| region.to_physical_precise_round(scale))
.collect()
}
fn alpha(&self) -> f32 {
self.state.alpha
}
fn kind(&self) -> Kind {
self.state.kind
}
}
impl RenderElement<GlesRenderer> for SharedPixelShaderElement {
fn draw(
&self,
frame: &mut GlesFrame<'_, '_>,
src: Rectangle<f64, Buffer>,
dst: Rectangle<i32, Physical>,
damage: &[Rectangle<i32, Physical>],
_opaque: &[Rectangle<i32, Physical>],
) -> Result<(), GlesError> {
frame.render_pixel_shader_to(
&self.shader,
src,
dst,
self.state.area.size.to_buffer(1, Transform::Normal),
Some(damage),
self.state.alpha,
&self.state.uniforms,
)
}
}
#[cfg(test)]
mod tests {
use std::borrow::Cow;
use smithay::backend::allocator::Fourcc;
use smithay::backend::egl::{EGLContext, EGLDevice, EGLDisplay};
use smithay::backend::renderer::gles::element::PixelShaderElement;
use smithay::backend::renderer::gles::{GlesTexture, UniformName, UniformType};
use smithay::backend::renderer::{Bind, Color32F, ExportMem, Frame, Offscreen, Renderer};
use super::*;
fn pixels(renderer: &mut GlesRenderer, element: &impl RenderElement<GlesRenderer>) -> Vec<u8> {
let size = (32, 32).into();
let mut texture: GlesTexture = renderer.create_buffer(Fourcc::Abgr8888, size).unwrap();
let rect = Rectangle::from_size((32, 32).into());
let mut target = renderer.bind(&mut texture).unwrap();
{
let mut frame = renderer
.render(&mut target, (32, 32).into(), Transform::Normal)
.unwrap();
frame.clear(Color32F::TRANSPARENT, &[rect]).unwrap();
element.draw(&mut frame, element.src(), rect, &[rect], &[]).unwrap();
let _ = frame.finish().unwrap();
}
let mapping = renderer
.copy_framebuffer(&target, Rectangle::from_size(size), Fourcc::Abgr8888)
.unwrap();
renderer.map_texture(&mapping).unwrap().to_vec()
}
#[test]
#[ignore = "requires an EGL rendering device"]
fn shared_shader_matches_smithay_and_keeps_old_frames_immutable() {
let device = EGLDevice::enumerate().unwrap().last().expect("an EGL device");
let display = unsafe { EGLDisplay::new(device).unwrap() };
let mut renderer = unsafe { GlesRenderer::new(EGLContext::new(&display).unwrap()).unwrap() };
let program = renderer
.compile_custom_pixel_shader(
super::super::corner_shader(super::super::ROUNDED_SOLID_SHADER),
&[
UniformName::new("clip_rect", UniformType::_4f),
UniformName::new("radius", UniformType::_1f),
UniformName::new("color", UniformType::_4f),
],
)
.unwrap();
let area = Rectangle::new((2, 3).into(), (32, 32).into());
let uniforms = |color| {
vec![
Uniform::new("clip_rect", [0.0_f32, 0.0, 32.0, 32.0]),
Uniform::new("radius", 8.0_f32),
Uniform::new("color", color),
]
};
let red = [0.5_f32, 0.0, 0.0, 0.5];
let green = [0.0_f32, 0.5, 0.0, 0.5];
let opaque = Some(vec![Rectangle::from_size((20, 20).into())]);
let baseline = PixelShaderElement::new(
program.clone(),
area,
opaque.clone(),
0.5,
uniforms(red),
Kind::Unspecified,
);
let mut shared = SharedPixelShaderElement::new(program, area, opaque, 0.5, uniforms(red), Kind::Unspecified);
let old = shared.clone();
let old_commit = old.current_commit();
assert!(Arc::ptr_eq(&shared.state, &old.state));
assert!(
shared
.state
.uniforms
.iter()
.all(|uniform| matches!(uniform.name, Cow::Borrowed(_)))
);
for scale in [1.0, 1.25, 2.0] {
assert_eq!(shared.geometry(scale.into()), baseline.geometry(scale.into()));
assert_eq!(
&*shared.opaque_regions(scale.into()),
&*baseline.opaque_regions(scale.into())
);
}
assert_eq!(pixels(&mut renderer, &shared), pixels(&mut renderer, &baseline));
shared.resize(area, Some(vec![Rectangle::from_size((20, 20).into())]));
assert!(Arc::ptr_eq(&shared.state, &old.state));
shared.update_uniforms(uniforms(green));
assert!(!Arc::ptr_eq(&shared.state, &old.state));
assert_eq!(shared.id(), old.id());
assert_eq!(old.current_commit(), old_commit);
assert_ne!(shared.current_commit(), old_commit);
assert_eq!(pixels(&mut renderer, &old), pixels(&mut renderer, &baseline));
assert_ne!(pixels(&mut renderer, &shared), pixels(&mut renderer, &baseline));
let retained = shared.clone();
shared.resize(Rectangle::from_size((16, 16).into()), None);
assert_eq!(retained.geometry(1.0.into()), area.to_physical_precise_round(1.0));
assert_eq!(shared.geometry(1.0.into()).size, (16, 16).into());
assert!(shared.opaque_regions(1.0.into()).is_empty());
assert_eq!(shared.alpha(), baseline.alpha());
assert_eq!(shared.kind(), baseline.kind());
}
}