From 2f8f12a8fd73f6ccf771007bd19a5864b9ee54da Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 2 Jun 2026 20:29:30 +0200 Subject: [PATCH] Map renderer viewport and scissor to OpenGL --- docs/modernization/build-inventory.md | 11 ++++--- docs/modernization/roadmap.md | 5 +-- src/renderer_gl/opengl_capabilities.cpp | 23 ++++++++++++++ src/renderer_gl/opengl_capabilities.h | 21 +++++++++++++ tests/renderer_gl/capabilities_tests.cpp | 39 ++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 7 deletions(-) diff --git a/docs/modernization/build-inventory.md b/docs/modernization/build-inventory.md index 32742b8..03b54bd 100644 --- a/docs/modernization/build-inventory.md +++ b/docs/modernization/build-inventory.md @@ -224,11 +224,12 @@ Known local toolchain state: 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, - default depth/program-point/line-smooth state, blend factor/equation, and UI - render-target RGBA8 format tokens are cataloged and tested here too, including - the legacy convert command and resize path. App clear color-buffer masks, - default framebuffer binding, scissor state, and sampler filter/wrap tokens - also consume the backend mapping. OpenGL extension enumeration query tokens + renderer API viewport/scissor rect conversion, default depth/program-point/ + line-smooth state, blend factor/equation, and UI render-target RGBA8 format + tokens are cataloged and tested here too, including the legacy convert command + and resize path. App clear color-buffer masks, default framebuffer binding, + scissor state, and sampler filter/wrap tokens also consume the backend mapping. + OpenGL extension enumeration query tokens used before runtime capability detection are cataloged here. Legacy font atlas texture formats, text mesh buffer targets, attribute component and normalization tokens, draw primitive/index type, upload usage, and active diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index a2c62a8..b59f826 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -481,8 +481,9 @@ depth-state to OpenGL enable/write/compare mapping also live in 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 -string, default depth/program-point/line-smooth state, blend factor/equation, -and UI render-target RGBA8 format tokens are now also cataloged and tested in +string, renderer API viewport/scissor rect conversion, default +depth/program-point/line-smooth state, blend factor/equation, and UI +render-target RGBA8 format tokens are now also cataloged and tested in `pp_renderer_gl`; the legacy convert command and resize path consume the same backend-owned mapping. App clear color-buffer masks, default framebuffer binding, scissor state, and sampler filter/wrap tokens now share that backend diff --git a/src/renderer_gl/opengl_capabilities.cpp b/src/renderer_gl/opengl_capabilities.cpp index 0edcab9..b857605 100644 --- a/src/renderer_gl/opengl_capabilities.cpp +++ b/src/renderer_gl/opengl_capabilities.cpp @@ -669,6 +669,18 @@ std::uint32_t viewport_query() noexcept return gl_viewport; } +OpenGlViewportRect viewport_for_renderer_viewport(pp::renderer::Viewport viewport) noexcept +{ + return OpenGlViewportRect { + .x = viewport.x, + .y = viewport.y, + .width = static_cast(viewport.width), + .height = static_cast(viewport.height), + .min_depth = viewport.min_depth, + .max_depth = viewport.max_depth, + }; +} + std::uint32_t color_clear_value_query() noexcept { return gl_color_clear_value; @@ -749,6 +761,17 @@ std::uint32_t scissor_test_state() noexcept return gl_scissor_test; } +OpenGlScissorRect scissor_rect_for_renderer_scissor(pp::renderer::ScissorRect scissor) noexcept +{ + return OpenGlScissorRect { + .enabled = scissor.enabled ? gl_boolean_true : gl_boolean_false, + .x = scissor.x, + .y = scissor.y, + .width = static_cast(scissor.width), + .height = static_cast(scissor.height), + }; +} + std::uint32_t program_point_size_state() noexcept { return gl_program_point_size; diff --git a/src/renderer_gl/opengl_capabilities.h b/src/renderer_gl/opengl_capabilities.h index 11a1cfa..6614ae2 100644 --- a/src/renderer_gl/opengl_capabilities.h +++ b/src/renderer_gl/opengl_capabilities.h @@ -34,6 +34,23 @@ struct OpenGlTextureParameter { std::uint32_t value = 0; }; +struct OpenGlViewportRect { + std::int32_t x = 0; + std::int32_t y = 0; + std::int32_t width = 0; + std::int32_t height = 0; + float min_depth = 0.0F; + float max_depth = 1.0F; +}; + +struct OpenGlScissorRect { + std::uint8_t enabled = 0; + std::int32_t x = 0; + std::int32_t y = 0; + std::int32_t width = 0; + std::int32_t height = 0; +}; + struct OpenGlEnumMapping { std::uint32_t value = 0; bool supported = false; @@ -158,6 +175,8 @@ struct OpenGlWindowsWglContextConfig { [[nodiscard]] std::uint32_t renderer_string_name() noexcept; [[nodiscard]] std::uint32_t shading_language_version_string_name() noexcept; [[nodiscard]] std::uint32_t viewport_query() noexcept; +[[nodiscard]] OpenGlViewportRect viewport_for_renderer_viewport( + pp::renderer::Viewport viewport) noexcept; [[nodiscard]] std::uint32_t color_clear_value_query() noexcept; [[nodiscard]] std::uint32_t current_program_query() noexcept; [[nodiscard]] std::uint32_t active_texture_query() noexcept; @@ -171,6 +190,8 @@ struct OpenGlWindowsWglContextConfig { [[nodiscard]] OpenGlDepthState depth_state_for_renderer_depth_state( pp::renderer::DepthState state) noexcept; [[nodiscard]] std::uint32_t scissor_test_state() noexcept; +[[nodiscard]] OpenGlScissorRect scissor_rect_for_renderer_scissor( + pp::renderer::ScissorRect scissor) noexcept; [[nodiscard]] std::uint32_t program_point_size_state() noexcept; [[nodiscard]] std::uint32_t line_smooth_state() noexcept; [[nodiscard]] std::uint32_t source_alpha_blend_factor() noexcept; diff --git a/tests/renderer_gl/capabilities_tests.cpp b/tests/renderer_gl/capabilities_tests.cpp index 4fa6b3e..fed0f4d 100644 --- a/tests/renderer_gl/capabilities_tests.cpp +++ b/tests/renderer_gl/capabilities_tests.cpp @@ -529,6 +529,44 @@ void maps_app_initialization_parameters(pp::tests::Harness& h) PP_EXPECT(h, pp::renderer::gl::active_texture_unit(4U) == 0x84C4U); } +void maps_renderer_viewports_and_scissors(pp::tests::Harness& h) +{ + const auto viewport = pp::renderer::gl::viewport_for_renderer_viewport( + pp::renderer::Viewport { + .x = 4, + .y = 8, + .width = 640U, + .height = 320U, + .min_depth = 0.25F, + .max_depth = 0.75F, + }); + const auto disabled_scissor = pp::renderer::gl::scissor_rect_for_renderer_scissor( + pp::renderer::ScissorRect {}); + const auto enabled_scissor = pp::renderer::gl::scissor_rect_for_renderer_scissor( + pp::renderer::ScissorRect { + .enabled = true, + .x = 12, + .y = 16, + .width = 128U, + .height = 64U, + }); + + PP_EXPECT(h, viewport.x == 4); + PP_EXPECT(h, viewport.y == 8); + PP_EXPECT(h, viewport.width == 640); + PP_EXPECT(h, viewport.height == 320); + PP_EXPECT(h, viewport.min_depth == 0.25F); + PP_EXPECT(h, viewport.max_depth == 0.75F); + PP_EXPECT(h, disabled_scissor.enabled == 0U); + PP_EXPECT(h, disabled_scissor.width == 0); + PP_EXPECT(h, disabled_scissor.height == 0); + PP_EXPECT(h, enabled_scissor.enabled == 1U); + PP_EXPECT(h, enabled_scissor.x == 12); + PP_EXPECT(h, enabled_scissor.y == 16); + PP_EXPECT(h, enabled_scissor.width == 128); + PP_EXPECT(h, enabled_scissor.height == 64); +} + 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); @@ -863,6 +901,7 @@ int main() harness.run("maps_renderer_sampler_tokens", maps_renderer_sampler_tokens); 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_viewports_and_scissors", maps_renderer_viewports_and_scissors); 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_blend_states", maps_renderer_blend_states);