#include "renderer_gl/opengl_capabilities.h" #include "renderer_gl/shader_bindings.h" #include "test_harness.h" #include #include #include #include namespace { void detects_common_extension_capabilities(pp::tests::Harness& h) { constexpr std::array extensions { "GL_EXT_shader_framebuffer_fetch", "GL_ARB_map_buffer_alignment", }; const auto capabilities = pp::renderer::gl::detect_opengl_capabilities( extensions, pp::renderer::gl::OpenGlRuntime {}); PP_EXPECT(h, capabilities.framebuffer_fetch); PP_EXPECT(h, capabilities.map_buffer_alignment); PP_EXPECT(h, !capabilities.float32_textures); PP_EXPECT(h, !capabilities.float16_textures); } void treats_desktop_gl_float_rendering_as_core(pp::tests::Harness& h) { const auto capabilities = pp::renderer::gl::detect_opengl_capabilities( {}, pp::renderer::gl::OpenGlRuntime { .desktop_gl = true }); PP_EXPECT(h, capabilities.float32_textures); PP_EXPECT(h, capabilities.float32_linear); PP_EXPECT(h, capabilities.float16_textures); } void detects_gles_texture_float_extensions(pp::tests::Harness& h) { constexpr std::array extensions { "GL_OES_texture_float", "GL_OES_texture_float_linear", "GL_EXT_color_buffer_half_float", }; const auto capabilities = pp::renderer::gl::detect_opengl_capabilities( extensions, pp::renderer::gl::OpenGlRuntime { .gles = true }); PP_EXPECT(h, capabilities.float32_textures); PP_EXPECT(h, capabilities.float32_linear); PP_EXPECT(h, capabilities.float16_textures); } void ignores_gles_texture_extensions_for_webgl_runtime(pp::tests::Harness& h) { constexpr std::array extensions { "GL_OES_texture_float", "GL_OES_texture_float_linear", "GL_EXT_color_buffer_half_float", }; const auto capabilities = pp::renderer::gl::detect_opengl_capabilities( extensions, pp::renderer::gl::OpenGlRuntime { .gles = true, .web = true }); PP_EXPECT(h, !capabilities.float32_textures); PP_EXPECT(h, !capabilities.float32_linear); PP_EXPECT(h, !capabilities.float16_textures); } void selects_texture_upload_type_from_internal_format(pp::tests::Harness& h) { constexpr std::uint32_t gl_unsigned_byte = 0x1401U; constexpr std::uint32_t gl_float = 0x1406U; constexpr std::uint32_t gl_half_float = 0x140BU; constexpr std::uint32_t gl_rgba8 = 0x8058U; constexpr std::uint32_t gl_rgba32f = 0x8814U; constexpr std::uint32_t gl_rgba16f = 0x881AU; PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba8) == gl_unsigned_byte); PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba32f) == gl_float); PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(gl_rgba16f) == gl_half_float); PP_EXPECT(h, pp::renderer::gl::texture_upload_type_for_internal_format(0U) == gl_unsigned_byte); } void maps_image_channel_count_to_texture_format(pp::tests::Harness& h) { constexpr std::uint32_t gl_red = 0x1903U; constexpr std::uint32_t gl_rgb = 0x1907U; constexpr std::uint32_t gl_rgba = 0x1908U; constexpr std::uint32_t gl_rg = 0x8227U; constexpr std::uint32_t gl_r8 = 0x8229U; constexpr std::uint32_t gl_rg8 = 0x822BU; constexpr std::uint32_t gl_rgb8 = 0x8051U; constexpr std::uint32_t gl_rgba8 = 0x8058U; const auto r = pp::renderer::gl::texture_format_for_channel_count(1U); const auto rg = pp::renderer::gl::texture_format_for_channel_count(2U); const auto rgb = pp::renderer::gl::texture_format_for_channel_count(3U); const auto rgba = pp::renderer::gl::texture_format_for_channel_count(4U); const auto invalid = pp::renderer::gl::texture_format_for_channel_count(5U); PP_EXPECT(h, r.internal_format == gl_r8); PP_EXPECT(h, r.pixel_format == gl_red); PP_EXPECT(h, rg.internal_format == gl_rg8); PP_EXPECT(h, rg.pixel_format == gl_rg); PP_EXPECT(h, rgb.internal_format == gl_rgb8); PP_EXPECT(h, rgb.pixel_format == gl_rgb); PP_EXPECT(h, rgba.internal_format == gl_rgba8); PP_EXPECT(h, rgba.pixel_format == gl_rgba); PP_EXPECT(h, invalid.channel_count == 0U); PP_EXPECT(h, invalid.internal_format == 0U); PP_EXPECT(h, invalid.pixel_format == 0U); } void names_framebuffer_status_codes(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD5U) == std::string_view("GL_FRAMEBUFFER_COMPLETE")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8219U) == std::string_view("GL_FRAMEBUFFER_UNDEFINED")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD6U) == std::string_view("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CD7U) == std::string_view("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDBU) == std::string_view("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDCU) == std::string_view("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8CDDU) == std::string_view("GL_FRAMEBUFFER_UNSUPPORTED")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0x8D56U) == std::string_view("GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE")); PP_EXPECT(h, pp::renderer::gl::framebuffer_status_name(0U) == std::string_view("UNKNOWN")); } void maps_shape_index_and_primitive_modes(pp::tests::Harness& h) { constexpr std::uint32_t gl_points = 0x0000U; constexpr std::uint32_t gl_lines = 0x0001U; constexpr std::uint32_t gl_triangles = 0x0004U; constexpr std::uint32_t gl_unsigned_short = 0x1403U; constexpr std::uint32_t gl_unsigned_int = 0x1405U; PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(2U) == gl_unsigned_short); PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(4U) == gl_unsigned_int); PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(1U) == 0U); PP_EXPECT(h, pp::renderer::gl::index_type_for_index_size(8U) == 0U); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(1U) == gl_points); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(2U) == gl_lines); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(3U) == gl_triangles); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_fill_count(99U) == gl_triangles); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(1U) == gl_points); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(2U) == gl_lines); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_stroke_count(99U) == gl_lines); } void exposes_shader_attribute_binding_catalog(pp::tests::Harness& h) { const auto bindings = pp::renderer::gl::panopainter_shader_attribute_bindings(); PP_EXPECT(h, bindings.size() == 5U); PP_EXPECT(h, pp::renderer::gl::validate_shader_attribute_bindings(bindings).ok()); PP_EXPECT(h, std::strcmp(bindings[0].name, "pos") == 0); PP_EXPECT(h, bindings[0].location == 0U); PP_EXPECT(h, std::strcmp(bindings[1].name, "uvs") == 0); PP_EXPECT(h, bindings[1].location == 1U); PP_EXPECT(h, std::strcmp(bindings[2].name, "uvs2") == 0); PP_EXPECT(h, bindings[2].location == 2U); PP_EXPECT(h, std::strcmp(bindings[3].name, "col") == 0); PP_EXPECT(h, bindings[3].location == 3U); PP_EXPECT(h, std::strcmp(bindings[4].name, "nor") == 0); PP_EXPECT(h, bindings[4].location == 3U); } void rejects_invalid_shader_attribute_binding_catalogs(pp::tests::Harness& h) { const std::array empty {}; const std::array unnamed { pp::renderer::gl::OpenGlAttributeBinding { .name = "", .location = 0 }, }; const std::array null_named { pp::renderer::gl::OpenGlAttributeBinding { .name = nullptr, .location = 0 }, }; const std::array duplicate_name { pp::renderer::gl::OpenGlAttributeBinding { .name = "pos", .location = 0 }, pp::renderer::gl::OpenGlAttributeBinding { .name = "pos", .location = 1 }, }; const std::array duplicate_location { pp::renderer::gl::OpenGlAttributeBinding { .name = "col", .location = 3 }, pp::renderer::gl::OpenGlAttributeBinding { .name = "nor", .location = 3 }, }; PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(empty).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(unnamed).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(null_named).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_attribute_bindings(duplicate_name).ok()); PP_EXPECT(h, pp::renderer::gl::validate_shader_attribute_bindings(duplicate_location).ok()); } } int main() { pp::tests::Harness harness; harness.run("detects_common_extension_capabilities", detects_common_extension_capabilities); harness.run("treats_desktop_gl_float_rendering_as_core", treats_desktop_gl_float_rendering_as_core); harness.run("detects_gles_texture_float_extensions", detects_gles_texture_float_extensions); harness.run("ignores_gles_texture_extensions_for_webgl_runtime", ignores_gles_texture_extensions_for_webgl_runtime); harness.run("selects_texture_upload_type_from_internal_format", selects_texture_upload_type_from_internal_format); harness.run("maps_image_channel_count_to_texture_format", maps_image_channel_count_to_texture_format); harness.run("names_framebuffer_status_codes", names_framebuffer_status_codes); harness.run("maps_shape_index_and_primitive_modes", maps_shape_index_and_primitive_modes); harness.run("exposes_shader_attribute_binding_catalog", exposes_shader_attribute_binding_catalog); harness.run("rejects_invalid_shader_attribute_binding_catalogs", rejects_invalid_shader_attribute_binding_catalogs); return harness.finish(); }