mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-07 21:59:54 +00:00
LibWeb: Add API to allow DecodedImageData to paint itself directly
Instead of painting DecodedImageData by first asking it for a bitmap
and then painting that, this commit adds two new APIs:
- frame_rect(frame_index):
Gets the size of the animation frame at the given index.
- paint(context, ...):
Paints the DecodedImageData into a DisplayListRecordingContext.
The main powerful thing here is that this allows SVGDecodedImageData
to render itself using the GPU when available.
This commit is contained in:
parent
cebd4cc10d
commit
4c2a02370d
Notes:
github-actions[bot]
2025-11-05 08:13:04 +00:00
Author: https://github.com/awesomekling
Commit: 4c2a02370d
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6699
Reviewed-by: https://github.com/kalenikaliaksandr
6 changed files with 97 additions and 5 deletions
|
|
@ -19,7 +19,6 @@
|
|||
#include <LibWeb/Page/Page.h>
|
||||
#include <LibWeb/Painting/DisplayListPlayerSkia.h>
|
||||
#include <LibWeb/Painting/DisplayListRecordingContext.h>
|
||||
#include <LibWeb/Painting/ViewportPaintable.h>
|
||||
#include <LibWeb/SVG/SVGDecodedImageData.h>
|
||||
#include <LibWeb/SVG/SVGSVGElement.h>
|
||||
#include <LibWeb/XML/XMLDocumentBuilder.h>
|
||||
|
|
@ -120,6 +119,33 @@ RefPtr<Gfx::Bitmap> SVGDecodedImageData::render(Gfx::IntSize size) const
|
|||
return bitmap;
|
||||
}
|
||||
|
||||
RefPtr<Gfx::PaintingSurface> SVGDecodedImageData::render_to_surface(Gfx::IntSize size) const
|
||||
{
|
||||
VERIFY(m_document->navigable());
|
||||
|
||||
auto surface = Gfx::PaintingSurface::create_with_size(m_document->navigable()->skia_backend_context(), size, Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
|
||||
|
||||
m_document->navigable()->set_viewport_size(size.to_type<CSSPixels>());
|
||||
m_document->update_layout(DOM::UpdateLayoutReason::SVGDecodedImageDataRender);
|
||||
|
||||
auto display_list = m_document->record_display_list({});
|
||||
if (!display_list)
|
||||
return nullptr;
|
||||
|
||||
switch (m_page_client->display_list_player_type()) {
|
||||
case DisplayListPlayerType::SkiaGPUIfAvailable:
|
||||
case DisplayListPlayerType::SkiaCPU: {
|
||||
Painting::DisplayListPlayerSkia display_list_player;
|
||||
display_list_player.execute(*display_list, {}, surface);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
RefPtr<Gfx::ImmutableBitmap> SVGDecodedImageData::bitmap(size_t, Gfx::IntSize size) const
|
||||
{
|
||||
if (size.is_empty())
|
||||
|
|
@ -192,4 +218,39 @@ void SVGDecodedImageData::SVGPageClient::visit_edges(Visitor& visitor)
|
|||
visitor.visit(m_svg_page);
|
||||
}
|
||||
|
||||
Optional<Gfx::IntRect> SVGDecodedImageData::frame_rect(size_t) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
RefPtr<Gfx::PaintingSurface> SVGDecodedImageData::surface(size_t, Gfx::IntSize size) const
|
||||
{
|
||||
if (size.is_empty())
|
||||
return nullptr;
|
||||
|
||||
if (auto it = m_cached_rendered_surfaces.find(size); it != m_cached_rendered_surfaces.end())
|
||||
return it->value;
|
||||
|
||||
// Prevent the cache from growing too big.
|
||||
// FIXME: Evict least used entries.
|
||||
if (m_cached_rendered_surfaces.size() > 10)
|
||||
m_cached_rendered_surfaces.remove(m_cached_rendered_surfaces.begin());
|
||||
|
||||
auto surface = render_to_surface(size);
|
||||
if (!surface)
|
||||
return nullptr;
|
||||
m_cached_rendered_surfaces.set(size, *surface);
|
||||
return surface;
|
||||
}
|
||||
|
||||
void SVGDecodedImageData::paint(DisplayListRecordingContext& context, size_t, Gfx::IntRect dst_rect, Gfx::IntRect, Gfx::ScalingMode scaling_mode) const
|
||||
{
|
||||
auto surface = this->surface(0, dst_rect.size());
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
Gfx::IntRect src_rect(0, 0, dst_rect.width(), dst_rect.height());
|
||||
context.display_list_recorder().draw_painting_surface(dst_rect, *surface, src_rect, scaling_mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,13 +37,22 @@ public:
|
|||
|
||||
virtual void visit_edges(Cell::Visitor& visitor) override;
|
||||
|
||||
virtual Optional<Gfx::IntRect> frame_rect(size_t frame_index) const override;
|
||||
virtual void paint(DisplayListRecordingContext&, size_t frame_index, Gfx::IntRect dst_rect, Gfx::IntRect clip_rect, Gfx::ScalingMode scaling_mode) const override;
|
||||
|
||||
private:
|
||||
SVGDecodedImageData(GC::Ref<Page>, GC::Ref<SVGPageClient>, GC::Ref<DOM::Document>, GC::Ref<SVG::SVGSVGElement>);
|
||||
|
||||
RefPtr<Gfx::Bitmap> render(Gfx::IntSize) const;
|
||||
|
||||
RefPtr<Gfx::PaintingSurface> surface(size_t frame_index, Gfx::IntSize) const;
|
||||
RefPtr<Gfx::PaintingSurface> render_to_surface(Gfx::IntSize) const;
|
||||
|
||||
// FIXME: Remove this once everything is using surfaces instead.
|
||||
mutable HashMap<Gfx::IntSize, NonnullRefPtr<Gfx::ImmutableBitmap>> m_cached_rendered_bitmaps;
|
||||
|
||||
mutable HashMap<Gfx::IntSize, NonnullRefPtr<Gfx::PaintingSurface>> m_cached_rendered_surfaces;
|
||||
|
||||
GC::Ref<Page> m_page;
|
||||
GC::Ref<SVGPageClient> m_page_client;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue