LibGfx+LibWeb: Store Skia images with display list resources
DisplayListPlayerSkia kept a separate DecodedImageFrameSkiaImageCache that was pruned during flushes. That made Skia image lifetime independent of display list resource lifetime, even though resource storage is what knows when image frames and compositor surfaces are no longer needed. Make DisplayListResourceStorage own an opaque stored image-frame resource that holds the decoded frame and its lazily-created SkImage. Removing image frames or compositor surfaces now drops the decoded frame and Skia image together, while transactions still carry only Skia-free decoded frames.
This commit is contained in:
parent
e03e407f43
commit
91bcd50224
7 changed files with 96 additions and 203 deletions
|
|
@ -32,7 +32,6 @@ set(SOURCES
|
|||
ImageFormats/WebPSharedLossless.cpp
|
||||
ImageFormats/WebPWriter.cpp
|
||||
ImageFormats/WebPWriterLossless.cpp
|
||||
DecodedImageFrameSkiaImageCache.cpp
|
||||
PaintStyle.cpp
|
||||
Painter.cpp
|
||||
PainterSkia.cpp
|
||||
|
|
|
|||
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/HashFunctions.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <LibGfx/DecodedImageFrame.h>
|
||||
#include <LibGfx/DecodedImageFrameSkiaImageCache.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
#include <LibGfx/SkiaUtils.h>
|
||||
|
||||
#include <core/SkColorSpace.h>
|
||||
#include <core/SkImage.h>
|
||||
#include <core/SkRefCnt.h>
|
||||
#include <gpu/ganesh/GrDirectContext.h>
|
||||
#include <gpu/ganesh/SkImageGanesh.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
static constexpr size_t image_cache_max_entries = 128;
|
||||
static constexpr size_t image_cache_max_bytes = 64 * MiB;
|
||||
|
||||
struct DecodedImageFrameSkiaImageCache::Impl {
|
||||
Impl() = default;
|
||||
|
||||
explicit Impl(RefPtr<SkiaBackendContext> skia_backend_context)
|
||||
: skia_backend_context(move(skia_backend_context))
|
||||
{
|
||||
}
|
||||
|
||||
struct DecodedImageFrameKeyTraits : public Traits<DecodedImageFrame> {
|
||||
static unsigned hash(DecodedImageFrame const& frame)
|
||||
{
|
||||
return pair_int_hash(
|
||||
ptr_hash(&frame.bitmap()),
|
||||
ptr_hash(color_space_pointer(frame)));
|
||||
}
|
||||
|
||||
static bool equals(DecodedImageFrame const& a, DecodedImageFrame const& b)
|
||||
{
|
||||
return &a.bitmap() == &b.bitmap()
|
||||
&& color_space_pointer(a) == color_space_pointer(b);
|
||||
}
|
||||
|
||||
static constexpr bool may_have_slow_equality_check() { return false; }
|
||||
|
||||
private:
|
||||
static SkColorSpace const* color_space_pointer(DecodedImageFrame const& frame)
|
||||
{
|
||||
return frame.color_space().color_space<sk_sp<SkColorSpace>>().get();
|
||||
}
|
||||
};
|
||||
|
||||
struct CachedImage {
|
||||
sk_sp<SkImage> image;
|
||||
u64 last_used_sequence_number { 0 };
|
||||
size_t approximate_byte_size { 0 };
|
||||
};
|
||||
|
||||
u64 next_use_sequence_number()
|
||||
{
|
||||
return ++use_sequence_number;
|
||||
}
|
||||
|
||||
void prune_to_limits()
|
||||
{
|
||||
while (images.size() > image_cache_max_entries || approximate_byte_size > image_cache_max_bytes) {
|
||||
Optional<DecodedImageFrame> least_recently_used_frame;
|
||||
Optional<u64> least_recently_used_sequence_number;
|
||||
for (auto const& image : images) {
|
||||
if (!least_recently_used_sequence_number.has_value()
|
||||
|| image.value.last_used_sequence_number < least_recently_used_sequence_number.value()) {
|
||||
least_recently_used_frame = image.key;
|
||||
least_recently_used_sequence_number = image.value.last_used_sequence_number;
|
||||
}
|
||||
}
|
||||
|
||||
if (!least_recently_used_frame.has_value())
|
||||
break;
|
||||
|
||||
auto cached_image = images.get(least_recently_used_frame.value()).release_value();
|
||||
approximate_byte_size -= min(approximate_byte_size, cached_image.approximate_byte_size);
|
||||
images.remove(least_recently_used_frame.value());
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<SkiaBackendContext> skia_backend_context;
|
||||
HashMap<DecodedImageFrame, CachedImage, DecodedImageFrameKeyTraits> images;
|
||||
size_t approximate_byte_size { 0 };
|
||||
u64 use_sequence_number { 0 };
|
||||
};
|
||||
|
||||
DecodedImageFrameSkiaImageCache::DecodedImageFrameSkiaImageCache()
|
||||
: m_impl(make<Impl>())
|
||||
{
|
||||
}
|
||||
|
||||
DecodedImageFrameSkiaImageCache::DecodedImageFrameSkiaImageCache(RefPtr<SkiaBackendContext> skia_backend_context)
|
||||
: m_impl(make<Impl>(move(skia_backend_context)))
|
||||
{
|
||||
}
|
||||
|
||||
DecodedImageFrameSkiaImageCache::~DecodedImageFrameSkiaImageCache() = default;
|
||||
|
||||
sk_sp<SkImage> DecodedImageFrameSkiaImageCache::image_for_frame(DecodedImageFrame const& frame)
|
||||
{
|
||||
auto const& bitmap = frame.bitmap();
|
||||
if (auto it = m_impl->images.find(frame); it != m_impl->images.end()) {
|
||||
it->value.last_used_sequence_number = m_impl->next_use_sequence_number();
|
||||
return it->value.image;
|
||||
}
|
||||
|
||||
auto raster_image = sk_image_from_bitmap(bitmap, frame.color_space());
|
||||
sk_sp<SkImage> image;
|
||||
auto* gr_context = m_impl->skia_backend_context ? m_impl->skia_backend_context->sk_context() : nullptr;
|
||||
if (gr_context) {
|
||||
image = SkImages::TextureFromImage(gr_context, raster_image.get(), skgpu::Mipmapped::kNo, skgpu::Budgeted::kYes);
|
||||
if (!image)
|
||||
image = move(raster_image);
|
||||
} else {
|
||||
image = move(raster_image);
|
||||
}
|
||||
|
||||
if (!image)
|
||||
return nullptr;
|
||||
|
||||
Impl::CachedImage cached_image {
|
||||
.image = image,
|
||||
.last_used_sequence_number = m_impl->next_use_sequence_number(),
|
||||
.approximate_byte_size = bitmap.size_in_bytes(),
|
||||
};
|
||||
m_impl->approximate_byte_size += cached_image.approximate_byte_size;
|
||||
m_impl->images.set(frame, move(cached_image));
|
||||
m_impl->prune_to_limits();
|
||||
return image;
|
||||
}
|
||||
|
||||
void DecodedImageFrameSkiaImageCache::prune()
|
||||
{
|
||||
m_impl->prune_to_limits();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2026, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
|
||||
class SkImage;
|
||||
|
||||
template<typename T>
|
||||
class sk_sp;
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class DecodedImageFrameSkiaImageCache final {
|
||||
public:
|
||||
DecodedImageFrameSkiaImageCache();
|
||||
explicit DecodedImageFrameSkiaImageCache(RefPtr<SkiaBackendContext>);
|
||||
~DecodedImageFrameSkiaImageCache();
|
||||
|
||||
sk_sp<SkImage> image_for_frame(DecodedImageFrame const&);
|
||||
void prune();
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
OwnPtr<Impl> m_impl;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -50,7 +50,6 @@ DisplayListPlayerSkia::DisplayListPlayerSkia()
|
|||
|
||||
DisplayListPlayerSkia::DisplayListPlayerSkia(RefPtr<Gfx::SkiaBackendContext> skia_backend_context)
|
||||
: m_skia_backend_context(move(skia_backend_context))
|
||||
, m_image_cache(m_skia_backend_context)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +106,6 @@ static SkM44 to_skia_matrix4x4(Gfx::FloatMatrix4x4 const& matrix)
|
|||
|
||||
void DisplayListPlayerSkia::flush(Gfx::PaintingSurface& surface)
|
||||
{
|
||||
m_image_cache.prune();
|
||||
if (auto context = surface.skia_backend_context())
|
||||
context->flush_and_submit(&surface.sk_surface());
|
||||
surface.flush();
|
||||
|
|
@ -115,7 +113,6 @@ void DisplayListPlayerSkia::flush(Gfx::PaintingSurface& surface)
|
|||
|
||||
void DisplayListPlayerSkia::flush_async(Gfx::PaintingSurface& surface, Function<void()>&& callback)
|
||||
{
|
||||
m_image_cache.prune();
|
||||
if (auto context = surface.skia_backend_context())
|
||||
context->flush_and_submit_async(&surface.sk_surface(), move(callback));
|
||||
else
|
||||
|
|
@ -210,11 +207,7 @@ void DisplayListPlayerSkia::play_command(FillRect const& command)
|
|||
|
||||
void DisplayListPlayerSkia::play_command(DrawCompositorSurface const& command)
|
||||
{
|
||||
auto frame = resource_storage().compositor_surface(command.surface_id);
|
||||
if (!frame.has_value())
|
||||
return;
|
||||
|
||||
auto image = m_image_cache.image_for_frame(frame.value());
|
||||
auto image = resource_storage().skia_image_for_compositor_surface(command.surface_id, m_skia_backend_context);
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
|
|
@ -293,8 +286,7 @@ void DisplayListPlayerSkia::play_command(DrawVideoFrame const& command)
|
|||
|
||||
void DisplayListPlayerSkia::play_command(DrawScaledDecodedImageFrame const& command)
|
||||
{
|
||||
auto const& frame = resource_storage().image_frame(command.frame_id);
|
||||
auto image = m_image_cache.image_for_frame(frame);
|
||||
auto image = resource_storage().skia_image_for_image_frame(command.frame_id, m_skia_backend_context);
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
|
|
@ -311,7 +303,7 @@ void DisplayListPlayerSkia::play_command(DrawScaledDecodedImageFrame const& comm
|
|||
void DisplayListPlayerSkia::play_command(DrawRepeatedDecodedImageFrame const& command)
|
||||
{
|
||||
auto const& frame = resource_storage().image_frame(command.frame_id);
|
||||
auto image = m_image_cache.image_for_frame(frame);
|
||||
auto image = resource_storage().skia_image_for_image_frame(command.frame_id, m_skia_backend_context);
|
||||
if (!image)
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/Function.h>
|
||||
#include <LibGfx/DecodedImageFrameSkiaImageCache.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibWeb/Painting/DisplayList.h>
|
||||
#include <LibWeb/Painting/DisplayListCommand.h>
|
||||
#include <LibWeb/Painting/DisplayListRecorder.h>
|
||||
|
|
@ -45,7 +46,6 @@ private:
|
|||
ReadonlySpan<float> gradient_positions(DisplayListGradientColorStops) const;
|
||||
|
||||
RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
|
||||
Gfx::DecodedImageFrameSkiaImageCache m_image_cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,52 @@
|
|||
#include <LibGfx/Filter.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/SharedImageBuffer.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
#include <LibGfx/SkiaUtils.h>
|
||||
#include <LibMedia/VideoFrame.h>
|
||||
#include <LibWeb/Painting/DisplayList.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceStorage.h>
|
||||
|
||||
#include <core/SkImage.h>
|
||||
#include <gpu/ganesh/GrDirectContext.h>
|
||||
#include <gpu/ganesh/SkImageGanesh.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
struct DisplayListStoredImageFrameResource {
|
||||
explicit DisplayListStoredImageFrameResource(Gfx::DecodedImageFrame frame)
|
||||
: frame(move(frame))
|
||||
{
|
||||
}
|
||||
|
||||
Gfx::DecodedImageFrame frame;
|
||||
mutable sk_sp<SkImage> skia_image;
|
||||
mutable RefPtr<Gfx::SkiaBackendContext> skia_backend_context;
|
||||
};
|
||||
|
||||
static sk_sp<SkImage> create_skia_image(Gfx::DecodedImageFrame const& frame, RefPtr<Gfx::SkiaBackendContext> const& skia_backend_context)
|
||||
{
|
||||
auto raster_image = Gfx::sk_image_from_bitmap(frame.bitmap(), frame.color_space());
|
||||
auto* gr_context = skia_backend_context ? skia_backend_context->sk_context() : nullptr;
|
||||
if (!gr_context)
|
||||
return raster_image;
|
||||
|
||||
auto texture_image = SkImages::TextureFromImage(gr_context, raster_image.get(), skgpu::Mipmapped::kNo, skgpu::Budgeted::kYes);
|
||||
if (texture_image)
|
||||
return texture_image;
|
||||
return raster_image;
|
||||
}
|
||||
|
||||
static sk_sp<SkImage> skia_image_for_stored_image_frame(DisplayListStoredImageFrameResource const& resource, RefPtr<Gfx::SkiaBackendContext> const& skia_backend_context)
|
||||
{
|
||||
if (resource.skia_image && resource.skia_backend_context.ptr() == skia_backend_context.ptr())
|
||||
return resource.skia_image;
|
||||
|
||||
resource.skia_image = create_skia_image(resource.frame, skia_backend_context);
|
||||
resource.skia_backend_context = skia_backend_context;
|
||||
return resource.skia_image;
|
||||
}
|
||||
|
||||
bool DisplayListResourceSet::is_empty() const
|
||||
{
|
||||
return fonts.is_empty()
|
||||
|
|
@ -51,6 +91,9 @@ DisplayListResource::DisplayListResource(DisplayList const& display_list, Accumu
|
|||
{
|
||||
}
|
||||
|
||||
DisplayListResourceStorage::DisplayListResourceStorage() = default;
|
||||
DisplayListResourceStorage::DisplayListResourceStorage(DisplayListResourceStorage&&) = default;
|
||||
DisplayListResourceStorage& DisplayListResourceStorage::operator=(DisplayListResourceStorage&&) = default;
|
||||
DisplayListResourceStorage::~DisplayListResourceStorage() = default;
|
||||
|
||||
FontResourceId DisplayListResourceStorage::add_font(Gfx::Font const& font)
|
||||
|
|
@ -63,7 +106,7 @@ FontResourceId DisplayListResourceStorage::add_font(Gfx::Font const& font)
|
|||
ImageFrameResourceId DisplayListResourceStorage::add_image_frame(Gfx::DecodedImageFrame const& frame)
|
||||
{
|
||||
auto id = frame.id();
|
||||
m_image_frames.ensure(id, [&] { return frame; });
|
||||
m_image_frames.ensure(id, [&] { return make<DisplayListStoredImageFrameResource>(frame); });
|
||||
return { id };
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +139,17 @@ void DisplayListResourceStorage::set_font(FontResourceId id, NonnullRefPtr<Gfx::
|
|||
|
||||
void DisplayListResourceStorage::set_image_frame(ImageFrameResourceId id, Gfx::DecodedImageFrame frame)
|
||||
{
|
||||
m_image_frames.set(id.value(), move(frame));
|
||||
m_image_frames.set(id.value(), make<DisplayListStoredImageFrameResource>(move(frame)));
|
||||
}
|
||||
|
||||
Gfx::DecodedImageFrame const& DisplayListResourceStorage::image_frame(ImageFrameResourceId id) const
|
||||
{
|
||||
return m_image_frames.get(id.value()).value()->frame;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> DisplayListResourceStorage::skia_image_for_image_frame(ImageFrameResourceId id, RefPtr<Gfx::SkiaBackendContext> const& skia_backend_context) const
|
||||
{
|
||||
return skia_image_for_stored_image_frame(*m_image_frames.get(id.value()).value(), skia_backend_context);
|
||||
}
|
||||
|
||||
static ReadonlyBytes inline_data(ReadonlyBytes payload, DisplayListDataSpan span)
|
||||
|
|
@ -286,7 +339,8 @@ void DisplayListResourceStorage::retain_only(DisplayListResourceSet const& resou
|
|||
&& !m_font_cache_reference_counts.contains(id);
|
||||
});
|
||||
m_image_frames.remove_all_matching([&](auto id, auto const&) {
|
||||
return !resource_set.image_frames.contains(ImageFrameResourceId { id })
|
||||
auto image_frame_id = ImageFrameResourceId { id };
|
||||
return !resource_set.image_frames.contains(image_frame_id)
|
||||
&& !m_image_frame_cache_reference_counts.contains(id);
|
||||
});
|
||||
m_video_frames.remove_all_matching([&](auto id, auto const&) {
|
||||
|
|
@ -313,7 +367,7 @@ void DisplayListResourceStorage::clear_video_frame(VideoFrameResourceId frame_id
|
|||
void DisplayListResourceStorage::update_compositor_surface(CompositorSurfaceId surface_id, Gfx::SharedImage&& shared_image)
|
||||
{
|
||||
auto shared_image_buffer = Gfx::SharedImageBuffer::import_from_shared_image(move(shared_image));
|
||||
m_compositor_surfaces.set(surface_id.value(), Gfx::DecodedImageFrame { *shared_image_buffer.bitmap() });
|
||||
m_compositor_surfaces.set(surface_id.value(), make<DisplayListStoredImageFrameResource>(Gfx::DecodedImageFrame { *shared_image_buffer.bitmap() }));
|
||||
}
|
||||
|
||||
void DisplayListResourceStorage::clear_compositor_surface(CompositorSurfaceId surface_id)
|
||||
|
|
@ -321,4 +375,20 @@ void DisplayListResourceStorage::clear_compositor_surface(CompositorSurfaceId su
|
|||
m_compositor_surfaces.remove(surface_id.value());
|
||||
}
|
||||
|
||||
Optional<Gfx::DecodedImageFrame const&> DisplayListResourceStorage::compositor_surface(CompositorSurfaceId id) const
|
||||
{
|
||||
auto frame = m_compositor_surfaces.get(id.value());
|
||||
if (!frame.has_value())
|
||||
return {};
|
||||
return frame.value()->frame;
|
||||
}
|
||||
|
||||
sk_sp<SkImage> DisplayListResourceStorage::skia_image_for_compositor_surface(CompositorSurfaceId id, RefPtr<Gfx::SkiaBackendContext> const& skia_backend_context) const
|
||||
{
|
||||
auto resource = m_compositor_surfaces.get(id.value());
|
||||
if (!resource.has_value())
|
||||
return nullptr;
|
||||
return skia_image_for_stored_image_frame(*resource.value(), skia_backend_context);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <AK/HashMap.h>
|
||||
#include <AK/HashTable.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/NonnullRefPtr.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/RefPtr.h>
|
||||
|
|
@ -24,6 +25,11 @@
|
|||
#include <LibWeb/Painting/AccumulatedVisualContext.h>
|
||||
#include <LibWeb/Painting/DisplayListResourceIds.h>
|
||||
|
||||
class SkImage;
|
||||
|
||||
template<typename T>
|
||||
class sk_sp;
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
struct DisplayListResourceSet {
|
||||
|
|
@ -51,6 +57,8 @@ struct DisplayListVideoFrameResource {
|
|||
RefPtr<Media::VideoFrame const> frame;
|
||||
};
|
||||
|
||||
struct DisplayListStoredImageFrameResource;
|
||||
|
||||
struct DisplayListResource {
|
||||
DisplayListResource(NonnullRefPtr<DisplayList>, AccumulatedVisualContextTree);
|
||||
DisplayListResource(NonnullRefPtr<DisplayList const>, AccumulatedVisualContextTree);
|
||||
|
|
@ -74,10 +82,11 @@ struct DisplayListResourceTransaction {
|
|||
|
||||
class WEB_API DisplayListResourceStorage {
|
||||
AK_MAKE_NONCOPYABLE(DisplayListResourceStorage);
|
||||
AK_MAKE_DEFAULT_MOVABLE(DisplayListResourceStorage);
|
||||
|
||||
public:
|
||||
DisplayListResourceStorage() = default;
|
||||
DisplayListResourceStorage();
|
||||
DisplayListResourceStorage(DisplayListResourceStorage&&);
|
||||
DisplayListResourceStorage& operator=(DisplayListResourceStorage&&);
|
||||
~DisplayListResourceStorage();
|
||||
|
||||
FontResourceId add_font(Gfx::Font const&);
|
||||
|
|
@ -101,21 +110,23 @@ public:
|
|||
void clear_compositor_surface(CompositorSurfaceId);
|
||||
|
||||
Gfx::Font const& font(FontResourceId id) const { return *m_fonts.get(id.value()).value(); }
|
||||
Gfx::DecodedImageFrame const& image_frame(ImageFrameResourceId id) const { return m_image_frames.get(id.value()).value(); }
|
||||
Gfx::DecodedImageFrame const& image_frame(ImageFrameResourceId) const;
|
||||
sk_sp<SkImage> skia_image_for_image_frame(ImageFrameResourceId, RefPtr<Gfx::SkiaBackendContext> const&) const;
|
||||
RefPtr<Media::VideoFrame const> video_frame(VideoFrameResourceId id) const { return m_video_frames.get(id.value()).value(); }
|
||||
DisplayListResource const& display_list_resource(DisplayListResourceId id) const { return m_display_lists.get(id.value()).value(); }
|
||||
DisplayList const& display_list(DisplayListResourceId id) const { return *display_list_resource(id).display_list; }
|
||||
AccumulatedVisualContextTree const& display_list_visual_context_tree(DisplayListResourceId id) const { return display_list_resource(id).visual_context_tree; }
|
||||
Optional<Gfx::DecodedImageFrame const&> compositor_surface(CompositorSurfaceId id) const { return m_compositor_surfaces.get(id.value()); }
|
||||
Optional<Gfx::DecodedImageFrame const&> compositor_surface(CompositorSurfaceId) const;
|
||||
sk_sp<SkImage> skia_image_for_compositor_surface(CompositorSurfaceId, RefPtr<Gfx::SkiaBackendContext> const&) const;
|
||||
|
||||
private:
|
||||
void collect_referenced_resources(ReadonlyBytes command_bytes, DisplayListResourceSet&) const;
|
||||
|
||||
HashMap<u64, NonnullRefPtr<Gfx::Font const>> m_fonts;
|
||||
HashMap<u64, Gfx::DecodedImageFrame> m_image_frames;
|
||||
HashMap<u64, NonnullOwnPtr<DisplayListStoredImageFrameResource>> m_image_frames;
|
||||
HashMap<u64, RefPtr<Media::VideoFrame const>> m_video_frames;
|
||||
HashMap<u64, DisplayListResource> m_display_lists;
|
||||
HashMap<u64, Gfx::DecodedImageFrame> m_compositor_surfaces;
|
||||
HashMap<u64, NonnullOwnPtr<DisplayListStoredImageFrameResource>> m_compositor_surfaces;
|
||||
|
||||
HashMap<u64, size_t> m_font_cache_reference_counts;
|
||||
HashMap<u64, size_t> m_image_frame_cache_reference_counts;
|
||||
|
|
|
|||
Loading…
Reference in a new issue