Route RTT lifecycle through GL backend

This commit is contained in:
2026-06-04 21:47:19 +02:00
parent fc20851462
commit ce787ce186
7 changed files with 569 additions and 77 deletions

View File

@@ -55,6 +55,12 @@ struct RecordedOpenGlTextureImageCall {
bool sub_image = false;
};
struct RecordedOpenGlTextureParameterCall {
std::uint32_t target = 0;
std::uint32_t parameter = 0;
float value = 0.0F;
};
struct RecordedOpenGlFramebufferTextureCopyCall {
std::uint32_t target = 0;
std::int32_t level = 0;
@@ -204,6 +210,7 @@ std::vector<RecordedOpenGlBindingCall> recorded_binding_calls;
std::vector<std::uint32_t> recorded_generated_texture_counts;
std::vector<std::uint32_t> recorded_deleted_textures;
std::vector<RecordedOpenGlTextureImageCall> recorded_texture_image_calls;
std::vector<RecordedOpenGlTextureParameterCall> recorded_texture_parameter_calls;
std::vector<RecordedOpenGlFramebufferTextureCopyCall> recorded_framebuffer_texture_copy_calls;
std::vector<std::uint32_t> recorded_mipmap_targets;
std::vector<std::uint32_t> recorded_generated_framebuffer_counts;
@@ -545,6 +552,15 @@ void record_tex_sub_image_2d(
});
}
void record_tex_parameter_f(std::uint32_t target, std::uint32_t parameter, float value) noexcept
{
recorded_texture_parameter_calls.push_back(RecordedOpenGlTextureParameterCall {
.target = target,
.parameter = parameter,
.value = value,
});
}
void record_copy_tex_sub_image_2d(
std::uint32_t target,
std::int32_t level,
@@ -2607,6 +2623,75 @@ void deletes_texture_objects_through_dispatch(pp::tests::Harness& h)
PP_EXPECT(h, recorded_deleted_textures[2] == 11U);
}
void sets_texture_2d_parameters_through_dispatch(pp::tests::Harness& h)
{
recorded_binding_calls.clear();
recorded_texture_parameter_calls.clear();
constexpr std::array parameters {
pp::renderer::gl::OpenGlTextureParameter { .name = 0x2800U, .value = 0x2601U },
pp::renderer::gl::OpenGlTextureParameter { .name = 0x2801U, .value = 0x2600U },
};
const auto status = pp::renderer::gl::set_opengl_texture_2d_parameters(
37U,
parameters,
pp::renderer::gl::OpenGlTexture2DParameterDispatch {
.bind_texture = record_bind_texture,
.tex_parameter_f = record_tex_parameter_f,
});
PP_EXPECT(h, status.ok());
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_texture);
PP_EXPECT(h, recorded_binding_calls[0].first == 0x0DE1U);
PP_EXPECT(h, recorded_binding_calls[0].second == 37U);
PP_EXPECT(h, recorded_binding_calls[1].second == 0U);
PP_EXPECT(h, recorded_texture_parameter_calls.size() == 2U);
PP_EXPECT(h, recorded_texture_parameter_calls[0].target == 0x0DE1U);
PP_EXPECT(h, recorded_texture_parameter_calls[0].parameter == 0x2800U);
PP_EXPECT(h, recorded_texture_parameter_calls[0].value == 0x2601U);
PP_EXPECT(h, recorded_texture_parameter_calls[1].parameter == 0x2801U);
PP_EXPECT(h, recorded_texture_parameter_calls[1].value == 0x2600U);
}
void rejects_invalid_texture_2d_parameter_dispatch(pp::tests::Harness& h)
{
constexpr std::array parameters {
pp::renderer::gl::OpenGlTextureParameter { .name = 0x2800U, .value = 0x2601U },
};
constexpr std::array invalid_parameters {
pp::renderer::gl::OpenGlTextureParameter { .name = 0U, .value = 0x2601U },
};
const auto missing_dispatch = pp::renderer::gl::set_opengl_texture_2d_parameters(
37U,
parameters,
pp::renderer::gl::OpenGlTexture2DParameterDispatch {
.bind_texture = record_bind_texture,
});
const auto invalid_texture = pp::renderer::gl::set_opengl_texture_2d_parameters(
0U,
parameters,
pp::renderer::gl::OpenGlTexture2DParameterDispatch {
.bind_texture = record_bind_texture,
.tex_parameter_f = record_tex_parameter_f,
});
const auto invalid_parameter = pp::renderer::gl::set_opengl_texture_2d_parameters(
37U,
invalid_parameters,
pp::renderer::gl::OpenGlTexture2DParameterDispatch {
.bind_texture = record_bind_texture,
.tex_parameter_f = record_tex_parameter_f,
});
PP_EXPECT(h, !missing_dispatch.ok());
PP_EXPECT(h, missing_dispatch.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !invalid_texture.ok());
PP_EXPECT(h, invalid_texture.code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !invalid_parameter.ok());
PP_EXPECT(h, invalid_parameter.code == pp::foundation::StatusCode::invalid_argument);
}
void allocates_texture_cube_through_dispatch(pp::tests::Harness& h)
{
recorded_generated_texture_counts.clear();
@@ -4433,6 +4518,121 @@ void rejects_incomplete_framebuffer_binding_dispatch(pp::tests::Harness& h)
PP_EXPECT(h, restore.code == pp::foundation::StatusCode::invalid_argument);
}
void allocates_and_deletes_render_target_framebuffer(pp::tests::Harness& h)
{
recorded_integer_queries.clear();
recorded_generated_framebuffer_counts.clear();
recorded_binding_calls.clear();
recorded_framebuffer_attachment_calls.clear();
recorded_framebuffer_status_queries.clear();
recorded_deleted_framebuffers.clear();
configured_framebuffer_status = 0x8CD5U;
next_framebuffer_id = 44U;
const auto framebuffer = pp::renderer::gl::allocate_opengl_render_target_framebuffer(
27U,
81U,
pp::renderer::gl::OpenGlRenderTargetFramebufferAllocationDispatch {
.gen_framebuffers = record_gen_framebuffers,
.get_integer = record_get_integer,
.bind_framebuffer = record_bind_framebuffer,
.framebuffer_texture_2d = record_framebuffer_texture_2d,
.framebuffer_renderbuffer = record_framebuffer_renderbuffer,
.check_framebuffer_status = record_check_framebuffer_status,
});
const auto deleted = pp::renderer::gl::delete_opengl_framebuffer(
framebuffer.ok() ? framebuffer.value().framebuffer_id : 0U,
pp::renderer::gl::OpenGlFramebufferDeleteDispatch {
.delete_framebuffers = record_delete_framebuffers,
});
PP_EXPECT(h, framebuffer.ok());
PP_EXPECT(h, framebuffer.value().framebuffer_id == 44U);
PP_EXPECT(h, framebuffer.value().framebuffer_status == 0x8CD5U);
PP_EXPECT(h, deleted.ok());
PP_EXPECT(h, recorded_integer_queries.size() == 1U);
PP_EXPECT(h, recorded_integer_queries[0] == 0x8CA6U);
PP_EXPECT(h, recorded_generated_framebuffer_counts.size() == 1U);
PP_EXPECT(h, recorded_generated_framebuffer_counts[0] == 1U);
PP_EXPECT(h, recorded_binding_calls.size() == 2U);
PP_EXPECT(h, recorded_binding_calls[0].kind == RecordedOpenGlBindingCall::Kind::bind_framebuffer);
PP_EXPECT(h, recorded_binding_calls[0].first == 0x8D40U);
PP_EXPECT(h, recorded_binding_calls[0].second == 44U);
PP_EXPECT(h, recorded_binding_calls[1].first == 0x8D40U);
PP_EXPECT(h, recorded_binding_calls[1].second == 7U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls.size() == 2U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].target == 0x8D40U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].attachment == 0x8CE0U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].texture_target == 0x0DE1U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].texture == 27U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[1].attachment == 0x8D00U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[1].texture_target == 0x8D41U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[1].texture == 81U);
PP_EXPECT(h, recorded_framebuffer_status_queries.size() == 1U);
PP_EXPECT(h, recorded_framebuffer_status_queries[0] == 0x8D40U);
PP_EXPECT(h, recorded_deleted_framebuffers.size() == 1U);
PP_EXPECT(h, recorded_deleted_framebuffers[0] == 44U);
}
void reports_incomplete_render_target_framebuffer(pp::tests::Harness& h)
{
recorded_framebuffer_attachment_calls.clear();
configured_framebuffer_status = 0x8CD6U;
next_framebuffer_id = 45U;
const auto framebuffer = pp::renderer::gl::allocate_opengl_render_target_framebuffer(
27U,
0U,
pp::renderer::gl::OpenGlRenderTargetFramebufferAllocationDispatch {
.gen_framebuffers = record_gen_framebuffers,
.get_integer = record_get_integer,
.bind_framebuffer = record_bind_framebuffer,
.framebuffer_texture_2d = record_framebuffer_texture_2d,
.framebuffer_renderbuffer = record_framebuffer_renderbuffer,
.check_framebuffer_status = record_check_framebuffer_status,
});
PP_EXPECT(h, framebuffer.ok());
PP_EXPECT(h, framebuffer.value().framebuffer_id == 45U);
PP_EXPECT(h, framebuffer.value().framebuffer_status == 0x8CD6U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls.size() == 1U);
PP_EXPECT(h, recorded_framebuffer_attachment_calls[0].texture == 27U);
configured_framebuffer_status = 0x8CD5U;
}
void rejects_invalid_render_target_framebuffer_dispatch(pp::tests::Harness& h)
{
const auto missing_dispatch = pp::renderer::gl::allocate_opengl_render_target_framebuffer(
27U,
0U,
pp::renderer::gl::OpenGlRenderTargetFramebufferAllocationDispatch {
.gen_framebuffers = record_gen_framebuffers,
.get_integer = record_get_integer,
.bind_framebuffer = record_bind_framebuffer,
});
const auto invalid_texture = pp::renderer::gl::allocate_opengl_render_target_framebuffer(
0U,
0U,
pp::renderer::gl::OpenGlRenderTargetFramebufferAllocationDispatch {
.gen_framebuffers = record_gen_framebuffers,
.get_integer = record_get_integer,
.bind_framebuffer = record_bind_framebuffer,
.framebuffer_texture_2d = record_framebuffer_texture_2d,
.framebuffer_renderbuffer = record_framebuffer_renderbuffer,
.check_framebuffer_status = record_check_framebuffer_status,
});
const auto missing_delete_dispatch = pp::renderer::gl::delete_opengl_framebuffer(
44U,
pp::renderer::gl::OpenGlFramebufferDeleteDispatch {});
PP_EXPECT(h, !missing_dispatch.ok());
PP_EXPECT(h, missing_dispatch.status().code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !invalid_texture.ok());
PP_EXPECT(h, invalid_texture.status().code == pp::foundation::StatusCode::invalid_argument);
PP_EXPECT(h, !missing_delete_dispatch.ok());
PP_EXPECT(h, missing_delete_dispatch.code == pp::foundation::StatusCode::invalid_argument);
}
void allocates_attaches_and_deletes_depth_renderbuffer(pp::tests::Harness& h)
{
recorded_generated_renderbuffer_counts.clear();
@@ -4942,6 +5142,8 @@ int main()
harness.run("rejects_invalid_texture_2d_allocation", rejects_invalid_texture_2d_allocation);
harness.run("deletes_and_binds_texture_2d_through_dispatch", deletes_and_binds_texture_2d_through_dispatch);
harness.run("deletes_texture_objects_through_dispatch", deletes_texture_objects_through_dispatch);
harness.run("sets_texture_2d_parameters_through_dispatch", sets_texture_2d_parameters_through_dispatch);
harness.run("rejects_invalid_texture_2d_parameter_dispatch", rejects_invalid_texture_2d_parameter_dispatch);
harness.run("allocates_texture_cube_through_dispatch", allocates_texture_cube_through_dispatch);
harness.run("rejects_invalid_texture_cube_allocation", rejects_invalid_texture_cube_allocation);
harness.run("binds_texture_cube_through_dispatch", binds_texture_cube_through_dispatch);
@@ -4984,6 +5186,9 @@ int main()
harness.run("binds_framebuffer_draw_read_through_dispatch", binds_framebuffer_draw_read_through_dispatch);
harness.run("restores_framebuffer_draw_read_through_dispatch", restores_framebuffer_draw_read_through_dispatch);
harness.run("rejects_incomplete_framebuffer_binding_dispatch", rejects_incomplete_framebuffer_binding_dispatch);
harness.run("allocates_and_deletes_render_target_framebuffer", allocates_and_deletes_render_target_framebuffer);
harness.run("reports_incomplete_render_target_framebuffer", reports_incomplete_render_target_framebuffer);
harness.run("rejects_invalid_render_target_framebuffer_dispatch", rejects_invalid_render_target_framebuffer_dispatch);
harness.run("allocates_attaches_and_deletes_depth_renderbuffer", allocates_attaches_and_deletes_depth_renderbuffer);
harness.run("rejects_invalid_depth_renderbuffer_dispatch", rejects_invalid_depth_renderbuffer_dispatch);
harness.run("maps_renderer_viewports_and_scissors", maps_renderer_viewports_and_scissors);