From 1e85bf221d2ce3222504341e14f27fdc73e0e662 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 2 Nov 2023 00:01:16 +0100 Subject: [PATCH] LibAccelGfx+WebContent: Use the same Painter across page repaints In the upcoming changes, Painter will be used to store the state of OpenGL context. For example, if Painter is aware of the shader that have already been loaded, it will be possible to reuse them across repaints. Also, it would be possible to manage state of loaded textures and add/remove them depending on which ones are present in the next sequence of painting commands. --- Userland/Libraries/LibAccelGfx/Context.cpp | 6 +++++ Userland/Libraries/LibAccelGfx/Painter.cpp | 20 +++++++++------ Userland/Libraries/LibAccelGfx/Painter.h | 11 +++++--- .../Painting/PaintingCommandExecutorGPU.cpp | 8 +++--- .../Painting/PaintingCommandExecutorGPU.h | 6 ++--- Userland/Services/WebContent/PageHost.cpp | 25 +++++++++++++------ Userland/Services/WebContent/PageHost.h | 5 ++++ 7 files changed, 54 insertions(+), 27 deletions(-) diff --git a/Userland/Libraries/LibAccelGfx/Context.cpp b/Userland/Libraries/LibAccelGfx/Context.cpp index 8188cab9879..f8e56db81ea 100644 --- a/Userland/Libraries/LibAccelGfx/Context.cpp +++ b/Userland/Libraries/LibAccelGfx/Context.cpp @@ -69,6 +69,12 @@ OwnPtr Context::create() }; EGLContext egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attributes); + EGLBoolean result = eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_context); + if (result == EGL_FALSE) { + dbgln("eglMakeCurrent failed"); + VERIFY_NOT_REACHED(); + } + return make(egl_display, egl_context, egl_config); } diff --git a/Userland/Libraries/LibAccelGfx/Painter.cpp b/Userland/Libraries/LibAccelGfx/Painter.cpp index b67c9a04635..812787f02c3 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.cpp +++ b/Userland/Libraries/LibAccelGfx/Painter.cpp @@ -33,17 +33,23 @@ static ColorComponents gfx_color_to_opengl_color(Gfx::Color color) Gfx::FloatRect Painter::to_clip_space(Gfx::FloatRect const& screen_rect) const { - float x = 2.0f * screen_rect.x() / m_canvas.width() - 1.0f; - float y = -1.0f + 2.0f * screen_rect.y() / m_canvas.height(); + float x = 2.0f * screen_rect.x() / m_canvas->width() - 1.0f; + float y = -1.0f + 2.0f * screen_rect.y() / m_canvas->height(); - float width = 2.0f * screen_rect.width() / m_canvas.width(); - float height = 2.0f * screen_rect.height() / m_canvas.height(); + float width = 2.0f * screen_rect.width() / m_canvas->width(); + float height = 2.0f * screen_rect.height() / m_canvas->height(); return { x, y, width, height }; } -Painter::Painter(Canvas& canvas) - : m_canvas(canvas) +OwnPtr Painter::create() +{ + auto& context = Context::the(); + return make(context); +} + +Painter::Painter(Context& context) + : m_context(context) { m_state_stack.empend(State()); } @@ -171,7 +177,7 @@ void Painter::restore() void Painter::flush() { - m_canvas.flush(); + m_canvas->flush(); } } diff --git a/Userland/Libraries/LibAccelGfx/Painter.h b/Userland/Libraries/LibAccelGfx/Painter.h index fe270a08f61..9e0c6f6b7bd 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.h +++ b/Userland/Libraries/LibAccelGfx/Painter.h @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -19,7 +20,9 @@ class Painter { AK_MAKE_NONMOVABLE(Painter); public: - Painter(Canvas&); + static OwnPtr create(); + + Painter(Context&); ~Painter(); void clear(Gfx::Color); @@ -33,10 +36,12 @@ public: void fill_rect(Gfx::FloatRect, Gfx::Color); void fill_rect(Gfx::IntRect, Gfx::Color); -private: + void set_canvas(Canvas& canvas) { m_canvas = canvas; } void flush(); - Canvas& m_canvas; +private: + Context& m_context; + Optional m_canvas; struct State { Gfx::AffineTransform transform; diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp index 525003c0313..4cac0265c40 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.cpp @@ -8,16 +8,14 @@ namespace Web::Painting { -PaintingCommandExecutorGPU::PaintingCommandExecutorGPU(Gfx::Bitmap& bitmap) - : m_target_bitmap(bitmap) - , m_canvas(AccelGfx::Canvas::create(AccelGfx::Context::the(), bitmap)) - , m_painter(m_canvas) +PaintingCommandExecutorGPU::PaintingCommandExecutorGPU(AccelGfx::Painter& painter) + : m_painter(painter) { } PaintingCommandExecutorGPU::~PaintingCommandExecutorGPU() { - m_canvas.flush(); + m_painter.flush(); } CommandResult PaintingCommandExecutorGPU::draw_text_run(Color const&, Gfx::IntPoint const&, String const&, Gfx::Font const&) diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h index 89473cc137a..75c9b5ffe25 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h @@ -50,15 +50,13 @@ public: bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override; - PaintingCommandExecutorGPU(Gfx::Bitmap& bitmap); + PaintingCommandExecutorGPU(AccelGfx::Painter& painter); ~PaintingCommandExecutorGPU() override; private: AccelGfx::Painter& painter() { return m_painter; } - Gfx::Bitmap& m_target_bitmap; - AccelGfx::Canvas m_canvas; - AccelGfx::Painter m_painter; + AccelGfx::Painter& m_painter; }; } diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index 16fe226a907..29d96dc35fc 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -27,6 +27,13 @@ namespace WebContent { +static bool s_use_gpu_painter = false; + +void PageHost::set_use_gpu_painter() +{ + s_use_gpu_painter = true; +} + PageHost::PageHost(ConnectionFromClient& client) : m_client(client) , m_page(make(*this)) @@ -36,17 +43,16 @@ PageHost::PageHost(ConnectionFromClient& client) m_client.async_did_invalidate_content_rect({ m_invalidation_rect.x().value(), m_invalidation_rect.y().value(), m_invalidation_rect.width().value(), m_invalidation_rect.height().value() }); m_invalidation_rect = {}; }); + + if (s_use_gpu_painter) { +#ifdef HAS_ACCELERATED_GRAPHICS + m_accelerated_painter = AccelGfx::Painter::create(); +#endif + } } PageHost::~PageHost() = default; -static bool s_use_gpu_painter = false; - -void PageHost::set_use_gpu_painter() -{ - s_use_gpu_painter = true; -} - void PageHost::set_has_focus(bool has_focus) { m_has_focus = has_focus; @@ -158,8 +164,11 @@ void PageHost::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& targ if (s_use_gpu_painter) { #ifdef HAS_ACCELERATED_GRAPHICS - Web::Painting::PaintingCommandExecutorGPU painting_command_executor(target); + auto canvas = AccelGfx::Canvas::create(AccelGfx::Context::the(), target); + m_accelerated_painter->set_canvas(canvas); + Web::Painting::PaintingCommandExecutorGPU painting_command_executor(*m_accelerated_painter); recording_painter.execute(painting_command_executor); + m_accelerated_painter->flush(); #endif } else { Web::Painting::PaintingCommandExecutorCPU painting_command_executor(target); diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h index 407d7320da1..5b00bc017c2 100644 --- a/Userland/Services/WebContent/PageHost.h +++ b/Userland/Services/WebContent/PageHost.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -139,6 +140,10 @@ private: Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto }; RefPtr m_webdriver; + +#ifdef HAS_ACCELERATED_GRAPHICS + OwnPtr m_accelerated_painter; +#endif }; }