Map renderer blend state to OpenGL

This commit is contained in:
2026-06-02 20:26:55 +02:00
parent 36f9e73dd4
commit 728116da8f
5 changed files with 114 additions and 8 deletions

View File

@@ -216,10 +216,11 @@ Known local toolchain state:
queries, active-uniform count query, and matrix-uniform transpose token used queries, active-uniform count query, and matrix-uniform transpose token used
by legacy `Shader` creation also live here. Renderer API blend factor/op to 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` OpenGL token mapping is tested here with explicit support flags so `GL_ZERO`
stays distinguishable from unsupported enum values. Renderer API blend-state stays distinguishable from unsupported enum values. Aggregate renderer API
color-write masks, depth compare-op to OpenGL depth-function mapping, and blend-state to OpenGL enable/factor/equation/color-mask mapping, depth
aggregate renderer API depth-state to OpenGL enable/write/compare mapping are compare-op to OpenGL depth-function mapping, and aggregate renderer API
tested here too. `Shader` no longer spells GL enum depth-state to OpenGL enable/write/compare mapping are tested here too.
`Shader` no longer spells GL enum
names directly. It also owns the PanoPainter shader uniform catalog and legacy hash names directly. It also owns the PanoPainter shader uniform catalog and legacy hash
mapping used by `Shader` active-uniform discovery and the uniform uniqueness mapping used by `Shader` active-uniform discovery and the uniform uniqueness
check. App OpenGL initialization debug severity, debug output, GL info string, check. App OpenGL initialization debug severity, debug output, GL info string,

View File

@@ -473,10 +473,11 @@ binding catalog, shader stage tokens, compile/link status queries, active-unifor
count query, and matrix-uniform transpose token also live in `pp_renderer_gl` 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 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 OpenGL token mapping also lives in `pp_renderer_gl`, with explicit support flags
so `GL_ZERO` remains distinguishable from unsupported enum values. Renderer API so `GL_ZERO` remains distinguishable from unsupported enum values. Aggregate
blend-state color-write masks, depth compare-op to OpenGL depth-function renderer API blend-state to OpenGL enable/factor/equation/color-mask mapping,
mapping, and aggregate renderer API depth-state to OpenGL enable/write/compare depth compare-op to OpenGL depth-function mapping, and aggregate renderer API
mapping also live in `pp_renderer_gl`. Shader uniform hashing, catalog depth-state to OpenGL enable/write/compare mapping also live in
`pp_renderer_gl`. Shader uniform hashing, catalog
validation, active-uniform mapping, and the legacy uniform uniqueness check now 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 delegate to `pp_renderer_gl` as well. `Shader` no longer spells GL enum names
directly. App OpenGL initialization debug severity, debug output, GL info directly. App OpenGL initialization debug severity, debug output, GL info

View File

@@ -813,6 +813,33 @@ OpenGlEnumMapping blend_equation_for_renderer_op(pp::renderer::BlendOp op) noexc
} }
} }
OpenGlBlendState blend_state_for_renderer_blend_state(pp::renderer::BlendState state) noexcept
{
const auto source_color = blend_factor_for_renderer_factor(state.source_color);
const auto destination_color = blend_factor_for_renderer_factor(state.destination_color);
const auto color_op = blend_equation_for_renderer_op(state.color_op);
const auto source_alpha = blend_factor_for_renderer_factor(state.source_alpha);
const auto destination_alpha = blend_factor_for_renderer_factor(state.destination_alpha);
const auto alpha_op = blend_equation_for_renderer_op(state.alpha_op);
return OpenGlBlendState {
.enabled = state.enabled ? gl_boolean_true : gl_boolean_false,
.source_color_factor = source_color.value,
.destination_color_factor = destination_color.value,
.color_equation = color_op.value,
.source_alpha_factor = source_alpha.value,
.destination_alpha_factor = destination_alpha.value,
.alpha_equation = alpha_op.value,
.color_write_mask = color_write_mask_for_renderer_blend_state(state),
.supported = source_color.supported
&& destination_color.supported
&& color_op.supported
&& source_alpha.supported
&& destination_alpha.supported
&& alpha_op.supported,
};
}
std::uint32_t rgba8_internal_format() noexcept std::uint32_t rgba8_internal_format() noexcept
{ {
return gl_rgba8; return gl_rgba8;

View File

@@ -46,6 +46,18 @@ struct OpenGlColorWriteMask {
std::uint8_t a = 0; std::uint8_t a = 0;
}; };
struct OpenGlBlendState {
std::uint8_t enabled = 0;
std::uint32_t source_color_factor = 0;
std::uint32_t destination_color_factor = 0;
std::uint32_t color_equation = 0;
std::uint32_t source_alpha_factor = 0;
std::uint32_t destination_alpha_factor = 0;
std::uint32_t alpha_equation = 0;
OpenGlColorWriteMask color_write_mask;
bool supported = false;
};
struct OpenGlDepthState { struct OpenGlDepthState {
std::uint8_t test_enabled = 0; std::uint8_t test_enabled = 0;
std::uint8_t write_enabled = 0; std::uint8_t write_enabled = 0;
@@ -169,6 +181,8 @@ struct OpenGlWindowsWglContextConfig {
pp::renderer::BlendFactor factor) noexcept; pp::renderer::BlendFactor factor) noexcept;
[[nodiscard]] OpenGlEnumMapping blend_equation_for_renderer_op( [[nodiscard]] OpenGlEnumMapping blend_equation_for_renderer_op(
pp::renderer::BlendOp op) noexcept; pp::renderer::BlendOp op) noexcept;
[[nodiscard]] OpenGlBlendState blend_state_for_renderer_blend_state(
pp::renderer::BlendState state) noexcept;
[[nodiscard]] std::uint32_t rgba8_internal_format() noexcept; [[nodiscard]] std::uint32_t rgba8_internal_format() noexcept;
[[nodiscard]] std::uint32_t rgba16f_internal_format() noexcept; [[nodiscard]] std::uint32_t rgba16f_internal_format() noexcept;
[[nodiscard]] std::uint32_t rgba32f_internal_format() noexcept; [[nodiscard]] std::uint32_t rgba32f_internal_format() noexcept;

View File

@@ -599,6 +599,68 @@ void maps_renderer_color_write_masks(pp::tests::Harness& h)
PP_EXPECT(h, disabled_mask.a == 0U); PP_EXPECT(h, disabled_mask.a == 0U);
} }
void maps_renderer_blend_states(pp::tests::Harness& h)
{
const auto disabled = pp::renderer::gl::blend_state_for_renderer_blend_state(
pp::renderer::BlendState {});
const auto alpha_blend = pp::renderer::gl::blend_state_for_renderer_blend_state(
pp::renderer::BlendState {
.enabled = true,
.source_color = pp::renderer::BlendFactor::source_alpha,
.destination_color = pp::renderer::BlendFactor::one_minus_source_alpha,
.color_op = pp::renderer::BlendOp::add,
.source_alpha = pp::renderer::BlendFactor::one,
.destination_alpha = pp::renderer::BlendFactor::one_minus_destination_alpha,
.alpha_op = pp::renderer::BlendOp::reverse_subtract,
.write_r = true,
.write_g = false,
.write_b = true,
.write_a = false,
});
const auto invalid_factor = pp::renderer::gl::blend_state_for_renderer_blend_state(
pp::renderer::BlendState {
.enabled = true,
.source_color = static_cast<pp::renderer::BlendFactor>(255U),
});
const auto invalid_op = pp::renderer::gl::blend_state_for_renderer_blend_state(
pp::renderer::BlendState {
.enabled = true,
.color_op = static_cast<pp::renderer::BlendOp>(255U),
});
PP_EXPECT(h, disabled.supported);
PP_EXPECT(h, disabled.enabled == 0U);
PP_EXPECT(h, disabled.source_color_factor == 1U);
PP_EXPECT(h, disabled.destination_color_factor == 0U);
PP_EXPECT(h, disabled.color_equation == 0x8006U);
PP_EXPECT(h, disabled.source_alpha_factor == 1U);
PP_EXPECT(h, disabled.destination_alpha_factor == 0U);
PP_EXPECT(h, disabled.alpha_equation == 0x8006U);
PP_EXPECT(h, disabled.color_write_mask.r == 1U);
PP_EXPECT(h, disabled.color_write_mask.g == 1U);
PP_EXPECT(h, disabled.color_write_mask.b == 1U);
PP_EXPECT(h, disabled.color_write_mask.a == 1U);
PP_EXPECT(h, alpha_blend.supported);
PP_EXPECT(h, alpha_blend.enabled == 1U);
PP_EXPECT(h, alpha_blend.source_color_factor == 0x0302U);
PP_EXPECT(h, alpha_blend.destination_color_factor == 0x0303U);
PP_EXPECT(h, alpha_blend.color_equation == 0x8006U);
PP_EXPECT(h, alpha_blend.source_alpha_factor == 1U);
PP_EXPECT(h, alpha_blend.destination_alpha_factor == 0x0305U);
PP_EXPECT(h, alpha_blend.alpha_equation == 0x800BU);
PP_EXPECT(h, alpha_blend.color_write_mask.r == 1U);
PP_EXPECT(h, alpha_blend.color_write_mask.g == 0U);
PP_EXPECT(h, alpha_blend.color_write_mask.b == 1U);
PP_EXPECT(h, alpha_blend.color_write_mask.a == 0U);
PP_EXPECT(h, !invalid_factor.supported);
PP_EXPECT(h, invalid_factor.enabled == 1U);
PP_EXPECT(h, invalid_factor.source_color_factor == 0U);
PP_EXPECT(h, !invalid_op.supported);
PP_EXPECT(h, invalid_op.color_equation == 0U);
}
void maps_renderer_depth_compare_tokens(pp::tests::Harness& h) void maps_renderer_depth_compare_tokens(pp::tests::Harness& h)
{ {
const auto never = pp::renderer::gl::compare_function_for_renderer_compare_op( const auto never = pp::renderer::gl::compare_function_for_renderer_compare_op(
@@ -803,6 +865,7 @@ int main()
harness.run("maps_app_initialization_parameters", maps_app_initialization_parameters); 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_blend_state_tokens", maps_renderer_blend_state_tokens);
harness.run("maps_renderer_color_write_masks", maps_renderer_color_write_masks); harness.run("maps_renderer_color_write_masks", maps_renderer_color_write_masks);
harness.run("maps_renderer_blend_states", maps_renderer_blend_states);
harness.run("maps_renderer_depth_compare_tokens", maps_renderer_depth_compare_tokens); harness.run("maps_renderer_depth_compare_tokens", maps_renderer_depth_compare_tokens);
harness.run("maps_renderer_depth_states", maps_renderer_depth_states); harness.run("maps_renderer_depth_states", maps_renderer_depth_states);
harness.run("maps_windows_wgl_core_context_parameters", maps_windows_wgl_core_context_parameters); harness.run("maps_windows_wgl_core_context_parameters", maps_windows_wgl_core_context_parameters);