Route VR render state through renderer GL
This commit is contained in:
@@ -464,8 +464,9 @@ Known local toolchain state:
|
||||
version/vendor/renderer/GLSL string query dispatch, tested default clear
|
||||
color/buffer dispatch consumed by `App::clear`, tested app UI
|
||||
viewport/scissor dispatch consumed by `App::draw` and `App::vr_draw_ui`,
|
||||
plus renderer API to OpenGL token mapping and command-planning contracts used
|
||||
by the OpenGL parity work.
|
||||
tested generic capability/buffer-clear dispatch consumed by VR draw state
|
||||
setup, plus renderer API to OpenGL token mapping and command-planning
|
||||
contracts used by the OpenGL parity work.
|
||||
- `pano_cli plan-cloud-upload` exposes `pp_app_core` cloud upload availability,
|
||||
new-document warning, publish prompt, and save-before-upload planning as JSON;
|
||||
the live cloud upload command consumes the same start contract before
|
||||
|
||||
@@ -531,6 +531,10 @@ the live OpenGL call sequence.
|
||||
VR UI framebuffer viewport and scissor-test setup now also consumes those
|
||||
`pp_renderer_gl` contracts, keeping desktop and VR UI rendering aligned while
|
||||
the retained OpenVR app path is split incrementally.
|
||||
VR draw blend/depth state transitions and depth-buffer clears now use generic
|
||||
tested `pp_renderer_gl` capability and clear dispatch contracts, reducing
|
||||
direct OpenGL execution in the retained VR app path without changing state
|
||||
restore behavior.
|
||||
Windows RenderDoc frame capture hooks now also dispatch through
|
||||
`PlatformServices`, keeping capture integration in the platform service while
|
||||
leaving non-Windows adapters as no-ops.
|
||||
|
||||
@@ -39,6 +39,11 @@ void set_opengl_viewport(std::int32_t x, std::int32_t y, std::int32_t width, std
|
||||
glViewport(static_cast<GLint>(x), static_cast<GLint>(y), static_cast<GLsizei>(width), static_cast<GLsizei>(height));
|
||||
}
|
||||
|
||||
void clear_opengl_mask(std::uint32_t mask) noexcept
|
||||
{
|
||||
glClear(static_cast<GLbitfield>(mask));
|
||||
}
|
||||
|
||||
void apply_vr_ui_viewport(pp::renderer::gl::OpenGlViewportRect viewport)
|
||||
{
|
||||
const auto status = pp::renderer::gl::apply_opengl_viewport(
|
||||
@@ -62,6 +67,30 @@ void apply_vr_ui_scissor_test(bool enabled)
|
||||
LOG("OpenGL VR UI scissor test failed: %s", status.message);
|
||||
}
|
||||
|
||||
void apply_vr_render_capability(std::uint32_t state, bool enabled)
|
||||
{
|
||||
const auto status = pp::renderer::gl::apply_opengl_capability(
|
||||
state,
|
||||
enabled,
|
||||
pp::renderer::gl::OpenGlCapabilityDispatch {
|
||||
.enable = enable_opengl_state,
|
||||
.disable = disable_opengl_state,
|
||||
});
|
||||
if (!status.ok())
|
||||
LOG("OpenGL VR render state failed: %s", status.message);
|
||||
}
|
||||
|
||||
void clear_vr_depth_buffer()
|
||||
{
|
||||
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
||||
pp::renderer::gl::framebuffer_depth_buffer_mask(),
|
||||
pp::renderer::gl::OpenGlBufferClearDispatch {
|
||||
.clear = clear_opengl_mask,
|
||||
});
|
||||
if (!status.ok())
|
||||
LOG("OpenGL VR depth clear failed: %s", status.message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool trigger_down = false;
|
||||
@@ -247,9 +276,9 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
auto blend = glIsEnabled(pp::renderer::gl::blend_state());
|
||||
auto depth = glIsEnabled(pp::renderer::gl::depth_test_state());
|
||||
|
||||
glDisable(pp::renderer::gl::blend_state());
|
||||
glDisable(pp::renderer::gl::depth_test_state());
|
||||
glClear(pp::renderer::gl::framebuffer_depth_buffer_mask());
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), false);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
clear_vr_depth_buffer();
|
||||
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
@@ -264,9 +293,9 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
m_face_plane.draw_fill();
|
||||
}
|
||||
|
||||
glEnable(pp::renderer::gl::blend_state());
|
||||
glEnable(pp::renderer::gl::depth_test_state());
|
||||
glClear(pp::renderer::gl::framebuffer_depth_buffer_mask());
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), true);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), true);
|
||||
clear_vr_depth_buffer();
|
||||
|
||||
for (size_t i = 0; i < canvas->m_canvas->m_layers.size(); i++)
|
||||
{
|
||||
@@ -411,7 +440,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
m_face_plane.draw_stroke();
|
||||
}
|
||||
|
||||
glDisable(pp::renderer::gl::depth_test_state());
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), false);
|
||||
// draw the brush
|
||||
/*
|
||||
auto mode = dynamic_cast<CanvasModePen*>(canvas->m_canvas->modes[(int)canvas->m_canvas->m_current_mode][0]);
|
||||
@@ -436,7 +465,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_size / height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush->m_tip_angle * (float)(M_PI * 2.0))
|
||||
);
|
||||
glEnable(pp::renderer::gl::blend_state());
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), true);
|
||||
set_active_texture_unit(0);
|
||||
auto& tex = *canvas->m_canvas->m_current_brush->m_tip_texture;
|
||||
tex.bind();
|
||||
@@ -510,7 +539,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_size * 100.f / height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush->m_tip_angle * (float)(M_PI * 2.0))
|
||||
);
|
||||
glEnable(pp::renderer::gl::blend_state());
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), true);
|
||||
set_active_texture_unit(0);
|
||||
auto& tex = *canvas->m_canvas->m_current_brush->m_tip_texture;
|
||||
tex.bind();
|
||||
@@ -538,8 +567,8 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
mode->on_Draw(ortho_proj, proj, camera);
|
||||
*/
|
||||
|
||||
blend ? glEnable(pp::renderer::gl::blend_state()) : glDisable(pp::renderer::gl::blend_state());
|
||||
depth ? glEnable(pp::renderer::gl::depth_test_state()) : glDisable(pp::renderer::gl::depth_test_state());
|
||||
apply_vr_render_capability(pp::renderer::gl::blend_state(), blend != 0U);
|
||||
apply_vr_render_capability(pp::renderer::gl::depth_test_state(), depth != 0U);
|
||||
sampler.unbind();
|
||||
}
|
||||
|
||||
|
||||
@@ -326,6 +326,35 @@ pp::foundation::Status apply_opengl_scissor_test(
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status apply_opengl_capability(
|
||||
std::uint32_t state,
|
||||
bool enabled,
|
||||
OpenGlCapabilityDispatch dispatch) noexcept
|
||||
{
|
||||
if (dispatch.enable == nullptr || dispatch.disable == nullptr) {
|
||||
return pp::foundation::Status::invalid_argument("OpenGL capability dispatch callbacks must not be null");
|
||||
}
|
||||
|
||||
if (enabled) {
|
||||
dispatch.enable(state);
|
||||
} else {
|
||||
dispatch.disable(state);
|
||||
}
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
pp::foundation::Status clear_opengl_buffers(
|
||||
std::uint32_t mask,
|
||||
OpenGlBufferClearDispatch dispatch) noexcept
|
||||
{
|
||||
if (dispatch.clear == nullptr) {
|
||||
return pp::foundation::Status::invalid_argument("OpenGL buffer clear dispatch callback must not be null");
|
||||
}
|
||||
|
||||
dispatch.clear(mask);
|
||||
return pp::foundation::Status::success();
|
||||
}
|
||||
|
||||
std::uint32_t extension_count_query() noexcept
|
||||
{
|
||||
return gl_num_extensions;
|
||||
|
||||
@@ -178,6 +178,15 @@ struct OpenGlScissorTestDispatch {
|
||||
OpenGlCapabilityFn disable = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlCapabilityDispatch {
|
||||
OpenGlCapabilityFn enable = nullptr;
|
||||
OpenGlCapabilityFn disable = nullptr;
|
||||
};
|
||||
|
||||
struct OpenGlBufferClearDispatch {
|
||||
OpenGlClearFn clear = nullptr;
|
||||
};
|
||||
|
||||
[[nodiscard]] OpenGlCapabilities detect_opengl_capabilities(
|
||||
std::span<const std::string_view> extensions,
|
||||
OpenGlRuntime runtime) noexcept;
|
||||
@@ -198,6 +207,13 @@ struct OpenGlScissorTestDispatch {
|
||||
[[nodiscard]] pp::foundation::Status apply_opengl_scissor_test(
|
||||
bool enabled,
|
||||
OpenGlScissorTestDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status apply_opengl_capability(
|
||||
std::uint32_t state,
|
||||
bool enabled,
|
||||
OpenGlCapabilityDispatch dispatch) noexcept;
|
||||
[[nodiscard]] pp::foundation::Status clear_opengl_buffers(
|
||||
std::uint32_t mask,
|
||||
OpenGlBufferClearDispatch dispatch) noexcept;
|
||||
|
||||
[[nodiscard]] std::uint32_t extension_count_query() noexcept;
|
||||
[[nodiscard]] std::uint32_t extension_string_name() noexcept;
|
||||
|
||||
@@ -991,6 +991,72 @@ void rejects_incomplete_scissor_test_dispatch(pp::tests::Harness& h)
|
||||
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void applies_generic_capability_dispatch(pp::tests::Harness& h)
|
||||
{
|
||||
recorded_state_calls.clear();
|
||||
|
||||
const auto enabled_status = pp::renderer::gl::apply_opengl_capability(
|
||||
0x0BE2U,
|
||||
true,
|
||||
pp::renderer::gl::OpenGlCapabilityDispatch {
|
||||
.enable = record_enable,
|
||||
.disable = record_disable,
|
||||
});
|
||||
const auto disabled_status = pp::renderer::gl::apply_opengl_capability(
|
||||
0x0B71U,
|
||||
false,
|
||||
pp::renderer::gl::OpenGlCapabilityDispatch {
|
||||
.enable = record_enable,
|
||||
.disable = record_disable,
|
||||
});
|
||||
|
||||
PP_EXPECT(h, enabled_status.ok());
|
||||
PP_EXPECT(h, disabled_status.ok());
|
||||
PP_EXPECT(h, recorded_state_calls.size() == 2U);
|
||||
PP_EXPECT(h, recorded_state_calls[0].kind == RecordedOpenGlStateCall::Kind::enable);
|
||||
PP_EXPECT(h, recorded_state_calls[0].first == 0x0BE2U);
|
||||
PP_EXPECT(h, recorded_state_calls[1].kind == RecordedOpenGlStateCall::Kind::disable);
|
||||
PP_EXPECT(h, recorded_state_calls[1].first == 0x0B71U);
|
||||
}
|
||||
|
||||
void rejects_incomplete_generic_capability_dispatch(pp::tests::Harness& h)
|
||||
{
|
||||
const auto status = pp::renderer::gl::apply_opengl_capability(
|
||||
0x0BE2U,
|
||||
true,
|
||||
pp::renderer::gl::OpenGlCapabilityDispatch {
|
||||
.enable = record_enable,
|
||||
});
|
||||
|
||||
PP_EXPECT(h, !status.ok());
|
||||
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void applies_buffer_clear_dispatch(pp::tests::Harness& h)
|
||||
{
|
||||
recorded_clear_calls.clear();
|
||||
|
||||
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
||||
0x00000100U,
|
||||
pp::renderer::gl::OpenGlBufferClearDispatch {
|
||||
.clear = record_clear,
|
||||
});
|
||||
|
||||
PP_EXPECT(h, status.ok());
|
||||
PP_EXPECT(h, recorded_clear_calls.size() == 1U);
|
||||
PP_EXPECT(h, recorded_clear_calls[0].mask == 0x00000100U);
|
||||
}
|
||||
|
||||
void rejects_incomplete_buffer_clear_dispatch(pp::tests::Harness& h)
|
||||
{
|
||||
const auto status = pp::renderer::gl::clear_opengl_buffers(
|
||||
0x00000100U,
|
||||
pp::renderer::gl::OpenGlBufferClearDispatch {});
|
||||
|
||||
PP_EXPECT(h, !status.ok());
|
||||
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
|
||||
}
|
||||
|
||||
void maps_renderer_viewports_and_scissors(pp::tests::Harness& h)
|
||||
{
|
||||
const auto viewport = pp::renderer::gl::viewport_for_renderer_viewport(
|
||||
@@ -1377,6 +1443,10 @@ int main()
|
||||
harness.run("rejects_incomplete_scissor_dispatch", rejects_incomplete_scissor_dispatch);
|
||||
harness.run("applies_scissor_test_dispatch", applies_scissor_test_dispatch);
|
||||
harness.run("rejects_incomplete_scissor_test_dispatch", rejects_incomplete_scissor_test_dispatch);
|
||||
harness.run("applies_generic_capability_dispatch", applies_generic_capability_dispatch);
|
||||
harness.run("rejects_incomplete_generic_capability_dispatch", rejects_incomplete_generic_capability_dispatch);
|
||||
harness.run("applies_buffer_clear_dispatch", applies_buffer_clear_dispatch);
|
||||
harness.run("rejects_incomplete_buffer_clear_dispatch", rejects_incomplete_buffer_clear_dispatch);
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user