Skip to content
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

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

tronical
Copy link
Member

cc #7247

@tronical tronical marked this pull request as draft January 24, 2025 15:28
@tronical tronical requested a review from ogoffart January 24, 2025 15:28
@tronical tronical force-pushed the simon/bounding-rect branch from 1d734f1 to 88f9bdd Compare January 24, 2025 15:29
Comment on lines 972 to 979
*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()
Copy link
Member Author

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.

Copy link
Member

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

@tronical
Copy link
Member Author

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 ItemRendererFeatures with SUPPORTS_DROP_SHADOW or so and then try to shrink CachedItemGeometryAndTransform.

@tronical tronical changed the title Add support for box shadows with the partial renderer Add support for box shadows and out-of-geometry text items with the partial renderer Jan 24, 2025
internal/core/item_rendering.rs Outdated Show resolved Hide resolved
internal/core/item_rendering.rs Outdated Show resolved Hide resolved
Comment on lines 972 to 979
*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()
Copy link
Member

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(
Copy link
Member

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?)

Copy link
Member Author

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.

Copy link
Member

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.

internal/core/items/image.rs Show resolved Hide resolved
internal/core/items/text.rs Outdated Show resolved Hide resolved
_self_rc: &ItemRc,
geometry: LogicalRect,
) -> LogicalRect {
self.text_bounding_rect(window_adapter, geometry.cast()).cast()
Copy link
Member

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.

Copy link
Member Author

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.

tronical and others added 5 commits January 28, 2025 13:45
…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.
@tronical
Copy link
Member Author

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.

Copy link
Member

@ogoffart ogoffart left a 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();
Copy link
Member

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(
Copy link
Member

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 {
Copy link
Member

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(
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants