Move OpenGL shape draw mappings

This commit is contained in:
2026-06-01 17:52:59 +02:00
parent aa32c47e18
commit 05064b3a0d
6 changed files with 83 additions and 15 deletions

View File

@@ -130,7 +130,9 @@ Known local toolchain state:
upload-type mapping used by legacy `Texture2D` and `RTT` creation. It also upload-type mapping used by legacy `Texture2D` and `RTT` creation. It also
validates image channel-count to OpenGL texture format mapping, including validates image channel-count to OpenGL texture format mapping, including
invalid channel counts rejected by `Texture2D::create(Image)`, and 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 - `windows-msvc-vcpkg-headless` validates manifest install/configure/build/test
for the current headless component matrix; see DEBT-0007 for remaining app for the current headless component matrix; see DEBT-0007 for remaining app
and platform triplet migration. and platform triplet migration.

View File

@@ -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 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 by legacy `Texture2D` and `RTT` creation, plus image channel-count to texture
format mapping for `Texture2D` image uploads and framebuffer status naming for format mapping for `Texture2D` image uploads and framebuffer status naming for
`RTT` diagnostics. The legacy app delegates extension, upload-format, and `RTT` diagnostics. Mesh index-type and primitive-mode decisions used by legacy
framebuffer diagnostic interpretation to that backend library, but the existing `Shape` drawing also live in `pp_renderer_gl`. The legacy app delegates
renderer classes are not yet fully behind the renderer interfaces. 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: Implementation tasks:
@@ -633,7 +635,8 @@ Results:
alignment, desktop GL core float support, GLES float/half-float extensions, alignment, desktop GL core float support, GLES float/half-float extensions,
WebGL exclusion behavior, upload types for RGBA8/RGBA16F/RGBA32F internal WebGL exclusion behavior, upload types for RGBA8/RGBA16F/RGBA32F internal
formats, image channel-count format mapping including invalid counts, and 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 - PowerShell analyze automation returns JSON summaries and includes the shader
validation target. validation target.
- `windows-msvc-vcpkg-headless` configured through the Visual Studio bundled - `windows-msvc-vcpkg-headless` configured through the Visual Studio bundled

View File

@@ -5,8 +5,13 @@ namespace pp::renderer::gl {
namespace { namespace {
constexpr std::uint32_t gl_unsigned_byte = 0x1401U; 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_float = 0x1406U;
constexpr std::uint32_t gl_half_float = 0x140BU; 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_red = 0x1903U;
constexpr std::uint32_t gl_rgb = 0x1907U; constexpr std::uint32_t gl_rgb = 0x1907U;
constexpr std::uint32_t gl_rgba = 0x1908U; 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;
}
} }

View File

@@ -33,5 +33,8 @@ struct OpenGlPixelFormat {
[[nodiscard]] std::uint32_t texture_upload_type_for_internal_format(std::uint32_t internal_format) noexcept; [[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]] OpenGlPixelFormat texture_format_for_channel_count(std::uint32_t channel_count) noexcept;
[[nodiscard]] const char* framebuffer_status_name(std::uint32_t status) 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;
} }

View File

@@ -2,17 +2,20 @@
#include "log.h" #include "log.h"
#include "shape.h" #include "shape.h"
#include "app.h" #include "app.h"
#include "renderer_gl/opengl_capabilities.h"
#include <cstdint>
bool Shape::create_buffers(GLushort * idx, GLvoid * vertices, int isize, int vsize) bool Shape::create_buffers(GLushort * idx, GLvoid * vertices, int isize, int vsize)
{ {
index_type = GL_UNSIGNED_SHORT; index_type = static_cast<GLenum>(pp::renderer::gl::index_type_for_index_size(sizeof(GLushort)));
create_buffers_imp(idx, vertices, isize, vsize); create_buffers_imp(idx, vertices, isize, vsize);
return false; return false;
} }
bool Shape::create_buffers(GLuint* idx, GLvoid * vertices, int isize, int vsize) bool Shape::create_buffers(GLuint* idx, GLvoid * vertices, int isize, int vsize)
{ {
index_type = GL_UNSIGNED_INT; index_type = static_cast<GLenum>(pp::renderer::gl::index_type_for_index_size(sizeof(GLuint)));
create_buffers_imp(idx, vertices, isize, vsize); create_buffers_imp(idx, vertices, isize, vsize);
return false; return false;
} }
@@ -119,11 +122,7 @@ void Shape::draw_fill() const
{ {
if (count[0] == 0) return; if (count[0] == 0) return;
GLenum type = GL_TRIANGLES; const auto type = static_cast<GLenum>(pp::renderer::gl::primitive_mode_for_fill_count(count[0]));
if (count[0] == 1)
type = GL_POINTS;
if (count[0] == 2)
type = GL_LINES;
App::I->render_task([=] App::I->render_task([=]
{ {
#if USE_VBO #if USE_VBO
@@ -157,9 +156,7 @@ void Shape::draw_stroke() const
{ {
if (count[0] == 0) return; if (count[0] == 0) return;
GLenum type = GL_LINES; const auto type = static_cast<GLenum>(pp::renderer::gl::primitive_mode_for_stroke_count(count[1]));
if (count[1] == 1)
type = GL_POINTS;
App::I->render_task([=] App::I->render_task([=]
{ {
#if USE_VBO #if USE_VBO

View File

@@ -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")); 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() 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("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("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("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(); return harness.finish();
} }