diff --git a/build/vulkan/hash.rs b/build/vulkan/hash.rs index edd5f2e2..1a1d5573 100644 --- a/build/vulkan/hash.rs +++ b/build/vulkan/hash.rs @@ -25,9 +25,6 @@ pub const TREES: &[Tree] = &[Tree { "rounded_tex.vert", "blur_composite.vert", "blur_composite.frag", - "blur.vert", - "blur_down.frag", - "blur_up.frag", "legacy/fill.frag", "legacy/fill.vert", "legacy/tex.vert", diff --git a/jay-config/src/_private.rs b/jay-config/src/_private.rs index 83aeccad..9f0a92c5 100644 --- a/jay-config/src/_private.rs +++ b/jay-config/src/_private.rs @@ -169,55 +169,3 @@ impl Default for BlurConfigIpc { } } } - -#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)] -pub enum AnimationCurveIpc { - Linear, - EaseOut, - EaseInOut, - /// Standard CSS cubic-bezier(x1, y1, x2, y2). P0=(0,0), P3=(1,1) are fixed. - Bezier { - x1: f32, - y1: f32, - x2: f32, - y2: f32, - }, -} - -#[derive(Serialize, Deserialize, Copy, Clone, Debug)] -pub struct AnimationsConfigIpc { - pub enabled: bool, - pub open_duration_ms: u32, - pub open_curve: AnimationCurveIpc, - pub close_duration_ms: u32, - pub close_curve: AnimationCurveIpc, -} - -impl Default for AnimationsConfigIpc { - fn default() -> Self { - Self { - enabled: false, - open_duration_ms: 200, - open_curve: AnimationCurveIpc::EaseOut, - close_duration_ms: 200, - close_curve: AnimationCurveIpc::EaseOut, - } - } -} - -#[derive(Serialize, Deserialize, Copy, Clone, Debug)] -pub struct DamageVisualizationIpc { - pub enabled: bool, - pub color: crate::theme::Color, - pub decay_millis: u64, -} - -impl Default for DamageVisualizationIpc { - fn default() -> Self { - Self { - enabled: false, - color: crate::theme::Color::new_straight(255, 0, 0, 128), - decay_millis: 2000, - } - } -} diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 493c09a9..2717a3e4 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -880,14 +880,6 @@ impl ConfigClient { self.send(&ClientMessage::SetBlurConfig { config }) } - pub fn set_damage_visualization(&self, config: crate::_private::DamageVisualizationIpc) { - self.send(&ClientMessage::SetDamageVisualization { config }) - } - - pub fn set_animations_config(&self, config: crate::_private::AnimationsConfigIpc) { - self.send(&ClientMessage::SetAnimationsConfig { config }) - } - pub fn switch_to_vt(&self, vtnr: u32) { self.send(&ClientMessage::SwitchTo { vtnr }) } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index be54e511..5130a98e 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -1,8 +1,8 @@ use { crate::{ _private::{ - BlurConfigIpc, ClientCriterionIpc, DamageVisualizationIpc, LayerRuleIpc, PollableId, - WindowCriterionIpc, WireMode, + BlurConfigIpc, ClientCriterionIpc, LayerRuleIpc, PollableId, WindowCriterionIpc, + WireMode, }, Axis, Direction, PciId, Workspace, client::{Client, ClientCapabilities, ClientMatcher}, @@ -925,12 +925,6 @@ pub enum ClientMessage<'a> { SetBlurConfig { config: BlurConfigIpc, }, - SetDamageVisualization { - config: DamageVisualizationIpc, - }, - SetAnimationsConfig { - config: crate::_private::AnimationsConfigIpc, - }, } #[derive(Serialize, Deserialize, Debug)] diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index 220f0570..4d83f1e9 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -407,34 +407,6 @@ pub fn _set_blur_config(config: crate::_private::BlurConfigIpc) { get!().set_blur_config(config) } -#[doc(hidden)] -pub fn _set_damage_visualization(config: crate::_private::DamageVisualizationIpc) { - get!().set_damage_visualization(config) -} - -#[doc(hidden)] -pub fn _set_animations_config(config: crate::_private::AnimationsConfigIpc) { - get!().set_animations_config(config) -} - -/// Configures the damage region visualizer. -/// -/// When enabled, every damaged screen region is overlaid with `color` and fades -/// out over `decay` (producing a "blink" effect as new damage accumulates). -/// Useful for debugging damage-tracked rendering paths. -pub fn set_damage_visualization( - enabled: bool, - color: crate::theme::Color, - decay: std::time::Duration, -) { - let decay_millis = decay.as_millis().min(u64::MAX as u128) as u64; - _set_damage_visualization(crate::_private::DamageVisualizationIpc { - enabled, - color, - decay_millis, - }); -} - /// Returns the current corner radius for window borders. pub fn get_corner_radius() -> f32 { get!(0.0).get_corner_radius() diff --git a/src/animation.rs b/src/animation.rs deleted file mode 100644 index ec08b1db..00000000 --- a/src/animation.rs +++ /dev/null @@ -1,193 +0,0 @@ -use { - crate::{ - allocator::{BO_USE_RENDERING, BufferUsage}, - format::ARGB8888, - gfx_api::{AcquireSync, GfxTexture, ReleaseSync, needs_render_usage}, - rect::Rect, - renderer::Renderer, - state::State, - theme::Color, - tree::{OutputNode, ToplevelNode, Transform}, - video::Modifier, - }, - std::{cell::Cell, rc::Weak}, - std::rc::Rc, -}; - -/// A captured snapshot of a toplevel's last rendered state, used to drive the -/// close animation after the toplevel itself has been torn down. Owns its own -/// GPU texture so the source client buffers can be released immediately. -pub struct Snapshot { - pub texture: Rc, - /// The output the toplevel was on, used to schedule per-frame damage. - pub output: Weak, - /// Logical absolute position the toplevel occupied, used to draw the - /// snapshot into the correct screen region during the close animation. - pub rect: Rect, - /// Slide-out direction in logical pixels. The snapshot moves from (0, 0) - /// at start to (slide_dx, slide_dy) at end. - pub slide_dx: f32, - pub slide_dy: f32, - pub start_nsec: Cell, -} - -impl Snapshot { - /// Returns the eased close-animation progress in [0, 1], or None if the - /// animation has finished. - pub fn close_progress(&self, state: &State) -> Option { - let cfg = state.animations_config.get(); - if !cfg.enabled || cfg.close_duration_ms == 0 { - return None; - } - let now = state.now_nsec(); - let elapsed = now.saturating_sub(self.start_nsec.get()); - let dur = (cfg.close_duration_ms as u64).saturating_mul(1_000_000); - if elapsed >= dur { - return None; - } - let t = (elapsed as f32) / (dur as f32); - let eased = match cfg.close_curve { - jay_config::_private::AnimationCurveIpc::Linear => t, - jay_config::_private::AnimationCurveIpc::EaseOut => { - let inv = 1.0 - t; - 1.0 - inv * inv * inv - } - jay_config::_private::AnimationCurveIpc::EaseInOut => { - if t < 0.5 { - 4.0 * t * t * t - } else { - let f = -2.0 * t + 2.0; - 1.0 - f * f * f / 2.0 - } - } - jay_config::_private::AnimationCurveIpc::Bezier { x1, y1, x2, y2 } => { - cubic_bezier_y_at_x(t, x1, y1, x2, y2) - } - }; - Some(eased.clamp(0.0, 1.0)) - } -} - -fn cubic_bezier_y_at_x(x: f32, x1: f32, y1: f32, x2: f32, y2: f32) -> f32 { - fn bx(t: f32, x1: f32, x2: f32) -> f32 { - let it = 1.0 - t; - 3.0 * it * it * t * x1 + 3.0 * it * t * t * x2 + t * t * t - } - fn dbx(t: f32, x1: f32, x2: f32) -> f32 { - let it = 1.0 - t; - 3.0 * it * it * x1 + 6.0 * it * t * (x2 - x1) + 3.0 * t * t * (1.0 - x2) - } - let mut t = x; - for _ in 0..8 { - let err = bx(t, x1, x2) - x; - if err.abs() < 1e-4 { - break; - } - let d = dbx(t, x1, x2); - if d.abs() < 1e-6 { - break; - } - t = (t - err / d).clamp(0.0, 1.0); - } - let it = 1.0 - t; - 3.0 * it * it * t * y1 + 3.0 * it * t * t * y2 + t * t * t -} - -/// Renders the toplevel into a private GPU texture and returns the texture. -/// Used at unmap time to capture the last-rendered state, so a close animation -/// can run after the toplevel itself has been destroyed. Returns None if the -/// render context is unavailable, the toplevel has no workspace, or -/// allocation/rendering fails. -/// -/// Any open animation in flight on the toplevel is cleared before rendering so -/// the snapshot is at full opacity / final position. -pub fn capture_snapshot(state: &State, tl: &Rc) -> Option { - let ctx = state.render_ctx.get()?; - let formats = ctx.formats(); - let format_info = formats.get(&ARGB8888.drm)?; - let modifiers: Vec = format_info - .write_modifiers - .iter() - .filter(|(m, _)| format_info.read_modifiers.contains(*m)) - .map(|(m, _)| *m) - .collect(); - if modifiers.is_empty() { - return None; - } - let data = tl.tl_data(); - data.anim_open_start_nsec.set(None); - let workspace = data.workspace.get()?; - let output = workspace.output.get(); - let scale = output.global.persistent.scale.get(); - let scalef = scale.to_f64(); - let tl_rect = tl.node_absolute_position(); - let pw = (tl_rect.width() as f64 * scalef).round() as i32; - let ph = (tl_rect.height() as f64 * scalef).round() as i32; - if pw <= 0 || ph <= 0 { - return None; - } - let allocator = ctx.allocator(); - let mut usage = BO_USE_RENDERING; - if !needs_render_usage(format_info.write_modifiers.values()) { - usage = BufferUsage::none(); - } - let bo = allocator - .create_bo(&state.dma_buf_ids, pw, ph, ARGB8888, &modifiers, usage) - .ok()?; - let img = ctx.clone().dmabuf_img(bo.dmabuf()).ok()?; - let fb = img.clone().to_framebuffer().ok()?; - let mut ops = vec![]; - { - let mut renderer = Renderer { - base: fb.renderer_base(&mut ops, scale, Transform::None), - state, - logical_extents: tl_rect.at_point(0, 0), - pixel_extents: Rect::new_saturating(0, 0, pw, ph), - stretch: None, - corner_radius: None, - current_anim_node: None, - }; - tl.clone().node_render(&mut renderer, 0, 0, None); - } - let cd = state.color_manager.srgb_gamma22(); - fb.render( - AcquireSync::Unnecessary, - ReleaseSync::Implicit, - cd, - &ops, - Some(&Color::TRANSPARENT), - &cd.linear, - None, - cd, - ) - .ok()?; - let texture = img.to_texture().ok()?; - - // Slide-out direction: same closest-edge logic as the open animation, but - // the snapshot moves AWAY from its rect during close. Computed once here so - // we don't need the toplevel's tile lookup anymore once it's torn down. - let output_rect = output.global.pos.get(); - let dl = (tl_rect.x1() - output_rect.x1()).max(0) as f32; - let dr = (output_rect.x2() - tl_rect.x2()).max(0) as f32; - let dt = (tl_rect.y1() - output_rect.y1()).max(0) as f32; - let db = (output_rect.y2() - tl_rect.y2()).max(0) as f32; - let mind = dl.min(dr).min(dt).min(db); - let (slide_dx, slide_dy) = if mind == dl { - (-(tl_rect.width() as f32), 0.0) - } else if mind == dr { - (tl_rect.width() as f32, 0.0) - } else if mind == dt { - (0.0, -(tl_rect.height() as f32)) - } else { - (0.0, tl_rect.height() as f32) - }; - - Some(Snapshot { - texture, - output: Rc::downgrade(&output), - rect: tl_rect, - slide_dx, - slide_dy, - start_nsec: Cell::new(state.now_nsec()), - }) -} diff --git a/src/compositor.rs b/src/compositor.rs index c8fbb5e9..ebe6e599 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -399,10 +399,6 @@ fn start_compositor2( hyprland_global_shortcuts: Default::default(), layer_rules: Default::default(), blur_config: Default::default(), - blur_cache_epoch: Default::default(), - animations_config: Default::default(), - active_animations: Default::default(), - close_snapshots: Default::default(), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/config/handler.rs b/src/config/handler.rs index 07734fe3..18dbef71 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -3537,20 +3537,6 @@ impl ConfigProxyHandler { ClientMessage::SetBlurConfig { config } => { self.state.blur_config.set(config); } - ClientMessage::SetAnimationsConfig { config } => { - self.state.animations_config.set(config); - } - ClientMessage::SetDamageVisualization { config } => { - let [r, g, b, a] = config.color.to_u8_straight(); - let color = crate::theme::Color::from_srgba_straight(r, g, b, a); - self.state.damage_visualizer.set_color(color); - self.state - .damage_visualizer - .set_decay(std::time::Duration::from_millis(config.decay_millis)); - self.state - .damage_visualizer - .set_enabled(&self.state, config.enabled); - } } Ok(()) } diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 61183b61..bbe9d222 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -107,36 +107,12 @@ pub enum GfxApiOpt { BlurBackdrop(BlurBackdrop), } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct BlurBackdrop { pub rect: FramebufferRect, pub passes: u8, pub offset: f32, pub mask: Option, - pub cache: Option>>>, - pub cache_epoch: u64, - pub cache_pixel_rect: [i32; 4], -} - -impl std::fmt::Debug for BlurBackdrop { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("BlurBackdrop") - .field("rect", &self.rect) - .field("passes", &self.passes) - .field("offset", &self.offset) - .field("mask", &self.mask) - .field("cache_epoch", &self.cache_epoch) - .field("cache_pixel_rect", &self.cache_pixel_rect) - .finish() - } -} - -pub struct BlurCacheEntry { - pub pixel_rect: [i32; 4], - pub passes: u8, - pub offset: f32, - pub epoch: u64, - pub image: Rc, } #[derive(Clone)] @@ -144,9 +120,6 @@ pub struct BlurMask { pub texture: Rc, pub source: SampleRect, pub threshold: f32, - pub buffer_resv: Option>, - pub acquire_sync: AcquireSync, - pub release_sync: ReleaseSync, } impl std::fmt::Debug for BlurMask { @@ -812,7 +785,6 @@ impl dyn GfxFramebuffer { }, stretch: None, corner_radius: None, - current_anim_node: None, }; cursor.render_hardware_cursor(&mut renderer); self.render( @@ -1147,7 +1119,6 @@ pub fn create_render_pass( }, stretch: None, corner_radius: None, - current_anim_node: None, }; node.node_render(&mut renderer, 0, 0, None); if let Some(rect) = cursor_rect { @@ -1222,9 +1193,6 @@ pub fn renderer_base<'a>( fb_width: width as _, fb_height: height as _, discard_alpha: None, - alpha_mul: 1.0, - translate_x: 0.0, - translate_y: 0.0, } } diff --git a/src/gfx_apis/vulkan/blur.rs b/src/gfx_apis/vulkan/blur.rs index af781cea..b63cc924 100644 --- a/src/gfx_apis/vulkan/blur.rs +++ b/src/gfx_apis/vulkan/blur.rs @@ -2,9 +2,8 @@ use { crate::gfx_apis::vulkan::{ VulkanError, image::{QueueFamily, QueueState, VulkanImage, VulkanImageMemory}, - pipeline::VulkanPipeline, renderer::VulkanRenderer, - shaders::{BlurCompositePushConstants, BlurPushConstants}, + shaders::BlurCompositePushConstants, }, ash::vk::{ AccessFlags2, AttachmentLoadOp, AttachmentStoreOp, BlitImageInfo2, CommandBuffer, @@ -17,14 +16,13 @@ use { }, gpu_alloc::UsageFlags, run_on_drop::on_drop, - std::{cell::Cell, rc::Rc, slice}, + std::{cell::Cell, collections::hash_map::Entry, rc::Rc, slice}, }; const BLUR_SCRATCH_USAGE: ImageUsageFlags = ImageUsageFlags::from_raw( ImageUsageFlags::TRANSFER_SRC.as_raw() | ImageUsageFlags::TRANSFER_DST.as_raw() - | ImageUsageFlags::SAMPLED.as_raw() - | ImageUsageFlags::COLOR_ATTACHMENT.as_raw(), + | ImageUsageFlags::SAMPLED.as_raw(), ); pub(super) struct BlurMaskRecord<'a> { @@ -44,17 +42,12 @@ impl VulkanRenderer { ) -> Result, VulkanError> { let key = (width, height, format); let cached = &mut *self.blur_scratch.borrow_mut(); - - if let Some(weak) = cached.get(&key) { - if let Some(img) = weak.upgrade() { - if Rc::strong_count(&img) == 1 { - img.is_undefined.set(false); - img.contents_are_undefined.set(false); - return Ok(img); - } - } + let entry = cached.entry(key); + if let Entry::Occupied(e) = &entry + && let Some(img) = e.get().upgrade() + { + return Ok(img); } - let create_info = ImageCreateInfo::default() .image_type(ImageType::TYPE_2D) .format(format) @@ -84,6 +77,7 @@ impl VulkanRenderer { .bind_image_memory(image, allocation.memory, allocation.offset) }; res.map_err(VulkanError::BindImageMemory)?; + // No view needed (we only blit), but VulkanImage requires one. let image_view_create_info = ImageViewCreateInfo::default() .image(image) .format(format) @@ -102,6 +96,8 @@ impl VulkanRenderer { }; let view = view.map_err(VulkanError::CreateImageView)?; destroy_image.forget(); + // Reuse the BLEND_FORMAT placeholder; the format field is informational + // here, blit ops use the actual VkFormat above. let img = Rc::new(VulkanImage { renderer: self.clone(), format: crate::gfx_apis::vulkan::format::BLEND_FORMAT, @@ -121,30 +117,28 @@ impl VulkanRenderer { sampled_image_descriptor: None, execution_version: Default::default(), }); - cached.insert(key, Rc::downgrade(&img)); + match entry { + Entry::Occupied(mut e) => { + e.insert(Rc::downgrade(&img)); + } + Entry::Vacant(e) => { + e.insert(Rc::downgrade(&img)); + } + } Ok(img) } - /// Records a dual-Kawase backdrop blur of the given pixel rect on the target - /// image. Caller is responsible for ending the current dynamic render pass - /// before invoking, and for restarting it afterward (with LOAD). - /// - /// If `cached_blur` is Some, the cascade is skipped and that image is used - /// directly as the blurred input to the composite. The mask must also be Some - /// in that case, since cache+no-mask is just a no-op (blit-back of cached). - /// On a cache miss, the level-0 scratch image (holding the blurred result) - /// is returned via `out_blur_image` for the caller to store in the cache. + /// Records a backdrop blur of the given pixel rect on the target image. + /// Caller is responsible for ending the current dynamic render pass before + /// invoking, and for restarting it afterward (with LOAD). pub(super) fn record_blur( self: &Rc, buf: CommandBuffer, target: &VulkanImage, rect: [i32; 4], passes: u8, - offset: f32, scratch_out: &mut Vec>, mask: Option<&BlurMaskRecord<'_>>, - cached_blur: Option<&Rc>, - out_blur_image: &mut Option>, ) -> Result<(), VulkanError> { let [x1, y1, x2, y2] = rect; let x1 = x1.max(0).min(target.width as i32); @@ -156,26 +150,7 @@ impl VulkanRenderer { if w < 4 || h < 4 { return Ok(()); } - let passes = passes.clamp(1, 8) as u32; - let offset = offset.max(0.0); - - let dev = &self.device.device; - - // Cache hit fast path: skip cascade, just composite from cached image. - // The format check matters because BlurBarrier may run in either the - // BlendBuffer pass (linear format) or the FrameBuffer pass (gamma) - // depending on whether BB was elided. A cached image from one pass - // has the wrong format for the other. - if let (Some(cached), Some(mask)) = (cached_blur, mask) - && cached.width == w - && cached.height == h - && cached.format.vk_format == target.format.vk_format - { - self.record_blur_composite_only(buf, target, cached, mask, [x1, y1, x2, y2])?; - // Hold cached image alive for this frame's GPU execution. - scratch_out.push(cached.clone()); - return Ok(()); - } + let passes = passes.clamp(1, 6) as u32; let format = target.format.vk_format; let mut levels: Vec> = Vec::with_capacity(passes as usize + 1); @@ -188,8 +163,7 @@ impl VulkanRenderer { levels.push(self.acquire_blur_scratch(cw, ch, format)?); } - // After cascade, levels[0] holds the blurred result. Stash it for caching. - *out_blur_image = Some(levels[0].clone()); + let dev = &self.device.device; let subres = ImageSubresourceLayers::default() .aspect_mask(ImageAspectFlags::COLOR) .layer_count(1) @@ -229,7 +203,7 @@ impl VulkanRenderer { }; // Step 1: target COLOR_ATTACHMENT -> TRANSFER_SRC. - // levels[0] -> TRANSFER_DST (discard prior contents). + // Step 1: levels[0] UNDEFINED -> TRANSFER_DST. do_barriers(&[ barrier( target.image, @@ -250,7 +224,6 @@ impl VulkanRenderer { AccessFlags2::TRANSFER_WRITE, ), ]); - levels[0].is_undefined.set(false); // Step 2: blit target rect -> levels[0] full. let blit = ImageBlit2::default() @@ -279,153 +252,139 @@ impl VulkanRenderer { dev.cmd_blit_image2(buf, &blit_info); } - // Step 3: levels[0] TRANSFER_DST -> SHADER_READ_ONLY for sampling in - // the down pass. - do_barriers(&[barrier( - levels[0].image, - ImageLayout::TRANSFER_DST_OPTIMAL, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, - PipelineStageFlags2::TRANSFER, - AccessFlags2::TRANSFER_WRITE, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, - )]); - - let blur_down_pipeline = self.get_or_create_blur_down_pipeline(format)?; - let blur_up_pipeline = self.get_or_create_blur_up_pipeline(format)?; - - // Helper to run one blur pass: sample `src`, draw into `dst`. Caller - // must have transitioned dst to COLOR_ATTACHMENT and src to - // SHADER_READ_ONLY before this. Layouts after: dst stays in - // COLOR_ATTACHMENT (caller transitions next). - let run_pass = |pipeline: &VulkanPipeline, - src: &VulkanImage, - dst: &VulkanImage| - -> Result<(), VulkanError> { - let color_attachment = RenderingAttachmentInfo::default() - .image_view(dst.texture_view) - .image_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .load_op(AttachmentLoadOp::DONT_CARE) - .store_op(AttachmentStoreOp::STORE); - let render_area = Rect2D { - offset: Offset2D { x: 0, y: 0 }, - extent: Extent2D { - width: dst.width, - height: dst.height, - }, - }; - let rendering_info = RenderingInfo::default() - .render_area(render_area) - .layer_count(1) - .color_attachments(slice::from_ref(&color_attachment)); - let viewport = Viewport { - x: 0.0, - y: 0.0, - width: dst.width as f32, - height: dst.height as f32, - min_depth: 0.0, - max_depth: 1.0, - }; - let scissor = render_area; - let push = BlurPushConstants { - halfpixel: [0.5 / src.width as f32, 0.5 / src.height as f32], - offset, - }; - let src_image_info = DescriptorImageInfo::default() - .image_view(src.texture_view) - .image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL); - let writes = [WriteDescriptorSet::default() - .dst_binding(0) - .descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER) - .image_info(slice::from_ref(&src_image_info))]; - unsafe { - dev.cmd_begin_rendering(buf, &rendering_info); - dev.cmd_bind_pipeline(buf, PipelineBindPoint::GRAPHICS, pipeline.pipeline); - dev.cmd_set_viewport(buf, 0, slice::from_ref(&viewport)); - dev.cmd_set_scissor(buf, 0, slice::from_ref(&scissor)); - self.device.push_descriptor.cmd_push_descriptor_set( - buf, - PipelineBindPoint::GRAPHICS, - pipeline.pipeline_layout, - 0, - &writes, - ); - dev.cmd_push_constants( - buf, - pipeline.pipeline_layout, - ShaderStageFlags::FRAGMENT, - 0, - uapi::as_bytes(&push), - ); - dev.cmd_draw(buf, 4, 1, 0, 0); - dev.cmd_end_rendering(buf); - } - Ok(()) - }; - - // Down passes: levels[i-1] (SHADER_READ_ONLY) -> levels[i] (COLOR_ATT). - // Each iteration transitions the destination to COLOR_ATTACHMENT, - // draws, then to SHADER_READ_ONLY for the next iteration's read. + // Down passes: levels[i-1] -> levels[i] with linear filter. for i in 1..=passes as usize { - do_barriers(&[barrier( - levels[i].image, - ImageLayout::UNDEFINED, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - PipelineStageFlags2::TOP_OF_PIPE, - AccessFlags2::empty(), - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE, - )]); - levels[i].is_undefined.set(false); - run_pass(&blur_down_pipeline, &levels[i - 1], &levels[i])?; - do_barriers(&[barrier( - levels[i].image, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, - )]); + let (src, dst) = (&levels[i - 1], &levels[i]); + do_barriers(&[ + barrier( + src.image, + ImageLayout::TRANSFER_DST_OPTIMAL, + ImageLayout::TRANSFER_SRC_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_READ, + ), + barrier( + dst.image, + ImageLayout::UNDEFINED, + ImageLayout::TRANSFER_DST_OPTIMAL, + PipelineStageFlags2::TOP_OF_PIPE, + AccessFlags2::empty(), + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + ), + ]); + let blit = ImageBlit2::default() + .src_subresource(subres) + .dst_subresource(subres) + .src_offsets([ + Offset3D { x: 0, y: 0, z: 0 }, + Offset3D { + x: src.width as i32, + y: src.height as i32, + z: 1, + }, + ]) + .dst_offsets([ + Offset3D { x: 0, y: 0, z: 0 }, + Offset3D { + x: dst.width as i32, + y: dst.height as i32, + z: 1, + }, + ]); + let blit_info = BlitImageInfo2::default() + .src_image(src.image) + .src_image_layout(ImageLayout::TRANSFER_SRC_OPTIMAL) + .dst_image(dst.image) + .dst_image_layout(ImageLayout::TRANSFER_DST_OPTIMAL) + .filter(Filter::LINEAR) + .regions(slice::from_ref(&blit)); + unsafe { + dev.cmd_blit_image2(buf, &blit_info); + } } - // Up passes: levels[i+1] (SHADER_READ_ONLY) -> levels[i] (COLOR_ATT). + // Up passes: levels[i+1] -> levels[i] with linear filter. for i in (0..passes as usize).rev() { - do_barriers(&[barrier( - levels[i].image, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE, - )]); - run_pass(&blur_up_pipeline, &levels[i + 1], &levels[i])?; - do_barriers(&[barrier( - levels[i].image, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, - )]); + let (src, dst) = (&levels[i + 1], &levels[i]); + do_barriers(&[ + barrier( + src.image, + ImageLayout::TRANSFER_DST_OPTIMAL, + ImageLayout::TRANSFER_SRC_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_READ, + ), + barrier( + dst.image, + ImageLayout::TRANSFER_SRC_OPTIMAL, + ImageLayout::TRANSFER_DST_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_READ, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + ), + ]); + let blit = ImageBlit2::default() + .src_subresource(subres) + .dst_subresource(subres) + .src_offsets([ + Offset3D { x: 0, y: 0, z: 0 }, + Offset3D { + x: src.width as i32, + y: src.height as i32, + z: 1, + }, + ]) + .dst_offsets([ + Offset3D { x: 0, y: 0, z: 0 }, + Offset3D { + x: dst.width as i32, + y: dst.height as i32, + z: 1, + }, + ]); + let blit_info = BlitImageInfo2::default() + .src_image(src.image) + .src_image_layout(ImageLayout::TRANSFER_SRC_OPTIMAL) + .dst_image(dst.image) + .dst_image_layout(ImageLayout::TRANSFER_DST_OPTIMAL) + .filter(Filter::LINEAR) + .regions(slice::from_ref(&blit)); + unsafe { + dev.cmd_blit_image2(buf, &blit_info); + } } - // After cascade: levels[0] in SHADER_READ_ONLY, target in TRANSFER_SRC. - if let Some(mask) = mask { - // Masked composite path: restore target to COLOR_ATTACHMENT and - // draw the composite shader sampling levels[0] + mask. - do_barriers(&[barrier( - target.image, - ImageLayout::TRANSFER_SRC_OPTIMAL, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - PipelineStageFlags2::TRANSFER, - AccessFlags2::TRANSFER_READ, - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ, - )]); + // Masked composite path: + // levels[0] (TRANSFER_DST) -> SHADER_READ_ONLY_OPTIMAL + // target (TRANSFER_SRC) -> COLOR_ATTACHMENT_OPTIMAL + // draw composite shader sampling levels[0] + mask, blending onto fb + do_barriers(&[ + barrier( + levels[0].image, + ImageLayout::TRANSFER_DST_OPTIMAL, + ImageLayout::SHADER_READ_ONLY_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + PipelineStageFlags2::FRAGMENT_SHADER, + AccessFlags2::SHADER_SAMPLED_READ, + ), + barrier( + target.image, + ImageLayout::TRANSFER_SRC_OPTIMAL, + ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_READ, + PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, + AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ, + ), + ]); let pipeline = self.get_or_create_blur_composite_pipeline(target.format.vk_format)?; @@ -511,15 +470,14 @@ impl VulkanRenderer { dev.cmd_end_rendering(buf); } } else { - // Unmasked: transition levels[0] back to TRANSFER_SRC, target stays - // in TRANSFER_SRC, retarget target to TRANSFER_DST, blit-back. + // Final blit: levels[0] -> target rect. do_barriers(&[ barrier( levels[0].image, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, + ImageLayout::TRANSFER_DST_OPTIMAL, ImageLayout::TRANSFER_SRC_OPTIMAL, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, PipelineStageFlags2::TRANSFER, AccessFlags2::TRANSFER_READ, ), @@ -558,158 +516,21 @@ impl VulkanRenderer { unsafe { dev.cmd_blit_image2(buf, &blit_info); } - // Restore target to COLOR_ATTACHMENT for the resumed render pass. - // Also push levels[0] back to SHADER_READ_ONLY so its tracked layout - // matches what the cache-hit fast path expects on next frame. - do_barriers(&[ - barrier( - target.image, - ImageLayout::TRANSFER_DST_OPTIMAL, - ImageLayout::COLOR_ATTACHMENT_OPTIMAL, - PipelineStageFlags2::TRANSFER, - AccessFlags2::TRANSFER_WRITE, - PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, - AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ, - ), - barrier( - levels[0].image, - ImageLayout::TRANSFER_SRC_OPTIMAL, - ImageLayout::SHADER_READ_ONLY_OPTIMAL, - PipelineStageFlags2::TRANSFER, - AccessFlags2::TRANSFER_READ, - PipelineStageFlags2::FRAGMENT_SHADER, - AccessFlags2::SHADER_SAMPLED_READ, - ), - ]); + + // Restore target to COLOR_ATTACHMENT_OPTIMAL. + do_barriers(&[barrier( + target.image, + ImageLayout::TRANSFER_DST_OPTIMAL, + ImageLayout::COLOR_ATTACHMENT_OPTIMAL, + PipelineStageFlags2::TRANSFER, + AccessFlags2::TRANSFER_WRITE, + PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT, + AccessFlags2::COLOR_ATTACHMENT_WRITE | AccessFlags2::COLOR_ATTACHMENT_READ, + )]); } // Hold the scratch images until the frame is submitted. scratch_out.extend(levels); Ok(()) } - - /// Cache-hit fast path. Cached image is already in SHADER_READ_ONLY_OPTIMAL - /// (the layout we leave it in after the previous frame's composite). We just - /// re-bind the composite pipeline with the cached image as input and draw. - fn record_blur_composite_only( - self: &Rc, - buf: CommandBuffer, - target: &VulkanImage, - cached: &Rc, - mask: &BlurMaskRecord<'_>, - rect: [i32; 4], - ) -> Result<(), VulkanError> { - let [x1, y1, x2, y2] = rect; - let w = (x2 - x1) as u32; - let h = (y2 - y1) as u32; - let dev = &self.device.device; - // The caller (BlurBarrier handler) has already cmd_end_rendering'd the - // pass that produced the underlying scene. Without an explicit barrier - // here, the new render pass's LOAD reads can race with those prior - // COLOR_ATTACHMENT_WRITEs and pull stale memory — which manifests as - // per-frame flicker in the blurred region. - let target_load_barrier = ImageMemoryBarrier2::default() - .image(target.image) - .old_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .new_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .subresource_range(ImageSubresourceRange { - aspect_mask: ImageAspectFlags::COLOR, - base_mip_level: 0, - level_count: 1, - base_array_layer: 0, - layer_count: 1, - }) - .src_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT) - .src_access_mask(AccessFlags2::COLOR_ATTACHMENT_WRITE) - .dst_stage_mask(PipelineStageFlags2::COLOR_ATTACHMENT_OUTPUT) - .dst_access_mask( - AccessFlags2::COLOR_ATTACHMENT_READ | AccessFlags2::COLOR_ATTACHMENT_WRITE, - ) - .src_queue_family_index(ash::vk::QUEUE_FAMILY_IGNORED) - .dst_queue_family_index(ash::vk::QUEUE_FAMILY_IGNORED); - let dep = DependencyInfoKHR::default() - .image_memory_barriers(slice::from_ref(&target_load_barrier)); - unsafe { - dev.cmd_pipeline_barrier2(buf, &dep); - } - let pipeline = self.get_or_create_blur_composite_pipeline(target.format.vk_format)?; - let target_render_view = target.render_view.unwrap_or(target.texture_view); - let color_attachment = RenderingAttachmentInfo::default() - .image_view(target_render_view) - .image_layout(ImageLayout::COLOR_ATTACHMENT_OPTIMAL) - .load_op(AttachmentLoadOp::LOAD) - .store_op(AttachmentStoreOp::STORE); - let render_area = Rect2D { - offset: Offset2D { x: 0, y: 0 }, - extent: Extent2D { - width: target.width, - height: target.height, - }, - }; - let rendering_info = RenderingInfo::default() - .render_area(render_area) - .layer_count(1) - .color_attachments(slice::from_ref(&color_attachment)); - let viewport = Viewport { - x: 0.0, - y: 0.0, - width: target.width as f32, - height: target.height as f32, - min_depth: 0.0, - max_depth: 1.0, - }; - let scissor = Rect2D { - offset: Offset2D { x: x1, y: y1 }, - extent: Extent2D { - width: w, - height: h, - }, - }; - let blurred_tc: [[f32; 2]; 4] = [[1.0, 0.0], [0.0, 0.0], [1.0, 1.0], [0.0, 1.0]]; - let push = BlurCompositePushConstants { - pos: mask.target_points, - blurred_tex_pos: blurred_tc, - mask_tex_pos: mask.mask_source_points, - threshold: mask.threshold, - }; - let blurred_image_info = DescriptorImageInfo::default() - .image_view(cached.texture_view) - .image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL); - let mask_image_info = DescriptorImageInfo::default() - .image_view(mask.mask_view) - .image_layout(ImageLayout::SHADER_READ_ONLY_OPTIMAL); - let writes = [ - WriteDescriptorSet::default() - .dst_binding(0) - .descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER) - .image_info(slice::from_ref(&blurred_image_info)), - WriteDescriptorSet::default() - .dst_binding(1) - .descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER) - .image_info(slice::from_ref(&mask_image_info)), - ]; - unsafe { - dev.cmd_begin_rendering(buf, &rendering_info); - dev.cmd_bind_pipeline(buf, PipelineBindPoint::GRAPHICS, pipeline.pipeline); - dev.cmd_set_viewport(buf, 0, slice::from_ref(&viewport)); - dev.cmd_set_scissor(buf, 0, slice::from_ref(&scissor)); - self.device.push_descriptor.cmd_push_descriptor_set( - buf, - PipelineBindPoint::GRAPHICS, - pipeline.pipeline_layout, - 0, - &writes, - ); - dev.cmd_push_constants( - buf, - pipeline.pipeline_layout, - ShaderStageFlags::VERTEX | ShaderStageFlags::FRAGMENT, - 0, - uapi::as_bytes(&push), - ); - dev.cmd_draw(buf, 4, 1, 0, 0); - dev.cmd_end_rendering(buf); - } - Ok(()) - } } diff --git a/src/gfx_apis/vulkan/descriptor.rs b/src/gfx_apis/vulkan/descriptor.rs index 145ce007..fa207f7a 100644 --- a/src/gfx_apis/vulkan/descriptor.rs +++ b/src/gfx_apis/vulkan/descriptor.rs @@ -87,31 +87,6 @@ impl VulkanDevice { })) } - pub(super) fn create_blur_descriptor_set_layout( - self: &Rc, - sampler: &Rc, - ) -> Result, VulkanError> { - let immutable_sampler = [sampler.sampler]; - let binding = DescriptorSetLayoutBinding::default() - .binding(0) - .stage_flags(ShaderStageFlags::FRAGMENT) - .descriptor_count(1) - .descriptor_type(DescriptorType::COMBINED_IMAGE_SAMPLER) - .immutable_samplers(&immutable_sampler); - let create_info = DescriptorSetLayoutCreateInfo::default() - .bindings(slice::from_ref(&binding)) - .flags(DescriptorSetLayoutCreateFlags::PUSH_DESCRIPTOR_KHR); - let layout = unsafe { self.device.create_descriptor_set_layout(&create_info, None) }; - let layout = layout.map_err(VulkanError::CreateDescriptorSetLayout)?; - Ok(Rc::new(VulkanDescriptorSetLayout { - device: self.clone(), - layout, - size: 0, - offsets: Default::default(), - _sampler: Some(sampler.clone()), - })) - } - pub(super) fn create_tex_sampler_descriptor_set_layout( self: &Rc, sampler: &Rc, diff --git a/src/gfx_apis/vulkan/renderer.rs b/src/gfx_apis/vulkan/renderer.rs index bf94d6f2..c1de1a03 100644 --- a/src/gfx_apis/vulkan/renderer.rs +++ b/src/gfx_apis/vulkan/renderer.rs @@ -26,8 +26,7 @@ use { sampler::VulkanSampler, semaphore::VulkanSemaphore, shaders::{ - BLUR_COMPOSITE_FRAG, BLUR_COMPOSITE_VERT, BLUR_DOWN_FRAG, BLUR_UP_FRAG, BLUR_VERT, - BlurCompositePushConstants, BlurPushConstants, + BLUR_COMPOSITE_FRAG, BLUR_COMPOSITE_VERT, BlurCompositePushConstants, ColorManagementData, EotfArgs, FILL_FRAG, FILL_VERT, FillPushConstants, InvEotfArgs, LEGACY_FILL_FRAG, LEGACY_FILL_VERT, LEGACY_ROUNDED_FILL_FRAG, LEGACY_ROUNDED_FILL_VERT, LEGACY_ROUNDED_TEX_FRAG, LEGACY_ROUNDED_TEX_VERT, @@ -124,12 +123,6 @@ pub struct VulkanRenderer { pub(super) blur_composite_frag_shader: Rc, pub(super) blur_composite_descriptor_set_layout: Rc, pub(super) blur_composite_pipelines: CopyHashMap>, - pub(super) blur_vert_shader: Rc, - pub(super) blur_down_frag_shader: Rc, - pub(super) blur_up_frag_shader: Rc, - pub(super) blur_descriptor_set_layout: Rc, - pub(super) blur_down_pipelines: CopyHashMap>, - pub(super) blur_up_pipelines: CopyHashMap>, pub(super) defunct: Cell, pub(super) pending_cpu_jobs: CopyHashMap, pub(super) shm_allocator: Rc, @@ -236,20 +229,13 @@ enum VulkanOp { struct VulkanBlurOp { rect: crate::gfx_api::FramebufferRect, passes: u8, - offset: f32, mask: Option, - cache: Option>>>, - cache_epoch: u64, - cache_pixel_rect: [i32; 4], } struct VulkanBlurMask { tex: Rc, source: crate::gfx_api::SampleRect, threshold: f32, - buffer_resv: Option>, - acquire_sync: Option, - release_sync: ReleaseSync, } struct VulkanTexOp { @@ -260,7 +246,6 @@ struct VulkanTexOp { acquire_sync: Option, release_sync: ReleaseSync, alpha: f32, - discard_alpha: f32, source_type: TexSourceType, copy_type: TexCopyType, alpha_mode: AlphaMode, @@ -301,7 +286,6 @@ struct VulkanRoundedTexOp { acquire_sync: Option, release_sync: ReleaseSync, alpha: f32, - discard_alpha: f32, source_type: TexSourceType, copy_type: TexCopyType, alpha_mode: AlphaMode, @@ -422,10 +406,6 @@ impl VulkanDevice { let blur_composite_frag_shader = self.create_shader(BLUR_COMPOSITE_FRAG)?; let blur_composite_descriptor_set_layout = self.create_blur_composite_descriptor_set_layout(&sampler)?; - let blur_vert_shader = self.create_shader(BLUR_VERT)?; - let blur_down_frag_shader = self.create_shader(BLUR_DOWN_FRAG)?; - let blur_up_frag_shader = self.create_shader(BLUR_UP_FRAG)?; - let blur_descriptor_set_layout = self.create_blur_descriptor_set_layout(&sampler)?; let gfx_command_buffers = self.create_command_pool(self.graphics_queue_idx)?; let transfer_command_buffers = self .distinct_transfer_queue_family_idx @@ -517,12 +497,6 @@ impl VulkanDevice { blur_composite_frag_shader, blur_composite_descriptor_set_layout, blur_composite_pipelines: Default::default(), - blur_vert_shader, - blur_down_frag_shader, - blur_up_frag_shader, - blur_descriptor_set_layout, - blur_down_pipelines: Default::default(), - blur_up_pipelines: Default::default(), defunct: Cell::new(false), pending_cpu_jobs: Default::default(), shm_allocator, @@ -912,128 +886,6 @@ impl VulkanRenderer { })) } - pub(super) fn get_or_create_blur_down_pipeline( - &self, - format: vk::Format, - ) -> Result, VulkanError> { - if let Some(pl) = self.blur_down_pipelines.get(&format) { - return Ok(pl); - } - let pl = self.create_blur_pass_pipeline(format, &self.blur_down_frag_shader)?; - self.blur_down_pipelines.set(format, pl.clone()); - Ok(pl) - } - - pub(super) fn get_or_create_blur_up_pipeline( - &self, - format: vk::Format, - ) -> Result, VulkanError> { - if let Some(pl) = self.blur_up_pipelines.get(&format) { - return Ok(pl); - } - let pl = self.create_blur_pass_pipeline(format, &self.blur_up_frag_shader)?; - self.blur_up_pipelines.set(format, pl.clone()); - Ok(pl) - } - - fn create_blur_pass_pipeline( - &self, - format: vk::Format, - frag: &Rc, - ) -> Result, VulkanError> { - use ash::vk::{ - ColorComponentFlags, CullModeFlags, DynamicState, FrontFace, - GraphicsPipelineCreateInfo, PipelineCache, PipelineColorBlendAttachmentState, - PipelineColorBlendStateCreateInfo, PipelineDynamicStateCreateInfo, - PipelineInputAssemblyStateCreateInfo, PipelineLayoutCreateInfo, - PipelineMultisampleStateCreateInfo, PipelineRasterizationStateCreateInfo, - PipelineRenderingCreateInfo, PipelineShaderStageCreateInfo, - PipelineVertexInputStateCreateInfo, PipelineViewportStateCreateInfo, PolygonMode, - PrimitiveTopology, PushConstantRange, SampleCountFlags, - }; - let dev = &self.device.device; - let push_range = PushConstantRange::default() - .stage_flags(ShaderStageFlags::FRAGMENT) - .offset(0) - .size(size_of::() as u32); - let set_layouts = [self.blur_descriptor_set_layout.layout]; - let layout_info = PipelineLayoutCreateInfo::default() - .push_constant_ranges(slice::from_ref(&push_range)) - .set_layouts(&set_layouts); - let pipeline_layout = unsafe { dev.create_pipeline_layout(&layout_info, None) }; - let pipeline_layout = pipeline_layout.map_err(VulkanError::CreatePipelineLayout)?; - let destroy_layout = - run_on_drop::on_drop(|| unsafe { dev.destroy_pipeline_layout(pipeline_layout, None) }); - let stages = [ - PipelineShaderStageCreateInfo::default() - .stage(ShaderStageFlags::VERTEX) - .module(self.blur_vert_shader.module) - .name(c"main"), - PipelineShaderStageCreateInfo::default() - .stage(ShaderStageFlags::FRAGMENT) - .module(frag.module) - .name(c"main"), - ]; - let input_assembly_state = PipelineInputAssemblyStateCreateInfo::default() - .topology(PrimitiveTopology::TRIANGLE_STRIP); - let vertex_input_state = PipelineVertexInputStateCreateInfo::default(); - let rasterization_state = PipelineRasterizationStateCreateInfo::default() - .polygon_mode(PolygonMode::FILL) - .cull_mode(CullModeFlags::NONE) - .line_width(1.0) - .front_face(FrontFace::COUNTER_CLOCKWISE); - let multisampling_state = PipelineMultisampleStateCreateInfo::default() - .sample_shading_enable(false) - .rasterization_samples(SampleCountFlags::TYPE_1); - let blending = PipelineColorBlendAttachmentState::default() - .color_write_mask(ColorComponentFlags::RGBA) - .blend_enable(false); - let color_blend_state = - PipelineColorBlendStateCreateInfo::default().attachments(slice::from_ref(&blending)); - let dynamic_states = [DynamicState::VIEWPORT, DynamicState::SCISSOR]; - let dynamic_state = - PipelineDynamicStateCreateInfo::default().dynamic_states(&dynamic_states); - let viewport_state = PipelineViewportStateCreateInfo::default() - .viewport_count(1) - .scissor_count(1); - let mut pipeline_rendering_create_info = PipelineRenderingCreateInfo::default() - .color_attachment_formats(slice::from_ref(&format)); - let create_info = GraphicsPipelineCreateInfo::default() - .push_next(&mut pipeline_rendering_create_info) - .stages(&stages) - .input_assembly_state(&input_assembly_state) - .vertex_input_state(&vertex_input_state) - .rasterization_state(&rasterization_state) - .multisample_state(&multisampling_state) - .color_blend_state(&color_blend_state) - .dynamic_state(&dynamic_state) - .viewport_state(&viewport_state) - .layout(pipeline_layout); - let pipelines = unsafe { - dev.create_graphics_pipelines( - PipelineCache::null(), - slice::from_ref(&create_info), - None, - ) - }; - let mut pipelines = pipelines - .map_err(|e| e.1) - .map_err(VulkanError::CreatePipeline)?; - let pipeline = pipelines.pop().unwrap(); - destroy_layout.forget(); - Ok(Rc::new(VulkanPipeline { - vert: self.blur_vert_shader.clone(), - _frag: frag.clone(), - pipeline_layout, - pipeline, - _descriptor_set_layouts: { - let mut v = ArrayVec::new(); - v.push(self.blur_descriptor_set_layout.clone()); - v - }, - })) - } - pub(super) fn allocate_point(&self) -> u64 { self.last_point.fetch_add(1) + 1 } @@ -1411,7 +1263,6 @@ impl VulkanRenderer { acquire_sync: Some(ct.acquire_sync.clone()), release_sync: ct.release_sync, alpha: ct.alpha.unwrap_or_default(), - discard_alpha: ct.discard_alpha.unwrap_or(-1.0), source_type, copy_type, alpha_mode: ct.alpha_mode, @@ -1510,7 +1361,6 @@ impl VulkanRenderer { acquire_sync: Some(ct.acquire_sync.clone()), release_sync: ct.release_sync, alpha: ct.alpha.unwrap_or_default(), - discard_alpha: ct.discard_alpha.unwrap_or(-1.0), source_type, copy_type, alpha_mode: ct.alpha_mode, @@ -1526,6 +1376,9 @@ impl VulkanRenderer { } } GfxApiOpt::BlurBackdrop(b) => { + // Flush all pending ops in original order, then push a + // barrier op to FrameBuffer pass that will end + restart + // the render pass to do the blur work in between. sync(memory); let mask = if let Some(m) = &b.mask { let tex = m.texture.clone().into_vk(&self.device.device)?; @@ -1540,35 +1393,15 @@ impl VulkanRenderer { tex, source: m.source, threshold: m.threshold, - buffer_resv: m.buffer_resv.clone(), - acquire_sync: Some(m.acquire_sync.clone()), - release_sync: m.release_sync, }) } } else { None }; - // Route to whichever pass actually contains the scene. - // The BlendBuffer holds the linearly-composed scene - // (background + workspace + translucent layers) and is - // copied into the FrameBuffer only at the end of the FB - // pass. Reading FB before that copy would sample an - // empty target and produce a black blur. If BB has been - // elided (no blended content this frame), fall back to - // FB which then carries the full scene itself. - let target_pass = if !memory.paint_regions[RenderPass::BlendBuffer].is_empty() { - RenderPass::BlendBuffer - } else { - RenderPass::FrameBuffer - }; - memory.ops[target_pass].push(VulkanOp::BlurBarrier(VulkanBlurOp { + memory.ops[RenderPass::FrameBuffer].push(VulkanOp::BlurBarrier(VulkanBlurOp { rect: b.rect, passes: b.passes, - offset: b.offset, mask, - cache: b.cache.clone(), - cache_epoch: b.cache_epoch, - cache_pixel_rect: b.cache_pixel_rect, })); } } @@ -1753,7 +1586,7 @@ impl VulkanRenderer { release_sync, }); } else if let VulkanOp::BlurBarrier(b) = cmd - && let Some(m) = &mut b.mask + && let Some(m) = &b.mask { let tex = &m.tex; if tex.execution_version.replace(execution) != execution { @@ -1765,12 +1598,6 @@ impl VulkanRenderer { if let VulkanImageMemory::DmaBuf(_) = &tex.ty { memory.dmabuf_sample.push(tex.clone()) } - memory.textures.push(UsedTexture { - tex: tex.clone(), - resv: m.buffer_resv.take(), - acquire_sync: m.acquire_sync.take().unwrap(), - release_sync: m.release_sync, - }); } } } @@ -2102,7 +1929,6 @@ impl VulkanRenderer { let push = TexPushConstants { vertices: c.range_address, alpha: c.alpha, - discard_threshold: c.discard_alpha, }; unsafe { db.cmd_set_descriptor_buffer_offsets( @@ -2140,7 +1966,6 @@ impl VulkanRenderer { pos, tex_pos, alpha: c.alpha, - discard_threshold: c.discard_alpha, }; unsafe { dev.cmd_push_constants( @@ -2220,7 +2045,6 @@ impl VulkanRenderer { let push = RoundedTexPushConstants { vertices: c.range_address, alpha: c.alpha, - discard_threshold: c.discard_alpha, size_x: c.size[0], size_y: c.size[1], corner_radius_tl: c.corner_radius[0], @@ -2264,7 +2088,6 @@ impl VulkanRenderer { pos: c.target, tex_pos: c.source, alpha: c.alpha, - discard_threshold: c.discard_alpha, size_x: c.size[0], size_y: c.size[1], corner_radius_tl: c.corner_radius[0], @@ -2286,8 +2109,10 @@ impl VulkanRenderer { } } VulkanOp::BlurBarrier(blur) => { - // BlurBarrier is pushed to exactly one pass in convert_ops - // (BB if present, else FB), so no per-pass gating is needed. + // Blur is only meaningful in the FrameBuffer pass. + if pass != RenderPass::FrameBuffer { + continue; + } // End the current dynamic render pass, run the blur work // (image-blit cascade between scratch images), and resume // the render pass with LOAD so subsequent draws layer on @@ -2307,55 +2132,14 @@ impl VulkanRenderer { threshold: m.threshold, _phantom: std::marker::PhantomData, }); - - // Cache lookup: a hit lets us skip the entire blur cascade. - // Only masked blurs are cached. The masked path leaves the - // blurred scratch image in SHADER_READ_ONLY_OPTIMAL, which - // is the layout required by the cache-hit composite path. - let cached_blur: Option> = mask_record - .as_ref() - .and_then(|_| blur.cache.as_ref()) - .and_then(|slot| { - let slot_borrow = slot.borrow(); - slot_borrow.as_ref().and_then(|entry| { - if entry.epoch == blur.cache_epoch - && entry.passes == blur.passes - && entry.offset == blur.offset - && entry.pixel_rect == blur.cache_pixel_rect - { - entry.image.clone().into_vk(&self.device.device).ok() - } else { - None - } - }) - }); - - let mut produced_blur: Option> = None; self.record_blur( buf, target, rect_arr, blur.passes, - blur.offset, &mut local_blur_scratch, mask_record.as_ref(), - cached_blur.as_ref(), - &mut produced_blur, )?; - - // On a masked cache miss, store the freshly-blurred image - // for the next frame to reuse. - if let (Some(_), Some(slot), Some(image)) = - (mask_record.as_ref(), blur.cache.as_ref(), produced_blur) - { - *slot.borrow_mut() = Some(crate::gfx_api::BlurCacheEntry { - pixel_rect: blur.cache_pixel_rect, - passes: blur.passes, - offset: blur.offset, - epoch: blur.cache_epoch, - image, - }); - } self.begin_rendering_load(buf, target); // Pipeline state is invalidated across the render-pass // break — force re-bind on next draw. @@ -2895,7 +2679,6 @@ impl VulkanRenderer { let width = fb.width as f32; let height = fb.height as f32; let mut tag = 0; - let mut blur_rects: Vec = Vec::new(); for opt in opts.iter().rev() { let (opaque, fb_rect) = match opt { GfxApiOpt::Sync => continue, @@ -2923,10 +2706,7 @@ impl VulkanRenderer { (false, rf.rect) } GfxApiOpt::RoundedCopyTexture(ct) => (false, ct.target), - GfxApiOpt::BlurBackdrop(b) => { - blur_rects.push(b.rect.to_rect(width, height)); - continue; - } + GfxApiOpt::BlurBackdrop(_) => continue, }; if opaque || bb.is_none() { tag |= 1; @@ -2939,20 +2719,6 @@ impl VulkanRenderer { } memory.regions_2.push(rect.with_tag(tag)); } - // Force blur source rects into the effective damage region. The blur - // cascade reads its source from BB (or FB), and both buffers persist - // their contents across frames in undamaged regions. Without this, - // a cache-miss cascade can sample a stale composite — including the - // blur surface's own previously-drawn body — and re-blur it, - // producing visible double-shadow artifacts at the blur boundary. - let blur_region_owned = Region::from_rects2(&blur_rects); - let expanded_region; - let region: &Region = if blur_region_owned.is_empty() { - region - } else { - expanded_region = region.union_cow(&blur_region_owned).into_owned(); - &expanded_region - }; let clear_region = if clear.is_some() { let opaque_region = Region::from_rects2(&memory.regions_1); region.subtract_cow(&opaque_region) diff --git a/src/gfx_apis/vulkan/shaders.rs b/src/gfx_apis/vulkan/shaders.rs index a1894335..607fd49a 100644 --- a/src/gfx_apis/vulkan/shaders.rs +++ b/src/gfx_apis/vulkan/shaders.rs @@ -21,9 +21,6 @@ pub const ROUNDED_TEX_VERT: &[u8] = include_bytes!("shaders_bin/rounded_tex.vert pub const ROUNDED_TEX_FRAG: &[u8] = include_bytes!("shaders_bin/rounded_tex.frag.spv"); pub const BLUR_COMPOSITE_VERT: &[u8] = include_bytes!("shaders_bin/blur_composite.vert.spv"); pub const BLUR_COMPOSITE_FRAG: &[u8] = include_bytes!("shaders_bin/blur_composite.frag.spv"); -pub const BLUR_VERT: &[u8] = include_bytes!("shaders_bin/blur.vert.spv"); -pub const BLUR_DOWN_FRAG: &[u8] = include_bytes!("shaders_bin/blur_down.frag.spv"); -pub const BLUR_UP_FRAG: &[u8] = include_bytes!("shaders_bin/blur_up.frag.spv"); pub const LEGACY_ROUNDED_FILL_VERT: &[u8] = include_bytes!("shaders_bin/legacy_rounded_fill.vert.spv"); pub const LEGACY_ROUNDED_FILL_FRAG: &[u8] = @@ -72,7 +69,6 @@ unsafe impl Packed for TexVertex {} pub struct TexPushConstants { pub vertices: DeviceAddress, pub alpha: f32, - pub discard_threshold: f32, } unsafe impl Packed for TexPushConstants {} @@ -113,7 +109,6 @@ pub struct LegacyTexPushConstants { pub pos: [[f32; 2]; 4], pub tex_pos: [[f32; 2]; 4], pub alpha: f32, - pub discard_threshold: f32, } unsafe impl Packed for LegacyTexPushConstants {} @@ -153,7 +148,6 @@ unsafe impl Packed for LegacyRoundedFillPushConstants {} pub struct RoundedTexPushConstants { pub vertices: DeviceAddress, pub alpha: f32, - pub discard_threshold: f32, pub size_x: f32, pub size_y: f32, pub corner_radius_tl: f32, @@ -171,7 +165,6 @@ pub struct LegacyRoundedTexPushConstants { pub pos: [[f32; 2]; 4], pub tex_pos: [[f32; 2]; 4], pub alpha: f32, - pub discard_threshold: f32, pub size_x: f32, pub size_y: f32, pub corner_radius_tl: f32, @@ -202,15 +195,6 @@ pub struct BlurCompositePushConstants { unsafe impl Packed for BlurCompositePushConstants {} -#[derive(Copy, Clone, Debug)] -#[repr(C)] -pub struct BlurPushConstants { - pub halfpixel: [f32; 2], - pub offset: f32, -} - -unsafe impl Packed for BlurPushConstants {} - impl VulkanDevice { pub(super) fn create_shader( self: &Rc, diff --git a/src/gfx_apis/vulkan/shaders/blur.vert b/src/gfx_apis/vulkan/shaders/blur.vert deleted file mode 100644 index 7e0fde54..00000000 --- a/src/gfx_apis/vulkan/shaders/blur.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 - -layout(location = 0) out vec2 v_texcoord; - -void main() { - vec2 pos; - switch (gl_VertexIndex) { - case 0: - pos = vec2( 1.0, -1.0); - v_texcoord = vec2(1.0, 0.0); - break; - case 1: - pos = vec2(-1.0, -1.0); - v_texcoord = vec2(0.0, 0.0); - break; - case 2: - pos = vec2( 1.0, 1.0); - v_texcoord = vec2(1.0, 1.0); - break; - case 3: - pos = vec2(-1.0, 1.0); - v_texcoord = vec2(0.0, 1.0); - break; - } - gl_Position = vec4(pos, 0.0, 1.0); -} diff --git a/src/gfx_apis/vulkan/shaders/blur_down.frag b/src/gfx_apis/vulkan/shaders/blur_down.frag deleted file mode 100644 index 8afb493a..00000000 --- a/src/gfx_apis/vulkan/shaders/blur_down.frag +++ /dev/null @@ -1,21 +0,0 @@ -#version 450 - -layout(set = 0, binding = 0) uniform sampler2D tex; - -layout(push_constant, std430) uniform Data { - vec2 halfpixel; - float offset; -} data; - -layout(location = 0) in vec2 v_texcoord; -layout(location = 0) out vec4 out_color; - -void main() { - vec2 hp = data.halfpixel * data.offset; - vec4 sum = textureLod(tex, v_texcoord, 0.0) * 4.0; - sum += textureLod(tex, v_texcoord - hp, 0.0); - sum += textureLod(tex, v_texcoord + hp, 0.0); - sum += textureLod(tex, v_texcoord + vec2(hp.x, -hp.y), 0.0); - sum += textureLod(tex, v_texcoord - vec2(hp.x, -hp.y), 0.0); - out_color = sum / 8.0; -} diff --git a/src/gfx_apis/vulkan/shaders/blur_up.frag b/src/gfx_apis/vulkan/shaders/blur_up.frag deleted file mode 100644 index 2397d687..00000000 --- a/src/gfx_apis/vulkan/shaders/blur_up.frag +++ /dev/null @@ -1,24 +0,0 @@ -#version 450 - -layout(set = 0, binding = 0) uniform sampler2D tex; - -layout(push_constant, std430) uniform Data { - vec2 halfpixel; - float offset; -} data; - -layout(location = 0) in vec2 v_texcoord; -layout(location = 0) out vec4 out_color; - -void main() { - vec2 hp = data.halfpixel * data.offset; - vec4 sum = textureLod(tex, v_texcoord + vec2(-hp.x * 2.0, 0.0), 0.0); - sum += textureLod(tex, v_texcoord + vec2(-hp.x, hp.y), 0.0) * 2.0; - sum += textureLod(tex, v_texcoord + vec2(0.0, hp.y * 2.0), 0.0); - sum += textureLod(tex, v_texcoord + vec2(hp.x, hp.y), 0.0) * 2.0; - sum += textureLod(tex, v_texcoord + vec2(hp.x * 2.0, 0.0), 0.0); - sum += textureLod(tex, v_texcoord + vec2(hp.x, -hp.y), 0.0) * 2.0; - sum += textureLod(tex, v_texcoord + vec2(0.0, -hp.y * 2.0), 0.0); - sum += textureLod(tex, v_texcoord + vec2(-hp.x, -hp.y), 0.0) * 2.0; - out_color = sum / 12.0; -} diff --git a/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl b/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl index 1e95d980..f221ff6a 100644 --- a/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl +++ b/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl @@ -2,12 +2,11 @@ layout(push_constant, std430) uniform Data { layout(offset = 0) vec2 pos[4]; layout(offset = 32) vec2 tex_pos[4]; layout(offset = 64) float mul; - layout(offset = 68) float discard_threshold; - layout(offset = 72) float size_x; - layout(offset = 76) float size_y; - layout(offset = 80) float corner_radius_tl; - layout(offset = 84) float corner_radius_tr; - layout(offset = 88) float corner_radius_br; - layout(offset = 92) float corner_radius_bl; - layout(offset = 96) float scale; + layout(offset = 68) float size_x; + layout(offset = 72) float size_y; + layout(offset = 76) float corner_radius_tl; + layout(offset = 80) float corner_radius_tr; + layout(offset = 84) float corner_radius_br; + layout(offset = 88) float corner_radius_bl; + layout(offset = 92) float scale; } data; diff --git a/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag b/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag index 8c84529f..cec6f001 100644 --- a/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag +++ b/src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag @@ -38,9 +38,6 @@ void main() { vec2 size = vec2(data.size_x, data.size_y); vec4 corner_radius = vec4(data.corner_radius_tl, data.corner_radius_tr, data.corner_radius_br, data.corner_radius_bl); vec4 c = textureLod(tex, tex_pos, 0); - if (c.a < data.discard_threshold) { - discard; - } if (has_alpha_multiplier) { if (src_has_alpha) { c *= data.mul; diff --git a/src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl b/src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl index 82ec59ba..61f3ef3c 100644 --- a/src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl +++ b/src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl @@ -2,5 +2,4 @@ layout(push_constant, std430) uniform Data { layout(offset = 0) vec2 pos[4]; layout(offset = 32) vec2 tex_pos[4]; layout(offset = 64) float mul; - layout(offset = 68) float discard_threshold; } data; diff --git a/src/gfx_apis/vulkan/shaders/legacy/tex.frag b/src/gfx_apis/vulkan/shaders/legacy/tex.frag index ab862b32..2896bc87 100644 --- a/src/gfx_apis/vulkan/shaders/legacy/tex.frag +++ b/src/gfx_apis/vulkan/shaders/legacy/tex.frag @@ -9,9 +9,6 @@ layout(location = 0) out vec4 out_color; void main() { vec4 c = textureLod(tex, tex_pos, 0); - if (c.a < data.discard_threshold) { - discard; - } if (has_alpha_multiplier) { if (src_has_alpha) { c *= data.mul; diff --git a/src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl b/src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl index 62c11e74..9a07f0b0 100644 --- a/src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl +++ b/src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl @@ -12,12 +12,11 @@ layout(buffer_reference, buffer_reference_align = 8, std430) readonly buffer Ver layout(push_constant, std430) uniform Data { layout(offset = 0) Vertices vertices; layout(offset = 8) float mul; - layout(offset = 12) float discard_threshold; - layout(offset = 16) float size_x; - layout(offset = 20) float size_y; - layout(offset = 24) float corner_radius_tl; - layout(offset = 28) float corner_radius_tr; - layout(offset = 32) float corner_radius_br; - layout(offset = 36) float corner_radius_bl; - layout(offset = 40) float scale; + layout(offset = 12) float size_x; + layout(offset = 16) float size_y; + layout(offset = 20) float corner_radius_tl; + layout(offset = 24) float corner_radius_tr; + layout(offset = 28) float corner_radius_br; + layout(offset = 32) float corner_radius_bl; + layout(offset = 36) float scale; } data; diff --git a/src/gfx_apis/vulkan/shaders/rounded_tex.frag b/src/gfx_apis/vulkan/shaders/rounded_tex.frag index aebbdb32..0c506bc2 100644 --- a/src/gfx_apis/vulkan/shaders/rounded_tex.frag +++ b/src/gfx_apis/vulkan/shaders/rounded_tex.frag @@ -45,9 +45,6 @@ void main() { vec2 size = vec2(data.size_x, data.size_y); vec4 corner_radius = vec4(data.corner_radius_tl, data.corner_radius_tr, data.corner_radius_br, data.corner_radius_bl); vec4 c = textureLod(sampler2D(tex, sam), tex_pos, 0); - if (c.a < data.discard_threshold) { - discard; - } if (eotf != inv_eotf || has_matrix || alpha_mode != AM_PREMULTIPLIED_ELECTRICAL) { vec3 rgb = c.rgb; if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_ELECTRICAL) { diff --git a/src/gfx_apis/vulkan/shaders/tex.common.glsl b/src/gfx_apis/vulkan/shaders/tex.common.glsl index 45b7119a..8576231b 100644 --- a/src/gfx_apis/vulkan/shaders/tex.common.glsl +++ b/src/gfx_apis/vulkan/shaders/tex.common.glsl @@ -12,5 +12,4 @@ layout(buffer_reference, buffer_reference_align = 8, std430) readonly buffer Ver layout(push_constant, std430) uniform Data { Vertices vertices; float mul; - float discard_threshold; } data; diff --git a/src/gfx_apis/vulkan/shaders/tex.frag b/src/gfx_apis/vulkan/shaders/tex.frag index 2e09c32c..e1ccacda 100644 --- a/src/gfx_apis/vulkan/shaders/tex.frag +++ b/src/gfx_apis/vulkan/shaders/tex.frag @@ -16,9 +16,6 @@ layout(location = 0) out vec4 out_color; void main() { vec4 c = textureLod(sampler2D(tex, sam), tex_pos, 0); - if (c.a < data.discard_threshold) { - discard; - } if (eotf != inv_eotf || has_matrix || alpha_mode != AM_PREMULTIPLIED_ELECTRICAL) { vec3 rgb = c.rgb; if (src_has_alpha && alpha_mode == AM_PREMULTIPLIED_ELECTRICAL) { diff --git a/src/gfx_apis/vulkan/shaders_bin/blur.vert.spv b/src/gfx_apis/vulkan/shaders_bin/blur.vert.spv deleted file mode 100644 index 6b57ef62..00000000 Binary files a/src/gfx_apis/vulkan/shaders_bin/blur.vert.spv and /dev/null differ diff --git a/src/gfx_apis/vulkan/shaders_bin/blur_down.frag.spv b/src/gfx_apis/vulkan/shaders_bin/blur_down.frag.spv deleted file mode 100644 index d455ae52..00000000 Binary files a/src/gfx_apis/vulkan/shaders_bin/blur_down.frag.spv and /dev/null differ diff --git a/src/gfx_apis/vulkan/shaders_bin/blur_up.frag.spv b/src/gfx_apis/vulkan/shaders_bin/blur_up.frag.spv deleted file mode 100644 index 56b6fe73..00000000 Binary files a/src/gfx_apis/vulkan/shaders_bin/blur_up.frag.spv and /dev/null differ diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.frag.spv index 300db829..9fd78f9b 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.vert.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.vert.spv index c296a7ec..0a0d73e2 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.vert.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_rounded_tex.vert.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv index 669b3064..9664f044 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.vert.spv b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.vert.spv index 7361189a..edf86be6 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/legacy_tex.vert.spv and b/src/gfx_apis/vulkan/shaders_bin/legacy_tex.vert.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/rounded_tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/rounded_tex.frag.spv index 3ff5c280..2bdd1fd3 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/rounded_tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/rounded_tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/rounded_tex.vert.spv b/src/gfx_apis/vulkan/shaders_bin/rounded_tex.vert.spv index 7e11b397..3ac5e409 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/rounded_tex.vert.spv and b/src/gfx_apis/vulkan/shaders_bin/rounded_tex.vert.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv b/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv index f1ca6188..c013804d 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv and b/src/gfx_apis/vulkan/shaders_bin/tex.frag.spv differ diff --git a/src/gfx_apis/vulkan/shaders_bin/tex.vert.spv b/src/gfx_apis/vulkan/shaders_bin/tex.vert.spv index 00f1aa5a..74f97643 100644 Binary files a/src/gfx_apis/vulkan/shaders_bin/tex.vert.spv and b/src/gfx_apis/vulkan/shaders_bin/tex.vert.spv differ diff --git a/src/gfx_apis/vulkan/shaders_hash.txt b/src/gfx_apis/vulkan/shaders_hash.txt index f8b7f0e8..de378df5 100644 --- a/src/gfx_apis/vulkan/shaders_hash.txt +++ b/src/gfx_apis/vulkan/shaders_hash.txt @@ -1,9 +1,6 @@ 302a9f250bdc4f8e0e71a9f77c9a8a7aa55fd003bc91c2422a700c4abd83f54e src/gfx_apis/vulkan/shaders/alpha_modes.glsl -65acbe7a6496279fa22f520ad2036d3e14a7cb1707c6a509ce7858adc4a2dcba src/gfx_apis/vulkan/shaders/blur.vert 16ad6f1eb029ccce5e0204a7d79709b05a8a708133feaf8bb20a24371de25ed7 src/gfx_apis/vulkan/shaders/blur_composite.frag 6399e23afa2e07c98b9fd1a4e853ea974a9958547ce65734846483bd7cbc8461 src/gfx_apis/vulkan/shaders/blur_composite.vert -a04b2453c39efb018754fc25d45a369b5813359c55fad1c99020804cbb3a18e0 src/gfx_apis/vulkan/shaders/blur_down.frag -f6d51f3b5410387d1474529c44e71bfdc31ceb80174ea6e3e4c2df30d03f11c3 src/gfx_apis/vulkan/shaders/blur_up.frag b6a0df1e231fab533499329636b7a580384784418baee06c147af5fcc384cf5c src/gfx_apis/vulkan/shaders/eotfs.glsl 8a38df18851cd13884499820f26939fb7319f45d913d867f254d8118d59fb117 src/gfx_apis/vulkan/shaders/fill.common.glsl 21c488d12aa5ad2f109ec44cb856dfe837e02ea9025b5ed64439d742c17cbf30 src/gfx_apis/vulkan/shaders/fill.frag @@ -15,11 +12,11 @@ ad22a79e1a88a12daa40c0a2b953084c129a408297c8ca544d60e0b6001470b9 src/gfx_apis/vu b77838c0aac9ec90ae76cd0d94d3891d72d9a30b09ce77009afd9f4e567dd042 src/gfx_apis/vulkan/shaders/legacy/rounded_fill.common.glsl fa39734aea1c96960f5dc95b999ae2fa5576ecf4b527fd70ee0f643c8ddcc452 src/gfx_apis/vulkan/shaders/legacy/rounded_fill.frag c1914cc00fb4827f65cd55bd0737d159fe44a098a3085a500822fc91cc2bfcad src/gfx_apis/vulkan/shaders/legacy/rounded_fill.vert -0305f0bf2ab87de4280e32adfda21906304db595590baa0f024d4e5e67d80d9c src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl -02405debc59f254cd95f6b7f94df27438c952b22f357f411359898f430bcd770 src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag +bd249cf170b72cd833e92a7719e88da0a91e563956579707e693679b443d73d5 src/gfx_apis/vulkan/shaders/legacy/rounded_tex.common.glsl +28f3249e0d974a332b2926fb7565930627a093d6ac21ca17f2bf191740d299bd src/gfx_apis/vulkan/shaders/legacy/rounded_tex.frag 6ef0bde549dc163cd08f68d975071f5d74213c07ccc4a06b30c6f179b2f848ae src/gfx_apis/vulkan/shaders/legacy/rounded_tex.vert -f5bfdb445c501ab97a19c7d435996a03ed45d31e8e54e29143f1daad8fa60d5b src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl -3a9b36f72c82067e1892481054acb0948097d6c766e62e8bfad766fa2c2e3de6 src/gfx_apis/vulkan/shaders/legacy/tex.frag +e0a8769dd7938dd02e66db9e9048ed6bef8f8c42671f2e2c7a7976a6d498f685 src/gfx_apis/vulkan/shaders/legacy/tex.common.glsl +0e7c72ea11671065842c8b4ad4131a7df33b427dc0ea76bf5a896546f6636cb0 src/gfx_apis/vulkan/shaders/legacy/tex.frag 4402f7ccdbb9fb52fb6cda3aab13cf89e2980c79b541f8be0463efd64a5f98ed src/gfx_apis/vulkan/shaders/legacy/tex.vert 3ba5d05c2b95099e5424b3ade5d1c31d431f5730b1d0b51a9fb5f8afc4ea14b4 src/gfx_apis/vulkan/shaders/out.common.glsl 5069f619c7d722815a022e2d84720a2d8290af49a3ed49ea0cd26b52115cc39a src/gfx_apis/vulkan/shaders/out.frag @@ -27,10 +24,10 @@ f5bfdb445c501ab97a19c7d435996a03ed45d31e8e54e29143f1daad8fa60d5b src/gfx_apis/vu 9202d5c9fc4ce0d5f40ed147f245bd037728c9e060ea46a0f0a1767ca55e6c48 src/gfx_apis/vulkan/shaders/rounded_fill.common.glsl 9085625d2afb1365685ae79a58108bf6566573ed94d9913397cf74dc6ef9b6e8 src/gfx_apis/vulkan/shaders/rounded_fill.frag 7665319a706e514f125d80f51f10b643f01cdae54d8a6ea56c218f78de7c0ecb src/gfx_apis/vulkan/shaders/rounded_fill.vert -0fa53622bbee536bdf0b32438c276b9e5231e1fe5fac93ed395426da3893bd74 src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl -adeba99236ee7606170bfb48e62c0df11c71a83018d8a201cde760c4f569fe5e src/gfx_apis/vulkan/shaders/rounded_tex.frag +dd100d048c0b380c913cffd7ac48fed3a341b3cb052302a11c369967f38aba9a src/gfx_apis/vulkan/shaders/rounded_tex.common.glsl +454f34754ea4102190821c2d168dedd8c6bf624f1712b6136d902428f801a1e9 src/gfx_apis/vulkan/shaders/rounded_tex.frag 21b18ba369b505b9aedb8cf2e7e31bc417f6704fd2daac353b0db52f9ae44c70 src/gfx_apis/vulkan/shaders/rounded_tex.vert -6ebf70abd2a06cb8a14cea7022a19d5d4bc95b1ef5e5a7ca22ab4c5fa37b6244 src/gfx_apis/vulkan/shaders/tex.common.glsl -fdfc60c64a22e7745dc82642ea23ef214dbd3b92d6a4f0ae1d75d33e89ae6a6a src/gfx_apis/vulkan/shaders/tex.frag +e22d4d3318a350def8ef19c7b27dc6a308a84c2fe9d7c02b81107f72073cd481 src/gfx_apis/vulkan/shaders/tex.common.glsl +1f196cee646a934072beb3e5648a5042c035953d9a0c26b0a22e330c2f8bb994 src/gfx_apis/vulkan/shaders/tex.frag 423cf327c9fcc4070dbf75321c1224a1589b6cf3d2f1ea5e8bd0362e1a9f3aa1 src/gfx_apis/vulkan/shaders/tex.vert b982f7101c22931a33b32dce3408387f3392c0f0ad0ca5852da265b0d12856bb src/gfx_apis/vulkan/shaders/tex_set.glsl diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index 79a3f19b..877151c4 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -1582,9 +1582,7 @@ impl WlSeatGlobal { { con.disconnect(TextDisconnectReason::FocusLost); } - if !surface.destroyed.get() - && let Some(tis) = self.text_inputs.borrow().get(&surface.client.id) - { + if let Some(tis) = self.text_inputs.borrow().get(&surface.client.id) { for ti in tis.lock().values() { ti.send_leave(surface); ti.send_done(); diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index e9ae9d7b..547b7e2a 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -318,7 +318,7 @@ pub struct WlSurface { pub content_type: Cell>, pub drm_feedback: CopyHashMap>, syncobj_surface: CloneCell>>, - pub destroyed: Cell, + destroyed: Cell, commit_timeline: CommitTimeline, alpha_modifier: CloneCell>>, alpha: Cell>, @@ -1019,7 +1019,6 @@ impl WlSurfaceRequestHandler for WlSurface { self.unset_dnd_icons(); self.unset_cursors(); self.ext.get().on_surface_destroy()?; - self.destroyed.set(true); self.destroy_node(); { let mut children = self.children.borrow_mut(); @@ -1030,19 +1029,6 @@ impl WlSurfaceRequestHandler for WlSurface { } *children = None; } - // Capture a close-animation snapshot if the client is destroying the - // surface while it still has a buffer (i.e. without a clean null-attach - // commit first — typical for crash/disconnect paths). - if self.buffer.is_some() - && let Some(tl) = self.toplevel.get() - && let Some(snap) = crate::animation::capture_snapshot(&self.client.state, &tl) - { - self.client - .state - .close_snapshots - .borrow_mut() - .push(Rc::new(snap)); - } self.buffer.set(None); self.reset_shm_textures(); if let Some(xwayland_serial) = self.xwayland_serial.get() { @@ -1055,6 +1041,7 @@ impl WlSurfaceRequestHandler for WlSurface { self.client.remove_obj(self)?; self.idle_inhibitors.clear(); self.constraints.take(); + self.destroyed.set(true); Ok(()) } @@ -1251,24 +1238,8 @@ impl WlSurface { let mut buffer_changed = false; let mut old_raw_size = None; let (mut dx, mut dy) = mem::take(&mut pending.offset); - let mut buffer_presence_changed = false; if let Some(buffer_change) = pending.buffer.take() { buffer_changed = true; - buffer_presence_changed = buffer_change.is_some() != self.buffer.is_some(); - // If the client just attached a null buffer to the main surface of - // a mapped toplevel, capture a snapshot before we drop the buffer - // so the close animation has something to render after teardown. - if buffer_change.is_none() - && self.buffer.is_some() - && let Some(tl) = self.toplevel.get() - && let Some(snap) = crate::animation::capture_snapshot(&self.client.state, &tl) - { - self.client - .state - .close_snapshots - .borrow_mut() - .push(Rc::new(snap)); - } if let Some(buffer) = self.buffer.take() { old_raw_size = Some(buffer.buffer.buf.rect); } @@ -1437,16 +1408,6 @@ impl WlSurface { }; self.is_opaque.set(is_opaque); } - if buffer_abs_pos_size_changed || buffer_presence_changed { - // Pointer focus depends on whether this surface accepts input. - // It just changed (size shrank/grew, or buffer went from null to - // non-null or vice versa — the latter happens when a client - // dismisses a subsurface by null-attaching while keeping its - // wp_viewport destination). Force a re-evaluation so the pointer - // stack doesn't keep a now-invisible surface focused until the - // next motion event. - self.client.state.tree_changed(); - } let mut tearing_changed = false; if let Some(tearing) = pending.tearing.take() && self.tearing.replace(tearing) != tearing @@ -1636,13 +1597,6 @@ impl WlSurface { } fn accepts_input_at(&self, mut x: i32, mut y: i32) -> bool { - // Per the wayland spec, a surface without a buffer is invisible and - // cannot receive input. Without this check, a client that null-buffers - // but keeps a wp_viewport destination set (as foot does for its - // fractional-scaling subsurfaces) would keep an invisible hit-rect. - if self.buffer.is_none() { - return false; - } let rect = self.buffer_abs_pos.get().at_point(0, 0); if !rect.contains(x, y) { return false; diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index e31f90b1..7f7d053b 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -26,7 +26,7 @@ use { Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, NodeVisitor, OutputNode, StackedNode, }, - utils::{clonecell::CloneCell, numcell::NumCell, smallmap::SmallMap}, + utils::{clonecell::CloneCell, smallmap::SmallMap}, wire::{XdgPopupId, xdg_popup::*}, }, std::{ @@ -72,7 +72,6 @@ pub struct LayerPopupBlur { } pub struct XdgPopup { - pub blur_pre_rendered: Cell, pub id: XdgPopupId, node_id: PopupId, pub xdg: Rc, @@ -80,8 +79,6 @@ pub struct XdgPopup { relative_position: Cell, pos: RefCell, pub tracker: Tracker, - pub blur_cache: Rc>>, - pub blur_cache_epoch: NumCell, seat_state: NodeSeatState, set_visible_prepared: Cell, jay_popup_ext: CloneCell>>, @@ -107,11 +104,8 @@ impl XdgPopup { Ok(Self { id, node_id: xdg.surface.client.state.node_ids.next(), - blur_pre_rendered: Cell::new(false), xdg: xdg.clone(), parent: Default::default(), - blur_cache: Default::default(), - blur_cache_epoch: Default::default(), relative_position: Cell::new(Default::default()), pos: RefCell::new(pos), tracker: Default::default(), @@ -320,9 +314,6 @@ impl XdgPopupRequestHandler for XdgPopup { } impl XdgPopup { - pub fn layer_blur_settings(&self) -> Option { - self.parent.get()?.layer_blur_settings() - } pub fn set_visible(&self, visible: bool) { let surface = &self.xdg.surface; let extents = surface.extents.get(); @@ -427,56 +418,33 @@ impl Node for XdgPopup { } fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32, bounds: Option<&Rect>) { - let settings = self.layer_blur_settings(); + let settings = self.parent.get().and_then(|p| p.layer_blur_settings()); if let Some(s) = settings { - if s.blur && !self.blur_pre_rendered.get() { - // Only push blur if it wasn't already pushed in the pre-pass + if s.blur { let extents = self.xdg.surface.extents.get(); let geo = self.xdg.geometry(); let (gx, gy) = geo.translate(x, y); let rect = extents.move_(gx, gy); - let popup_blur_rect = if let Some(parent) = self.parent.get() { - let parent_rect = parent.position(); - if parent_rect.contains_rect(&rect) { - None - } else { - Some(rect) - } - } else { - Some(rect) - }; - if let Some(blur_rect) = popup_blur_rect { - let scaled = renderer.base.scale_rect(blur_rect); - let cfg = renderer.state.blur_config.get(); - let mask = s.ignore_alpha.and_then(|threshold| { - let buffer = self.xdg.surface.buffer.get()?; - let texture = buffer.buffer.buf.get_texture(&self.xdg.surface)?; - let source = *self.xdg.surface.buffer_points_norm.borrow(); - let release_sync = buffer.release_sync; - Some(crate::gfx_api::BlurMask { - texture, - source, - threshold, - buffer_resv: Some(buffer), - acquire_sync: crate::gfx_api::AcquireSync::Unnecessary, - release_sync, - }) - }); - renderer.base.push_blur_backdrop( - scaled, - cfg.passes, - cfg.size, - mask, - Some(self.blur_cache.clone()), - self.blur_cache_epoch.get(), - ); - } + let scaled = renderer.base.scale_rect(rect); + let cfg = renderer.state.blur_config.get(); + let mask = s.ignore_alpha.and_then(|threshold| { + let buffer = self.xdg.surface.buffer.get()?; + let texture = buffer.buffer.buf.get_texture(&self.xdg.surface)?; + let source = *self.xdg.surface.buffer_points_norm.borrow(); + Some(crate::gfx_api::BlurMask { + texture, + source, + threshold, + }) + }); + renderer + .base + .push_blur_backdrop(scaled, cfg.passes, cfg.size, mask); } - // Always clear the flag after node_render regardless of path - self.blur_pre_rendered.set(false); + renderer.base.discard_alpha = s.ignore_alpha; renderer.render_xdg_surface(&self.xdg, x, y, bounds); + renderer.base.discard_alpha = None; } else { - self.blur_pre_rendered.set(false); renderer.render_xdg_surface(&self.xdg, x, y, bounds); } } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index 28728e28..768a8367 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -555,7 +555,6 @@ impl XdgToplevel { self.state.tree_changed(); self.toplevel_data.mapped_source.trigger(); self.toplevel_data.broadcast(self.clone()); - self.toplevel_data.start_open_animation(); } self.toplevel_data .set_content_type(self.xdg.surface.content_type.get()); diff --git a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs index 8829fc9d..f3b1e45f 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -53,7 +53,6 @@ pub struct ZwlrLayerSurfaceV1 { pub client: Rc, pub surface: Rc, pub output: Rc, - pub blur_cache_epoch: NumCell, pub namespace: String, pub tracker: Tracker, output_extents: Cell, @@ -63,7 +62,6 @@ pub struct ZwlrLayerSurfaceV1 { pub blur: Cell, pub blur_popups: Cell, pub ignore_alpha: Cell>, - pub blur_cache: Rc>>, requested_serial: NumCell, size: Cell<(i32, i32)>, anchor: Cell, @@ -160,7 +158,6 @@ impl ZwlrLayerSurfaceV1 { ) -> Self { Self { id, - blur_cache_epoch: Default::default(), node_id: shell.client.state.node_ids.next(), shell: shell.clone(), client: shell.client.clone(), @@ -175,7 +172,6 @@ impl ZwlrLayerSurfaceV1 { blur: Cell::new(false), blur_popups: Cell::new(false), ignore_alpha: Cell::new(None), - blur_cache: Default::default(), requested_serial: Default::default(), size: Cell::new((0, 0)), anchor: Cell::new(0), diff --git a/src/main.rs b/src/main.rs index 161d3d99..5a566f9b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,7 +48,6 @@ mod leaks; mod tracy; mod acceptor; mod allocator; -mod animation; mod async_engine; mod backend; mod backends; diff --git a/src/renderer.rs b/src/renderer.rs index c3a97c2f..ddb5ab7c 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -5,7 +5,7 @@ use { ifs::wl_surface::{ SurfaceBuffer, WlSurface, x_surface::xwindow::Xwindow, - xdg_surface::{XdgSurface, xdg_popup::XdgPopup, xdg_toplevel::XdgToplevel}, + xdg_surface::{XdgSurface, xdg_toplevel::XdgToplevel}, zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, }, rect::Rect, @@ -14,9 +14,8 @@ use { state::State, theme::{Color, CornerRadius}, tree::{ - ContainerNode, DisplayNode, FloatNode, NodeId, OutputNode, PlaceholderNode, - StackedNode, ToplevelData, ToplevelNode, ToplevelNodeBase, WorkspaceNode, - tab_bar::TabBar, + ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelData, + ToplevelNodeBase, WorkspaceNode, tab_bar::TabBar, }, }, std::{ops::Deref, rc::Rc, slice}, @@ -31,60 +30,9 @@ pub struct Renderer<'a> { pub pixel_extents: Rect, pub stretch: Option<(i32, i32)>, pub corner_radius: Option, - /// The toplevel whose open-animation transform is currently applied to the - /// renderer base. Used to prevent double-applying when a parent (container, - /// float) has already entered the animation scope before drawing its own - /// per-child decorations. - pub current_anim_node: Option, -} - -#[must_use] -pub struct OpenAnimSaved { - alpha_mul: f32, - translate_x: f32, - translate_y: f32, - prev_node: Option, } impl Renderer<'_> { - pub fn render_layer_popup_blur_only(&mut self, popup: &XdgPopup, x: i32, y: i32) { - let Some(settings) = popup.layer_blur_settings() else { - return; - }; - if !settings.blur { - return; - } - let extents = popup.xdg.surface.extents.get(); - let geo = popup.xdg.geometry(); - let (gx, gy) = geo.translate(x, y); - let rect = extents.move_(gx, gy); - let scaled = self.base.scale_rect(rect); - let cfg = self.state.blur_config.get(); - let mask = settings.ignore_alpha.and_then(|threshold| { - let buffer = popup.xdg.surface.buffer.get()?; - let texture = buffer.buffer.buf.get_texture(&popup.xdg.surface)?; - let source = *popup.xdg.surface.buffer_points_norm.borrow(); - let release_sync = buffer.release_sync; - Some(crate::gfx_api::BlurMask { - texture, - source, - threshold, - buffer_resv: Some(buffer), - acquire_sync: AcquireSync::Unnecessary, - release_sync, - }) - }); - popup.blur_pre_rendered.set(true); - self.base.push_blur_backdrop( - scaled, - cfg.passes, - cfg.size, - mask, - Some(popup.blur_cache.clone()), - popup.blur_cache_epoch.get(), - ); - self.base.sync(); - } pub fn scale(&self) -> Scale { self.base.scale } @@ -267,28 +215,14 @@ impl Renderer<'_> { }; } render_stacked!(self.state.root.stacked); + // Flush RoundedFillRect ops from container/float borders so they don't + // sort after (and render on top of) layer-shell CopyTexture ops. self.base.sync(); if fullscreen.is_none() { - // Pre-pass: push blur backdrops for layer-shell popups before - // the bar renders, so they sample the raw background rather than - // the already-composited bar content. - for stacked in self.state.root.stacked_above_layers.iter() { - if stacked.node_visible() { - let pos = stacked.node_absolute_position(); - if pos.intersects(&opos) { - let (sx, sy) = opos.translate(pos.x1(), pos.y1()); - let stacked_rc: Rc = stacked.deref().clone(); - if let Some(popup) = stacked_rc.node_into_popup() { - self.render_layer_popup_blur_only(&popup, sx, sy); - } - } - } - } render_layer!(output.layers[2]); } render_layer!(output.layers[3]); render_stacked!(self.state.root.stacked_above_layers); - self.render_close_snapshots(output, x, y); if let Some(ws) = output.workspace.get() && ws.render_highlight.get() > 0 { @@ -473,7 +407,6 @@ impl Renderer<'_> { self.render_tab_bar(tb, x, y, container.width.get()); } } - let saved_anim = self.enter_open_anim(&*child.node); let mb = container.mono_body.get(); if self.state.theme.sizes.gap.get() != 0 { let srgb_srgb = self.state.color_manager.srgb_gamma22(); @@ -554,7 +487,6 @@ impl Renderer<'_> { .node_render(self, x + content.x1(), y + content.y1(), Some(&body)); self.stretch = None; self.corner_radius = None; - self.exit_open_anim(saved_anim); } else { let gap = self.state.theme.sizes.gap.get(); let (srgb_srgb, bw, border_color, focused_border_color) = if gap != 0 { @@ -572,7 +504,6 @@ impl Renderer<'_> { if body.x1() >= container.width.get() || body.y1() >= container.height.get() { break; } - let saved_anim = self.enter_open_anim(&*child.node); if let Some(srgb_srgb) = srgb_srgb { let srgb = &srgb_srgb.linear; let c = if child.border_color_is_focused.get() { @@ -643,7 +574,6 @@ impl Renderer<'_> { .node_render(self, x + content.x1(), y + content.y1(), Some(&body)); self.stretch = None; self.corner_radius = None; - self.exit_open_anim(saved_anim); } } @@ -651,135 +581,13 @@ impl Renderer<'_> { } pub fn render_xwindow(&mut self, tl: &Xwindow, x: i32, y: i32, bounds: Option<&Rect>) { - let saved = self.enter_open_anim(tl); - let bounds = if tl.tl_data().anim_open_alpha().is_some() { - None - } else { - bounds - }; self.render_surface(&tl.x.surface, x, y, bounds); self.render_tl_aux(tl.tl_data(), bounds, true); - self.exit_open_anim(saved); } pub fn render_xdg_toplevel(&mut self, tl: &XdgToplevel, x: i32, y: i32, bounds: Option<&Rect>) { - let saved = self.enter_open_anim(tl); - let bounds = if tl.tl_data().anim_open_alpha().is_some() { - None - } else { - bounds - }; self.render_xdg_surface(&tl.xdg, x, y, bounds); self.render_tl_aux(tl.tl_data(), bounds, true); - self.exit_open_anim(saved); - } - - /// Enters open-animation scope for `tl`: applies its eased alpha + slide - /// translate to the renderer base. If a parent has already entered scope - /// for the same toplevel (so its borders/decorations slide too), this is a - /// no-op and returns `None`. Pair every `Some` return with `exit_open_anim`. - pub fn enter_open_anim(&mut self, tl: &dyn ToplevelNode) -> Option { - let data = tl.tl_data(); - let eased = data.anim_open_alpha()?; - if self.current_anim_node == Some(data.node_id) { - return None; - } - let saved = OpenAnimSaved { - alpha_mul: self.base.alpha_mul, - translate_x: self.base.translate_x, - translate_y: self.base.translate_y, - prev_node: self.current_anim_node, - }; - self.current_anim_node = Some(data.node_id); - self.base.alpha_mul *= eased; - if let Some(ws) = data.workspace.get() { - let tl_rect = tl.node_absolute_position(); - let output_rect = ws.output.get().global.pos.get(); - let dl = (tl_rect.x1() - output_rect.x1()).max(0) as f32; - let dr = (output_rect.x2() - tl_rect.x2()).max(0) as f32; - let dt = (tl_rect.y1() - output_rect.y1()).max(0) as f32; - let db = (output_rect.y2() - tl_rect.y2()).max(0) as f32; - let mind = dl.min(dr).min(dt).min(db); - let (sx, sy) = if mind == dl { - (-(tl_rect.width() as f32), 0.0) - } else if mind == dr { - (tl_rect.width() as f32, 0.0) - } else if mind == dt { - (0.0, -(tl_rect.height() as f32)) - } else { - (0.0, tl_rect.height() as f32) - }; - let factor = (1.0 - eased) * self.base.scalef as f32; - self.base.translate_x += sx * factor; - self.base.translate_y += sy * factor; - } - Some(saved) - } - - pub fn exit_open_anim(&mut self, saved: Option) { - if let Some(s) = saved { - self.base.alpha_mul = s.alpha_mul; - self.base.translate_x = s.translate_x; - self.base.translate_y = s.translate_y; - self.current_anim_node = s.prev_node; - } - } - - /// Renders any active close-animation snapshots that belong to this output. - /// Each snapshot fades out and slides toward its closest output edge — - /// mirroring the open animation in reverse. Finished snapshots stay in the - /// list until `tick_animations` cleans them up. - fn render_close_snapshots(&mut self, output: &OutputNode, x: i32, y: i32) { - let snaps = self.state.close_snapshots.borrow(); - if snaps.is_empty() { - return; - } - let output_pos = output.global.pos.get(); - for snap in snaps.iter() { - let Some(snap_output) = snap.output.upgrade() else { - continue; - }; - if !std::ptr::eq(&*snap_output, output) { - continue; - } - let Some(progress) = snap.close_progress(self.state) else { - continue; - }; - let alpha = (1.0 - progress).clamp(0.0, 1.0); - let prev_alpha = self.base.alpha_mul; - let prev_tx = self.base.translate_x; - let prev_ty = self.base.translate_y; - self.base.alpha_mul *= alpha; - self.base.translate_x += snap.slide_dx * progress * self.base.scalef as f32; - self.base.translate_y += snap.slide_dy * progress * self.base.scalef as f32; - let local_x = x + snap.rect.x1() - output_pos.x1(); - let local_y = y + snap.rect.y1() - output_pos.y1(); - let (sx, sy) = self.base.scale_point(local_x, local_y); - let scalef = self.base.scalef; - let tw = (snap.rect.width() as f64 * scalef).round() as i32; - let th = (snap.rect.height() as f64 * scalef).round() as i32; - let cd = self.state.color_manager.srgb_gamma22(); - self.base.render_texture( - &snap.texture, - None, - sx, - sy, - None, - Some((tw, th)), - self.base.scale, - None, - None, - AcquireSync::Unnecessary, - ReleaseSync::Implicit, - false, - cd, - RenderIntent::Perceptual, - AlphaMode::PremultipliedElectrical, - ); - self.base.alpha_mul = prev_alpha; - self.base.translate_x = prev_tx; - self.base.translate_y = prev_ty; - } } pub fn render_xdg_surface( @@ -996,7 +804,6 @@ impl Renderer<'_> { Some(c) => c, _ => return, }; - let saved_anim = self.enter_open_anim(&*child); let pos = floating.position.get(); let theme = &self.state.theme; let bw = theme.sizes.border_width.get(); @@ -1041,13 +848,11 @@ impl Renderer<'_> { } child.node_render(self, body.x1(), body.y1(), Some(&scissor_body)); self.corner_radius = None; - self.exit_open_anim(saved_anim); } pub fn render_layer_surface(&mut self, surface: &ZwlrLayerSurfaceV1, x: i32, y: i32) { let (dx, dy) = surface.surface.extents.get().position(); let blur = surface.blur.get(); - let ignore_alpha = surface.ignore_alpha.get(); if blur { let extents = surface.surface.extents.get(); @@ -1058,22 +863,18 @@ impl Renderer<'_> { let buffer = surface.surface.buffer.get()?; let texture = buffer.buffer.buf.get_texture(&surface.surface)?; let source = *surface.surface.buffer_points_norm.borrow(); - let release_sync = buffer.release_sync; Some(crate::gfx_api::BlurMask { texture, source, threshold, - buffer_resv: Some(buffer), - acquire_sync: AcquireSync::Unnecessary, - release_sync, }) }); - let cache_epoch = surface.blur_cache_epoch.get(); - let cache = Some(surface.blur_cache.clone()); self.base - .push_blur_backdrop(scaled, cfg.passes, cfg.size, mask, cache, cache_epoch); + .push_blur_backdrop(scaled, cfg.passes, cfg.size, mask); } + self.base.discard_alpha = ignore_alpha; self.render_surface(&surface.surface, x - dx, y - dy, None); + self.base.discard_alpha = None; } fn bounds_are_opaque( diff --git a/src/renderer/renderer_base.rs b/src/renderer/renderer_base.rs index 467e25e8..f2c95265 100644 --- a/src/renderer/renderer_base.rs +++ b/src/renderer/renderer_base.rs @@ -26,9 +26,6 @@ pub struct RendererBase<'a> { pub fb_width: f32, pub fb_height: f32, pub discard_alpha: Option, - pub alpha_mul: f32, - pub translate_x: f32, - pub translate_y: f32, } impl RendererBase<'_> { @@ -36,26 +33,6 @@ impl RendererBase<'_> { self.scale } - fn apply_alpha_mul(&self, alpha: Option) -> Option { - if self.alpha_mul >= 1.0 { - alpha - } else { - Some(alpha.unwrap_or(1.0) * self.alpha_mul) - } - } - - fn fb_rect(&self, x1: f32, y1: f32, x2: f32, y2: f32) -> FramebufferRect { - FramebufferRect::new( - x1 + self.translate_x, - y1 + self.translate_y, - x2 + self.translate_x, - y2 + self.translate_y, - self.transform, - self.fb_width, - self.fb_height, - ) - } - pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) { if self.scaled { [x, y] = self.scale.pixel_size([x, y]); @@ -146,14 +123,17 @@ impl RendererBase<'_> { true => bx, }; self.ops.push(GfxApiOpt::FillRect(FillRect { - rect: self.fb_rect( + rect: FramebufferRect::new( bx.x1() as f32, bx.y1() as f32, bx.x2() as f32, bx.y2() as f32, + self.transform, + self.fb_width, + self.fb_height, ), color: *color, - alpha: self.apply_alpha_mul(alpha), + alpha, render_intent, cd: cd.clone(), })); @@ -186,9 +166,17 @@ impl RendererBase<'_> { for bx in boxes { let (x1, y1, x2, y2) = self.scale_rect_f(*bx); self.ops.push(GfxApiOpt::FillRect(FillRect { - rect: self.fb_rect(x1 + dx, y1 + dy, x2 + dx, y2 + dy), + rect: FramebufferRect::new( + x1 + dx, + y1 + dy, + x2 + dx, + y2 + dy, + self.transform, + self.fb_width, + self.fb_height, + ), color: *color, - alpha: self.apply_alpha_mul(None), + alpha: None, render_intent, cd: cd.clone(), })); @@ -239,20 +227,21 @@ impl RendererBase<'_> { return; } - let target = self.fb_rect( + let target = FramebufferRect::new( target_x[0] as f32, target_y[0] as f32, target_x[1] as f32, target_y[1] as f32, + self.transform, + self.fb_width, + self.fb_height, ); - let new_alpha = self.apply_alpha_mul(alpha); - let opaque = opaque && new_alpha == alpha; self.ops.push(GfxApiOpt::CopyTexture(CopyTexture { tex: texture.clone(), source: texcoord, target, - alpha: new_alpha, + alpha, buffer_resv, acquire_sync, release_sync, @@ -307,14 +296,17 @@ impl RendererBase<'_> { let fitted = corner_radius.fit_to(width, height); let cr: [f32; 4] = fitted.into(); self.ops.push(GfxApiOpt::RoundedFillRect(RoundedFillRect { - rect: self.fb_rect( + rect: FramebufferRect::new( rect.x1() as f32, rect.y1() as f32, rect.x2() as f32, rect.y2() as f32, + self.transform, + self.fb_width, + self.fb_height, ), color: *color, - alpha: self.apply_alpha_mul(alpha), + alpha, render_intent, cd: cd.clone(), size: [width, height], @@ -366,11 +358,14 @@ impl RendererBase<'_> { return; } - let target = self.fb_rect( + let target = FramebufferRect::new( target_x[0] as f32, target_y[0] as f32, target_x[1] as f32, target_y[1] as f32, + self.transform, + self.fb_width, + self.fb_height, ); let width = (target_x[1] - target_x[0]) as f32; @@ -384,7 +379,7 @@ impl RendererBase<'_> { tex: texture.clone(), source: texcoord, target, - alpha: self.apply_alpha_mul(alpha), + alpha, buffer_resv, acquire_sync, release_sync, @@ -409,8 +404,6 @@ impl RendererBase<'_> { passes: u8, offset: f32, mask: Option, - cache: Option>>>, - cache_epoch: u64, ) { let target = FramebufferRect::new( rect.x1() as f32, @@ -421,15 +414,11 @@ impl RendererBase<'_> { self.fb_width, self.fb_height, ); - let cache_pixel_rect = [rect.x1(), rect.y1(), rect.x2(), rect.y2()]; self.ops.push(GfxApiOpt::BlurBackdrop(BlurBackdrop { rect: target, passes, offset, mask, - cache, - cache_epoch, - cache_pixel_rect, })); } } diff --git a/src/state.rs b/src/state.rs index 136597d1..9decfcd9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -306,10 +306,6 @@ pub struct State { pub hyprland_global_shortcuts: CopyHashMap<(String, String), Rc>, pub layer_rules: RefCell>, pub blur_config: Cell, - pub blur_cache_epoch: NumCell, - pub animations_config: Cell, - pub active_animations: RefCell>>, - pub close_snapshots: RefCell>>, } // impl Drop for State { @@ -1053,25 +1049,6 @@ impl State { if rect.is_empty() { return; } - if !cursor { - for output in self.root.outputs.lock().values() { - for layer in &output.layers { - for surface in layer.iter() { - if surface.blur.get() && surface.node_absolute_position().intersects(&rect) - { - surface.blur_cache_epoch.fetch_add(1); - } - if surface.blur.get() && surface.blur_popups.get() { - surface.for_each_popup(|popup| { - if popup.node_absolute_position().intersects(&rect) { - popup.blur_cache_epoch.fetch_add(1); - } - }); - } - } - } - } - } self.damage_visualizer.add(rect); for output in self.root.outputs.lock().values() { if output.global.pos.get().intersects(&rect) { @@ -1313,7 +1290,6 @@ impl State { }, stretch: None, corner_radius: None, - current_anim_node: None, }; let mut sample_rect = SampleRect::identity(); sample_rect.buffer_transform = transform; @@ -1488,55 +1464,6 @@ impl State { self.eng.now().msec() } - /// Walks the active-animations list, damages each toplevel's slide region - /// (so the next frame re-renders it), and removes any whose animation is - /// done. Also ticks close-animation snapshots: damages their output and - /// drops finished ones. Intended to be called once per output present cycle. - pub fn tick_animations(&self) { - { - let mut animations = self.active_animations.borrow_mut(); - if !animations.is_empty() { - animations.retain(|weak| { - let Some(tl) = weak.upgrade() else { - return false; - }; - let data = tl.tl_data(); - if data.anim_open_alpha().is_none() { - return false; - } - // Damage the entire output the toplevel is on: the slide - // can render outside the toplevel's nominal rect, so the - // narrow rect alone would leave the slid-out portion - // unredrawn. - if let Some(ws) = data.workspace.get() { - self.damage(ws.output.get().global.pos.get()); - } else { - self.damage(tl.node_absolute_position()); - } - true - }); - } - } - let mut snapshots = self.close_snapshots.borrow_mut(); - if snapshots.is_empty() { - return; - } - snapshots.retain(|snap| { - if snap.close_progress(self).is_none() { - // Final damage so the snapshot's last-rendered position gets - // repainted (clearing any leftover pixels). - if let Some(output) = snap.output.upgrade() { - self.damage(output.global.pos.get()); - } - return false; - } - if let Some(output) = snap.output.upgrade() { - self.damage(output.global.pos.get()); - } - true - }); - } - pub fn output_extents_changed(&self) { self.root.update_extents(); for seat in self.globals.seats.lock().values() { diff --git a/src/tree/output.rs b/src/tree/output.rs index b18c6624..611eb822 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -236,7 +236,6 @@ impl OutputNode { for listener in self.presentation_event.iter() { listener.presented(self, tv_sec, tv_nsec, refresh, seq, flags, vrr); } - self.state.tick_animations(); if locked && let Some(lock) = self.state.lock.lock.get() { lock.check_locked() } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 752d9d77..02bba848 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -428,7 +428,6 @@ pub struct ToplevelData { pub property_changed_source: OnceCell>, pub mapped_source: Rc, pub unmapped_source: Rc, - pub anim_open_start_nsec: Cell>, } impl ToplevelData { @@ -486,7 +485,6 @@ impl ToplevelData { property_changed_source: Default::default(), mapped_source: state.lazy_event_sources.create_source(), unmapped_source: state.lazy_event_sources.create_source(), - anim_open_start_nsec: Cell::new(None), } } @@ -533,63 +531,6 @@ impl ToplevelData { } } - /// Returns the eased alpha multiplier for the open animation, or None if no - /// animation is active. When the animation has finished, clears the start - /// time and returns None. - pub fn anim_open_alpha(&self) -> Option { - let start = self.anim_open_start_nsec.get()?; - let cfg = self.state.animations_config.get(); - if !cfg.enabled || cfg.open_duration_ms == 0 { - self.anim_open_start_nsec.set(None); - return None; - } - let now = self.state.now_nsec(); - let elapsed_ns = now.saturating_sub(start); - let dur_ns = (cfg.open_duration_ms as u64).saturating_mul(1_000_000); - if elapsed_ns >= dur_ns { - self.anim_open_start_nsec.set(None); - return None; - } - let t = (elapsed_ns as f32) / (dur_ns as f32); - let eased = match cfg.open_curve { - jay_config::_private::AnimationCurveIpc::Linear => t, - jay_config::_private::AnimationCurveIpc::EaseOut => { - let inv = 1.0 - t; - 1.0 - inv * inv * inv - } - jay_config::_private::AnimationCurveIpc::EaseInOut => { - if t < 0.5 { - 4.0 * t * t * t - } else { - let f = -2.0 * t + 2.0; - 1.0 - f * f * f / 2.0 - } - } - jay_config::_private::AnimationCurveIpc::Bezier { x1, y1, x2, y2 } => { - cubic_bezier_y_at_x(t, x1, y1, x2, y2) - } - }; - Some(eased.clamp(0.0, 1.0)) - } - - /// Starts the open animation if animations are enabled. Inserts the - /// toplevel into the state's active-animations list so the present loop - /// can drive redraws. - pub fn start_open_animation(&self) { - let cfg = self.state.animations_config.get(); - if !cfg.enabled || cfg.open_duration_ms == 0 { - return; - } - if self.anim_open_start_nsec.get().is_some() { - return; - } - self.anim_open_start_nsec.set(Some(self.state.now_nsec())); - self.state - .active_animations - .borrow_mut() - .push(self.slf.clone()); - } - pub fn property_changed(&self, change: TlMatcherChange) { self.trigger_property_source(); let mgr = &self.state.tl_matcher_manager; @@ -1167,31 +1108,3 @@ pub fn toplevel_set_workspace(state: &Rc, tl: Rc, ws: & tl.tl_set_fullscreen(true, Some(ws.clone())); } } - -/// Evaluates a cubic Bezier easing curve `cubic-bezier(x1, y1, x2, y2)` at the -/// given input time `x`. P0=(0,0) and P3=(1,1) are fixed. Uses Newton-Raphson -/// to invert the x(t) parametric form, then evaluates y(t). -fn cubic_bezier_y_at_x(x: f32, x1: f32, y1: f32, x2: f32, y2: f32) -> f32 { - fn bx(t: f32, x1: f32, x2: f32) -> f32 { - let it = 1.0 - t; - 3.0 * it * it * t * x1 + 3.0 * it * t * t * x2 + t * t * t - } - fn dbx(t: f32, x1: f32, x2: f32) -> f32 { - let it = 1.0 - t; - 3.0 * it * it * x1 + 6.0 * it * t * (x2 - x1) + 3.0 * t * t * (1.0 - x2) - } - let mut t = x; - for _ in 0..8 { - let err = bx(t, x1, x2) - x; - if err.abs() < 1e-4 { - break; - } - let d = dbx(t, x1, x2); - if d.abs() < 1e-6 { - break; - } - t = (t - err / d).clamp(0.0, 1.0); - } - let it = 1.0 - t; - 3.0 * it * it * t * y1 + 3.0 * it * t * t * y2 + t * t * t -} diff --git a/toml-config/src/config.rs b/toml-config/src/config.rs index 1e408803..66326d57 100644 --- a/toml-config/src/config.rs +++ b/toml-config/src/config.rs @@ -393,30 +393,6 @@ pub struct BlurConfig { pub size: Option, } -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum AnimationCurve { - Linear, - EaseOut, - EaseInOut, - Bezier { x1: f32, y1: f32, x2: f32, y2: f32 }, -} - -#[derive(Debug, Clone, Copy)] -pub struct AnimationsConfig { - pub enabled: Option, - pub open_duration_ms: Option, - pub open_curve: Option, - pub close_duration_ms: Option, - pub close_curve: Option, -} - -#[derive(Debug, Clone, Copy)] -pub struct DamageVisualization { - pub enabled: Option, - pub color: Option, - pub decay_ms: Option, -} - #[derive(Debug, Clone)] pub enum DrmDeviceMatch { Any(Vec), @@ -631,8 +607,6 @@ pub struct Config { pub window_rules: Vec, pub layer_rules: Vec, pub blur: Option, - pub damage_visualization: Option, - pub animations: Option, pub pointer_revert_key: Option, pub use_hardware_cursor: Option, pub show_bar: Option, diff --git a/toml-config/src/config/parsers.rs b/toml-config/src/config/parsers.rs index 8e6a2404..766522b3 100644 --- a/toml-config/src/config/parsers.rs +++ b/toml-config/src/config/parsers.rs @@ -8,7 +8,6 @@ use { pub mod action; mod actions; -mod animations; mod blur; mod capabilities; mod clean_logs_older_than; @@ -20,7 +19,6 @@ pub mod config; mod connector; mod connector_match; mod content_type; -mod damage_visualization; mod drm_device; mod drm_device_match; mod env; diff --git a/toml-config/src/config/parsers/animations.rs b/toml-config/src/config/parsers/animations.rs deleted file mode 100644 index 747b98f5..00000000 --- a/toml-config/src/config/parsers/animations.rs +++ /dev/null @@ -1,73 +0,0 @@ -use { - crate::{ - config::{ - AnimationCurve, AnimationsConfig, - context::Context, - extractor::{Extractor, ExtractorError, bol, int, opt, recover, str}, - parser::{DataType, ParseResult, Parser, UnexpectedDataType}, - }, - toml::{ - toml_span::{DespanExt, Span, Spanned, SpannedExt}, - toml_value::Value, - }, - }, - indexmap::IndexMap, - thiserror::Error, -}; - -#[derive(Debug, Error)] -pub enum AnimationsConfigParserError { - #[error(transparent)] - Expected(#[from] UnexpectedDataType), - #[error(transparent)] - Extract(#[from] ExtractorError), - #[error("unknown animation curve `{0}`; expected one of: linear, ease-out, ease-in-out")] - UnknownCurve(String), -} - -pub struct AnimationsConfigParser<'a>(pub &'a Context<'a>); - -impl Parser for AnimationsConfigParser<'_> { - type Value = AnimationsConfig; - type Error = AnimationsConfigParserError; - const EXPECTED: &'static [DataType] = &[DataType::Table]; - - fn parse_table( - &mut self, - span: Span, - table: &IndexMap, Spanned>, - ) -> ParseResult { - let mut ext = Extractor::new(self.0, span, table); - let (enabled_val, open_duration_val, open_curve_val, close_duration_val, close_curve_val) = - ext.extract(( - recover(opt(bol("enabled"))), - recover(opt(int("open-duration-ms"))), - opt(str("open-curve")), - recover(opt(int("close-duration-ms"))), - opt(str("close-curve")), - ))?; - let enabled = enabled_val.despan(); - let open_duration_ms = open_duration_val.despan().and_then(|v| u32::try_from(v).ok()); - let close_duration_ms = close_duration_val.despan().and_then(|v| u32::try_from(v).ok()); - let parse_curve = |val: Option>| match val { - Some(s) => match s.value { - "linear" => Ok(Some(AnimationCurve::Linear)), - "ease-out" => Ok(Some(AnimationCurve::EaseOut)), - "ease-in-out" => Ok(Some(AnimationCurve::EaseInOut)), - other => { - Err(AnimationsConfigParserError::UnknownCurve(other.to_string()).spanned(s.span)) - } - }, - None => Ok(None), - }; - let open_curve = parse_curve(open_curve_val)?; - let close_curve = parse_curve(close_curve_val)?; - Ok(AnimationsConfig { - enabled, - open_duration_ms, - open_curve, - close_duration_ms, - close_curve, - }) - } -} diff --git a/toml-config/src/config/parsers/config.rs b/toml-config/src/config/parsers/config.rs index a3df8be3..ab169895 100644 --- a/toml-config/src/config/parsers/config.rs +++ b/toml-config/src/config/parsers/config.rs @@ -8,10 +8,8 @@ use { parsers::{ action::ActionParser, actions::ActionsParser, - animations::AnimationsConfigParser, blur::BlurConfigParser, clean_logs_older_than::CleanLogsOlderThanParser, - damage_visualization::DamageVisualizationParser, client_rule::ClientRulesParser, color_management::ColorManagementParser, connector::ConnectorsParser, @@ -159,7 +157,7 @@ impl Parser for ConfigParser<'_> { mouse_follows_focus, layer_rules_val, ), - (blur_val, damage_visualization_val, animations_val), + (blur_val,), ) = ext.extract(( ( opt(val("keymap")), @@ -221,11 +219,7 @@ impl Parser for ConfigParser<'_> { recover(opt(bol("unstable-mouse-follows-focus"))), opt(val("layers")), ), - ( - opt(val("blur")), - opt(val("damage-visualization")), - opt(val("animations")), - ), + (opt(val("blur")),), ))?; let mut keymap = None; if let Some(value) = keymap_val { @@ -521,26 +515,6 @@ impl Parser for ConfigParser<'_> { Err(e) => log::warn!("Could not parse the blur config: {}", self.0.error(e)), } } - let mut damage_visualization = None; - if let Some(value) = damage_visualization_val { - match value.parse(&mut DamageVisualizationParser(self.0)) { - Ok(v) => damage_visualization = Some(v), - Err(e) => log::warn!( - "Could not parse the damage-visualization config: {}", - self.0.error(e) - ), - } - } - let mut animations = None; - if let Some(value) = animations_val { - match value.parse(&mut AnimationsConfigParser(self.0)) { - Ok(v) => animations = Some(v), - Err(e) => log::warn!( - "Could not parse the animations config: {}", - self.0.error(e) - ), - } - } let mut pointer_revert_key = None; if let Some(value) = pointer_revert_key_str { match Keysym::from_str(value.value) { @@ -642,8 +616,6 @@ impl Parser for ConfigParser<'_> { window_rules, layer_rules, blur, - damage_visualization, - animations, pointer_revert_key, use_hardware_cursor: use_hardware_cursor.despan(), show_bar: show_bar.despan(), diff --git a/toml-config/src/config/parsers/damage_visualization.rs b/toml-config/src/config/parsers/damage_visualization.rs deleted file mode 100644 index 65feeb80..00000000 --- a/toml-config/src/config/parsers/damage_visualization.rs +++ /dev/null @@ -1,65 +0,0 @@ -use { - crate::{ - config::{ - DamageVisualization, - context::Context, - extractor::{Extractor, ExtractorError, bol, int, opt, recover, str}, - parser::{DataType, ParseResult, Parser, UnexpectedDataType}, - parsers::color::{ColorParser, ColorParserError}, - }, - toml::{ - toml_span::{DespanExt, Span, Spanned, SpannedExt}, - toml_value::Value, - }, - }, - indexmap::IndexMap, - thiserror::Error, -}; - -#[derive(Debug, Error)] -pub enum DamageVisualizationParserError { - #[error(transparent)] - Expected(#[from] UnexpectedDataType), - #[error(transparent)] - Extract(#[from] ExtractorError), - #[error(transparent)] - Color(#[from] ColorParserError), -} - -pub struct DamageVisualizationParser<'a>(pub &'a Context<'a>); - -impl Parser for DamageVisualizationParser<'_> { - type Value = DamageVisualization; - type Error = DamageVisualizationParserError; - const EXPECTED: &'static [DataType] = &[DataType::Table]; - - fn parse_table( - &mut self, - span: Span, - table: &IndexMap, Spanned>, - ) -> ParseResult { - let mut ext = Extractor::new(self.0, span, table); - let (enabled_val, color_val, decay_val) = ext.extract(( - recover(opt(bol("enabled"))), - opt(str("color")), - recover(opt(int("decay-ms"))), - ))?; - let enabled = enabled_val.despan(); - let color = match color_val { - Some(s) => match ColorParser.parse_string(s.span, s.value) { - Ok(c) => Some(c), - Err(e) => { - return Err(DamageVisualizationParserError::Color(e.value) - .spanned(s.span)); - } - }, - None => None, - }; - let decay_ms = decay_val.despan().and_then(|v| u64::try_from(v).ok()); - Ok(DamageVisualization { - enabled, - color, - decay_ms, - }) - } -} diff --git a/toml-config/src/lib.rs b/toml-config/src/lib.rs index 49b85f66..85b92127 100644 --- a/toml-config/src/lib.rs +++ b/toml-config/src/lib.rs @@ -13,8 +13,7 @@ mod toml; use { crate::{ config::{ - Action, AnimationCurve, AnimationsConfig, BlurConfig, ClientRule, Config, - ConfigConnector, ConfigDrmDevice, ConfigKeymap, + Action, BlurConfig, ClientRule, Config, ConfigConnector, ConfigDrmDevice, ConfigKeymap, ConnectorMatch, DrmDeviceMatch, Exec, Input, InputMatch, LayerKind, LayerRule, Output, OutputMatch, SimpleCommand, Status, Theme, WindowRule, parse_config, }, @@ -24,12 +23,8 @@ use { ahash::{AHashMap, AHashSet}, error_reporter::Report, jay_config::{ - _private::{ - AnimationCurveIpc, AnimationsConfigIpc, BlurConfigIpc, DamageVisualizationIpc, - LayerKindIpc, LayerMatchIpc, LayerRuleIpc, - }, - _set_animations_config, _set_blur_config, _set_damage_visualization, _set_layer_rules, - Axis, + _private::{BlurConfigIpc, LayerKindIpc, LayerMatchIpc, LayerRuleIpc}, + _set_blur_config, _set_layer_rules, Axis, client::Client, config, config_dir, exec::{Command, set_env, unset_env}, @@ -1476,8 +1471,6 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc) { - let default = AnimationsConfigIpc::default(); - let to_ipc = |c: AnimationCurve| match c { - AnimationCurve::Linear => AnimationCurveIpc::Linear, - AnimationCurve::EaseOut => AnimationCurveIpc::EaseOut, - AnimationCurve::EaseInOut => AnimationCurveIpc::EaseInOut, - AnimationCurve::Bezier { x1, y1, x2, y2 } => AnimationCurveIpc::Bezier { x1, y1, x2, y2 }, - }; - let cfg = match anim { - Some(a) => AnimationsConfigIpc { - enabled: a.enabled.unwrap_or(default.enabled), - open_duration_ms: a - .open_duration_ms - .unwrap_or(default.open_duration_ms) - .clamp(0, 10_000), - open_curve: to_ipc(a.open_curve.unwrap_or(AnimationCurve::EaseOut)), - close_duration_ms: a - .close_duration_ms - .unwrap_or(default.close_duration_ms) - .clamp(0, 10_000), - close_curve: to_ipc(a.close_curve.unwrap_or(AnimationCurve::EaseOut)), - }, - None => default, - }; - _set_animations_config(cfg); -} - fn push_blur_config(blur: Option) { let default = BlurConfigIpc::default(); let cfg = match blur { @@ -1766,19 +1732,6 @@ fn push_blur_config(blur: Option) { _set_blur_config(cfg); } -fn push_damage_visualization(dv: Option) { - let default = DamageVisualizationIpc::default(); - let cfg = match dv { - Some(d) => DamageVisualizationIpc { - enabled: d.enabled.unwrap_or(default.enabled), - color: d.color.unwrap_or(default.color), - decay_millis: d.decay_ms.unwrap_or(default.decay_millis), - }, - None => default, - }; - _set_damage_visualization(cfg); -} - fn push_layer_rules(rules: &[LayerRule]) { let ipc: Vec = rules .iter()