LibWeb: Share decoded images at the Resource level :^)

This patch adds ImageResource as a subclass of Resource. This new class
also keeps a Gfx::ImageDecoder so that we can share decoded bitmaps
between all clients of an image resource inside LibWeb.

With this, we now share both encoded and decoded data for images. :^)

I had to change how the purgeable-volatile flag is updated to keep the
volatile-images-outside-the-visible-viewport optimization working.
HTMLImageElement now inherits from ImageResourceClient (a subclass of
ResourceClient with additional image-specific stuff) and informs its
ImageResource about whether it's inside the viewport or outside.

This is pretty awesome! :^)
This commit is contained in:
Andreas Kling 2020-06-02 20:27:26 +02:00
parent 1c6e4e04a8
commit d4ddb0013c
Notes: sideshowbarker 2024-07-19 05:53:00 +09:00
14 changed files with 200 additions and 30 deletions

View file

@ -56,7 +56,7 @@ void HTMLImageElement::load_image(const String& src)
{
LoadRequest request;
request.set_url(document().complete_url(src));
set_resource(ResourceLoader::the().load_resource(request));
set_resource(ResourceLoader::the().load_resource(Resource::Type::Image, request));
}
void HTMLImageElement::resource_did_load()
@ -70,7 +70,8 @@ void HTMLImageElement::resource_did_load()
dbg() << "HTMLImageElement: Resource did load, encoded data looks tasty: " << this->src();
m_image_decoder = Gfx::ImageDecoder::create(resource()->encoded_data());
ASSERT(!m_image_decoder);
m_image_decoder = resource()->ensure_decoder();
if (m_image_decoder->is_animated() && m_image_decoder->frame_count() > 1) {
const auto& first_frame = m_image_decoder->frame(0);
@ -91,6 +92,11 @@ void HTMLImageElement::resource_did_fail()
dispatch_event(Event::create("error"));
}
void HTMLImageElement::resource_did_replace_decoder()
{
m_image_decoder = resource()->ensure_decoder();
}
void HTMLImageElement::animate()
{
if (!layout_node()) {
@ -161,19 +167,17 @@ const Gfx::Bitmap* HTMLImageElement::bitmap() const
return m_image_decoder->bitmap();
}
void HTMLImageElement::set_volatile(Badge<LayoutDocument>, bool v)
void HTMLImageElement::set_visible_in_viewport(Badge<LayoutDocument>, bool visible_in_viewport)
{
if (!m_image_decoder)
if (m_visible_in_viewport == visible_in_viewport)
return;
if (v) {
m_image_decoder->set_volatile();
return;
}
bool has_image = m_image_decoder->set_nonvolatile();
if (has_image)
return;
ASSERT(resource());
m_image_decoder = Gfx::ImageDecoder::create(resource()->encoded_data());
m_visible_in_viewport = visible_in_viewport;
// FIXME: Don't update volatility every time. If we're here, we're probably scanning through
// the whole document, updating "is visible in viewport" flags, and this could lead
// to the same bitmap being marked volatile back and forth unnecessarily.
if (resource())
resource()->update_volatility();
}
}