mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 05:44:58 +00:00
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.
This commit is contained in:
parent
99caf4e649
commit
6d1a1daff9
12 changed files with 70 additions and 132 deletions
|
@ -3,7 +3,6 @@ include(accelerated_graphics)
|
|||
if (HAS_ACCELERATED_GRAPHICS)
|
||||
set(SOURCES
|
||||
GL.cpp
|
||||
Canvas.cpp
|
||||
Context.cpp
|
||||
Painter.cpp
|
||||
Program.cpp
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibAccelGfx/Canvas.h>
|
||||
#include <LibAccelGfx/GL.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
|
||||
namespace AccelGfx {
|
||||
|
||||
Canvas Canvas::create(Context& context, NonnullRefPtr<Gfx::Bitmap> bitmap)
|
||||
{
|
||||
VERIFY(bitmap->format() == Gfx::BitmapFormat::BGRA8888);
|
||||
Canvas canvas { move(bitmap), context };
|
||||
canvas.initialize();
|
||||
return canvas;
|
||||
}
|
||||
|
||||
Canvas::Canvas(NonnullRefPtr<Gfx::Bitmap> 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);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibAccelGfx/Context.h>
|
||||
#include <LibAccelGfx/Forward.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/Rect.h>
|
||||
|
||||
namespace AccelGfx {
|
||||
|
||||
class Canvas {
|
||||
public:
|
||||
static Canvas create(Context& context, NonnullRefPtr<Gfx::Bitmap> 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<Gfx::Bitmap>, Context&);
|
||||
|
||||
void initialize();
|
||||
|
||||
NonnullRefPtr<Gfx::Bitmap> m_bitmap;
|
||||
|
||||
Context& m_context;
|
||||
Context::Surface m_surface;
|
||||
};
|
||||
|
||||
}
|
|
@ -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> Context::create()
|
||||
{
|
||||
EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
|
|
|
@ -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<Context> create();
|
||||
|
||||
Context(EGLDisplay egl_display, EGLContext egl_context, EGLConfig egl_config)
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
namespace AccelGfx {
|
||||
|
||||
class Canvas;
|
||||
class Painter;
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibAccelGfx/Canvas.h>
|
||||
#include <LibAccelGfx/GL.h>
|
||||
#include <LibAccelGfx/Painter.h>
|
||||
#include <LibGfx/Color.h>
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#include <AK/HashMap.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibAccelGfx/Canvas.h>
|
||||
#include <LibAccelGfx/Context.h>
|
||||
#include <LibAccelGfx/Forward.h>
|
||||
#include <LibAccelGfx/GL.h>
|
||||
#include <LibAccelGfx/Program.h>
|
||||
|
@ -67,12 +67,11 @@ public:
|
|||
|
||||
void draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> 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<Canvas> m_canvas;
|
||||
|
||||
struct State {
|
||||
Gfx::AffineTransform transform;
|
||||
|
@ -91,6 +90,9 @@ private:
|
|||
HashMap<GlyphsTextureKey, Gfx::IntRect> m_glyphs_texture_map;
|
||||
Gfx::IntSize m_glyphs_texture_size;
|
||||
GL::Texture m_glyphs_texture;
|
||||
|
||||
Optional<Gfx::Bitmap&> m_target_bitmap;
|
||||
Optional<GL::Framebuffer> m_target_framebuffer;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibAccelGfx/Canvas.h>
|
||||
#include <LibAccelGfx/Painter.h>
|
||||
#include <LibWeb/Painting/RecordingPainter.h>
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue