Route GL state snapshot through renderer GL

This commit is contained in:
2026-06-03 06:15:51 +02:00
parent 3e15b2f46c
commit 9971b2b7f2
6 changed files with 516 additions and 37 deletions

View File

@@ -24,11 +24,29 @@ struct RecordedOpenGlStateCall {
std::uint32_t second = 0;
};
struct RecordedOpenGlBindingCall {
enum class Kind {
bind_framebuffer,
use_program,
active_texture,
bind_texture,
bind_sampler,
};
Kind kind = Kind::bind_framebuffer;
std::uint32_t first = 0;
std::uint32_t second = 0;
};
std::vector<RecordedOpenGlStateCall> recorded_state_calls;
std::vector<std::uint32_t> recorded_string_queries;
std::vector<pp::renderer::gl::OpenGlDefaultClear> recorded_clear_calls;
std::vector<pp::renderer::gl::OpenGlViewportRect> recorded_viewport_calls;
std::vector<pp::renderer::gl::OpenGlScissorRect> recorded_scissor_calls;
std::vector<std::uint32_t> recorded_integer_queries;
std::vector<std::uint32_t> recorded_float_queries;
std::vector<std::uint32_t> recorded_active_texture_calls;
std::vector<RecordedOpenGlBindingCall> recorded_binding_calls;
void record_enable(std::uint32_t state) noexcept
{
@@ -116,6 +134,108 @@ void record_scissor(std::int32_t x, std::int32_t y, std::int32_t width, std::int
});
}
std::uint8_t record_is_enabled(std::uint32_t state) noexcept
{
if (state == 0x0BE2U) {
return 1U;
}
if (state == 0x0B71U) {
return 0U;
}
if (state == 0x0C11U) {
return 1U;
}
return 0U;
}
void record_get_integer(std::uint32_t name, std::int32_t* value) noexcept
{
recorded_integer_queries.push_back(name);
switch (name) {
case 0x0BA2U:
value[0] = 2;
value[1] = 4;
value[2] = 640;
value[3] = 320;
break;
case 0x8B8DU:
*value = 42;
break;
case 0x8CA6U:
*value = 7;
break;
case 0x8CAAU:
*value = 9;
break;
case 0x84E0U:
*value = 0x84C4;
break;
case 0x8514U:
*value = 88;
break;
case 0x8069U:
*value = 100 + static_cast<std::int32_t>(recorded_active_texture_calls.size());
break;
case 0x8919U:
*value = 200 + static_cast<std::int32_t>(recorded_active_texture_calls.size());
break;
default:
*value = -1;
break;
}
}
void record_get_float(std::uint32_t name, float* value) noexcept
{
recorded_float_queries.push_back(name);
if (name == 0x0C22U) {
value[0] = 0.25F;
value[1] = 0.5F;
value[2] = 0.75F;
value[3] = 1.0F;
}
}
void record_active_texture(std::uint32_t texture_unit) noexcept
{
recorded_active_texture_calls.push_back(texture_unit);
}
void record_bind_framebuffer(std::uint32_t target, std::uint32_t framebuffer) noexcept
{
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
.kind = RecordedOpenGlBindingCall::Kind::bind_framebuffer,
.first = target,
.second = framebuffer,
});
}
void record_use_program(std::uint32_t program) noexcept
{
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
.kind = RecordedOpenGlBindingCall::Kind::use_program,
.first = program,
});
}
void record_bind_texture(std::uint32_t target, std::uint32_t texture) noexcept
{
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
.kind = RecordedOpenGlBindingCall::Kind::bind_texture,
.first = target,
.second = texture,
});
}
void record_bind_sampler(std::uint32_t unit, std::uint32_t sampler) noexcept
{
recorded_binding_calls.push_back(RecordedOpenGlBindingCall {
.kind = RecordedOpenGlBindingCall::Kind::bind_sampler,
.first = unit,
.second = sampler,
});
}
void detects_common_extension_capabilities(pp::tests::Harness& h)
{
constexpr std::array<std::string_view, 2> extensions {
@@ -794,6 +914,146 @@ void rejects_incomplete_app_initialization_state_dispatch(pp::tests::Harness& h)
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
}
void snapshots_legacy_gl_state(pp::tests::Harness& h)
{
recorded_integer_queries.clear();
recorded_float_queries.clear();
recorded_active_texture_calls.clear();
const auto result = pp::renderer::gl::snapshot_opengl_state(
pp::renderer::gl::OpenGlStateSnapshotDispatch {
.is_enabled = record_is_enabled,
.get_integer = record_get_integer,
.get_float = record_get_float,
.active_texture = record_active_texture,
});
PP_EXPECT(h, result.ok());
const auto& state = result.value();
PP_EXPECT(h, state.blend_enabled == 1U);
PP_EXPECT(h, state.depth_test_enabled == 0U);
PP_EXPECT(h, state.scissor_test_enabled == 1U);
PP_EXPECT(h, state.viewport[0] == 2);
PP_EXPECT(h, state.viewport[1] == 4);
PP_EXPECT(h, state.viewport[2] == 640);
PP_EXPECT(h, state.viewport[3] == 320);
PP_EXPECT(h, state.clear_color[0] == 0.25F);
PP_EXPECT(h, state.clear_color[1] == 0.5F);
PP_EXPECT(h, state.clear_color[2] == 0.75F);
PP_EXPECT(h, state.clear_color[3] == 1.0F);
PP_EXPECT(h, state.program == 42);
PP_EXPECT(h, state.draw_framebuffer == 7);
PP_EXPECT(h, state.read_framebuffer == 9);
PP_EXPECT(h, state.active_texture == 0x84C4);
PP_EXPECT(h, state.cube_map_binding == 88);
PP_EXPECT(h, state.texture_2d_bindings[0] == 101);
PP_EXPECT(h, state.texture_2d_bindings[9] == 110);
PP_EXPECT(h, state.sampler_bindings[0] == 201);
PP_EXPECT(h, state.sampler_bindings[9] == 210);
PP_EXPECT(h, recorded_float_queries.size() == 1U);
PP_EXPECT(h, recorded_active_texture_calls.size() == 10U);
PP_EXPECT(h, recorded_active_texture_calls[0] == 0x84C0U);
PP_EXPECT(h, recorded_active_texture_calls[9] == 0x84C9U);
}
void rejects_incomplete_gl_state_snapshot_dispatch(pp::tests::Harness& h)
{
const auto result = pp::renderer::gl::snapshot_opengl_state(
pp::renderer::gl::OpenGlStateSnapshotDispatch {
.is_enabled = record_is_enabled,
.get_integer = record_get_integer,
.get_float = record_get_float,
});
PP_EXPECT(h, !result.ok());
PP_EXPECT(h, result.status().code == pp::foundation::StatusCode::invalid_argument);
}
void restores_legacy_gl_state(pp::tests::Harness& h)
{
recorded_state_calls.clear();
recorded_viewport_calls.clear();
recorded_clear_calls.clear();
recorded_active_texture_calls.clear();
recorded_binding_calls.clear();
pp::renderer::gl::OpenGlSavedState state {};
state.blend_enabled = 1U;
state.depth_test_enabled = 0U;
state.scissor_test_enabled = 1U;
state.viewport = { 3, 6, 800, 600 };
state.clear_color = { 0.1F, 0.2F, 0.3F, 0.4F };
state.program = 12;
state.draw_framebuffer = 21;
state.read_framebuffer = 22;
state.active_texture = 0x84C7;
state.cube_map_binding = 77;
for (std::size_t i = 0; i < state.texture_2d_bindings.size(); ++i) {
state.texture_2d_bindings[i] = 300 + static_cast<std::int32_t>(i);
state.sampler_bindings[i] = 400 + static_cast<std::int32_t>(i);
}
const auto status = pp::renderer::gl::restore_opengl_state(
state,
pp::renderer::gl::OpenGlStateRestoreDispatch {
.enable = record_enable,
.disable = record_disable,
.viewport = record_viewport,
.clear_color = record_clear_color,
.bind_framebuffer = record_bind_framebuffer,
.use_program = record_use_program,
.active_texture = record_active_texture,
.bind_texture = record_bind_texture,
.bind_sampler = record_bind_sampler,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_state_calls.size() == 3U);
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);
PP_EXPECT(h, recorded_state_calls[2].kind == RecordedOpenGlStateCall::Kind::enable);
PP_EXPECT(h, recorded_state_calls[2].first == 0x0C11U);
PP_EXPECT(h, recorded_viewport_calls.size() == 1U);
PP_EXPECT(h, recorded_viewport_calls[0].width == 800);
PP_EXPECT(h, recorded_clear_calls.size() == 1U);
PP_EXPECT(h, recorded_clear_calls[0].color[2] == 0.3F);
PP_EXPECT(h, recorded_binding_calls.size() == 24U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8CA9U);
PP_EXPECT(h, recorded_binding_calls[0].second == 21U);
PP_EXPECT(h, recorded_binding_calls[1].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8CA8U);
PP_EXPECT(h, recorded_binding_calls[1].second == 22U);
PP_EXPECT(h, recorded_binding_calls[2].kind == RecordedOpenGlBindingCall::Kind::use_program);
PP_EXPECT(h, recorded_binding_calls[2].first == 12U);
PP_EXPECT(h, recorded_active_texture_calls.size() == 11U);
PP_EXPECT(h, recorded_active_texture_calls[0] == 0x84C0U);
PP_EXPECT(h, recorded_active_texture_calls[9] == 0x84C9U);
PP_EXPECT(h, recorded_active_texture_calls[10] == 0x84C7U);
PP_EXPECT(h, recorded_binding_calls[3].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
PP_EXPECT(h, recorded_binding_calls[3].first == 0x0DE1U);
PP_EXPECT(h, recorded_binding_calls[3].second == 300U);
PP_EXPECT(h, recorded_binding_calls[23].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
PP_EXPECT(h, recorded_binding_calls[23].first == 0x8513U);
PP_EXPECT(h, recorded_binding_calls[23].second == 77U);
}
void rejects_incomplete_gl_state_restore_dispatch(pp::tests::Harness& h)
{
const auto status = pp::renderer::gl::restore_opengl_state(
pp::renderer::gl::OpenGlSavedState {},
pp::renderer::gl::OpenGlStateRestoreDispatch {
.enable = record_enable,
.disable = record_disable,
.viewport = record_viewport,
});
PP_EXPECT(h, !status.ok());
PP_EXPECT(h, status.code == pp::foundation::StatusCode::invalid_argument);
}
void queries_app_runtime_info(pp::tests::Harness& h)
{
recorded_string_queries.clear();
@@ -1433,6 +1693,10 @@ int main()
harness.run("maps_app_initialization_parameters", maps_app_initialization_parameters);
harness.run("applies_app_initialization_state", applies_app_initialization_state);
harness.run("rejects_incomplete_app_initialization_state_dispatch", rejects_incomplete_app_initialization_state_dispatch);
harness.run("snapshots_legacy_gl_state", snapshots_legacy_gl_state);
harness.run("rejects_incomplete_gl_state_snapshot_dispatch", rejects_incomplete_gl_state_snapshot_dispatch);
harness.run("restores_legacy_gl_state", restores_legacy_gl_state);
harness.run("rejects_incomplete_gl_state_restore_dispatch", rejects_incomplete_gl_state_restore_dispatch);
harness.run("queries_app_runtime_info", queries_app_runtime_info);
harness.run("rejects_incomplete_app_runtime_info_dispatch", rejects_incomplete_app_runtime_info_dispatch);
harness.run("clears_app_default_target", clears_app_default_target);