From cc4eaef3e6c210d1292ab70649cc8a8f9db4e0aa Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 2 Jun 2026 20:15:56 +0200 Subject: [PATCH] Map renderer color write masks to OpenGL --- docs/modernization/build-inventory.md | 5 +++-- docs/modernization/roadmap.md | 4 ++-- src/renderer_gl/opengl_capabilities.cpp | 10 ++++++++++ src/renderer_gl/opengl_capabilities.h | 9 +++++++++ tests/renderer_gl/capabilities_tests.cpp | 24 ++++++++++++++++++++++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 64ae0e2..48aa1d6 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -215,8 +215,9 @@ Known local toolchain state: queries, active-uniform count query, and matrix-uniform transpose token used 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. Renderer API depth - compare-op to OpenGL depth-function mapping is tested here too. `Shader` no longer spells GL enum + stays distinguishable from unsupported enum values. Renderer API blend-state + color-write masks and depth compare-op to OpenGL depth-function mapping are + tested here too. `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 cc63976..4fbc1d8 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -473,8 +473,8 @@ count query, and matrix-uniform transpose token also live in `pp_renderer_gl` 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. Renderer API -depth compare-op to OpenGL depth-function mapping also lives in -`pp_renderer_gl`. Shader uniform hashing, catalog +blend-state color-write masks and depth compare-op to OpenGL depth-function +mapping also live in `pp_renderer_gl`. 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 022f560..607d2d1 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -803,6 +803,16 @@ std::uint8_t color_write_enabled() noexcept return gl_boolean_true; } +OpenGlColorWriteMask color_write_mask_for_renderer_blend_state(pp::renderer::BlendState state) noexcept +{ + return OpenGlColorWriteMask { + .r = state.write_r ? gl_boolean_true : gl_boolean_false, + .g = state.write_g ? gl_boolean_true : gl_boolean_false, + .b = state.write_b ? gl_boolean_true : gl_boolean_false, + .a = state.write_a ? gl_boolean_true : gl_boolean_false, + }; +} + std::uint32_t linear_texture_filter() noexcept { return gl_linear; diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index cf807b3..13fb2c6 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -39,6 +39,13 @@ struct OpenGlEnumMapping { bool supported = false; }; +struct OpenGlColorWriteMask { + std::uint8_t r = 0; + std::uint8_t g = 0; + std::uint8_t b = 0; + std::uint8_t a = 0; +}; + struct OpenGlReadbackFormat { std::uint32_t pixel_format = 0; std::uint32_t component_type = 0; @@ -155,6 +162,8 @@ struct OpenGlWindowsWglContextConfig { [[nodiscard]] std::uint32_t rgba32f_internal_format() noexcept; [[nodiscard]] std::uint8_t color_write_disabled() noexcept; [[nodiscard]] std::uint8_t color_write_enabled() noexcept; +[[nodiscard]] OpenGlColorWriteMask color_write_mask_for_renderer_blend_state( + pp::renderer::BlendState state) noexcept; [[nodiscard]] std::uint32_t linear_texture_filter() noexcept; [[nodiscard]] std::uint32_t linear_mipmap_linear_texture_filter() noexcept; [[nodiscard]] std::uint32_t nearest_texture_filter() noexcept; diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 076e43b..7aecbcb 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -535,6 +535,29 @@ void maps_renderer_blend_state_tokens(pp::tests::Harness& h) PP_EXPECT(h, invalid_op.value == 0U); } +void maps_renderer_color_write_masks(pp::tests::Harness& h) +{ + const auto default_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( + pp::renderer::BlendState {}); + const auto mixed_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( + pp::renderer::BlendState { .write_r = true, .write_g = false, .write_b = true, .write_a = false }); + const auto disabled_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( + pp::renderer::BlendState { .write_r = false, .write_g = false, .write_b = false, .write_a = false }); + + PP_EXPECT(h, default_mask.r == 1U); + PP_EXPECT(h, default_mask.g == 1U); + PP_EXPECT(h, default_mask.b == 1U); + PP_EXPECT(h, default_mask.a == 1U); + PP_EXPECT(h, mixed_mask.r == 1U); + PP_EXPECT(h, mixed_mask.g == 0U); + PP_EXPECT(h, mixed_mask.b == 1U); + PP_EXPECT(h, mixed_mask.a == 0U); + PP_EXPECT(h, disabled_mask.r == 0U); + PP_EXPECT(h, disabled_mask.g == 0U); + PP_EXPECT(h, disabled_mask.b == 0U); + PP_EXPECT(h, disabled_mask.a == 0U); +} + void maps_renderer_depth_compare_tokens(pp::tests::Harness& h) { const auto never = pp::renderer::gl::compare_function_for_renderer_compare_op( @@ -706,6 +729,7 @@ int main() 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_renderer_color_write_masks", maps_renderer_color_write_masks); harness.run("maps_renderer_depth_compare_tokens", maps_renderer_depth_compare_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);