Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub(super) fn render_frame_window_overlays_with_toolbar_resources(
child_frame_style: &ChildFrameStyle,
scroll_indicators_enabled: bool,
toolbar: &ToolbarResources,
) {
) -> Result<(), super::surface::FrameRenderFailure> {
// Content overlays are the *editor's* picture — child frames, breadcrumbs,
// scroll indicators, watermarks — and belong to `scene`, which is where
// they are drawn. They open this pass rather than closing `scene` because
Expand All @@ -68,7 +68,7 @@ pub(super) fn render_frame_window_overlays_with_toolbar_resources(
animated_cursor,
child_frame_style,
scroll_indicators_enabled,
);
)?;

frame_bands::draw(renderer, native, render, surface_view, frame, toolbar);
transient_overlays::draw_panels(
Expand Down Expand Up @@ -101,4 +101,5 @@ pub(super) fn render_frame_window_overlays_with_toolbar_resources(
native.content_size().1,
);
transient_overlays::draw_typing_speed(renderer, render, surface_view, frame);
Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub(super) fn through_composition_ring(
cursor_visible: bool,
accept_derived_effects: bool,
pane_blits: &[PaneBlit],
) {
) -> Result<(), super::surface::FrameRenderFailure> {
super::render_frame_window_contents(
renderer,
native,
Expand All @@ -50,7 +50,7 @@ pub(super) fn through_composition_ring(
inputs,
cursor_visible,
false,
);
)?;

detect_transitions(acquired, renderer, render, frame, accept_derived_effects);
if render.compositor.renderer_effects.needs_redraw() {
Expand Down Expand Up @@ -106,7 +106,8 @@ pub(super) fn through_composition_ring(
inputs.child_frame_style,
inputs.scroll_indicators_enabled,
inputs.toolbar,
);
)?;
Ok(())
}

/// Place and pin a pane picture using the content-local geometry supplied by
Expand Down Expand Up @@ -155,7 +156,7 @@ pub(super) fn onto_target(
inputs: &FrameDrawInputs<'_>,
cursor_visible: bool,
accept_derived_effects: bool,
) {
) -> Result<(), super::surface::FrameRenderFailure> {
super::render_frame_window_contents(
renderer,
native,
Expand All @@ -165,9 +166,10 @@ pub(super) fn onto_target(
inputs,
cursor_visible,
true,
);
)?;
detect_transitions(acquired, renderer, render, frame, accept_derived_effects);
render.mark_active_visuals_dirty();
Ok(())
}

/// Measure this frame against the last presented one and start whatever motion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ fn render_frame_window_contents(
inputs: &FrameDrawInputs<'_>,
cursor_visible: bool,
include_overlays: bool,
) {
) -> Result<(), FrameRenderFailure> {
scene::render_frame_root_glyphs(
renderer,
render,
Expand All @@ -122,7 +122,7 @@ fn render_frame_window_contents(

if !include_overlays {
render.set_dirty(renderer_effects_still_active);
return;
return Ok(());
}

chrome::render_frame_window_overlays_with_toolbar_resources(
Expand All @@ -136,10 +136,11 @@ fn render_frame_window_contents(
inputs.child_frame_style,
inputs.scroll_indicators_enabled,
inputs.toolbar,
);
)?;
if renderer_effects_still_active {
render.mark_dirty();
}
Ok(())
}

fn composition_surface(
Expand Down Expand Up @@ -412,7 +413,7 @@ fn render_frame_window_contents_reserved(
.unwrap_or((-1.0, -1.0));
if retained_static::is_eligible(compositor_only_hint, &pane_blits, render) {
let hovered_scroll_bar = render.hovered_scroll_bar(&frame);
retained_static::draw(
let draw_result = retained_static::draw(
renderer,
native,
render,
Expand All @@ -422,6 +423,12 @@ fn render_frame_window_contents_reserved(
cursor_visible,
hovered_scroll_bar,
);
if let Err(error) = draw_result {
renderer.set_scale_factor(old_scale_factor);
renderer.resize(old_width, old_height);
render.mark_dirty();
return Err(error);
}
if frame_post_active {
renderer.frame_post_to_view(
&composition_view,
Expand Down Expand Up @@ -462,7 +469,7 @@ fn render_frame_window_contents_reserved(
let composition = need_offscreen
.then(|| composition_targets::advance_frame_composition(renderer, render, surface_size))
.flatten();
match composition.as_ref() {
let draw_result = match composition.as_ref() {
Some(composition) => full_render::through_composition_ring(
&acquired,
renderer,
Expand All @@ -487,6 +494,12 @@ fn render_frame_window_contents_reserved(
cursor_visible,
feature_plan.accept_derived_effects,
),
};
if let Err(error) = draw_result {
renderer.set_scale_factor(old_scale_factor);
renderer.resize(old_width, old_height);
render.mark_dirty();
return Err(error);
}

if frame_post_active {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,13 @@ pub(super) fn draw(
inputs: &FrameDrawInputs<'_>,
cursor_visible: bool,
hovered_scroll_bar: Option<neomacs_display_protocol::ScrollBarIdentity>,
) {
) -> Result<(), super::surface::FrameRenderFailure> {
let Some(native_size) = SnapshotSize::new(native.content_size().0, native.content_size().1)
else {
// wgpu rejects a zero extent, so there is no scene to retain and
// nothing to composite from. Reaching this would mean the window was
// asked to draw at a size `resize` already refuses to configure.
return;
return Ok(());
};
let generation = render.compositor.current_scene_generation;
let retained_valid = is_valid(render, native_size);
Expand All @@ -116,7 +116,7 @@ pub(super) fn draw(
inputs,
false,
true,
);
)?;
let cells = build_filled_box_cursor_cells(
frame,
native.scale_factor as f32,
Expand Down Expand Up @@ -160,6 +160,7 @@ pub(super) fn draw(
);
}
frame_stats::count(&frame_stats::COMPOSITE_ONLY_FRAMES);
Ok(())
}

/// Build a single-glyph mini-frame for each filled-box cursor in the frame
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub(super) fn render_frame_content_overlays(
animated_cursor: Option<crate::core::types::AnimatedCursor>,
child_frame_style: &ChildFrameStyle,
scroll_indicators_enabled: bool,
) {
) -> Result<(), super::surface::FrameRenderFailure> {
let pointer_appearance = render.pointer_appearance;
// One sample drives every child-frame lifecycle animation on this
// surface. Sampling -- not stepping -- is what makes a frame redrawn at
Expand All @@ -122,7 +122,7 @@ pub(super) fn render_frame_content_overlays(
// Whether the corpse-clearing (or crossfade-closing) repaint was
// requested this pass.
let mut crossfade_finished = false;
renderer.with_frame_effects(&mut render.compositor.renderer_effects, |renderer| {
let result = renderer.with_frame_effects(&mut render.compositor.renderer_effects, |renderer| {
// One merged draw order: living frames and dying corpses
// interleaved in z-path order, a corpse drawing before a living
// frame at equal z -- a dismissed popup is normally being replaced
Expand Down Expand Up @@ -309,6 +309,32 @@ pub(super) fn render_frame_content_overlays(
scale,
)
};
let resize = crossfade_layer.map(|(old, old_width, old_height, mix)| {
neomacs_renderer_wgpu::renderer::ChildResizePicture {
old,
old_width,
old_height,
mix,
}
});
let size = neomacs_renderer_wgpu::SnapshotSize::new(content_size.0, content_size.1)
.ok_or(super::surface::FrameRenderFailure::WindowNotReady)?;
let prepared = neomacs_renderer_wgpu::renderer::PreparedChildFrame::new(
child_frame,
alpha,
size,
render.child_opacity_src.as_ref(),
resize,
render.child_resize_src.as_ref(),
)
.map_err(|error| {
tracing::error!(
?error,
child_id,
"child preparation rejected; retrying without present"
);
super::surface::FrameRenderFailure::WindowNotReady
})?;
let pointer_selection = pointer_appearance.selection_for(child_frame);
if let Some(atlas) = render.compositor.glyph_atlas.as_mut() {
atlas.set_current_frame_fonts(child_frame.font_bindings());
Expand All @@ -335,15 +361,16 @@ pub(super) fn render_frame_content_overlays(
"child_frame_lifecycle: render_child_frame_start"
);
}
if crossfade_layer.is_some() {
frame_stats::count(&frame_stats::CHILD_FRAME_CROSSFADE_QUADS);
}
renderer.render_child_frame_prepared(
surface_view,
child_frame,
prepared,
base_x,
base_y + offset_y,
clip_in_root,
render.compositor.glyph_atlas.as_mut().unwrap(),
content_size.0,
content_size.1,
cursor_visible,
animated_cursor.filter(|ac| ac.frame_id == DisplayFrameId::new(child_id)),
child_frame_style.corner_radius,
Expand All @@ -352,25 +379,10 @@ pub(super) fn render_frame_content_overlays(
child_frame_style.shadow_offset,
child_frame_style.shadow_opacity,
pointer_selection,
alpha,
scale,
// The scale anchors at the frame's drawn top-left, so the
// picture grows outward from the point that anchored it.
[base_x, base_y + offset_y],
render.child_opacity_src.as_ref(),
crossfade_layer.map(|(old, old_width, old_height, mix)| {
frame_stats::count(&frame_stats::CHILD_FRAME_CROSSFADE_QUADS);
neomacs_renderer_wgpu::renderer::ChildResizePicture {
old,
old_width,
old_height,
mix,
composition: render
.child_resize_src
.as_ref()
.expect("resize composition was preflighted"),
}
}),
);
if !dying {
tracing::debug!(
Expand All @@ -380,7 +392,13 @@ pub(super) fn render_frame_content_overlays(
);
}
}
Ok(())
});
// Restore the root font bindings even when a later child fails preparation.
if let Some(atlas) = render.compositor.glyph_atlas.as_mut() {
atlas.set_current_frame_fonts(frame.font_bindings());
}
result?;
// The pass reports continued animation the only way it may: by marking
// the frame dirty, so the scheduler asks for another one. Finished dying
// frames are pruned afterwards, on the same sample they were drawn with.
Expand Down Expand Up @@ -422,10 +440,6 @@ pub(super) fn render_frame_content_overlays(
render.mark_dirty();
}

if let Some(atlas) = render.compositor.glyph_atlas.as_mut() {
atlas.set_current_frame_fonts(frame.font_bindings());
}

renderer.with_frame_effects(&mut render.compositor.renderer_effects, |renderer| {
render_frame_common_overlays(
renderer,
Expand All @@ -440,6 +454,7 @@ pub(super) fn render_frame_content_overlays(
if render.compositor.renderer_effects.needs_redraw() {
render.mark_dirty();
}
Ok(())
}

fn render_frame_common_overlays(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ fn obsolete_native_owner_retires_before_required_child_under_same_pressure() {
None,
&style,
false,
);
)
.unwrap();
renderer.place_native_content_with_opacity(
NativeContentPlacement::new(RenderTarget::new(&view, surface), &retained).unwrap(),
root.background,
Expand Down Expand Up @@ -172,7 +173,8 @@ fn obsolete_native_owner_retires_before_required_child_under_same_pressure() {
None,
&style,
false,
);
)
.unwrap();
let data = pixels(&renderer, &out);
assert_eq!(px(&data, 60, 40), [0, 0, 255, 255], "sibling order");
assert!(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ fn pane_conversion_refuses_before_motion_and_recovers_under_held_pressure() {
None,
&style,
false,
);
)
.unwrap();
assert_eq!(
px(&pixels(&renderer, &out), 48, 40)[3],
255,
Expand Down Expand Up @@ -452,7 +453,8 @@ fn wrong_size_required_native_owner_retires_before_child_under_same_pressure() {
None,
&style,
false,
);
)
.unwrap();
let out = target(&renderer);
let view = out.create_view(&Default::default());
renderer.place_native_content_with_opacity(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ fn present(
None,
&style,
false,
);
)
.unwrap();
if let Some(native) = &result.native {
renderer.place_native_content_with_opacity(
NativeContentPlacement::new(
Expand Down
Loading
Loading