From 05064b3a0df3f1e5cdc5b172f6bd9a1ac24cfe2f Mon Sep 17 00:00:00 2001 From: omigamedev Date: Mon, 1 Jun 2026 17:52:59 +0200 Subject: [PATCH] Move OpenGL shape draw mappings --- docs/modernization/build-inventory.md | 4 ++- docs/modernization/roadmap.md | 11 ++++--- src/renderer_gl/opengl_capabilities.cpp | 39 ++++++++++++++++++++++++ src/renderer_gl/opengl_capabilities.h | 3 ++ src/shape.cpp | 17 +++++------ tests/renderer_gl/capabilities_tests.cpp | 24 +++++++++++++++ 6 files changed, 83 insertions(+), 15 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 56a96fb..c79091e 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -130,7 +130,9 @@ Known local toolchain state: upload-type mapping used by legacy `Texture2D` and `RTT` creation. It also validates image channel-count to OpenGL texture format mapping, including invalid channel counts rejected by `Texture2D::create(Image)`, and - framebuffer status naming used by `RTT` diagnostics. + framebuffer status naming used by `RTT` diagnostics. It also validates + Shape index-type and fill/stroke primitive-mode mapping used by the legacy + mesh draw path. - `windows-msvc-vcpkg-headless` validates manifest install/configure/build/test for the current headless component matrix; see DEBT-0007 for remaining app and platform triplet migration. diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 12b644b..7371188 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -390,9 +390,11 @@ OpenGL capability detection for framebuffer fetch, map-buffer alignment, and float texture support. It also owns the OpenGL texture upload-type mapping used by legacy `Texture2D` and `RTT` creation, plus image channel-count to texture format mapping for `Texture2D` image uploads and framebuffer status naming for -`RTT` diagnostics. The legacy app delegates extension, upload-format, and -framebuffer diagnostic interpretation to that backend library, but the existing -renderer classes are not yet fully behind the renderer interfaces. +`RTT` diagnostics. Mesh index-type and primitive-mode decisions used by legacy +`Shape` drawing also live in `pp_renderer_gl`. The legacy app delegates +extension, upload-format, framebuffer diagnostic, and mesh draw-mode +interpretation to that backend library, but the existing renderer classes are +not yet fully behind the renderer interfaces. Implementation tasks: @@ -633,7 +635,8 @@ Results: alignment, desktop GL core float support, GLES float/half-float extensions, WebGL exclusion behavior, upload types for RGBA8/RGBA16F/RGBA32F internal formats, image channel-count format mapping including invalid counts, and - framebuffer status names. + framebuffer status names, plus Shape index-type and fill/stroke primitive + mode mapping. - PowerShell analyze automation returns JSON summaries and includes the shader validation target. - `windows-msvc-vcpkg-headless` configured through the Visual Studio bundled diff --git a/src/renderer_gl/opengl_capabilities.cpp b/src/renderer_gl/opengl_capabilities.cpp index 1aedf3c..f4a5871 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -5,8 +5,13 @@ namespace pp::renderer::gl { namespace { constexpr std::uint32_t gl_unsigned_byte = 0x1401U; +constexpr std::uint32_t gl_unsigned_short = 0x1403U; +constexpr std::uint32_t gl_unsigned_int = 0x1405U; constexpr std::uint32_t gl_float = 0x1406U; constexpr std::uint32_t gl_half_float = 0x140BU; +constexpr std::uint32_t gl_points = 0x0000U; +constexpr std::uint32_t gl_lines = 0x0001U; +constexpr std::uint32_t gl_triangles = 0x0004U; constexpr std::uint32_t gl_red = 0x1903U; constexpr std::uint32_t gl_rgb = 0x1907U; constexpr std::uint32_t gl_rgba = 0x1908U; @@ -124,4 +129,38 @@ const char* framebuffer_status_name(std::uint32_t status) noexcept } } +std::uint32_t index_type_for_index_size(std::uint32_t index_size_bytes) noexcept +{ + switch (index_size_bytes) { + case 2: + return gl_unsigned_short; + case 4: + return gl_unsigned_int; + default: + return 0U; + } +} + +std::uint32_t primitive_mode_for_fill_count(std::uint32_t vertex_or_index_count) noexcept +{ + if (vertex_or_index_count == 1U) { + return gl_points; + } + + if (vertex_or_index_count == 2U) { + return gl_lines; + } + + return gl_triangles; +} + +std::uint32_t primitive_mode_for_stroke_count(std::uint32_t vertex_or_index_count) noexcept +{ + if (vertex_or_index_count == 1U) { + return gl_points; + } + + return gl_lines; +} + } diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index 847d4a0..c9de5de 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -33,5 +33,8 @@ struct OpenGlPixelFormat { [[nodiscard]] std::uint32_t texture_upload_type_for_internal_format(std::uint32_t internal_format) noexcept; [[nodiscard]] OpenGlPixelFormat texture_format_for_channel_count(std::uint32_t channel_count) noexcept; [[nodiscard]] const char* framebuffer_status_name(std::uint32_t status) noexcept; +[[nodiscard]] std::uint32_t index_type_for_index_size(std::uint32_t index_size_bytes) noexcept; +[[nodiscard]] std::uint32_t primitive_mode_for_fill_count(std::uint32_t vertex_or_index_count) noexcept; +[[nodiscard]] std::uint32_t primitive_mode_for_stroke_count(std::uint32_t vertex_or_index_count) noexcept; } diff --git a/src/shape.cpp b/src/shape.cpp index 68c827a..bba55d1 100644 --- a/src/shape.cpp +++ b/src/shape.cpp @@ -2,17 +2,20 @@ #include "log.h" #include "shape.h" #include "app.h" +#include "renderer_gl/opengl_capabilities.h" + +#include bool Shape::create_buffers(GLushort * idx, GLvoid * vertices, int isize, int vsize) { - index_type = GL_UNSIGNED_SHORT; + index_type = static_cast(pp::renderer::gl::index_type_for_index_size(sizeof(GLushort))); create_buffers_imp(idx, vertices, isize, vsize); return false; } bool Shape::create_buffers(GLuint* idx, GLvoid * vertices, int isize, int vsize) { - index_type = GL_UNSIGNED_INT; + index_type = static_cast(pp::renderer::gl::index_type_for_index_size(sizeof(GLuint))); create_buffers_imp(idx, vertices, isize, vsize); return false; } @@ -119,11 +122,7 @@ void Shape::draw_fill() const { if (count[0] == 0) return; - GLenum type = GL_TRIANGLES; - if (count[0] == 1) - type = GL_POINTS; - if (count[0] == 2) - type = GL_LINES; + const auto type = static_cast(pp::renderer::gl::primitive_mode_for_fill_count(count[0])); App::I->render_task([=] { #if USE_VBO @@ -157,9 +156,7 @@ void Shape::draw_stroke() const { if (count[0] == 0) return; - GLenum type = GL_LINES; - if (count[1] == 1) - type = GL_POINTS; + const auto type = static_cast(pp::renderer::gl::primitive_mode_for_stroke_count(count[1])); App::I->render_task([=] { #if USE_VBO diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 6e248c1..505dde9 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -133,6 +133,29 @@ void names_framebuffer_status_codes(pp::tests::Harness& h) PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0U) == std::string_view("UNKNOWN")); } +void maps_shape_index_and_primitive_modes(pp::tests::Harness& h) +{ + constexpr std::uint32_t gl_points = 0x0000U; + constexpr std::uint32_t gl_lines = 0x0001U; + constexpr std::uint32_t gl_triangles = 0x0004U; + constexpr std::uint32_t gl_unsigned_short = 0x1403U; + constexpr std::uint32_t gl_unsigned_int = 0x1405U; + + PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(2U) == gl_unsigned_short); + PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(4U) == gl_unsigned_int); + PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(1U) == 0U); + PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(8U) == 0U); + + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(1U) == gl_points); + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(2U) == gl_lines); + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(3U) == gl_triangles); + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(99U) == gl_triangles); + + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(1U) == gl_points); + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(2U) == gl_lines); + PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(99U) == gl_lines); +} + } int main() @@ -145,5 +168,6 @@ int main() harness.run("selects_texture_upload_type_from_internal_format", selects_texture_upload_type_from_internal_format); harness.run("maps_image_channel_count_to_texture_format", maps_image_channel_count_to_texture_format); harness.run("names_framebuffer_status_codes", names_framebuffer_status_codes); + harness.run("maps_shape_index_and_primitive_modes", maps_shape_index_and_primitive_modes); return harness.finish(); }