diff --git a/Userland/Libraries/LibAccelGfx/Painter.cpp b/Userland/Libraries/LibAccelGfx/Painter.cpp index 4e220f2ca20..864b19e4d39 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.cpp +++ b/Userland/Libraries/LibAccelGfx/Painter.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include namespace AccelGfx { @@ -136,6 +137,8 @@ void main() { } )"; +HashMap s_immutable_bitmap_texture_cache; + OwnPtr Painter::create() { auto& context = Context::the(); @@ -319,6 +322,18 @@ void Painter::draw_scaled_bitmap(Gfx::IntRect const& dest_rect, Gfx::Bitmap cons draw_scaled_bitmap(dest_rect.to_type(), bitmap, src_rect.to_type(), scaling_mode); } +void Painter::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, ScalingMode scaling_mode) +{ + draw_scaled_immutable_bitmap(dst_rect.to_type(), immutable_bitmap, src_rect.to_type(), scaling_mode); +} + +void Painter::draw_scaled_immutable_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::FloatRect const& src_rect, ScalingMode scaling_mode) +{ + auto texture = s_immutable_bitmap_texture_cache.get(immutable_bitmap.id()); + VERIFY(texture.has_value()); + blit_scaled_texture(dst_rect, texture.value(), src_rect, scaling_mode); +} + static Gfx::FloatRect to_texture_space(Gfx::FloatRect rect, Gfx::IntSize image_size) { auto x = rect.x() / image_size.width(); @@ -690,4 +705,23 @@ void Painter::blit_scaled_texture(Gfx::FloatRect const& dst_rect, GL::Texture co GL::delete_vertex_array(vao); } +void Painter::update_immutable_bitmap_texture_cache(HashMap& immutable_bitmaps) +{ + for (auto immutable_bitmap_id : s_immutable_bitmap_texture_cache.keys()) { + if (!immutable_bitmaps.contains(immutable_bitmap_id)) { + auto texture = s_immutable_bitmap_texture_cache.get(immutable_bitmap_id).value(); + GL::delete_texture(texture); + s_immutable_bitmap_texture_cache.remove(immutable_bitmap_id); + } + } + + for (auto const& [id, immutable_bitmap] : immutable_bitmaps) { + if (s_immutable_bitmap_texture_cache.contains(id)) + continue; + auto texture = GL::create_texture(); + GL::upload_texture_data(texture, immutable_bitmap->bitmap()); + s_immutable_bitmap_texture_cache.set(id, texture); + } +} + } diff --git a/Userland/Libraries/LibAccelGfx/Painter.h b/Userland/Libraries/LibAccelGfx/Painter.h index e2d71195b48..ef20e8b3985 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.h +++ b/Userland/Libraries/LibAccelGfx/Painter.h @@ -57,6 +57,9 @@ public: void draw_scaled_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap const&, Gfx::FloatRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor); void draw_scaled_bitmap(Gfx::IntRect const& dst_rect, Gfx::Bitmap const&, Gfx::IntRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor); + void draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::IntRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor); + void draw_scaled_immutable_bitmap(Gfx::FloatRect const& dst_rect, Gfx::ImmutableBitmap const&, Gfx::FloatRect const& src_rect, ScalingMode = ScalingMode::NearestNeighbor); + void prepare_glyph_texture(HashMap> const& unique_glyphs); struct GlyphsTextureKey { @@ -90,6 +93,8 @@ public: void blit_canvas(Gfx::IntRect const& dst_rect, Canvas const&, float opacity = 1.0f); void blit_canvas(Gfx::FloatRect const& dst_rect, Canvas const&, float opacity = 1.0f); + void update_immutable_bitmap_texture_cache(HashMap&); + private: Context& m_context; diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorCPU.h b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorCPU.h index 5d089794eb9..d5d5f6d5ddf 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorCPU.h +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorCPU.h @@ -52,6 +52,9 @@ public: bool needs_prepare_glyphs_texture() const override { return false; } void prepare_glyph_texture(HashMap> const&) override {}; + bool needs_update_immutable_bitmap_texture_cache() const override { return false; } + void update_immutable_bitmap_texture_cache(HashMap&) override {}; + PaintingCommandExecutorCPU(Gfx::Bitmap& bitmap); private: diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp index 18df9fe9904..f4712d5bf9f 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp @@ -67,7 +67,7 @@ CommandResult PaintingCommandExecutorGPU::draw_scaled_bitmap(Gfx::IntRect const& CommandResult PaintingCommandExecutorGPU::draw_scaled_immutable_bitmap(Gfx::IntRect const& dst_rect, Gfx::ImmutableBitmap const& immutable_bitmap, Gfx::IntRect const& src_rect, Gfx::Painter::ScalingMode scaling_mode) { - painter().draw_scaled_bitmap(dst_rect, immutable_bitmap.bitmap(), src_rect, to_accelgfx_scaling_mode(scaling_mode)); + painter().draw_scaled_immutable_bitmap(dst_rect, immutable_bitmap, src_rect, to_accelgfx_scaling_mode(scaling_mode)); return CommandResult::Continue; } @@ -316,4 +316,9 @@ void PaintingCommandExecutorGPU::prepare_glyph_texture(HashMap& immutable_bitmaps) +{ + painter().update_immutable_bitmap_texture_cache(immutable_bitmaps); +} + } diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h index f9eb72556d4..fba5fa605bf 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h @@ -52,6 +52,9 @@ public: virtual bool needs_prepare_glyphs_texture() const override { return true; } void prepare_glyph_texture(HashMap> const&) override; + bool needs_update_immutable_bitmap_texture_cache() const override { return true; } + void update_immutable_bitmap_texture_cache(HashMap&) override; + PaintingCommandExecutorGPU(Gfx::Bitmap& bitmap); ~PaintingCommandExecutorGPU() override; diff --git a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp index eb38d5565f7..6261ea2b19f 100644 --- a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp +++ b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp @@ -425,6 +425,17 @@ void RecordingPainter::execute(PaintingCommandExecutor& executor) executor.prepare_glyph_texture(unique_glyphs); } + if (executor.needs_update_immutable_bitmap_texture_cache()) { + HashMap immutable_bitmaps; + for (auto const& command : m_painting_commands) { + if (command.has()) { + auto const& immutable_bitmap = command.get().bitmap; + immutable_bitmaps.set(immutable_bitmap->id(), immutable_bitmap.ptr()); + } + } + executor.update_immutable_bitmap_texture_cache(immutable_bitmaps); + } + size_t next_command_index = 0; while (next_command_index < m_painting_commands.size()) { auto& command = m_painting_commands[next_command_index++]; diff --git a/Userland/Libraries/LibWeb/Painting/RecordingPainter.h b/Userland/Libraries/LibWeb/Painting/RecordingPainter.h index b1ee715e5e5..89cb70bbcc2 100644 --- a/Userland/Libraries/LibWeb/Painting/RecordingPainter.h +++ b/Userland/Libraries/LibWeb/Painting/RecordingPainter.h @@ -396,6 +396,9 @@ public: virtual bool needs_prepare_glyphs_texture() const { return false; } virtual void prepare_glyph_texture(HashMap> const& unique_glyphs) = 0; + + virtual bool needs_update_immutable_bitmap_texture_cache() const = 0; + virtual void update_immutable_bitmap_texture_cache(HashMap&) = 0; }; class RecordingPainter {