LibWeb: Pass whole command by reference into painting command executor

Now after making a change in a painting command we could avoid updating
method's parameters list across 3 classes.
This commit is contained in:
Aliaksandr Kalenik 2024-05-26 22:27:48 +01:00 committed by Andreas Kling
commit eff9bbf4c8
Notes: sideshowbarker 2024-07-17 01:23:08 +09:00
6 changed files with 318 additions and 345 deletions

View file

@ -31,32 +31,33 @@ CommandExecutorGPU::~CommandExecutorGPU()
painter().flush(m_target_bitmap);
}
CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> const& glyph_run, Color const& color, Gfx::FloatPoint translation, double scale)
CommandResult CommandExecutorGPU::draw_glyph_run(DrawGlyphRun const& command)
{
Vector<Gfx::DrawGlyphOrEmoji> transformed_glyph_run;
transformed_glyph_run.ensure_capacity(glyph_run.size());
for (auto& glyph : glyph_run) {
auto const& glyphs = command.glyph_run->glyphs();
transformed_glyph_run.ensure_capacity(glyphs.size());
for (auto& glyph : glyphs) {
auto transformed_glyph = glyph;
transformed_glyph.visit([&](auto& glyph) {
glyph.position = glyph.position.scaled(scale).translated(translation);
glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
glyph.position = glyph.position.scaled(command.scale).translated(command.translation);
glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(command.scale));
});
transformed_glyph_run.append(transformed_glyph);
}
painter().draw_glyph_run(transformed_glyph_run, color);
painter().draw_glyph_run(transformed_glyph_run, command.color);
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_text(Gfx::IntRect const&, String const&, Gfx::TextAlignment, Color const&, Gfx::TextElision, Gfx::TextWrapping, Optional<NonnullRefPtr<Gfx::Font>> const&)
CommandResult CommandExecutorGPU::draw_text(DrawText const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::fill_rect(Gfx::IntRect const& rect, Color const& color, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::fill_rect(FillRect const& command)
{
// FIXME: Support clip paths
painter().fill_rect(rect, color);
painter().fill_rect(command.rect, command.color);
return CommandResult::Continue;
}
@ -75,82 +76,82 @@ static AccelGfx::Painter::ScalingMode to_accelgfx_scaling_mode(Gfx::Painter::Sca
}
}
CommandResult CommandExecutorGPU::draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode)
CommandResult CommandExecutorGPU::draw_scaled_bitmap(DrawScaledBitmap const& command)
{
painter().draw_scaled_bitmap(dst_rect, bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode));
painter().draw_scaled_bitmap(command.dst_rect, command.bitmap, command.src_rect, to_accelgfx_scaling_mode(command.scaling_mode));
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::draw_scaled_immutable_bitmap(DrawScaledImmutableBitmap const& command)
{
// TODO: Support clip paths
painter().draw_scaled_immutable_bitmap(dst_rect, immutable_bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode));
painter().draw_scaled_immutable_bitmap(command.dst_rect, command.bitmap, command.src_rect, to_accelgfx_scaling_mode(command.scaling_mode));
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::set_clip_rect(Gfx::IntRect const& rect)
CommandResult CommandExecutorGPU::set_clip_rect(SetClipRect const& command)
{
painter().set_clip_rect(rect);
painter().set_clip_rect(command.rect);
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::clear_clip_rect()
CommandResult CommandExecutorGPU::clear_clip_rect(ClearClipRect const&)
{
painter().clear_clip_rect();
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::push_stacking_context(float opacity, bool is_fixed_position, Gfx::IntRect const& source_paintable_rect, Gfx::IntPoint post_transform_translation, CSS::ImageRendering, StackingContextTransform transform, Optional<StackingContextMask>)
CommandResult CommandExecutorGPU::push_stacking_context(PushStackingContext const& command)
{
if (source_paintable_rect.is_empty())
if (command.source_paintable_rect.is_empty())
return CommandResult::SkipStackingContext;
m_stacking_contexts.last().stacking_context_depth++;
painter().save();
if (is_fixed_position) {
if (command.is_fixed_position) {
auto const& translation = painter().transform().translation();
painter().translate(-translation);
}
auto stacking_context_transform = Gfx::extract_2d_affine_transform(transform.matrix);
auto stacking_context_transform = Gfx::extract_2d_affine_transform(command.transform.matrix);
Gfx::AffineTransform inverse_origin_translation;
inverse_origin_translation.translate(-transform.origin);
inverse_origin_translation.translate(-command.transform.origin);
Gfx::AffineTransform origin_translation;
origin_translation.translate(transform.origin);
origin_translation.translate(command.transform.origin);
Gfx::AffineTransform final_transform = origin_translation;
final_transform.multiply(stacking_context_transform);
final_transform.multiply(inverse_origin_translation);
if (opacity < 1 || !stacking_context_transform.is_identity_or_translation()) {
if (command.opacity < 1 || !stacking_context_transform.is_identity_or_translation()) {
// If, due to layout mistakes, we encounter an excessively large rectangle here, it must be skipped to prevent
// framebuffer allocation failure.
if (source_paintable_rect.width() > 10000 || source_paintable_rect.height() > 10000) {
dbgln("FIXME: Skipping stacking context with excessively large paintable rect: {}", source_paintable_rect);
if (command.source_paintable_rect.width() > 10000 || command.source_paintable_rect.height() > 10000) {
dbgln("FIXME: Skipping stacking context with excessively large paintable rect: {}", command.source_paintable_rect);
return CommandResult::SkipStackingContext;
}
auto canvas = AccelGfx::Canvas::create(source_paintable_rect.size());
auto canvas = AccelGfx::Canvas::create(command.source_paintable_rect.size());
auto painter = AccelGfx::Painter::create(m_context, canvas);
painter->translate(-source_paintable_rect.location().to_type<float>());
painter->translate(-command.source_paintable_rect.location().to_type<float>());
painter->clear(Color::Transparent);
m_stacking_contexts.append({ .canvas = canvas,
.painter = move(painter),
.opacity = opacity,
.destination = source_paintable_rect,
.opacity = command.opacity,
.destination = command.source_paintable_rect,
.transform = final_transform });
} else {
painter().translate(stacking_context_transform.translation() + post_transform_translation.to_type<float>());
painter().translate(stacking_context_transform.translation() + command.post_transform_translation.to_type<float>());
m_stacking_contexts.append({ .canvas = {},
.painter = MaybeOwned(painter()),
.opacity = opacity,
.opacity = command.opacity,
.destination = {},
.transform = final_transform });
}
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::pop_stacking_context()
CommandResult CommandExecutorGPU::pop_stacking_context(PopStackingContext const&)
{
auto stacking_context = m_stacking_contexts.take_last();
VERIFY(stacking_context.stacking_context_depth == 0);
@ -162,96 +163,97 @@ CommandResult CommandExecutorGPU::pop_stacking_context()
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_linear_gradient(Gfx::IntRect const& rect, Web::Painting::LinearGradientData const& data, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::paint_linear_gradient(PaintLinearGradient const& command)
{
// FIXME: Support clip paths
painter().fill_rect_with_linear_gradient(rect, data.color_stops.list, data.gradient_angle, data.color_stops.repeat_length);
auto const& linear_gradient_data = command.linear_gradient_data;
painter().fill_rect_with_linear_gradient(command.gradient_rect, linear_gradient_data.color_stops.list, linear_gradient_data.gradient_angle, linear_gradient_data.color_stops.repeat_length);
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_outer_box_shadow(PaintOuterBoxShadowParams const&)
CommandResult CommandExecutorGPU::paint_outer_box_shadow(PaintOuterBoxShadow const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_inner_box_shadow(PaintOuterBoxShadowParams const&)
CommandResult CommandExecutorGPU::paint_inner_box_shadow(PaintInnerBoxShadow const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_text_shadow(int blur_radius, Gfx::IntRect const& shadow_bounding_rect, Gfx::IntRect const& text_rect, Span<Gfx::DrawGlyphOrEmoji const> glyph_run, Color const& color, int fragment_baseline, Gfx::IntPoint const& draw_location)
CommandResult CommandExecutorGPU::paint_text_shadow(PaintTextShadow const& command)
{
auto text_shadow_canvas = AccelGfx::Canvas::create(shadow_bounding_rect.size());
auto text_shadow_canvas = AccelGfx::Canvas::create(command.shadow_bounding_rect.size());
auto text_shadow_painter = AccelGfx::Painter::create(m_context, text_shadow_canvas);
text_shadow_painter->clear(color.with_alpha(0));
text_shadow_painter->clear(command.color.with_alpha(0));
Gfx::FloatRect const shadow_location { draw_location, shadow_bounding_rect.size() };
Gfx::IntPoint const baseline_start(text_rect.x(), text_rect.y() + fragment_baseline);
Gfx::FloatRect const shadow_location { command.draw_location, command.shadow_bounding_rect.size() };
Gfx::IntPoint const baseline_start(command.text_rect.x(), command.text_rect.y() + command.fragment_baseline);
text_shadow_painter->translate(baseline_start.to_type<float>());
text_shadow_painter->draw_glyph_run(glyph_run, color);
if (blur_radius == 0) {
text_shadow_painter->draw_glyph_run(command.glyph_run, command.color);
if (command.blur_radius == 0) {
painter().blit_canvas(shadow_location, *text_shadow_canvas);
return CommandResult::Continue;
}
auto horizontal_blur_canvas = AccelGfx::Canvas::create(shadow_bounding_rect.size());
auto horizontal_blur_canvas = AccelGfx::Canvas::create(command.shadow_bounding_rect.size());
auto horizontal_blur_painter = AccelGfx::Painter::create(m_context, horizontal_blur_canvas);
horizontal_blur_painter->clear(color.with_alpha(0));
horizontal_blur_painter->blit_blurred_canvas(shadow_bounding_rect.to_type<float>(), *text_shadow_canvas, blur_radius, AccelGfx::Painter::BlurDirection::Horizontal);
painter().blit_blurred_canvas(shadow_location, *horizontal_blur_canvas, blur_radius, AccelGfx::Painter::BlurDirection::Vertical);
horizontal_blur_painter->clear(command.color.with_alpha(0));
horizontal_blur_painter->blit_blurred_canvas(command.shadow_bounding_rect.to_type<float>(), *text_shadow_canvas, command.blur_radius, AccelGfx::Painter::BlurDirection::Horizontal);
painter().blit_blurred_canvas(shadow_location, *horizontal_blur_canvas, command.blur_radius, AccelGfx::Painter::BlurDirection::Vertical);
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::fill_rect_with_rounded_corners(Gfx::IntRect const& rect, Color const& color, Gfx::AntiAliasingPainter::CornerRadius const& top_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& top_right_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_left_radius, Gfx::AntiAliasingPainter::CornerRadius const& bottom_right_radius, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::fill_rect_with_rounded_corners(FillRectWithRoundedCorners const& command)
{
// FIXME: Support clip paths
painter().fill_rect_with_rounded_corners(
rect, color,
{ static_cast<float>(top_left_radius.horizontal_radius), static_cast<float>(top_left_radius.vertical_radius) },
{ static_cast<float>(top_right_radius.horizontal_radius), static_cast<float>(top_right_radius.vertical_radius) },
{ static_cast<float>(bottom_left_radius.horizontal_radius), static_cast<float>(bottom_left_radius.vertical_radius) },
{ static_cast<float>(bottom_right_radius.horizontal_radius), static_cast<float>(bottom_right_radius.vertical_radius) });
command.rect, command.color,
{ static_cast<float>(command.top_left_radius.horizontal_radius), static_cast<float>(command.top_left_radius.vertical_radius) },
{ static_cast<float>(command.top_right_radius.horizontal_radius), static_cast<float>(command.top_right_radius.vertical_radius) },
{ static_cast<float>(command.bottom_left_radius.horizontal_radius), static_cast<float>(command.bottom_left_radius.vertical_radius) },
{ static_cast<float>(command.bottom_right_radius.horizontal_radius), static_cast<float>(command.bottom_right_radius.vertical_radius) });
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::fill_path_using_color(Gfx::Path const&, Color const&, Gfx::Painter::WindingRule, Gfx::FloatPoint const&)
CommandResult CommandExecutorGPU::fill_path_using_color(FillPathUsingColor const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::fill_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const&, Gfx::Painter::WindingRule, float, Gfx::FloatPoint const&)
CommandResult CommandExecutorGPU::fill_path_using_paint_style(FillPathUsingPaintStyle const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::stroke_path_using_color(Gfx::Path const&, Color const&, float, Gfx::FloatPoint const&)
CommandResult CommandExecutorGPU::stroke_path_using_color(StrokePathUsingColor const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::stroke_path_using_paint_style(Gfx::Path const&, Gfx::PaintStyle const&, float, float, Gfx::FloatPoint const&)
CommandResult CommandExecutorGPU::stroke_path_using_paint_style(StrokePathUsingPaintStyle const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_ellipse(Gfx::IntRect const&, Color const&, int)
CommandResult CommandExecutorGPU::draw_ellipse(DrawEllipse const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::fill_ellipse(Gfx::IntRect const& rect, Color const& color)
CommandResult CommandExecutorGPU::fill_ellipse(FillEllipse const& command)
{
auto horizontal_radius = static_cast<float>(rect.width() / 2);
auto vertical_radius = static_cast<float>(rect.height() / 2);
auto horizontal_radius = static_cast<float>(command.rect.width() / 2);
auto vertical_radius = static_cast<float>(command.rect.height() / 2);
painter().fill_rect_with_rounded_corners(
rect, color,
command.rect, command.color,
{ horizontal_radius, vertical_radius },
{ horizontal_radius, vertical_radius },
{ horizontal_radius, vertical_radius },
@ -259,61 +261,61 @@ CommandResult CommandExecutorGPU::fill_ellipse(Gfx::IntRect const& rect, Color c
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_line(Color const& color, Gfx::IntPoint const& a, Gfx::IntPoint const& b, int thickness, Gfx::Painter::LineStyle, Color const&)
CommandResult CommandExecutorGPU::draw_line(DrawLine const& command)
{
// FIXME: Pass line style and alternate color once AccelGfx::Painter supports it
painter().draw_line(a, b, thickness, color);
painter().draw_line(command.from, command.to, command.thickness, command.color);
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_signed_distance_field(Gfx::IntRect const&, Color const&, Gfx::GrayscaleBitmap const&, float)
CommandResult CommandExecutorGPU::draw_signed_distance_field(DrawSignedDistanceField const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::apply_backdrop_filter(Gfx::IntRect const&, Web::CSS::ResolvedBackdropFilter const&)
CommandResult CommandExecutorGPU::apply_backdrop_filter(ApplyBackdropFilter const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_rect(Gfx::IntRect const&, Color const&, bool)
CommandResult CommandExecutorGPU::draw_rect(DrawRect const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_radial_gradient(Gfx::IntRect const&, Web::Painting::RadialGradientData const&, Gfx::IntPoint const&, Gfx::IntSize const&, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::paint_radial_gradient(PaintRadialGradient const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_conic_gradient(Gfx::IntRect const&, Web::Painting::ConicGradientData const&, Gfx::IntPoint const&, Vector<Gfx::Path> const&)
CommandResult CommandExecutorGPU::paint_conic_gradient(PaintConicGradient const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::draw_triangle_wave(Gfx::IntPoint const&, Gfx::IntPoint const&, Color const&, int, int)
CommandResult CommandExecutorGPU::draw_triangle_wave(DrawTriangleWave const&)
{
// FIXME
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::sample_under_corners(u32 id, CornerRadii const& corner_radii, Gfx::IntRect const& border_rect, CornerClip)
CommandResult CommandExecutorGPU::sample_under_corners(SampleUnderCorners const& command)
{
m_corner_clippers.resize(id + 1);
m_corner_clippers[id] = make<BorderRadiusCornerClipper>();
auto& corner_clipper = *m_corner_clippers[id];
m_corner_clippers.resize(command.id + 1);
m_corner_clippers[command.id] = make<BorderRadiusCornerClipper>();
auto& corner_clipper = *m_corner_clippers[command.id];
auto const& top_left = corner_radii.top_left;
auto const& top_right = corner_radii.top_right;
auto const& bottom_right = corner_radii.bottom_right;
auto const& bottom_left = corner_radii.bottom_left;
auto const& top_left = command.corner_radii.top_left;
auto const& top_right = command.corner_radii.top_right;
auto const& bottom_right = command.corner_radii.bottom_right;
auto const& bottom_left = command.corner_radii.bottom_left;
auto sampling_config = calculate_border_radius_sampling_config(corner_radii, border_rect);
auto sampling_config = calculate_border_radius_sampling_config(command.corner_radii, command.border_rect);
auto const& page_locations = sampling_config.page_locations;
auto const& bitmap_locations = sampling_config.bitmap_locations;
@ -358,9 +360,9 @@ CommandResult CommandExecutorGPU::sample_under_corners(u32 id, CornerRadii const
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::blit_corner_clipping(u32 id)
CommandResult CommandExecutorGPU::blit_corner_clipping(BlitCornerClipping const& command)
{
auto const& corner_clipper = *m_corner_clippers[id];
auto const& corner_clipper = *m_corner_clippers[command.id];
auto const& corner_sample_canvas = *corner_clipper.corners_sample_canvas;
if (!corner_clipper.sample_canvas_top_left_rect.is_empty())
painter().blit_canvas(corner_clipper.page_top_left_rect, corner_sample_canvas, corner_clipper.sample_canvas_top_left_rect);
@ -371,15 +373,17 @@ CommandResult CommandExecutorGPU::blit_corner_clipping(u32 id)
if (!corner_clipper.sample_canvas_bottom_left_rect.is_empty())
painter().blit_canvas(corner_clipper.page_bottom_left_rect, corner_sample_canvas, corner_clipper.sample_canvas_bottom_left_rect);
m_corner_clippers[id].clear();
m_corner_clippers[command.id].clear();
return CommandResult::Continue;
}
CommandResult CommandExecutorGPU::paint_borders(DevicePixelRect const& border_rect, CornerRadii const& corner_radii, BordersDataDevicePixels const& borders_data)
CommandResult CommandExecutorGPU::paint_borders(PaintBorders const& command)
{
// FIXME: Add support for corner radiuses
(void)corner_radii;
auto const& border_rect = command.border_rect;
auto const& borders_data = command.borders_data;
Gfx::IntRect top_border_rect = {
border_rect.x(),