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();