From b6c66f3e41d5668afef1da68d3ecaeef8e6f9478 Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 2 Jun 2026 18:21:52 +0200 Subject: [PATCH] Map renderer blend tokens to OpenGL --- docs/modernization/build-inventory.md | 4 +- docs/modernization/roadmap.md | 4 +- src/renderer_gl/opengl_capabilities.cpp | 40 ++++++++++++++++++++ src/renderer_gl/opengl_capabilities.h | 9 +++++ tests/renderer_gl/capabilities_tests.cpp | 48 ++++++++++++++++++++++++ 5 files changed, 103 insertions(+), 2 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index c2de205..65e066a 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -210,7 +210,9 @@ Known local toolchain state: border-color parameter mapping used by legacy `Sampler`. The PanoPainter shader attribute binding catalog, shader stage tokens, compile/link status queries, active-uniform count query, and matrix-uniform transpose token used - by legacy `Shader` creation also live here. `Shader` no longer spells GL enum + by legacy `Shader` creation also live here. Renderer API blend factor/op to + OpenGL token mapping is tested here with explicit support flags so `GL_ZERO` + stays distinguishable from unsupported enum values. `Shader` no longer spells GL enum names directly. It also owns the PanoPainter shader uniform catalog and legacy hash mapping used by `Shader` active-uniform discovery and the uniform uniqueness check. App OpenGL initialization debug severity, debug output, GL info string, diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 0402987..c7caced 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -467,7 +467,9 @@ interpretation to that backend library. Sampler wrap, min/mag filter, and deskto mapping for legacy `Sampler` also lives in `pp_renderer_gl`. The PanoPainter shader attribute binding catalog, shader stage tokens, compile/link status queries, active-uniform count query, and matrix-uniform transpose token also live in `pp_renderer_gl` -and are consumed by legacy `Shader` creation. Shader uniform hashing, catalog +and are consumed by legacy `Shader` creation. Renderer API blend factor/op to +OpenGL token mapping also lives in `pp_renderer_gl`, with explicit support flags +so `GL_ZERO` remains distinguishable from unsupported enum values. Shader uniform hashing, catalog validation, active-uniform mapping, and the legacy uniform uniqueness check now delegate to `pp_renderer_gl` as well. `Shader` no longer spells GL enum names directly. App OpenGL initialization debug severity, debug output, GL info diff --git a/src/renderer_gl/opengl_capabilities.cpp b/src/renderer_gl/opengl_capabilities.cpp index 89e5e44..82afb73 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -40,8 +40,12 @@ constexpr std::uint32_t gl_debug_severity_high = 0x9146U; constexpr std::uint32_t gl_debug_severity_medium = 0x9147U; constexpr std::uint32_t gl_debug_severity_low = 0x9148U; constexpr std::uint32_t gl_debug_severity_notification = 0x826BU; +constexpr std::uint32_t gl_zero = 0U; +constexpr std::uint32_t gl_one = 1U; constexpr std::uint32_t gl_src_alpha = 0x0302U; constexpr std::uint32_t gl_one_minus_src_alpha = 0x0303U; +constexpr std::uint32_t gl_dst_alpha = 0x0304U; +constexpr std::uint32_t gl_one_minus_dst_alpha = 0x0305U; constexpr std::uint32_t gl_line_smooth = 0x0B20U; constexpr std::uint32_t gl_viewport = 0x0BA2U; constexpr std::uint32_t gl_blend = 0x0BE2U; @@ -55,6 +59,8 @@ constexpr std::uint32_t gl_texture_binding_cube_map = 0x8514U; constexpr std::uint32_t gl_sampler_binding = 0x8919U; constexpr std::uint32_t gl_func_add = 0x8006U; constexpr std::uint32_t gl_max = 0x8008U; +constexpr std::uint32_t gl_func_subtract = 0x800AU; +constexpr std::uint32_t gl_func_reverse_subtract = 0x800BU; constexpr std::uint32_t gl_program_point_size = 0x8642U; constexpr std::uint32_t gl_array_buffer = 0x8892U; constexpr std::uint32_t gl_element_array_buffer = 0x8893U; @@ -693,6 +699,40 @@ std::uint32_t max_blend_equation() noexcept return gl_max; } +OpenGlEnumMapping blend_factor_for_renderer_factor(pp::renderer::BlendFactor factor) noexcept +{ + switch (factor) { + case pp::renderer::BlendFactor::zero: + return OpenGlEnumMapping { .value = gl_zero, .supported = true }; + case pp::renderer::BlendFactor::one: + return OpenGlEnumMapping { .value = gl_one, .supported = true }; + case pp::renderer::BlendFactor::source_alpha: + return OpenGlEnumMapping { .value = gl_src_alpha, .supported = true }; + case pp::renderer::BlendFactor::one_minus_source_alpha: + return OpenGlEnumMapping { .value = gl_one_minus_src_alpha, .supported = true }; + case pp::renderer::BlendFactor::destination_alpha: + return OpenGlEnumMapping { .value = gl_dst_alpha, .supported = true }; + case pp::renderer::BlendFactor::one_minus_destination_alpha: + return OpenGlEnumMapping { .value = gl_one_minus_dst_alpha, .supported = true }; + default: + return OpenGlEnumMapping {}; + } +} + +OpenGlEnumMapping blend_equation_for_renderer_op(pp::renderer::BlendOp op) noexcept +{ + switch (op) { + case pp::renderer::BlendOp::add: + return OpenGlEnumMapping { .value = gl_func_add, .supported = true }; + case pp::renderer::BlendOp::subtract: + return OpenGlEnumMapping { .value = gl_func_subtract, .supported = true }; + case pp::renderer::BlendOp::reverse_subtract: + return OpenGlEnumMapping { .value = gl_func_reverse_subtract, .supported = true }; + default: + return OpenGlEnumMapping {}; + } +} + std::uint32_t rgba8_internal_format() noexcept { return gl_rgba8; diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index ba1ca7e..1aaa22a 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -34,6 +34,11 @@ struct OpenGlTextureParameter { std::uint32_t value = 0; }; +struct OpenGlEnumMapping { + std::uint32_t value = 0; + bool supported = false; +}; + struct OpenGlReadbackFormat { std::uint32_t pixel_format = 0; std::uint32_t component_type = 0; @@ -137,6 +142,10 @@ struct OpenGlWindowsWglContextConfig { [[nodiscard]] std::uint32_t one_minus_source_alpha_blend_factor() noexcept; [[nodiscard]] std::uint32_t add_blend_equation() noexcept; [[nodiscard]] std::uint32_t max_blend_equation() noexcept; +[[nodiscard]] OpenGlEnumMapping blend_factor_for_renderer_factor( + pp::renderer::BlendFactor factor) noexcept; +[[nodiscard]] OpenGlEnumMapping blend_equation_for_renderer_op( + pp::renderer::BlendOp op) noexcept; [[nodiscard]] std::uint32_t rgba8_internal_format() noexcept; [[nodiscard]] std::uint32_t rgba16f_internal_format() noexcept; [[nodiscard]] std::uint32_t rgba32f_internal_format() noexcept; diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 28012a3..fcd3c32 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -440,6 +440,53 @@ void maps_app_initialization_parameters(pp::tests::Harness& h) PP_EXPECT(h, pp::renderer::gl::active_texture_unit(4U) == 0x84C4U); } +void maps_renderer_blend_state_tokens(pp::tests::Harness& h) +{ + const auto zero = pp::renderer::gl::blend_factor_for_renderer_factor(pp::renderer::BlendFactor::zero); + const auto one = pp::renderer::gl::blend_factor_for_renderer_factor(pp::renderer::BlendFactor::one); + const auto source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( + pp::renderer::BlendFactor::source_alpha); + const auto one_minus_source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( + pp::renderer::BlendFactor::one_minus_source_alpha); + const auto destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( + pp::renderer::BlendFactor::destination_alpha); + const auto one_minus_destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( + pp::renderer::BlendFactor::one_minus_destination_alpha); + const auto invalid_factor = pp::renderer::gl::blend_factor_for_renderer_factor( + static_cast(255U)); + + const auto add = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::add); + const auto subtract = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::subtract); + const auto reverse_subtract = pp::renderer::gl::blend_equation_for_renderer_op( + pp::renderer::BlendOp::reverse_subtract); + const auto invalid_op = pp::renderer::gl::blend_equation_for_renderer_op( + static_cast(255U)); + + PP_EXPECT(h, zero.supported); + PP_EXPECT(h, zero.value == 0U); + PP_EXPECT(h, one.supported); + PP_EXPECT(h, one.value == 1U); + PP_EXPECT(h, source_alpha.supported); + PP_EXPECT(h, source_alpha.value == 0x0302U); + PP_EXPECT(h, one_minus_source_alpha.supported); + PP_EXPECT(h, one_minus_source_alpha.value == 0x0303U); + PP_EXPECT(h, destination_alpha.supported); + PP_EXPECT(h, destination_alpha.value == 0x0304U); + PP_EXPECT(h, one_minus_destination_alpha.supported); + PP_EXPECT(h, one_minus_destination_alpha.value == 0x0305U); + PP_EXPECT(h, !invalid_factor.supported); + PP_EXPECT(h, invalid_factor.value == 0U); + + PP_EXPECT(h, add.supported); + PP_EXPECT(h, add.value == 0x8006U); + PP_EXPECT(h, subtract.supported); + PP_EXPECT(h, subtract.value == 0x800AU); + PP_EXPECT(h, reverse_subtract.supported); + PP_EXPECT(h, reverse_subtract.value == 0x800BU); + PP_EXPECT(h, !invalid_op.supported); + PP_EXPECT(h, invalid_op.value == 0U); +} + void maps_windows_wgl_core_context_parameters(pp::tests::Harness& h) { const auto config = pp::renderer::gl::windows_wgl_core_context_3_3_config(); @@ -568,6 +615,7 @@ int main() harness.run("maps_sampler_parameters", maps_sampler_parameters); harness.run("exposes_shader_attribute_binding_catalog", exposes_shader_attribute_binding_catalog); harness.run("maps_app_initialization_parameters", maps_app_initialization_parameters); + harness.run("maps_renderer_blend_state_tokens", maps_renderer_blend_state_tokens); harness.run("maps_windows_wgl_core_context_parameters", maps_windows_wgl_core_context_parameters); harness.run("rejects_invalid_shader_attribute_binding_catalogs", rejects_invalid_shader_attribute_binding_catalogs); harness.run("exposes_shader_uniform_catalog", exposes_shader_uniform_catalog);