From 61d4da99342c5219638746b79cac1cf26c7c9d7d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 26 Mar 2021 10:28:05 +0100 Subject: [PATCH] Introduce layer clipping --- gpui/src/elements/stack.rs | 11 ++++++----- gpui/src/elements/uniform_list.rs | 8 +++----- gpui/src/platform/mac/renderer.rs | 20 +++++++++++++++++++- gpui/src/scene.rs | 19 ++++++++++++++++--- zed/src/editor/buffer_element.rs | 6 +++--- 5 files changed, 47 insertions(+), 17 deletions(-) diff --git a/gpui/src/elements/stack.rs b/gpui/src/elements/stack.rs index f0d33e3afc..0cfcf48cc5 100644 --- a/gpui/src/elements/stack.rs +++ b/gpui/src/elements/stack.rs @@ -1,6 +1,7 @@ use crate::{ - geometry::vector::Vector2F, AfterLayoutContext, Element, ElementBox, Event, EventContext, - LayoutContext, PaintContext, SizeConstraint, + geometry::{rect::RectF, vector::Vector2F}, + AfterLayoutContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, + SizeConstraint, }; pub struct Stack { @@ -44,12 +45,12 @@ impl Element for Stack { fn paint( &mut self, - bounds: pathfinder_geometry::rect::RectF, + bounds: RectF, _: &mut Self::LayoutState, ctx: &mut PaintContext, ) -> Self::PaintState { for child in &mut self.children { - ctx.scene.push_layer(); + ctx.scene.push_layer(None); child.paint(bounds.origin(), ctx); ctx.scene.pop_layer(); } @@ -58,7 +59,7 @@ impl Element for Stack { fn dispatch_event( &mut self, event: &Event, - _: pathfinder_geometry::rect::RectF, + _: RectF, _: &mut Self::LayoutState, _: &mut Self::PaintState, ctx: &mut EventContext, diff --git a/gpui/src/elements/uniform_list.rs b/gpui/src/elements/uniform_list.rs index 3cb5f4198b..637dfdbd55 100644 --- a/gpui/src/elements/uniform_list.rs +++ b/gpui/src/elements/uniform_list.rs @@ -195,10 +195,7 @@ where layout: &mut Self::LayoutState, ctx: &mut PaintContext, ) -> Self::PaintState { - // ctx.canvas.save(); - // let mut clip_path = Path2D::new(); - // clip_path.rect(RectF::new(origin, self.size.unwrap())); - // ctx.canvas.clip_path(clip_path, FillRule::Winding); + ctx.scene.push_layer(Some(bounds)); let mut item_origin = bounds.origin() - vec2f(0.0, self.state.scroll_top() % layout.item_height); @@ -207,7 +204,8 @@ where item.paint(item_origin, ctx); item_origin += vec2f(0.0, layout.item_height); } - // ctx.canvas.restore(); + + ctx.scene.pop_layer(); } fn dispatch_event( diff --git a/gpui/src/platform/mac/renderer.rs b/gpui/src/platform/mac/renderer.rs index ba727c9bd1..a79ce15869 100644 --- a/gpui/src/platform/mac/renderer.rs +++ b/gpui/src/platform/mac/renderer.rs @@ -1,12 +1,16 @@ use super::{sprite_cache::SpriteCache, window::RenderContext}; use crate::{ color::ColorU, - geometry::vector::{vec2i, Vector2I}, + geometry::{ + rect::RectF, + vector::{vec2f, vec2i, Vector2I}, + }, platform, scene::Layer, Scene, }; use anyhow::{anyhow, Result}; +use cocoa::foundation::NSUInteger; use metal::{MTLResourceOptions, NSRange}; use shaders::{ToFloat2 as _, ToUchar4 as _}; use std::{collections::HashMap, ffi::c_void, mem, sync::Arc}; @@ -96,12 +100,26 @@ impl Renderer { let mut offset = 0; for layer in scene.layers() { + self.clip(scene, layer, ctx); self.render_shadows(scene, layer, &mut offset, ctx); self.render_quads(scene, layer, &mut offset, ctx); self.render_sprites(scene, layer, &mut offset, ctx); } } + fn clip(&mut self, scene: &Scene, layer: &Layer, ctx: &RenderContext) { + let clip_bounds = layer.clip_bounds().unwrap_or(RectF::new( + vec2f(0., 0.), + ctx.drawable_size / scene.scale_factor(), + )) * scene.scale_factor(); + ctx.command_encoder.set_scissor_rect(metal::MTLScissorRect { + x: clip_bounds.origin_x() as NSUInteger, + y: clip_bounds.origin_y() as NSUInteger, + width: clip_bounds.width() as NSUInteger, + height: clip_bounds.height() as NSUInteger, + }); + } + fn render_shadows( &mut self, scene: &Scene, diff --git a/gpui/src/scene.rs b/gpui/src/scene.rs index cd478a8493..ec396d7820 100644 --- a/gpui/src/scene.rs +++ b/gpui/src/scene.rs @@ -57,7 +57,7 @@ impl Scene { pub fn new(scale_factor: f32) -> Self { Scene { scale_factor, - layers: vec![Layer::default()], + layers: vec![Layer::new(None)], active_layer_stack: vec![0], } } @@ -70,9 +70,9 @@ impl Scene { self.layers.as_slice() } - pub fn push_layer(&mut self) { + pub fn push_layer(&mut self, clip_bounds: Option) { let ix = self.layers.len(); - self.layers.push(Layer::default()); + self.layers.push(Layer::new(clip_bounds)); self.active_layer_stack.push(ix); } @@ -99,6 +99,19 @@ impl Scene { } impl Layer { + pub fn new(clip_bounds: Option) -> Self { + Self { + clip_bounds, + quads: Vec::new(), + shadows: Vec::new(), + glyphs: Vec::new(), + } + } + + pub fn clip_bounds(&self) -> Option { + self.clip_bounds + } + fn push_quad(&mut self, quad: Quad) { self.quads.push(quad); } diff --git a/zed/src/editor/buffer_element.rs b/zed/src/editor/buffer_element.rs index 49e471a612..0f3e934f4e 100644 --- a/zed/src/editor/buffer_element.rs +++ b/zed/src/editor/buffer_element.rs @@ -168,7 +168,7 @@ impl BufferElement { let line_height = view.line_height(ctx.font_cache); let scroll_top = view.scroll_position().y() * line_height; - ctx.scene.push_layer(); + ctx.scene.push_layer(Some(rect)); ctx.scene.push_quad(Quad { bounds: rect, background: Some(ColorU::white()), @@ -202,7 +202,7 @@ impl BufferElement { let max_glyph_width = view.em_width(ctx.font_cache); let scroll_left = view.scroll_position().x() * max_glyph_width; - ctx.scene.push_layer(); + ctx.scene.push_layer(Some(bounds)); ctx.scene.push_quad(Quad { bounds, background: Some(ColorU::white()), @@ -290,7 +290,7 @@ impl BufferElement { ); } - ctx.scene.push_layer(); + ctx.scene.push_layer(Some(bounds)); for cursor in cursors { cursor.paint(ctx); }