Skip to content

Commit

Permalink
LibWeb+WebContent: Change event loop to synchronously paint next frame
Browse files Browse the repository at this point in the history
...instead of scheduling repaint timer in PageClient.

This change fixes flickering on Discord that happened because:
- Event loop schedules repainting by activating repaint timer
- `Document::tear_down_layout_tree()` destroys paintable tree
- Repaint timer invokes callback and renders an empty frame because
  paintable tree was destroyed
  • Loading branch information
kalenikaliaksandr committed May 28, 2024
1 parent d6297ec commit 6e4216e
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 24 deletions.
5 changes: 4 additions & 1 deletion Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,10 @@ void EventLoop::process()
if (navigable && navigable->needs_repaint()) {
auto* browsing_context = document.browsing_context();
auto& page = browsing_context->page();
page.client().schedule_repaint();
if (navigable->is_traversable()) {
VERIFY(page.client().is_ready_to_paint());
page.client().paint_next_frame();
}
}
});

Expand Down
5 changes: 3 additions & 2 deletions Userland/Libraries/LibWeb/HTML/Navigable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2133,8 +2133,9 @@ void Navigable::paint(Painting::RecordingPainter& recording_painter, PaintConfig
auto background_color = document->background_color();

recording_painter.fill_rect(bitmap_rect, background_color);
if (!document->paintable())
return;
if (!document->paintable()) {
VERIFY_NOT_REACHED();
}

Web::PaintContext context(recording_painter, page.palette(), page.client().device_pixels_per_css_pixel());
context.set_device_viewport_rect(viewport_rect);
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/Page/Page.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ class PageClient : public JS::Cell {
virtual DevicePixelRect screen_rect() const = 0;
virtual double device_pixels_per_css_pixel() const = 0;
virtual CSS::PreferredColorScheme preferred_color_scheme() const = 0;
virtual void paint_next_frame() = 0;
virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, PaintOptions = {}) = 0;
virtual void page_did_change_title(ByteString const&) { }
virtual void page_did_change_url(URL::URL const&) { }
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/SVG/SVGDecodedImageData.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class SVGDecodedImageData::SVGPageClient final : public PageClient {
virtual double device_pixels_per_css_pixel() const override { return 1.0; }
virtual CSS::PreferredColorScheme preferred_color_scheme() const override { return m_host_page->client().preferred_color_scheme(); }
virtual void request_file(FileRequest) override { }
virtual void paint_next_frame() override { }
virtual void paint(DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override { }
virtual void schedule_repaint() override { }
virtual bool is_ready_to_paint() const override { return true; }
Expand Down
38 changes: 18 additions & 20 deletions Userland/Services/WebContent/PageClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,6 @@ PageClient::PageClient(PageHost& owner, u64 id)
{
setup_palette();

m_repaint_timer = Web::Platform::Timer::create_single_shot(0, [this] {
if (!m_backing_stores.back_bitmap) {
return;
}

auto& back_bitmap = *m_backing_stores.back_bitmap;
auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect());
paint(viewport_rect, back_bitmap);

auto& backing_stores = m_backing_stores;
swap(backing_stores.front_bitmap, backing_stores.back_bitmap);
swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id);

m_paint_state = PaintState::WaitingForClient;
client().async_did_paint(m_id, viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
});

#ifdef HAS_ACCELERATED_GRAPHICS
if (s_use_gpu_painter) {
auto context = AccelGfx::Context::create();
Expand All @@ -92,9 +75,6 @@ void PageClient::schedule_repaint()
m_paint_state = PaintState::PaintWhenReady;
return;
}

if (!m_repaint_timer->is_active())
m_repaint_timer->start();
}

bool PageClient::is_ready_to_paint() const
Expand Down Expand Up @@ -197,6 +177,24 @@ Web::Layout::Viewport* PageClient::layout_root()
return document->layout_node();
}

void PageClient::paint_next_frame()
{
if (!m_backing_stores.back_bitmap) {
return;
}

auto& back_bitmap = *m_backing_stores.back_bitmap;
auto viewport_rect = page().css_to_device_rect(page().top_level_traversable()->viewport_rect());
paint(viewport_rect, back_bitmap);

auto& backing_stores = m_backing_stores;
swap(backing_stores.front_bitmap, backing_stores.back_bitmap);
swap(backing_stores.front_bitmap_id, backing_stores.back_bitmap_id);

m_paint_state = PaintState::WaitingForClient;
client().async_did_paint(m_id, viewport_rect.to_type<int>(), backing_stores.front_bitmap_id);
}

void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& target, Web::PaintOptions paint_options)
{
Web::Painting::CommandList painting_commands;
Expand Down
2 changes: 1 addition & 1 deletion Userland/Services/WebContent/PageClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class PageClient final : public Web::PageClient {

ErrorOr<void> connect_to_webdriver(ByteString const& webdriver_ipc_path);

virtual void paint_next_frame() override;
virtual void paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap&, Web::PaintOptions = {}) override;

void set_palette_impl(Gfx::PaletteImpl&);
Expand Down Expand Up @@ -177,7 +178,6 @@ class PageClient final : public Web::PageClient {
};

PaintState m_paint_state { PaintState::Ready };
RefPtr<Web::Platform::Timer> m_repaint_timer;

Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto };

Expand Down
1 change: 1 addition & 0 deletions Userland/Services/WebWorker/PageHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class PageHost final : public Web::PageClient {
virtual Web::DevicePixelRect screen_rect() const override;
virtual double device_pixels_per_css_pixel() const override;
virtual Web::CSS::PreferredColorScheme preferred_color_scheme() const override;
virtual void paint_next_frame() override {};
virtual void paint(Web::DevicePixelRect const&, Gfx::Bitmap&, Web::PaintOptions = {}) override;
virtual void request_file(Web::FileRequest) override;
virtual void schedule_repaint() override {};
Expand Down

0 comments on commit 6e4216e

Please sign in to comment.