From 6d1a1daff9dbdb03b4e202058adf4f1289f52bf5 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 11 Nov 2023 17:34:44 +0100 Subject: [PATCH] LibAccelGfx+LibWeb: Use framebuffer object instead of EGLs PBuffer Framebuffer object is allocated using OpenGL's API and is not platform specific which means it could be used on both macOS and Linux unlike EGL specific PBuffer. --- Userland/Libraries/LibAccelGfx/CMakeLists.txt | 1 - Userland/Libraries/LibAccelGfx/Canvas.cpp | 44 ------------------- Userland/Libraries/LibAccelGfx/Canvas.h | 41 ----------------- Userland/Libraries/LibAccelGfx/Context.cpp | 25 ----------- Userland/Libraries/LibAccelGfx/Context.h | 8 ---- Userland/Libraries/LibAccelGfx/Forward.h | 1 - Userland/Libraries/LibAccelGfx/GL.cpp | 35 +++++++++++++++ Userland/Libraries/LibAccelGfx/GL.h | 9 ++++ Userland/Libraries/LibAccelGfx/Painter.cpp | 26 ++++++++--- Userland/Libraries/LibAccelGfx/Painter.h | 8 ++-- .../Painting/PaintingCommandExecutorGPU.h | 1 - Userland/Services/WebContent/PageHost.cpp | 3 +- 12 files changed, 70 insertions(+), 132 deletions(-) delete mode 100644 Userland/Libraries/LibAccelGfx/Canvas.cpp delete mode 100644 Userland/Libraries/LibAccelGfx/Canvas.h diff --git a/Userland/Libraries/LibAccelGfx/CMakeLists.txt b/Userland/Libraries/LibAccelGfx/CMakeLists.txt index 94ec615d6b..4576622ae0 100644 --- a/Userland/Libraries/LibAccelGfx/CMakeLists.txt +++ b/Userland/Libraries/LibAccelGfx/CMakeLists.txt @@ -3,7 +3,6 @@ include(accelerated_graphics) if (HAS_ACCELERATED_GRAPHICS) set(SOURCES GL.cpp - Canvas.cpp Context.cpp Painter.cpp Program.cpp diff --git a/Userland/Libraries/LibAccelGfx/Canvas.cpp b/Userland/Libraries/LibAccelGfx/Canvas.cpp deleted file mode 100644 index 622f88a06a..0000000000 --- a/Userland/Libraries/LibAccelGfx/Canvas.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2023, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include - -namespace AccelGfx { - -Canvas Canvas::create(Context& context, NonnullRefPtr bitmap) -{ - VERIFY(bitmap->format() == Gfx::BitmapFormat::BGRA8888); - Canvas canvas { move(bitmap), context }; - canvas.initialize(); - return canvas; -} - -Canvas::Canvas(NonnullRefPtr bitmap, Context& context) - : m_bitmap(move(bitmap)) - , m_context(context) -{ -} - -void Canvas::initialize() -{ - m_surface = m_context.create_surface(width(), height()); - m_context.set_active_surface(m_surface); - GL::set_viewport({ 0, 0, width(), height() }); -} - -void Canvas::flush() -{ - GL::read_pixels({ 0, 0, width(), height() }, *m_bitmap); -} - -Canvas::~Canvas() -{ - m_context.destroy_surface(m_surface); -} - -} diff --git a/Userland/Libraries/LibAccelGfx/Canvas.h b/Userland/Libraries/LibAccelGfx/Canvas.h deleted file mode 100644 index 1175a78331..0000000000 --- a/Userland/Libraries/LibAccelGfx/Canvas.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023, Andreas Kling - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace AccelGfx { - -class Canvas { -public: - static Canvas create(Context& context, NonnullRefPtr bitmap); - - [[nodiscard]] Gfx::IntSize size() const { return m_bitmap->size(); } - [[nodiscard]] int width() const { return m_bitmap->width(); } - [[nodiscard]] int height() const { return m_bitmap->height(); } - - void flush(); - - [[nodiscard]] Gfx::Bitmap const& bitmap() const { return *m_bitmap; } - - ~Canvas(); - -private: - explicit Canvas(NonnullRefPtr, Context&); - - void initialize(); - - NonnullRefPtr m_bitmap; - - Context& m_context; - Context::Surface m_surface; -}; - -} diff --git a/Userland/Libraries/LibAccelGfx/Context.cpp b/Userland/Libraries/LibAccelGfx/Context.cpp index dee8e8ef6a..fea12f67f4 100644 --- a/Userland/Libraries/LibAccelGfx/Context.cpp +++ b/Userland/Libraries/LibAccelGfx/Context.cpp @@ -16,31 +16,6 @@ Context& Context::the() return *s_the; } -Context::Surface Context::create_surface(int width, int height) -{ - EGLint const pbuffer_attributes[] = { - EGL_WIDTH, - width, - EGL_HEIGHT, - height, - EGL_NONE, - }; - - auto egl_surface = eglCreatePbufferSurface(m_egl_display, m_egl_config, pbuffer_attributes); - return { egl_surface }; -} - -void Context::destroy_surface(Surface surface) -{ - if (surface.egl_surface) - eglDestroySurface(m_egl_display, surface.egl_surface); -} - -void Context::set_active_surface(Surface surface) -{ - VERIFY(eglMakeCurrent(m_egl_display, surface.egl_surface, surface.egl_surface, m_egl_context)); -} - OwnPtr Context::create() { EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); diff --git a/Userland/Libraries/LibAccelGfx/Context.h b/Userland/Libraries/LibAccelGfx/Context.h index ba51f203f6..6854d8fa3f 100644 --- a/Userland/Libraries/LibAccelGfx/Context.h +++ b/Userland/Libraries/LibAccelGfx/Context.h @@ -20,14 +20,6 @@ class Context { public: static Context& the(); - struct Surface { - EGLSurface egl_surface { 0 }; - }; - - Surface create_surface(int width, int height); - void destroy_surface(Surface surface); - void set_active_surface(Surface surface); - static OwnPtr create(); Context(EGLDisplay egl_display, EGLContext egl_context, EGLConfig egl_config) diff --git a/Userland/Libraries/LibAccelGfx/Forward.h b/Userland/Libraries/LibAccelGfx/Forward.h index 1c5b295aad..4c2879c3e0 100644 --- a/Userland/Libraries/LibAccelGfx/Forward.h +++ b/Userland/Libraries/LibAccelGfx/Forward.h @@ -8,7 +8,6 @@ namespace AccelGfx { -class Canvas; class Painter; } diff --git a/Userland/Libraries/LibAccelGfx/GL.cpp b/Userland/Libraries/LibAccelGfx/GL.cpp index ff465da0eb..28097abd57 100644 --- a/Userland/Libraries/LibAccelGfx/GL.cpp +++ b/Userland/Libraries/LibAccelGfx/GL.cpp @@ -220,4 +220,39 @@ void delete_vertex_array(VertexArray const& vertex_array) verify_no_error(); } +Framebuffer create_framebuffer(Gfx::IntSize size) +{ + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); + + GLuint fbo; + glGenFramebuffers(1, &fbo); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + VERIFY_NOT_REACHED(); + } + + verify_no_error(); + + return { fbo, texture }; +} + +void bind_framebuffer(Framebuffer const& framebuffer) +{ + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo_id); + verify_no_error(); +} + +void delete_framebuffer(Framebuffer const& framebuffer) +{ + glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.fbo_id); + glDeleteFramebuffers(1, &framebuffer.fbo_id); + glDeleteTextures(1, &framebuffer.texture_id); + verify_no_error(); +} + } diff --git a/Userland/Libraries/LibAccelGfx/GL.h b/Userland/Libraries/LibAccelGfx/GL.h index f10d3b7707..b3a2526ff1 100644 --- a/Userland/Libraries/LibAccelGfx/GL.h +++ b/Userland/Libraries/LibAccelGfx/GL.h @@ -45,6 +45,11 @@ struct VertexArray { GLuint id; }; +struct Framebuffer { + GLuint fbo_id; + GLuint texture_id; +}; + void set_viewport(Gfx::IntRect); void enable_blending(); @@ -89,4 +94,8 @@ VertexArray create_vertex_array(); void bind_vertex_array(VertexArray const&); void delete_vertex_array(VertexArray const&); +Framebuffer create_framebuffer(Gfx::IntSize); +void bind_framebuffer(Framebuffer const& framebuffer); +void delete_framebuffer(Framebuffer const& framebuffer); + } diff --git a/Userland/Libraries/LibAccelGfx/Painter.cpp b/Userland/Libraries/LibAccelGfx/Painter.cpp index 647551d6e6..5466786560 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.cpp +++ b/Userland/Libraries/LibAccelGfx/Painter.cpp @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -33,11 +32,11 @@ 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_target_bitmap->width() - 1.0f; + float y = -1.0f + 2.0f * screen_rect.y() / m_target_bitmap->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_target_bitmap->width(); + float height = 2.0f * screen_rect.height() / m_target_bitmap->height(); return { x, y, width, height }; } @@ -418,9 +417,24 @@ void Painter::restore() m_state_stack.take_last(); } +void Painter::set_target_bitmap(Gfx::Bitmap& bitmap) +{ + if (m_target_framebuffer.has_value()) { + GL::delete_framebuffer(*m_target_framebuffer); + m_target_framebuffer = {}; + } + + m_target_framebuffer = GL::create_framebuffer(bitmap.size()); + GL::bind_framebuffer(*m_target_framebuffer); + GL::set_viewport({ 0, 0, bitmap.width(), bitmap.height() }); + m_target_bitmap = bitmap; +} + void Painter::flush() { - m_canvas->flush(); + VERIFY(m_target_bitmap.has_value()); + GL::bind_framebuffer(*m_target_framebuffer); + GL::read_pixels({ 0, 0, m_target_bitmap->width(), m_target_bitmap->height() }, *m_target_bitmap); } } diff --git a/Userland/Libraries/LibAccelGfx/Painter.h b/Userland/Libraries/LibAccelGfx/Painter.h index e6b059936c..ca0494074b 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.h +++ b/Userland/Libraries/LibAccelGfx/Painter.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -67,12 +67,11 @@ public: void draw_glyph_run(Vector const& glyph_run, Color const& color); - void set_canvas(Canvas& canvas) { m_canvas = canvas; } + void set_target_bitmap(Gfx::Bitmap&); void flush(); private: Context& m_context; - Optional m_canvas; struct State { Gfx::AffineTransform transform; @@ -91,6 +90,9 @@ private: HashMap m_glyphs_texture_map; Gfx::IntSize m_glyphs_texture_size; GL::Texture m_glyphs_texture; + + Optional m_target_bitmap; + Optional m_target_framebuffer; }; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h index 706bfaf6cc..07f1814932 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h +++ b/Userland/Libraries/LibWeb/Painting/PaintingCommandExecutorGPU.h @@ -6,7 +6,6 @@ #pragma once -#include #include #include diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index 3f955f7c01..d8078a71b4 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -164,8 +164,7 @@ void PageHost::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& targ if (s_use_gpu_painter) { #ifdef HAS_ACCELERATED_GRAPHICS - auto canvas = AccelGfx::Canvas::create(AccelGfx::Context::the(), target); - m_accelerated_painter->set_canvas(canvas); + m_accelerated_painter->set_target_bitmap(target); Web::Painting::PaintingCommandExecutorGPU painting_command_executor(*m_accelerated_painter); recording_painter.execute(painting_command_executor); m_accelerated_painter->flush();