#include "renderer_gl/opengl_capabilities.h" #include "renderer_gl/shader_bindings.h" #include "test_harness.h" #include #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", }; PP_EXPECT(h, pp::renderer::gl::extension_count_query() == 0x821DU); PP_EXPECT(h, pp::renderer::gl::extension_string_name() == 0x1F03U); PP_EXPECT(h, pp::renderer::gl::no_error_code() == 0U); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0U) == std::string_view("GL_NO_ERROR")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0500U) == std::string_view("GL_INVALID_ENUM")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0501U) == std::string_view("GL_INVALID_VALUE")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0502U) == std::string_view("GL_INVALID_OPERATION")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0505U) == std::string_view("GL_OUT_OF_MEMORY")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0x0506U) == std::string_view("GL_INVALID_FRAMEBUFFER_OPERATION")); PP_EXPECT(h, pp::renderer::gl::opengl_error_name(0xffffffffU) == std::string_view("Unknown")); 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); const auto features = pp::renderer::gl::render_device_features(capabilities); PP_EXPECT(h, features.framebuffer_fetch); PP_EXPECT(h, !features.explicit_texture_transitions); PP_EXPECT(h, features.texture_copy); PP_EXPECT(h, features.render_target_blit); PP_EXPECT(h, features.frame_capture); PP_EXPECT(h, !features.float16_render_targets); PP_EXPECT(h, !features.float32_render_targets); } 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); const auto features = pp::renderer::gl::render_device_features(capabilities); PP_EXPECT(h, features.float16_render_targets); PP_EXPECT(h, features.float32_render_targets); } 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); PP_EXPECT(h, pp::renderer::gl::unsigned_byte_component_type() == gl_unsigned_byte); PP_EXPECT(h, pp::renderer::gl::rgba_pixel_format() == 0x1908U); } 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 maps_renderer_texture_formats_to_opengl_tokens(pp::tests::Harness& h) { const auto rgba8 = pp::renderer::gl::texture_format_for_renderer_format(pp::renderer::TextureFormat::rgba8); const auto r8 = pp::renderer::gl::texture_format_for_renderer_format(pp::renderer::TextureFormat::r8); const auto depth_stencil = pp::renderer::gl::texture_format_for_renderer_format( pp::renderer::TextureFormat::depth24_stencil8); const auto invalid = pp::renderer::gl::texture_format_for_renderer_format( static_cast(255U)); PP_EXPECT(h, rgba8.internal_format == 0x8058U); PP_EXPECT(h, rgba8.pixel_format == 0x1908U); PP_EXPECT(h, rgba8.component_type == 0x1401U); PP_EXPECT(h, rgba8.bytes_per_pixel == 4U); PP_EXPECT(h, r8.internal_format == 0x8229U); PP_EXPECT(h, r8.pixel_format == 0x1903U); PP_EXPECT(h, r8.component_type == 0x1401U); PP_EXPECT(h, r8.bytes_per_pixel == 1U); PP_EXPECT(h, depth_stencil.internal_format == 0x88F0U); PP_EXPECT(h, depth_stencil.pixel_format == 0x84F9U); PP_EXPECT(h, depth_stencil.component_type == 0x84FAU); PP_EXPECT(h, depth_stencil.bytes_per_pixel == 4U); PP_EXPECT(h, invalid.internal_format == 0U); PP_EXPECT(h, invalid.pixel_format == 0U); PP_EXPECT(h, invalid.component_type == 0U); PP_EXPECT(h, invalid.bytes_per_pixel == 0U); } void maps_readback_formats(pp::tests::Harness& h) { const auto rgba8 = pp::renderer::gl::rgba8_readback_format(); const auto rgba32f = pp::renderer::gl::rgba32f_readback_format(); PP_EXPECT(h, rgba8.pixel_format == 0x1908U); PP_EXPECT(h, rgba8.component_type == 0x1401U); PP_EXPECT(h, rgba8.bytes_per_pixel == 4U); PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba8, 3U, 5U) == 60U); PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba8, 0U, 5U) == 0U); PP_EXPECT(h, rgba32f.pixel_format == 0x1908U); PP_EXPECT(h, rgba32f.component_type == 0x1406U); PP_EXPECT(h, rgba32f.bytes_per_pixel == 16U); PP_EXPECT(h, pp::renderer::gl::readback_byte_count(rgba32f, 3U, 5U) == 240U); const auto invalid_format = pp::renderer::gl::OpenGlReadbackFormat { .pixel_format = rgba8.pixel_format, .component_type = rgba8.component_type, .bytes_per_pixel = 0U, }; const auto overflowing_format = pp::renderer::gl::OpenGlReadbackFormat { .pixel_format = rgba8.pixel_format, .component_type = rgba8.component_type, .bytes_per_pixel = std::numeric_limits::max(), }; PP_EXPECT(h, pp::renderer::gl::readback_byte_count(invalid_format, 1U, 1U) == 0U); PP_EXPECT(h, pp::renderer::gl::readback_byte_count( overflowing_format, std::numeric_limits::max(), std::numeric_limits::max()) == 0U); } void maps_pixel_buffer_parameters(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::pixel_pack_buffer_target() == 0x88EBU); PP_EXPECT(h, pp::renderer::gl::pixel_unpack_buffer_target() == 0x88ECU); PP_EXPECT(h, pp::renderer::gl::pixel_buffer_stream_read_usage() == 0x88E1U); PP_EXPECT(h, pp::renderer::gl::pixel_buffer_map_read_access() == 0x0001U); } void names_framebuffer_status_codes(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::framebuffer_complete_status() == 0x8CD5U); 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_framebuffer_render_target_parameters(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::texture_2d_target() == 0x0DE1U); PP_EXPECT(h, pp::renderer::gl::renderbuffer_target() == 0x8D41U); PP_EXPECT(h, pp::renderer::gl::depth_component24_format() == 0x81A6U); PP_EXPECT(h, pp::renderer::gl::framebuffer_target() == 0x8D40U); PP_EXPECT(h, pp::renderer::gl::draw_framebuffer_target() == 0x8CA9U); PP_EXPECT(h, pp::renderer::gl::read_framebuffer_target() == 0x8CA8U); PP_EXPECT(h, pp::renderer::gl::draw_framebuffer_binding_query() == 0x8CA6U); PP_EXPECT(h, pp::renderer::gl::read_framebuffer_binding_query() == 0x8CAAU); PP_EXPECT(h, pp::renderer::gl::framebuffer_color_attachment() == 0x8CE0U); PP_EXPECT(h, pp::renderer::gl::framebuffer_depth_attachment() == 0x8D00U); PP_EXPECT(h, pp::renderer::gl::default_framebuffer_id() == 0U); } void maps_framebuffer_blit_parameters(pp::tests::Harness& h) { const auto nearest = pp::renderer::gl::blit_filter_for_renderer_filter(pp::renderer::BlitFilter::nearest); const auto linear = pp::renderer::gl::blit_filter_for_renderer_filter(pp::renderer::BlitFilter::linear); const auto invalid = pp::renderer::gl::blit_filter_for_renderer_filter( static_cast(255U)); PP_EXPECT(h, pp::renderer::gl::framebuffer_color_buffer_mask() == 0x00004000U); PP_EXPECT(h, pp::renderer::gl::framebuffer_depth_buffer_mask() == 0x00000100U); PP_EXPECT(h, pp::renderer::gl::framebuffer_stencil_buffer_mask() == 0x00000400U); PP_EXPECT(h, pp::renderer::gl::color_write_mask_query() == 0x0C23U); PP_EXPECT(h, pp::renderer::gl::framebuffer_blit_filter(true) == 0x2601U); PP_EXPECT(h, pp::renderer::gl::framebuffer_blit_filter(false) == 0x2600U); PP_EXPECT(h, nearest.supported); PP_EXPECT(h, nearest.value == 0x2600U); PP_EXPECT(h, linear.supported); PP_EXPECT(h, linear.value == 0x2601U); PP_EXPECT(h, !invalid.supported); PP_EXPECT(h, invalid.value == 0U); } void maps_render_pass_clear_masks(pp::tests::Harness& h) { const auto no_clear = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc { .clear_color_enabled = false, .clear_color = {}, .clear_depth_enabled = false, .clear_stencil_enabled = false, }); const auto color_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc { .clear_color_enabled = true, .clear_color = {}, .clear_depth_enabled = false, .clear_stencil_enabled = false, }); const auto depth_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc { .clear_color_enabled = false, .clear_color = {}, .clear_depth_enabled = true, .clear_stencil_enabled = false, }); const auto stencil_only = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc { .clear_color_enabled = false, .clear_color = {}, .clear_depth_enabled = false, .clear_stencil_enabled = true, }); const auto all_buffers = pp::renderer::gl::clear_mask_for_render_pass(pp::renderer::RenderPassDesc { .clear_color_enabled = true, .clear_color = {}, .clear_depth_enabled = true, .clear_stencil_enabled = true, }); PP_EXPECT(h, no_clear == 0U); PP_EXPECT(h, color_only == 0x00004000U); PP_EXPECT(h, depth_only == 0x00000100U); PP_EXPECT(h, stencil_only == 0x00000400U); PP_EXPECT(h, all_buffers == 0x00004500U); } void maps_renderer_primitive_topologies_to_draw_modes(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology( pp::renderer::PrimitiveTopology::triangles) == 0x0004U); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology( pp::renderer::PrimitiveTopology::triangle_strip) == 0x0005U); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology( pp::renderer::PrimitiveTopology::lines) == 0x0001U); PP_EXPECT(h, pp::renderer::gl::primitive_mode_for_renderer_topology( static_cast(255U)) == 0U); } 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; constexpr std::uint32_t gl_float = 0x1406U; 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); PP_EXPECT(h, pp::renderer::gl::array_buffer_target() == 0x8892U); PP_EXPECT(h, pp::renderer::gl::element_array_buffer_target() == 0x8893U); PP_EXPECT(h, pp::renderer::gl::static_draw_buffer_usage() == 0x88E4U); PP_EXPECT(h, pp::renderer::gl::vertex_attribute_float_component_type() == gl_float); PP_EXPECT(h, pp::renderer::gl::vertex_attribute_not_normalized() == 0U); } void maps_panopainter_cube_faces_to_texture_targets(pp::tests::Harness& h) { const auto targets = pp::renderer::gl::panopainter_cube_face_texture_targets(); PP_EXPECT(h, pp::renderer::gl::texture_cube_map_target() == 0x8513U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(0U) == 0x8515U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(1U) == 0x8516U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(2U) == 0x8517U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(3U) == 0x8518U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(4U) == 0x8519U); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(5U) == 0x851AU); PP_EXPECT(h, pp::renderer::gl::cube_map_allocation_face_texture_target(6U) == 0U); PP_EXPECT(h, targets.size() == 6U); PP_EXPECT(h, targets[0] == 0x851AU); PP_EXPECT(h, targets[1] == 0x8516U); PP_EXPECT(h, targets[2] == 0x8519U); PP_EXPECT(h, targets[3] == 0x8515U); PP_EXPECT(h, targets[4] == 0x8518U); PP_EXPECT(h, targets[5] == 0x8517U); PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(0U) == 0x851AU); PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(5U) == 0x8517U); PP_EXPECT(h, pp::renderer::gl::cube_face_texture_target(6U) == 0U); } void exposes_default_render_target_texture_parameters(pp::tests::Harness& h) { const auto parameters = pp::renderer::gl::default_render_target_texture_parameters(); PP_EXPECT(h, parameters.size() == 4U); PP_EXPECT(h, parameters[0].name == 0x2800U); PP_EXPECT(h, parameters[0].value == 0x2601U); PP_EXPECT(h, parameters[1].name == 0x2801U); PP_EXPECT(h, parameters[1].value == 0x2601U); PP_EXPECT(h, parameters[2].name == 0x2802U); PP_EXPECT(h, parameters[2].value == 0x812FU); PP_EXPECT(h, parameters[3].name == 0x2803U); PP_EXPECT(h, parameters[3].value == 0x812FU); } void maps_sampler_parameters(pp::tests::Harness& h) { const auto parameters = pp::renderer::gl::sampler_parameters_for_filter_wrap(0x2601U, 0x812FU); PP_EXPECT(h, parameters.size() == 5U); PP_EXPECT(h, parameters[0].name == 0x2802U); PP_EXPECT(h, parameters[0].value == 0x812FU); PP_EXPECT(h, parameters[1].name == 0x2803U); PP_EXPECT(h, parameters[1].value == 0x812FU); PP_EXPECT(h, parameters[2].name == 0x8072U); PP_EXPECT(h, parameters[2].value == 0x812FU); PP_EXPECT(h, parameters[3].name == 0x2801U); PP_EXPECT(h, parameters[3].value == 0x2601U); PP_EXPECT(h, parameters[4].name == 0x2800U); PP_EXPECT(h, parameters[4].value == 0x2601U); const auto filters = pp::renderer::gl::sampler_filter_parameters(0x2600U, 0x2601U); PP_EXPECT(h, filters.size() == 2U); PP_EXPECT(h, filters[0].name == 0x2801U); PP_EXPECT(h, filters[0].value == 0x2600U); PP_EXPECT(h, filters[1].name == 0x2800U); PP_EXPECT(h, filters[1].value == 0x2601U); PP_EXPECT(h, pp::renderer::gl::sampler_border_color_parameter_name() == 0x1004U); } void maps_renderer_sampler_tokens(pp::tests::Harness& h) { const auto nearest = pp::renderer::gl::sampler_filter_for_renderer_filter( pp::renderer::SamplerFilter::nearest); const auto linear = pp::renderer::gl::sampler_filter_for_renderer_filter( pp::renderer::SamplerFilter::linear); const auto invalid_filter = pp::renderer::gl::sampler_filter_for_renderer_filter( static_cast(255U)); const auto clamp_to_edge = pp::renderer::gl::sampler_address_mode_for_renderer_mode( pp::renderer::SamplerAddressMode::clamp_to_edge); const auto repeat = pp::renderer::gl::sampler_address_mode_for_renderer_mode( pp::renderer::SamplerAddressMode::repeat); const auto mirrored_repeat = pp::renderer::gl::sampler_address_mode_for_renderer_mode( pp::renderer::SamplerAddressMode::mirrored_repeat); const auto clamp_to_border = pp::renderer::gl::sampler_address_mode_for_renderer_mode( pp::renderer::SamplerAddressMode::clamp_to_border); const auto invalid_mode = pp::renderer::gl::sampler_address_mode_for_renderer_mode( static_cast(255U)); PP_EXPECT(h, nearest.supported); PP_EXPECT(h, nearest.value == 0x2600U); PP_EXPECT(h, linear.supported); PP_EXPECT(h, linear.value == 0x2601U); PP_EXPECT(h, !invalid_filter.supported); PP_EXPECT(h, invalid_filter.value == 0U); PP_EXPECT(h, clamp_to_edge.supported); PP_EXPECT(h, clamp_to_edge.value == 0x812FU); PP_EXPECT(h, repeat.supported); PP_EXPECT(h, repeat.value == 0x2901U); PP_EXPECT(h, mirrored_repeat.supported); PP_EXPECT(h, mirrored_repeat.value == 0x8370U); PP_EXPECT(h, clamp_to_border.supported); PP_EXPECT(h, clamp_to_border.value == 0x812DU); PP_EXPECT(h, !invalid_mode.supported); PP_EXPECT(h, invalid_mode.value == 0U); } void exposes_shader_attribute_binding_catalog(pp::tests::Harness& h) { const auto bindings = pp::renderer::gl::panopainter_shader_attribute_bindings(); PP_EXPECT(h, pp::renderer::gl::vertex_shader_stage() == 0x8B31U); PP_EXPECT(h, pp::renderer::gl::fragment_shader_stage() == 0x8B30U); PP_EXPECT(h, pp::renderer::gl::shader_compile_status_query() == 0x8B81U); PP_EXPECT(h, pp::renderer::gl::program_link_status_query() == 0x8B82U); PP_EXPECT(h, pp::renderer::gl::active_uniform_count_query() == 0x8B86U); PP_EXPECT(h, pp::renderer::gl::matrix_uniform_not_transposed() == 0U); 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 maps_app_initialization_parameters(pp::tests::Harness& h) { PP_EXPECT(h, pp::renderer::gl::debug_severity_notification() == 0x826BU); PP_EXPECT(h, pp::renderer::gl::debug_severity_low() == 0x9148U); PP_EXPECT(h, pp::renderer::gl::debug_severity_medium() == 0x9147U); PP_EXPECT(h, pp::renderer::gl::debug_severity_high() == 0x9146U); PP_EXPECT(h, pp::renderer::gl::debug_output_state() == 0x92E0U); PP_EXPECT(h, pp::renderer::gl::debug_output_synchronous_state() == 0x8242U); PP_EXPECT(h, pp::renderer::gl::version_string_name() == 0x1F02U); PP_EXPECT(h, pp::renderer::gl::vendor_string_name() == 0x1F00U); PP_EXPECT(h, pp::renderer::gl::renderer_string_name() == 0x1F01U); PP_EXPECT(h, pp::renderer::gl::shading_language_version_string_name() == 0x8B8CU); PP_EXPECT(h, pp::renderer::gl::viewport_query() == 0x0BA2U); PP_EXPECT(h, pp::renderer::gl::color_clear_value_query() == 0x0C22U); PP_EXPECT(h, pp::renderer::gl::current_program_query() == 0x8B8DU); PP_EXPECT(h, pp::renderer::gl::active_texture_query() == 0x84E0U); PP_EXPECT(h, pp::renderer::gl::texture_binding_2d_query() == 0x8069U); PP_EXPECT(h, pp::renderer::gl::texture_binding_cube_map_query() == 0x8514U); PP_EXPECT(h, pp::renderer::gl::sampler_binding_query() == 0x8919U); PP_EXPECT(h, pp::renderer::gl::blend_state() == 0x0BE2U); PP_EXPECT(h, pp::renderer::gl::depth_test_state() == 0x0B71U); PP_EXPECT(h, pp::renderer::gl::scissor_test_state() == 0x0C11U); PP_EXPECT(h, pp::renderer::gl::program_point_size_state() == 0x8642U); PP_EXPECT(h, pp::renderer::gl::line_smooth_state() == 0x0B20U); PP_EXPECT(h, pp::renderer::gl::source_alpha_blend_factor() == 0x0302U); PP_EXPECT(h, pp::renderer::gl::one_minus_source_alpha_blend_factor() == 0x0303U); PP_EXPECT(h, pp::renderer::gl::add_blend_equation() == 0x8006U); PP_EXPECT(h, pp::renderer::gl::max_blend_equation() == 0x8008U); PP_EXPECT(h, pp::renderer::gl::rgba8_internal_format() == 0x8058U); PP_EXPECT(h, pp::renderer::gl::rgba16f_internal_format() == 0x881AU); PP_EXPECT(h, pp::renderer::gl::rgba32f_internal_format() == 0x8814U); PP_EXPECT(h, pp::renderer::gl::color_write_disabled() == 0U); PP_EXPECT(h, pp::renderer::gl::color_write_enabled() == 1U); PP_EXPECT(h, pp::renderer::gl::linear_texture_filter() == 0x2601U); PP_EXPECT(h, pp::renderer::gl::linear_mipmap_linear_texture_filter() == 0x2703U); PP_EXPECT(h, pp::renderer::gl::nearest_texture_filter() == 0x2600U); PP_EXPECT(h, pp::renderer::gl::repeat_texture_wrap() == 0x2901U); PP_EXPECT(h, pp::renderer::gl::clamp_to_edge_texture_wrap() == 0x812FU); PP_EXPECT(h, pp::renderer::gl::clamp_to_border_texture_wrap() == 0x812DU); PP_EXPECT(h, pp::renderer::gl::active_texture_unit(0U) == 0x84C0U); PP_EXPECT(h, pp::renderer::gl::active_texture_unit(4U) == 0x84C4U); } 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); const auto one = pp::renderer::gl::blend_factor_for_renderer_factor(pp::renderer::BlendFactor::one); const auto source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( pp::renderer::BlendFactor::source_alpha); const auto one_minus_source_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( pp::renderer::BlendFactor::one_minus_source_alpha); const auto destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( pp::renderer::BlendFactor::destination_alpha); const auto one_minus_destination_alpha = pp::renderer::gl::blend_factor_for_renderer_factor( pp::renderer::BlendFactor::one_minus_destination_alpha); const auto invalid_factor = pp::renderer::gl::blend_factor_for_renderer_factor( static_cast(255U)); const auto add = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::add); const auto subtract = pp::renderer::gl::blend_equation_for_renderer_op(pp::renderer::BlendOp::subtract); const auto reverse_subtract = pp::renderer::gl::blend_equation_for_renderer_op( pp::renderer::BlendOp::reverse_subtract); const auto invalid_op = pp::renderer::gl::blend_equation_for_renderer_op( static_cast(255U)); PP_EXPECT(h, zero.supported); PP_EXPECT(h, zero.value == 0U); PP_EXPECT(h, one.supported); PP_EXPECT(h, one.value == 1U); PP_EXPECT(h, source_alpha.supported); PP_EXPECT(h, source_alpha.value == 0x0302U); PP_EXPECT(h, one_minus_source_alpha.supported); PP_EXPECT(h, one_minus_source_alpha.value == 0x0303U); PP_EXPECT(h, destination_alpha.supported); PP_EXPECT(h, destination_alpha.value == 0x0304U); PP_EXPECT(h, one_minus_destination_alpha.supported); PP_EXPECT(h, one_minus_destination_alpha.value == 0x0305U); PP_EXPECT(h, !invalid_factor.supported); PP_EXPECT(h, invalid_factor.value == 0U); PP_EXPECT(h, add.supported); PP_EXPECT(h, add.value == 0x8006U); PP_EXPECT(h, subtract.supported); PP_EXPECT(h, subtract.value == 0x800AU); PP_EXPECT(h, reverse_subtract.supported); PP_EXPECT(h, reverse_subtract.value == 0x800BU); PP_EXPECT(h, !invalid_op.supported); PP_EXPECT(h, invalid_op.value == 0U); } void maps_renderer_color_write_masks(pp::tests::Harness& h) { const auto default_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( pp::renderer::BlendState {}); const auto mixed_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( pp::renderer::BlendState { .write_r = true, .write_g = false, .write_b = true, .write_a = false }); const auto disabled_mask = pp::renderer::gl::color_write_mask_for_renderer_blend_state( pp::renderer::BlendState { .write_r = false, .write_g = false, .write_b = false, .write_a = false }); PP_EXPECT(h, default_mask.r == 1U); PP_EXPECT(h, default_mask.g == 1U); PP_EXPECT(h, default_mask.b == 1U); PP_EXPECT(h, default_mask.a == 1U); PP_EXPECT(h, mixed_mask.r == 1U); PP_EXPECT(h, mixed_mask.g == 0U); PP_EXPECT(h, mixed_mask.b == 1U); PP_EXPECT(h, mixed_mask.a == 0U); PP_EXPECT(h, disabled_mask.r == 0U); PP_EXPECT(h, disabled_mask.g == 0U); PP_EXPECT(h, disabled_mask.b == 0U); PP_EXPECT(h, disabled_mask.a == 0U); } void maps_renderer_blend_states(pp::tests::Harness& h) { const auto disabled = pp::renderer::gl::blend_state_for_renderer_blend_state( pp::renderer::BlendState {}); const auto alpha_blend = pp::renderer::gl::blend_state_for_renderer_blend_state( pp::renderer::BlendState { .enabled = true, .source_color = pp::renderer::BlendFactor::source_alpha, .destination_color = pp::renderer::BlendFactor::one_minus_source_alpha, .color_op = pp::renderer::BlendOp::add, .source_alpha = pp::renderer::BlendFactor::one, .destination_alpha = pp::renderer::BlendFactor::one_minus_destination_alpha, .alpha_op = pp::renderer::BlendOp::reverse_subtract, .write_r = true, .write_g = false, .write_b = true, .write_a = false, }); const auto invalid_factor = pp::renderer::gl::blend_state_for_renderer_blend_state( pp::renderer::BlendState { .enabled = true, .source_color = static_cast(255U), }); const auto invalid_op = pp::renderer::gl::blend_state_for_renderer_blend_state( pp::renderer::BlendState { .enabled = true, .color_op = static_cast(255U), }); PP_EXPECT(h, disabled.supported); PP_EXPECT(h, disabled.enabled == 0U); PP_EXPECT(h, disabled.source_color_factor == 1U); PP_EXPECT(h, disabled.destination_color_factor == 0U); PP_EXPECT(h, disabled.color_equation == 0x8006U); PP_EXPECT(h, disabled.source_alpha_factor == 1U); PP_EXPECT(h, disabled.destination_alpha_factor == 0U); PP_EXPECT(h, disabled.alpha_equation == 0x8006U); PP_EXPECT(h, disabled.color_write_mask.r == 1U); PP_EXPECT(h, disabled.color_write_mask.g == 1U); PP_EXPECT(h, disabled.color_write_mask.b == 1U); PP_EXPECT(h, disabled.color_write_mask.a == 1U); PP_EXPECT(h, alpha_blend.supported); PP_EXPECT(h, alpha_blend.enabled == 1U); PP_EXPECT(h, alpha_blend.source_color_factor == 0x0302U); PP_EXPECT(h, alpha_blend.destination_color_factor == 0x0303U); PP_EXPECT(h, alpha_blend.color_equation == 0x8006U); PP_EXPECT(h, alpha_blend.source_alpha_factor == 1U); PP_EXPECT(h, alpha_blend.destination_alpha_factor == 0x0305U); PP_EXPECT(h, alpha_blend.alpha_equation == 0x800BU); PP_EXPECT(h, alpha_blend.color_write_mask.r == 1U); PP_EXPECT(h, alpha_blend.color_write_mask.g == 0U); PP_EXPECT(h, alpha_blend.color_write_mask.b == 1U); PP_EXPECT(h, alpha_blend.color_write_mask.a == 0U); PP_EXPECT(h, !invalid_factor.supported); PP_EXPECT(h, invalid_factor.enabled == 1U); PP_EXPECT(h, invalid_factor.source_color_factor == 0U); PP_EXPECT(h, !invalid_op.supported); PP_EXPECT(h, invalid_op.color_equation == 0U); } void maps_renderer_depth_compare_tokens(pp::tests::Harness& h) { const auto never = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::never); const auto less = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::less); const auto equal = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::equal); const auto less_or_equal = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::less_or_equal); const auto greater = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::greater); const auto not_equal = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::not_equal); const auto greater_or_equal = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::greater_or_equal); const auto always = pp::renderer::gl::compare_function_for_renderer_compare_op( pp::renderer::CompareOp::always); const auto invalid = pp::renderer::gl::compare_function_for_renderer_compare_op( static_cast(255U)); PP_EXPECT(h, never.supported); PP_EXPECT(h, never.value == 0x0200U); PP_EXPECT(h, less.supported); PP_EXPECT(h, less.value == 0x0201U); PP_EXPECT(h, equal.supported); PP_EXPECT(h, equal.value == 0x0202U); PP_EXPECT(h, less_or_equal.supported); PP_EXPECT(h, less_or_equal.value == 0x0203U); PP_EXPECT(h, greater.supported); PP_EXPECT(h, greater.value == 0x0204U); PP_EXPECT(h, not_equal.supported); PP_EXPECT(h, not_equal.value == 0x0205U); PP_EXPECT(h, greater_or_equal.supported); PP_EXPECT(h, greater_or_equal.value == 0x0206U); PP_EXPECT(h, always.supported); PP_EXPECT(h, always.value == 0x0207U); PP_EXPECT(h, !invalid.supported); PP_EXPECT(h, invalid.value == 0U); } void maps_renderer_depth_states(pp::tests::Harness& h) { const auto disabled = pp::renderer::gl::depth_state_for_renderer_depth_state( pp::renderer::DepthState {}); const auto read_write = pp::renderer::gl::depth_state_for_renderer_depth_state( pp::renderer::DepthState { .test_enabled = true, .write_enabled = true, .compare = pp::renderer::CompareOp::greater, }); const auto invalid_compare = pp::renderer::gl::depth_state_for_renderer_depth_state( pp::renderer::DepthState { .test_enabled = true, .write_enabled = false, .compare = static_cast(255U), }); PP_EXPECT(h, disabled.supported); PP_EXPECT(h, disabled.test_enabled == 0U); PP_EXPECT(h, disabled.write_enabled == 0U); PP_EXPECT(h, disabled.compare_function == 0x0203U); PP_EXPECT(h, read_write.supported); PP_EXPECT(h, read_write.test_enabled == 1U); PP_EXPECT(h, read_write.write_enabled == 1U); PP_EXPECT(h, read_write.compare_function == 0x0204U); PP_EXPECT(h, !invalid_compare.supported); PP_EXPECT(h, invalid_compare.test_enabled == 1U); PP_EXPECT(h, invalid_compare.write_enabled == 0U); PP_EXPECT(h, invalid_compare.compare_function == 0U); } void maps_windows_wgl_core_context_parameters(pp::tests::Harness& h) { const auto config = pp::renderer::gl::windows_wgl_core_context_3_3_config(); PP_EXPECT(h, config.context_attributes.size() == 9U); PP_EXPECT(h, config.context_attributes[0] == 0x2091); PP_EXPECT(h, config.context_attributes[1] == 3); PP_EXPECT(h, config.context_attributes[2] == 0x2092); PP_EXPECT(h, config.context_attributes[3] == 3); PP_EXPECT(h, config.context_attributes[4] == 0x2094); PP_EXPECT(h, config.context_attributes[5] == 0x0002); PP_EXPECT(h, config.context_attributes[6] == 0x9126); PP_EXPECT(h, config.context_attributes[7] == 0x00000001); PP_EXPECT(h, config.context_attributes[8] == 0); PP_EXPECT(h, config.pixel_format_attributes.size() == 15U); PP_EXPECT(h, config.pixel_format_attributes[0] == 0x2001); PP_EXPECT(h, config.pixel_format_attributes[1] == 1); PP_EXPECT(h, config.pixel_format_attributes[2] == 0x2010); PP_EXPECT(h, config.pixel_format_attributes[3] == 1); PP_EXPECT(h, config.pixel_format_attributes[4] == 0x2011); PP_EXPECT(h, config.pixel_format_attributes[5] == 1); PP_EXPECT(h, config.pixel_format_attributes[6] == 0x2003); PP_EXPECT(h, config.pixel_format_attributes[7] == 0x2027); PP_EXPECT(h, config.pixel_format_attributes[8] == 0x2013); PP_EXPECT(h, config.pixel_format_attributes[9] == 0x202B); PP_EXPECT(h, config.pixel_format_attributes[10] == 0x2014); PP_EXPECT(h, config.pixel_format_attributes[11] == 24); PP_EXPECT(h, config.pixel_format_attributes[12] == 0x2022); PP_EXPECT(h, config.pixel_format_attributes[13] == 16); PP_EXPECT(h, config.pixel_format_attributes[14] == 0); } 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()); } void exposes_shader_uniform_catalog(pp::tests::Harness& h) { const auto uniforms = pp::renderer::gl::panopainter_shader_uniform_names(); PP_EXPECT(h, uniforms.size() == 43U); PP_EXPECT(h, pp::renderer::gl::validate_shader_uniform_names(uniforms).ok()); PP_EXPECT(h, std::strcmp(uniforms[0].name, "mvp") == 0); PP_EXPECT(h, uniforms[0].id == pp::renderer::gl::shader_uniform_id("mvp")); PP_EXPECT(h, uniforms[0].id == 40696U); PP_EXPECT(h, std::strcmp(uniforms[1].name, "tex") == 0); PP_EXPECT(h, uniforms[1].id == pp::renderer::gl::shader_uniform_id("tex")); PP_EXPECT(h, uniforms[1].id == 48854U); PP_EXPECT(h, pp::renderer::gl::shader_uniform_id("pattern_contr") == 54920U); PP_EXPECT(h, pp::renderer::gl::shader_uniform_id("draw_outline") == 36178U); } void rejects_invalid_shader_uniform_catalogs(pp::tests::Harness& h) { const std::array empty {}; const std::array unnamed { pp::renderer::gl::OpenGlUniformName { .name = "", .id = 0 }, }; const std::array null_named { pp::renderer::gl::OpenGlUniformName { .name = nullptr, .id = 0 }, }; const std::array mismatched_hash { pp::renderer::gl::OpenGlUniformName { .name = "mvp", .id = 1 }, }; const std::array duplicate_name { pp::renderer::gl::OpenGlUniformName { .name = "mvp", .id = pp::renderer::gl::shader_uniform_id("mvp"), }, pp::renderer::gl::OpenGlUniformName { .name = "mvp", .id = pp::renderer::gl::shader_uniform_id("mvp"), }, }; PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(empty).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(unnamed).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(null_named).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(mismatched_hash).ok()); PP_EXPECT(h, !pp::renderer::gl::validate_shader_uniform_names(duplicate_name).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("maps_renderer_texture_formats_to_opengl_tokens", maps_renderer_texture_formats_to_opengl_tokens); harness.run("maps_readback_formats", maps_readback_formats); harness.run("maps_pixel_buffer_parameters", maps_pixel_buffer_parameters); harness.run("names_framebuffer_status_codes", names_framebuffer_status_codes); harness.run("maps_framebuffer_render_target_parameters", maps_framebuffer_render_target_parameters); harness.run("maps_framebuffer_blit_parameters", maps_framebuffer_blit_parameters); harness.run("maps_render_pass_clear_masks", maps_render_pass_clear_masks); harness.run("maps_renderer_primitive_topologies_to_draw_modes", maps_renderer_primitive_topologies_to_draw_modes); harness.run("maps_shape_index_and_primitive_modes", maps_shape_index_and_primitive_modes); harness.run("maps_panopainter_cube_faces_to_texture_targets", maps_panopainter_cube_faces_to_texture_targets); harness.run("exposes_default_render_target_texture_parameters", exposes_default_render_target_texture_parameters); harness.run("maps_sampler_parameters", maps_sampler_parameters); 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_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); harness.run("maps_renderer_depth_compare_tokens", maps_renderer_depth_compare_tokens); harness.run("maps_renderer_depth_states", maps_renderer_depth_states); harness.run("maps_windows_wgl_core_context_parameters", maps_windows_wgl_core_context_parameters); harness.run("rejects_invalid_shader_attribute_binding_catalogs", rejects_invalid_shader_attribute_binding_catalogs); harness.run("exposes_shader_uniform_catalog", exposes_shader_uniform_catalog); harness.run("rejects_invalid_shader_uniform_catalogs", rejects_invalid_shader_uniform_catalogs); return harness.finish(); }