#include "renderer_gl/opengl_capabilities.h" #include #include namespace pp::renderer::gl { namespace { constexpr std::uint32_t gl_unsigned_byte = 0x1401U; constexpr std::uint32_t gl_unsigned_short = 0x1403U; constexpr std::uint32_t gl_unsigned_int = 0x1405U; constexpr std::uint32_t gl_float = 0x1406U; constexpr std::uint32_t gl_half_float = 0x140BU; constexpr std::uint32_t gl_no_error = 0U; constexpr std::uint32_t gl_invalid_enum = 0x0500U; constexpr std::uint32_t gl_invalid_value = 0x0501U; constexpr std::uint32_t gl_invalid_operation = 0x0502U; constexpr std::uint32_t gl_out_of_memory = 0x0505U; constexpr std::uint32_t gl_invalid_framebuffer_operation = 0x0506U; constexpr std::uint32_t gl_false = 0U; 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_triangle_strip = 0x0005U; constexpr std::uint32_t gl_fragment_shader = 0x8B30U; constexpr std::uint32_t gl_vertex_shader = 0x8B31U; constexpr std::uint32_t gl_compile_status = 0x8B81U; constexpr std::uint32_t gl_link_status = 0x8B82U; constexpr std::uint32_t gl_active_uniforms = 0x8B86U; constexpr std::uint32_t gl_extensions = 0x1F03U; constexpr std::uint32_t gl_num_extensions = 0x821DU; constexpr std::uint32_t gl_version = 0x1F02U; constexpr std::uint32_t gl_vendor = 0x1F00U; constexpr std::uint32_t gl_renderer = 0x1F01U; constexpr std::uint32_t gl_shading_language_version = 0x8B8CU; constexpr std::uint32_t gl_debug_output_synchronous = 0x8242U; constexpr std::uint32_t gl_debug_output = 0x92E0U; constexpr std::uint32_t gl_debug_severity_high = 0x9146U; constexpr std::uint32_t gl_debug_severity_medium = 0x9147U; constexpr std::uint32_t gl_debug_severity_low = 0x9148U; constexpr std::uint32_t gl_debug_severity_notification = 0x826BU; constexpr std::uint32_t gl_zero = 0U; constexpr std::uint32_t gl_one = 1U; constexpr std::uint32_t gl_src_alpha = 0x0302U; constexpr std::uint32_t gl_one_minus_src_alpha = 0x0303U; constexpr std::uint32_t gl_dst_alpha = 0x0304U; constexpr std::uint32_t gl_one_minus_dst_alpha = 0x0305U; constexpr std::uint32_t gl_line_smooth = 0x0B20U; constexpr std::uint32_t gl_viewport = 0x0BA2U; constexpr std::uint32_t gl_blend = 0x0BE2U; constexpr std::uint32_t gl_color_clear_value = 0x0C22U; constexpr std::uint32_t gl_scissor_test = 0x0C11U; constexpr std::uint32_t gl_depth_test = 0x0B71U; constexpr std::uint32_t gl_never = 0x0200U; constexpr std::uint32_t gl_less = 0x0201U; constexpr std::uint32_t gl_equal = 0x0202U; constexpr std::uint32_t gl_lequal = 0x0203U; constexpr std::uint32_t gl_greater = 0x0204U; constexpr std::uint32_t gl_notequal = 0x0205U; constexpr std::uint32_t gl_gequal = 0x0206U; constexpr std::uint32_t gl_always = 0x0207U; constexpr std::uint32_t gl_current_program = 0x8B8DU; constexpr std::uint32_t gl_active_texture = 0x84E0U; constexpr std::uint32_t gl_texture_binding_2d = 0x8069U; constexpr std::uint32_t gl_texture_binding_cube_map = 0x8514U; constexpr std::uint32_t gl_sampler_binding = 0x8919U; constexpr std::uint32_t gl_func_add = 0x8006U; constexpr std::uint32_t gl_max = 0x8008U; constexpr std::uint32_t gl_func_subtract = 0x800AU; constexpr std::uint32_t gl_func_reverse_subtract = 0x800BU; constexpr std::uint32_t gl_program_point_size = 0x8642U; constexpr std::uint32_t gl_array_buffer = 0x8892U; constexpr std::uint32_t gl_element_array_buffer = 0x8893U; constexpr std::uint32_t gl_static_draw = 0x88E4U; 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; constexpr std::uint32_t gl_rgba32f = 0x8814U; constexpr std::uint32_t gl_rgba16f = 0x881AU; constexpr std::uint32_t gl_depth_stencil = 0x84F9U; constexpr std::uint32_t gl_unsigned_int_24_8 = 0x84FAU; constexpr std::uint32_t gl_depth24_stencil8 = 0x88F0U; constexpr std::uint32_t gl_texture_2d = 0x0DE1U; constexpr std::uint32_t gl_renderbuffer = 0x8D41U; constexpr std::uint32_t gl_depth_component24 = 0x81A6U; constexpr std::uint32_t gl_framebuffer = 0x8D40U; constexpr std::uint32_t gl_read_framebuffer = 0x8CA8U; constexpr std::uint32_t gl_draw_framebuffer = 0x8CA9U; constexpr std::uint32_t gl_draw_framebuffer_binding = 0x8CA6U; constexpr std::uint32_t gl_read_framebuffer_binding = 0x8CAAU; constexpr std::uint32_t gl_color_attachment0 = 0x8CE0U; constexpr std::uint32_t gl_depth_attachment = 0x8D00U; constexpr std::uint32_t gl_framebuffer_complete = 0x8CD5U; constexpr std::uint32_t gl_framebuffer_incomplete_attachment = 0x8CD6U; constexpr std::uint32_t gl_framebuffer_incomplete_missing_attachment = 0x8CD7U; constexpr std::uint32_t gl_framebuffer_incomplete_draw_buffer = 0x8CDBU; constexpr std::uint32_t gl_framebuffer_incomplete_read_buffer = 0x8CDCU; constexpr std::uint32_t gl_framebuffer_unsupported = 0x8CDDU; constexpr std::uint32_t gl_framebuffer_undefined = 0x8219U; constexpr std::uint32_t gl_framebuffer_incomplete_multisample = 0x8D56U; constexpr std::uint32_t gl_color_buffer_bit = 0x00004000U; constexpr std::uint32_t gl_depth_buffer_bit = 0x00000100U; constexpr std::uint32_t gl_color_writemask = 0x0C23U; constexpr std::uint32_t gl_texture_cube_map = 0x8513U; constexpr std::uint32_t gl_texture_cube_map_positive_x = 0x8515U; constexpr std::uint32_t gl_texture_cube_map_negative_x = 0x8516U; constexpr std::uint32_t gl_texture_cube_map_positive_y = 0x8517U; constexpr std::uint32_t gl_texture_cube_map_negative_y = 0x8518U; constexpr std::uint32_t gl_texture_cube_map_positive_z = 0x8519U; constexpr std::uint32_t gl_texture_cube_map_negative_z = 0x851AU; constexpr std::uint32_t gl_linear = 0x2601U; constexpr std::uint32_t gl_linear_mipmap_linear = 0x2703U; constexpr std::uint32_t gl_nearest = 0x2600U; constexpr std::uint32_t gl_texture_mag_filter = 0x2800U; constexpr std::uint32_t gl_texture_min_filter = 0x2801U; constexpr std::uint32_t gl_texture_wrap_s = 0x2802U; constexpr std::uint32_t gl_texture_wrap_t = 0x2803U; constexpr std::uint32_t gl_texture_wrap_r = 0x8072U; constexpr std::uint32_t gl_texture_border_color = 0x1004U; constexpr std::uint32_t gl_repeat = 0x2901U; constexpr std::uint32_t gl_mirrored_repeat = 0x8370U; constexpr std::uint32_t gl_clamp_to_border = 0x812DU; constexpr std::uint32_t gl_clamp_to_edge = 0x812FU; constexpr std::uint32_t gl_texture0 = 0x84C0U; constexpr std::uint32_t gl_pixel_pack_buffer = 0x88EBU; constexpr std::uint32_t gl_pixel_unpack_buffer = 0x88ECU; constexpr std::uint32_t gl_stream_read = 0x88E1U; constexpr std::uint32_t gl_map_read_bit = 0x0001U; constexpr std::uint8_t gl_boolean_false = 0U; constexpr std::uint8_t gl_boolean_true = 1U; constexpr std::int32_t wgl_draw_to_window_arb = 0x2001; constexpr std::int32_t wgl_acceleration_arb = 0x2003; constexpr std::int32_t wgl_support_opengl_arb = 0x2010; constexpr std::int32_t wgl_double_buffer_arb = 0x2011; constexpr std::int32_t wgl_pixel_type_arb = 0x2013; constexpr std::int32_t wgl_color_bits_arb = 0x2014; constexpr std::int32_t wgl_depth_bits_arb = 0x2022; constexpr std::int32_t wgl_full_acceleration_arb = 0x2027; constexpr std::int32_t wgl_type_rgba_arb = 0x202B; constexpr std::int32_t wgl_context_major_version_arb = 0x2091; constexpr std::int32_t wgl_context_minor_version_arb = 0x2092; constexpr std::int32_t wgl_context_flags_arb = 0x2094; constexpr std::int32_t wgl_context_forward_compatible_bit_arb = 0x0002; constexpr std::int32_t wgl_context_profile_mask_arb = 0x9126; constexpr std::int32_t wgl_context_core_profile_bit_arb = 0x00000001; [[nodiscard]] bool contains(std::string_view text, std::string_view needle) noexcept { return text.find(needle) != std::string_view::npos; } } OpenGlCapabilities detect_opengl_capabilities( std::span extensions, OpenGlRuntime runtime) noexcept { OpenGlCapabilities capabilities; if (runtime.desktop_gl) { capabilities.float32_textures = true; capabilities.float32_linear = true; capabilities.float16_textures = true; } for (const auto extension : extensions) { if (contains(extension, "shader_framebuffer_fetch")) { capabilities.framebuffer_fetch = true; } if (contains(extension, "map_buffer_alignment")) { capabilities.map_buffer_alignment = true; } if (runtime.gles && !runtime.web) { if (contains(extension, "texture_float") || contains(extension, "color_buffer_float")) { capabilities.float32_textures = true; } if (contains(extension, "texture_float_linear")) { capabilities.float32_linear = true; } if (contains(extension, "texture_half_float") || contains(extension, "color_buffer_half_float")) { capabilities.float16_textures = true; } } } return capabilities; } pp::renderer::RenderDeviceFeatures render_device_features(OpenGlCapabilities capabilities) noexcept { return pp::renderer::RenderDeviceFeatures { .framebuffer_fetch = capabilities.framebuffer_fetch, .texture_copy = true, .render_target_blit = true, .frame_capture = true, .float16_render_targets = capabilities.float16_textures, .float32_render_targets = capabilities.float32_textures, }; } std::uint32_t extension_count_query() noexcept { return gl_num_extensions; } std::uint32_t extension_string_name() noexcept { return gl_extensions; } std::uint32_t no_error_code() noexcept { return gl_no_error; } const char* opengl_error_name(std::uint32_t error_code) noexcept { switch (error_code) { case gl_no_error: return "GL_NO_ERROR"; case gl_invalid_enum: return "GL_INVALID_ENUM"; case gl_invalid_value: return "GL_INVALID_VALUE"; case gl_invalid_operation: return "GL_INVALID_OPERATION"; case gl_invalid_framebuffer_operation: return "GL_INVALID_FRAMEBUFFER_OPERATION"; case gl_out_of_memory: return "GL_OUT_OF_MEMORY"; default: return "Unknown"; } } std::uint32_t texture_upload_type_for_internal_format(std::uint32_t internal_format) noexcept { switch (internal_format) { case gl_rgba32f: return gl_float; case gl_rgba16f: return gl_half_float; default: return gl_unsigned_byte; } } std::uint32_t unsigned_byte_component_type() noexcept { return gl_unsigned_byte; } std::uint32_t rgba_pixel_format() noexcept { return gl_rgba; } OpenGlPixelFormat texture_format_for_channel_count(std::uint32_t channel_count) noexcept { switch (channel_count) { case 1: return OpenGlPixelFormat { .internal_format = gl_r8, .pixel_format = gl_red, .channel_count = 1 }; case 2: return OpenGlPixelFormat { .internal_format = gl_rg8, .pixel_format = gl_rg, .channel_count = 2 }; case 3: return OpenGlPixelFormat { .internal_format = gl_rgb8, .pixel_format = gl_rgb, .channel_count = 3 }; case 4: return OpenGlPixelFormat { .internal_format = gl_rgba8, .pixel_format = gl_rgba, .channel_count = 4 }; default: return OpenGlPixelFormat {}; } } OpenGlRendererTextureFormat texture_format_for_renderer_format(pp::renderer::TextureFormat format) noexcept { switch (format) { case pp::renderer::TextureFormat::rgba8: return OpenGlRendererTextureFormat { .internal_format = gl_rgba8, .pixel_format = gl_rgba, .component_type = gl_unsigned_byte, .bytes_per_pixel = 4U, }; case pp::renderer::TextureFormat::r8: return OpenGlRendererTextureFormat { .internal_format = gl_r8, .pixel_format = gl_red, .component_type = gl_unsigned_byte, .bytes_per_pixel = 1U, }; case pp::renderer::TextureFormat::depth24_stencil8: return OpenGlRendererTextureFormat { .internal_format = gl_depth24_stencil8, .pixel_format = gl_depth_stencil, .component_type = gl_unsigned_int_24_8, .bytes_per_pixel = 4U, }; default: return OpenGlRendererTextureFormat {}; } } OpenGlReadbackFormat rgba8_readback_format() noexcept { return OpenGlReadbackFormat { .pixel_format = gl_rgba, .component_type = gl_unsigned_byte, .bytes_per_pixel = 4U, }; } OpenGlReadbackFormat rgba32f_readback_format() noexcept { return OpenGlReadbackFormat { .pixel_format = gl_rgba, .component_type = gl_float, .bytes_per_pixel = 16U, }; } std::uint64_t readback_byte_count( OpenGlReadbackFormat format, std::uint32_t width, std::uint32_t height) noexcept { if (format.bytes_per_pixel == 0U) { return 0U; } const auto wide_width = static_cast(width); const auto wide_height = static_cast(height); if (wide_width != 0U && wide_height > std::numeric_limits::max() / wide_width) { return 0U; } const auto pixels = wide_width * wide_height; if (pixels != 0U && format.bytes_per_pixel > std::numeric_limits::max() / pixels) { return 0U; } return pixels * format.bytes_per_pixel; } std::uint32_t pixel_pack_buffer_target() noexcept { return gl_pixel_pack_buffer; } std::uint32_t pixel_unpack_buffer_target() noexcept { return gl_pixel_unpack_buffer; } std::uint32_t pixel_buffer_stream_read_usage() noexcept { return gl_stream_read; } std::uint32_t pixel_buffer_map_read_access() noexcept { return gl_map_read_bit; } std::uint32_t texture_2d_target() noexcept { return gl_texture_2d; } std::uint32_t renderbuffer_target() noexcept { return gl_renderbuffer; } std::uint32_t depth_component24_format() noexcept { return gl_depth_component24; } std::uint32_t framebuffer_target() noexcept { return gl_framebuffer; } std::uint32_t draw_framebuffer_target() noexcept { return gl_draw_framebuffer; } std::uint32_t read_framebuffer_target() noexcept { return gl_read_framebuffer; } std::uint32_t draw_framebuffer_binding_query() noexcept { return gl_draw_framebuffer_binding; } std::uint32_t read_framebuffer_binding_query() noexcept { return gl_read_framebuffer_binding; } std::uint32_t framebuffer_color_attachment() noexcept { return gl_color_attachment0; } std::uint32_t framebuffer_depth_attachment() noexcept { return gl_depth_attachment; } std::uint32_t framebuffer_complete_status() noexcept { return gl_framebuffer_complete; } std::uint32_t default_framebuffer_id() noexcept { return 0U; } const char* framebuffer_status_name(std::uint32_t status) noexcept { switch (status) { case gl_framebuffer_complete: return "GL_FRAMEBUFFER_COMPLETE"; case gl_framebuffer_undefined: return "GL_FRAMEBUFFER_UNDEFINED"; case gl_framebuffer_incomplete_attachment: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; case gl_framebuffer_incomplete_missing_attachment: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; case gl_framebuffer_incomplete_draw_buffer: return "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER"; case gl_framebuffer_incomplete_read_buffer: return "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER"; case gl_framebuffer_unsupported: return "GL_FRAMEBUFFER_UNSUPPORTED"; case gl_framebuffer_incomplete_multisample: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; default: return "UNKNOWN"; } } std::uint32_t framebuffer_color_buffer_mask() noexcept { return gl_color_buffer_bit; } std::uint32_t framebuffer_depth_buffer_mask() noexcept { return gl_depth_buffer_bit; } std::uint32_t color_write_mask_query() noexcept { return gl_color_writemask; } std::uint32_t framebuffer_blit_filter(bool linear) noexcept { return linear ? gl_linear : gl_nearest; } std::uint32_t primitive_mode_for_renderer_topology(pp::renderer::PrimitiveTopology topology) noexcept { switch (topology) { case pp::renderer::PrimitiveTopology::triangles: return gl_triangles; case pp::renderer::PrimitiveTopology::triangle_strip: return gl_triangle_strip; case pp::renderer::PrimitiveTopology::lines: return gl_lines; default: return 0U; } } std::uint32_t index_type_for_index_size(std::uint32_t index_size_bytes) noexcept { switch (index_size_bytes) { case 2: return gl_unsigned_short; case 4: return gl_unsigned_int; default: return 0U; } } std::uint32_t primitive_mode_for_fill_count(std::uint32_t vertex_or_index_count) noexcept { if (vertex_or_index_count == 1U) { return gl_points; } if (vertex_or_index_count == 2U) { return gl_lines; } return gl_triangles; } std::uint32_t primitive_mode_for_stroke_count(std::uint32_t vertex_or_index_count) noexcept { if (vertex_or_index_count == 1U) { return gl_points; } return gl_lines; } std::uint32_t array_buffer_target() noexcept { return gl_array_buffer; } std::uint32_t element_array_buffer_target() noexcept { return gl_element_array_buffer; } std::uint32_t static_draw_buffer_usage() noexcept { return gl_static_draw; } std::uint32_t vertex_attribute_float_component_type() noexcept { return gl_float; } std::uint32_t vertex_attribute_not_normalized() noexcept { return gl_false; } std::uint32_t vertex_shader_stage() noexcept { return gl_vertex_shader; } std::uint32_t fragment_shader_stage() noexcept { return gl_fragment_shader; } std::uint32_t shader_compile_status_query() noexcept { return gl_compile_status; } std::uint32_t program_link_status_query() noexcept { return gl_link_status; } std::uint32_t active_uniform_count_query() noexcept { return gl_active_uniforms; } std::uint32_t matrix_uniform_not_transposed() noexcept { return gl_false; } std::uint32_t debug_severity_notification() noexcept { return gl_debug_severity_notification; } std::uint32_t debug_severity_low() noexcept { return gl_debug_severity_low; } std::uint32_t debug_severity_medium() noexcept { return gl_debug_severity_medium; } std::uint32_t debug_severity_high() noexcept { return gl_debug_severity_high; } std::uint32_t debug_output_state() noexcept { return gl_debug_output; } std::uint32_t debug_output_synchronous_state() noexcept { return gl_debug_output_synchronous; } std::uint32_t version_string_name() noexcept { return gl_version; } std::uint32_t vendor_string_name() noexcept { return gl_vendor; } std::uint32_t renderer_string_name() noexcept { return gl_renderer; } std::uint32_t shading_language_version_string_name() noexcept { return gl_shading_language_version; } std::uint32_t viewport_query() noexcept { return gl_viewport; } std::uint32_t color_clear_value_query() noexcept { return gl_color_clear_value; } std::uint32_t current_program_query() noexcept { return gl_current_program; } std::uint32_t active_texture_query() noexcept { return gl_active_texture; } std::uint32_t texture_binding_2d_query() noexcept { return gl_texture_binding_2d; } std::uint32_t texture_binding_cube_map_query() noexcept { return gl_texture_binding_cube_map; } std::uint32_t sampler_binding_query() noexcept { return gl_sampler_binding; } std::uint32_t blend_state() noexcept { return gl_blend; } std::uint32_t depth_test_state() noexcept { return gl_depth_test; } OpenGlEnumMapping compare_function_for_renderer_compare_op(pp::renderer::CompareOp op) noexcept { switch (op) { case pp::renderer::CompareOp::never: return OpenGlEnumMapping { .value = gl_never, .supported = true }; case pp::renderer::CompareOp::less: return OpenGlEnumMapping { .value = gl_less, .supported = true }; case pp::renderer::CompareOp::equal: return OpenGlEnumMapping { .value = gl_equal, .supported = true }; case pp::renderer::CompareOp::less_or_equal: return OpenGlEnumMapping { .value = gl_lequal, .supported = true }; case pp::renderer::CompareOp::greater: return OpenGlEnumMapping { .value = gl_greater, .supported = true }; case pp::renderer::CompareOp::not_equal: return OpenGlEnumMapping { .value = gl_notequal, .supported = true }; case pp::renderer::CompareOp::greater_or_equal: return OpenGlEnumMapping { .value = gl_gequal, .supported = true }; case pp::renderer::CompareOp::always: return OpenGlEnumMapping { .value = gl_always, .supported = true }; default: return OpenGlEnumMapping {}; } } std::uint32_t scissor_test_state() noexcept { return gl_scissor_test; } std::uint32_t program_point_size_state() noexcept { return gl_program_point_size; } std::uint32_t line_smooth_state() noexcept { return gl_line_smooth; } std::uint32_t source_alpha_blend_factor() noexcept { return gl_src_alpha; } std::uint32_t one_minus_source_alpha_blend_factor() noexcept { return gl_one_minus_src_alpha; } std::uint32_t add_blend_equation() noexcept { return gl_func_add; } std::uint32_t max_blend_equation() noexcept { return gl_max; } OpenGlEnumMapping blend_factor_for_renderer_factor(pp::renderer::BlendFactor factor) noexcept { switch (factor) { case pp::renderer::BlendFactor::zero: return OpenGlEnumMapping { .value = gl_zero, .supported = true }; case pp::renderer::BlendFactor::one: return OpenGlEnumMapping { .value = gl_one, .supported = true }; case pp::renderer::BlendFactor::source_alpha: return OpenGlEnumMapping { .value = gl_src_alpha, .supported = true }; case pp::renderer::BlendFactor::one_minus_source_alpha: return OpenGlEnumMapping { .value = gl_one_minus_src_alpha, .supported = true }; case pp::renderer::BlendFactor::destination_alpha: return OpenGlEnumMapping { .value = gl_dst_alpha, .supported = true }; case pp::renderer::BlendFactor::one_minus_destination_alpha: return OpenGlEnumMapping { .value = gl_one_minus_dst_alpha, .supported = true }; default: return OpenGlEnumMapping {}; } } OpenGlEnumMapping blend_equation_for_renderer_op(pp::renderer::BlendOp op) noexcept { switch (op) { case pp::renderer::BlendOp::add: return OpenGlEnumMapping { .value = gl_func_add, .supported = true }; case pp::renderer::BlendOp::subtract: return OpenGlEnumMapping { .value = gl_func_subtract, .supported = true }; case pp::renderer::BlendOp::reverse_subtract: return OpenGlEnumMapping { .value = gl_func_reverse_subtract, .supported = true }; default: return OpenGlEnumMapping {}; } } std::uint32_t rgba8_internal_format() noexcept { return gl_rgba8; } std::uint32_t rgba16f_internal_format() noexcept { return gl_rgba16f; } std::uint32_t rgba32f_internal_format() noexcept { return gl_rgba32f; } std::uint8_t color_write_disabled() noexcept { return gl_boolean_false; } std::uint8_t color_write_enabled() noexcept { return gl_boolean_true; } std::uint32_t linear_texture_filter() noexcept { return gl_linear; } std::uint32_t linear_mipmap_linear_texture_filter() noexcept { return gl_linear_mipmap_linear; } std::uint32_t nearest_texture_filter() noexcept { return gl_nearest; } std::uint32_t repeat_texture_wrap() noexcept { return gl_repeat; } std::uint32_t clamp_to_edge_texture_wrap() noexcept { return gl_clamp_to_edge; } std::uint32_t clamp_to_border_texture_wrap() noexcept { return gl_clamp_to_border; } OpenGlEnumMapping sampler_filter_for_renderer_filter(pp::renderer::SamplerFilter filter) noexcept { switch (filter) { case pp::renderer::SamplerFilter::nearest: return OpenGlEnumMapping { .value = gl_nearest, .supported = true }; case pp::renderer::SamplerFilter::linear: return OpenGlEnumMapping { .value = gl_linear, .supported = true }; default: return OpenGlEnumMapping {}; } } OpenGlEnumMapping sampler_address_mode_for_renderer_mode(pp::renderer::SamplerAddressMode mode) noexcept { switch (mode) { case pp::renderer::SamplerAddressMode::clamp_to_edge: return OpenGlEnumMapping { .value = gl_clamp_to_edge, .supported = true }; case pp::renderer::SamplerAddressMode::repeat: return OpenGlEnumMapping { .value = gl_repeat, .supported = true }; case pp::renderer::SamplerAddressMode::mirrored_repeat: return OpenGlEnumMapping { .value = gl_mirrored_repeat, .supported = true }; case pp::renderer::SamplerAddressMode::clamp_to_border: return OpenGlEnumMapping { .value = gl_clamp_to_border, .supported = true }; default: return OpenGlEnumMapping {}; } } std::uint32_t active_texture_unit(std::uint32_t unit_index) noexcept { return gl_texture0 + unit_index; } std::uint32_t texture_cube_map_target() noexcept { return gl_texture_cube_map; } std::uint32_t cube_map_allocation_face_texture_target(std::uint32_t face_index) noexcept { if (face_index >= 6U) { return 0U; } return gl_texture_cube_map_positive_x + face_index; } std::span panopainter_cube_face_texture_targets() noexcept { static constexpr std::array targets { gl_texture_cube_map_negative_z, // front gl_texture_cube_map_negative_x, // right gl_texture_cube_map_positive_z, // back gl_texture_cube_map_positive_x, // left gl_texture_cube_map_negative_y, // top gl_texture_cube_map_positive_y, // bottom }; return targets; } std::uint32_t cube_face_texture_target(std::uint32_t face_index) noexcept { const auto targets = panopainter_cube_face_texture_targets(); if (face_index >= targets.size()) { return 0U; } return targets[face_index]; } std::span default_render_target_texture_parameters() noexcept { static constexpr std::array parameters { OpenGlTextureParameter { .name = gl_texture_mag_filter, .value = gl_linear }, OpenGlTextureParameter { .name = gl_texture_min_filter, .value = gl_linear }, OpenGlTextureParameter { .name = gl_texture_wrap_s, .value = gl_clamp_to_edge }, OpenGlTextureParameter { .name = gl_texture_wrap_t, .value = gl_clamp_to_edge }, }; return parameters; } std::array sampler_parameters_for_filter_wrap( std::uint32_t filter, std::uint32_t wrap) noexcept { return { OpenGlTextureParameter { .name = gl_texture_wrap_s, .value = wrap }, OpenGlTextureParameter { .name = gl_texture_wrap_t, .value = wrap }, OpenGlTextureParameter { .name = gl_texture_wrap_r, .value = wrap }, OpenGlTextureParameter { .name = gl_texture_min_filter, .value = filter }, OpenGlTextureParameter { .name = gl_texture_mag_filter, .value = filter }, }; } std::array sampler_filter_parameters( std::uint32_t filter_min, std::uint32_t filter_mag) noexcept { return { OpenGlTextureParameter { .name = gl_texture_min_filter, .value = filter_min }, OpenGlTextureParameter { .name = gl_texture_mag_filter, .value = filter_mag }, }; } std::uint32_t sampler_border_color_parameter_name() noexcept { return gl_texture_border_color; } OpenGlWindowsWglContextConfig windows_wgl_core_context_3_3_config() noexcept { return { .context_attributes = { wgl_context_major_version_arb, 3, wgl_context_minor_version_arb, 3, wgl_context_flags_arb, wgl_context_forward_compatible_bit_arb, wgl_context_profile_mask_arb, wgl_context_core_profile_bit_arb, 0, }, .pixel_format_attributes = { wgl_draw_to_window_arb, static_cast(gl_boolean_true), wgl_support_opengl_arb, static_cast(gl_boolean_true), wgl_double_buffer_arb, static_cast(gl_boolean_true), wgl_acceleration_arb, wgl_full_acceleration_arb, wgl_pixel_type_arb, wgl_type_rgba_arb, wgl_color_bits_arb, 24, wgl_depth_bits_arb, 16, 0, }, }; } }