From 2d12d1538dbfd88b21012e0272a8d7ea9a222864 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sat, 11 Nov 2023 14:07:10 +0100 Subject: [PATCH] LibAccelGfx: Create VBO to pass vertices data to GPU Before, we were using a feature of OpenGL that allows specifying a pointer to allocated vertex data without creating VBO and VAO, but as I found out, it does not work on macOS. --- Userland/Libraries/LibAccelGfx/GL.cpp | 51 +++++++++++++++++++++- Userland/Libraries/LibAccelGfx/GL.h | 19 +++++++- Userland/Libraries/LibAccelGfx/Painter.cpp | 47 ++++++++++++++++++-- 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibAccelGfx/GL.cpp b/Userland/Libraries/LibAccelGfx/GL.cpp index 9dad447bd2..ff465da0eb 100644 --- a/Userland/Libraries/LibAccelGfx/GL.cpp +++ b/Userland/Libraries/LibAccelGfx/GL.cpp @@ -143,9 +143,9 @@ void set_uniform(Uniform const& uniform, float value1, float value2, float value verify_no_error(); } -void set_vertex_attribute(VertexAttribute const& attribute, Span values, int number_of_components) +void set_vertex_attribute(VertexAttribute const& attribute, u32 offset, int number_of_components) { - glVertexAttribPointer(attribute.id, number_of_components, GL_FLOAT, GL_FALSE, number_of_components * sizeof(float), values.data()); + glVertexAttribPointer(attribute.id, number_of_components, GL_FLOAT, GL_FALSE, number_of_components * sizeof(float), reinterpret_cast(offset)); glEnableVertexAttribArray(attribute.id); verify_no_error(); } @@ -173,4 +173,51 @@ void draw_arrays(DrawPrimitive draw_primitive, size_t count) verify_no_error(); } +Buffer create_buffer() +{ + GLuint buffer; + glGenBuffers(1, &buffer); + verify_no_error(); + return { buffer }; +} + +void bind_buffer(Buffer const& buffer) +{ + glBindBuffer(GL_ARRAY_BUFFER, buffer.id); + verify_no_error(); +} + +void upload_to_buffer(Buffer const& buffer, Span values) +{ + glBindBuffer(GL_ARRAY_BUFFER, buffer.id); + glBufferData(GL_ARRAY_BUFFER, values.size() * sizeof(float), values.data(), GL_STATIC_DRAW); + verify_no_error(); +} + +void delete_buffer(Buffer const& buffer) +{ + glDeleteBuffers(1, &buffer.id); + verify_no_error(); +} + +VertexArray create_vertex_array() +{ + GLuint vertex_array; + glGenVertexArrays(1, &vertex_array); + verify_no_error(); + return { vertex_array }; +} + +void bind_vertex_array(VertexArray const& vertex_array) +{ + glBindVertexArray(vertex_array.id); + verify_no_error(); +} + +void delete_vertex_array(VertexArray const& vertex_array) +{ + glDeleteVertexArrays(1, &vertex_array.id); + verify_no_error(); +} + } diff --git a/Userland/Libraries/LibAccelGfx/GL.h b/Userland/Libraries/LibAccelGfx/GL.h index a69dba0c4f..f10d3b7707 100644 --- a/Userland/Libraries/LibAccelGfx/GL.h +++ b/Userland/Libraries/LibAccelGfx/GL.h @@ -37,6 +37,14 @@ struct Texture { GLuint id; }; +struct Buffer { + GLuint id; +}; + +struct VertexArray { + GLuint id; +}; + void set_viewport(Gfx::IntRect); void enable_blending(); @@ -55,7 +63,7 @@ void upload_texture_data(Texture const& texture, Gfx::Bitmap const& bitmap); void delete_texture(Texture const&); void set_uniform(Uniform const& uniform, float, float, float, float); -void set_vertex_attribute(VertexAttribute const& attribute, Span values, int number_of_components); +void set_vertex_attribute(VertexAttribute const& attribute, u32 offset, int number_of_components); enum class ScalingMode { Nearest, @@ -72,4 +80,13 @@ enum class DrawPrimitive { void draw_arrays(DrawPrimitive, size_t count); +Buffer create_buffer(); +void bind_buffer(Buffer const&); +void upload_to_buffer(Buffer const&, Span values); +void delete_buffer(Buffer const&); + +VertexArray create_vertex_array(); +void bind_vertex_array(VertexArray const&); +void delete_vertex_array(VertexArray const&); + } diff --git a/Userland/Libraries/LibAccelGfx/Painter.cpp b/Userland/Libraries/LibAccelGfx/Painter.cpp index 82f310be65..14caacb974 100644 --- a/Userland/Libraries/LibAccelGfx/Painter.cpp +++ b/Userland/Libraries/LibAccelGfx/Painter.cpp @@ -126,6 +126,13 @@ void Painter::fill_rect(Gfx::FloatRect rect, Gfx::Color color) auto vertices = rect_to_vertices(to_clip_space(transform().map(rect))); + auto vbo = GL::create_buffer(); + GL::upload_to_buffer(vbo, vertices); + + auto vao = GL::create_vertex_array(); + GL::bind_vertex_array(vao); + GL::bind_buffer(vbo); + auto [red, green, blue, alpha] = gfx_color_to_opengl_color(color); m_rectangle_program.use(); @@ -134,9 +141,12 @@ void Painter::fill_rect(Gfx::FloatRect rect, Gfx::Color color) auto color_uniform = m_rectangle_program.get_uniform_location("uColor"); GL::set_uniform(color_uniform, red, green, blue, alpha); - GL::set_vertex_attribute(position_attribute, vertices, 2); + GL::set_vertex_attribute(position_attribute, 0, 2); GL::enable_blending(); GL::draw_arrays(GL::DrawPrimitive::TriangleFan, 4); + + GL::delete_buffer(vbo); + GL::delete_vertex_array(vao); } void Painter::draw_line(Gfx::IntPoint a, Gfx::IntPoint b, float thickness, Gfx::Color color) @@ -157,6 +167,13 @@ void Painter::draw_line(Gfx::FloatPoint a, Gfx::FloatPoint b, float thickness, C auto vertices = rect_to_vertices(to_clip_space(transform().map(rect))); + auto vbo = GL::create_buffer(); + GL::upload_to_buffer(vbo, vertices); + + auto vao = GL::create_vertex_array(); + GL::bind_vertex_array(vao); + GL::bind_buffer(vbo); + auto [red, green, blue, alpha] = gfx_color_to_opengl_color(color); m_rectangle_program.use(); @@ -165,9 +182,12 @@ void Painter::draw_line(Gfx::FloatPoint a, Gfx::FloatPoint b, float thickness, C auto color_uniform = m_rectangle_program.get_uniform_location("uColor"); GL::set_uniform(color_uniform, red, green, blue, alpha); - GL::set_vertex_attribute(position_attribute, vertices, 2); + GL::set_vertex_attribute(position_attribute, 0, 2); GL::enable_blending(); GL::draw_arrays(GL::DrawPrimitive::TriangleFan, 4); + + GL::delete_buffer(vbo); + GL::delete_vertex_array(vao); } void Painter::draw_scaled_bitmap(Gfx::IntRect const& dest_rect, Gfx::Bitmap const& bitmap, Gfx::IntRect const& src_rect, ScalingMode scaling_mode) @@ -226,8 +246,15 @@ void Painter::draw_scaled_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap con add_vertex(dst_rect_in_clip_space.bottom_right(), src_rect_in_texture_space.bottom_right()); add_vertex(dst_rect_in_clip_space.top_right(), src_rect_in_texture_space.top_right()); + auto vbo = GL::create_buffer(); + GL::upload_to_buffer(vbo, vertices); + + auto vao = GL::create_vertex_array(); + GL::bind_vertex_array(vao); + GL::bind_buffer(vbo); + auto vertex_position_attribute = m_blit_program.get_attribute_location("aVertexPosition"); - GL::set_vertex_attribute(vertex_position_attribute, vertices, 4); + GL::set_vertex_attribute(vertex_position_attribute, 0, 4); auto color_uniform = m_blit_program.get_uniform_location("uColor"); GL::set_uniform(color_uniform, 1, 1, 1, 1); @@ -236,6 +263,8 @@ void Painter::draw_scaled_bitmap(Gfx::FloatRect const& dst_rect, Gfx::Bitmap con GL::draw_arrays(GL::DrawPrimitive::TriangleFan, 4); GL::delete_texture(texture); + GL::delete_buffer(vbo); + GL::delete_vertex_array(vao); } void Painter::prepare_glyph_texture(HashMap> const& unique_glyphs) @@ -349,6 +378,13 @@ void Painter::draw_glyph_run(Vector const& glyph_run, Col } } + auto vbo = GL::create_buffer(); + GL::upload_to_buffer(vbo, vertices); + + auto vao = GL::create_vertex_array(); + GL::bind_vertex_array(vao); + GL::bind_buffer(vbo); + auto [red, green, blue, alpha] = gfx_color_to_opengl_color(color); m_blit_program.use(); @@ -360,8 +396,11 @@ void Painter::draw_glyph_run(Vector const& glyph_run, Col auto color_uniform = m_blit_program.get_uniform_location("uColor"); GL::set_uniform(color_uniform, red, green, blue, alpha); - GL::set_vertex_attribute(position_attribute, vertices, 4); + GL::set_vertex_attribute(position_attribute, 0, 4); GL::draw_arrays(GL::DrawPrimitive::Triangles, vertices.size() / 4); + + GL::delete_buffer(vbo); + GL::delete_vertex_array(vao); } void Painter::save()