-
Notifications
You must be signed in to change notification settings - Fork 636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for box shadows and out-of-geometry text items with the partial renderer #7450
base: master
Are you sure you want to change the base?
Conversation
1d734f1
to
88f9bdd
Compare
internal/core/item_rendering.rs
Outdated
*data.geometry() | ||
} | ||
None => { | ||
let cache_entry = crate::graphics::CachedGraphicsData::new(eval); | ||
let geom = cache_entry.data.clone(); | ||
rendering_data.cache_index.set(cache.insert(cache_entry)); | ||
rendering_data.cache_generation.set(cache.generation()); | ||
geom.geometry | ||
*geom.geometry() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function here, filter_item
in the PartialRenderer
is the reason why CachedItemGeometryAndTransform
needs to store not only the translation but the entire geometry of an item.
As-is in this patch, CachedItemGeometryAndTransform
uses 48 bytes on aarch64. If I change this code to fetch the geometry from the item directly, then I can reduce the geometry in CachedItemGeometryAndTransform
to just a translation and the size goes to 40 bytes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.
I think it would be better to re-query the geometry again (untracked).
The reason filter_item returns the geometry is because it had the geometry for free. But IMHO it is better to query it again (untracked) than keeping it in the cache.
We could optimize for the common case of
- Geometry == bounding rect
- bounding rect is empty
Marked as draft, as I'm not entirely sure yet that this is the correct approach. It does seem to work (yay), but it increases the size of the partial renderer cache quite a bit. I could try to extend |
internal/core/item_rendering.rs
Outdated
*data.geometry() | ||
} | ||
None => { | ||
let cache_entry = crate::graphics::CachedGraphicsData::new(eval); | ||
let geom = cache_entry.data.clone(); | ||
rendering_data.cache_index.set(cache.insert(cache_entry)); | ||
rendering_data.cache_generation.set(cache.generation()); | ||
geom.geometry | ||
*geom.geometry() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.
I think it would be better to re-query the geometry again (untracked).
The reason filter_item returns the geometry is because it had the geometry for free. But IMHO it is better to query it again (untracked) than keeping it in the cache.
We could optimize for the common case of
- Geometry == bounding rect
- bounding rect is empty
@@ -236,6 +244,15 @@ impl Item for Empty { | |||
) -> RenderingResult { | |||
RenderingResult::ContinueRenderingChildren | |||
} | |||
|
|||
fn bounding_rect_for_geometry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(maybe documentation comment)
the other function like render uses the size instead of a geometry.
Is it because the geometry is in the parent's coordinate while render is supposed to draw in item coordinate?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why this function takes a geometry instead of a size is because the x/y can also change. That's the case with the drop shadow. Differently put: If configured accordingly, a drop shadow not only grows in direction of the x/y axis, but also in the other direction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the function be called just bounding_rect
?
I don't think the for_geometry adds value.
_self_rc: &ItemRc, | ||
geometry: LogicalRect, | ||
) -> LogicalRect { | ||
self.text_bounding_rect(window_adapter, geometry.cast()).cast() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that we register dependencies more than we need (eg, dependency on the text would be registed both by this call and by the render call)
dependencies cost in dependency nodes that are on the heap. We probably should make sure that bounding_rect_for_geometry is called without tracking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. For example a drop shadow's properties that affect the bounding rect are already tracked by the renderer's dirty tracker.
…king Co-authored-by: Olivier Goffart <[email protected]>
…stureHandler These don't draw anything.
…respect the bounding rect Remove the geometry field and merely store the offset/transform. This brings the size down from 40 to 32 bytes on aarch64. Related, filter_item() now respects the item's bounding rect for the decision whether to draw the item or not.
Ok, I think all the feedback is covered. I won't rebase this yet to facilitate there view, meanwhile the CI is red, but that's ok. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A test for the partial rendering would be nice with a shadow and some TouchArea (if the TouchArea moves it doesn't need to redraw the region)
) -> LogicalRect { | ||
geometry.size = LogicalSize::zero(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not return Default::default()
@@ -485,9 +491,18 @@ pub trait ItemRenderer { | |||
/// Returns | |||
/// - if the item needs to be drawn (false means it is clipped or doesn't need to be drawn) | |||
/// - the geometry of the item | |||
fn filter_item(&mut self, item: &ItemRc) -> (bool, LogicalRect) { | |||
fn filter_item( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.
fn from((geometry, children_transform): (LogicalRect, Option<ItemTransform>)) -> Self { | ||
Self { geometry, boxed_children_transform: children_transform.map(Into::into) } | ||
} | ||
pub enum CachedItemGeometryAndTransform { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the name, this caches the bounding box rather than the geometry
@@ -236,6 +244,15 @@ impl Item for Empty { | |||
) -> RenderingResult { | |||
RenderingResult::ContinueRenderingChildren | |||
} | |||
|
|||
fn bounding_rect_for_geometry( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the function be called just bounding_rect
?
I don't think the for_geometry adds value.
cc #7247